diff --git a/apps/frontend/app/(tabs)/(profile)/(pay-methods)/index.tsx b/apps/frontend/app/(tabs)/(profile)/(pay-methods)/index.tsx index f9c4190..e9427d3 100644 --- a/apps/frontend/app/(tabs)/(profile)/(pay-methods)/index.tsx +++ b/apps/frontend/app/(tabs)/(profile)/(pay-methods)/index.tsx @@ -18,8 +18,8 @@ const PayMethods = () => { const isEmpty = payMethods.length === 0; const listStyle = !isEmpty ? Platform.select({ - ios: 'pb-60 px-2 pt-4', - android: 'pb-24 px-2 pt-4', + ios: 'pb-60', + android: 'pb-24', }) : 'flex-1 items-center justify-center pb-48'; @@ -31,40 +31,43 @@ const PayMethods = () => { right={ setModalVisible(true)} // 👈 opens modal + onPress={() => setModalVisible(true)} /> } /> ), }); - }); + }, []); return ( - - - item.id} - showsVerticalScrollIndicator={false} - contentContainerClassName={listStyle} - renderItem={({ item, index }) => } - ItemSeparatorComponent={() => } - ListFooterComponent={() => !isEmpty && } - ListEmptyComponent={ - { - setModalVisible(true); - }} - /> - } - /> - - + <> + + + item.id} + showsVerticalScrollIndicator={false} + contentContainerClassName={listStyle} + renderItem={({ item, index }) => } + ItemSeparatorComponent={() => } + ListFooterComponent={() => + !isEmpty && + } + ListEmptyComponent={ + { + setModalVisible(true); + }} + /> + } + /> + + setModalVisible(false)} /> - + ); }; diff --git a/apps/frontend/app/_layout.tsx b/apps/frontend/app/_layout.tsx index 4a8dbcc..ded39ce 100644 --- a/apps/frontend/app/_layout.tsx +++ b/apps/frontend/app/_layout.tsx @@ -2,6 +2,7 @@ import toastConfig from '@/components/toasts'; import { useCustomFonts } from '@/hooks'; import { Stack } from 'expo-router'; import { useColorScheme } from 'react-native'; +import { Host } from 'react-native-portalize'; import Toast from 'react-native-toast-message'; import './globals.css'; @@ -11,7 +12,7 @@ const RootLayout = () => { if (!fontsLoaded) return null; return ( - <> + { }} /> - + ); }; diff --git a/apps/frontend/app/globals.css b/apps/frontend/app/globals.css index 53ccf29..8a06b71 100644 --- a/apps/frontend/app/globals.css +++ b/apps/frontend/app/globals.css @@ -505,7 +505,7 @@ } .deposit-form-icon-wrapper { - @apply w-14 items-center justify-center rounded-r-lg bg-base dark:bg-base-dark; + @apply w-14 items-center justify-center rounded-r-lg bg-base-white dark:bg-base-dark; } .deposit-form-footer { @@ -565,7 +565,7 @@ } .dropdown-icon-wrapper { - @apply w-14 items-center justify-center rounded-r-lg bg-base dark:bg-base-dark; + @apply w-14 items-center justify-center rounded-r-lg bg-base-white dark:bg-base-dark; } .dropdown-error { diff --git a/apps/frontend/app/verify/index.tsx b/apps/frontend/app/verify/index.tsx index d97a48c..7d447fd 100644 --- a/apps/frontend/app/verify/index.tsx +++ b/apps/frontend/app/verify/index.tsx @@ -19,7 +19,7 @@ const Verify = () => { /> - + {Strings.verify.SCREEN_TITLE} diff --git a/apps/frontend/components/cards/PayMethodCard.tsx b/apps/frontend/components/cards/PayMethodCard.tsx index a5323ad..00a3f2b 100644 --- a/apps/frontend/components/cards/PayMethodCard.tsx +++ b/apps/frontend/components/cards/PayMethodCard.tsx @@ -34,7 +34,7 @@ const PayMethodCard = (props: PayMethodCardProps) => { }; return ( - + {payMethodType?.name} diff --git a/apps/frontend/components/form/FormInputField.tsx b/apps/frontend/components/form/SecondaryInputField.tsx similarity index 92% rename from apps/frontend/components/form/FormInputField.tsx rename to apps/frontend/components/form/SecondaryInputField.tsx index be101c9..787984f 100644 --- a/apps/frontend/components/form/FormInputField.tsx +++ b/apps/frontend/components/form/SecondaryInputField.tsx @@ -2,7 +2,7 @@ import cn from 'clsx'; import { useState } from 'react'; import { Platform, Text, TextInput, View } from 'react-native'; -const FormInputField = (props: FormInputFieldProps) => { +const SecondaryInputField = (props: SecondaryInputFieldProps) => { const isIOS = Platform.OS === 'ios'; const value = props.value ?? ''; @@ -49,7 +49,7 @@ const FormInputField = (props: FormInputFieldProps) => { @@ -63,4 +63,4 @@ const FormInputField = (props: FormInputFieldProps) => { ); }; -export default FormInputField; +export default SecondaryInputField; diff --git a/apps/frontend/components/form/formInputField.tsx b/apps/frontend/components/form/formInputField.tsx deleted file mode 100644 index be101c9..0000000 --- a/apps/frontend/components/form/formInputField.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import cn from 'clsx'; -import { useState } from 'react'; -import { Platform, Text, TextInput, View } from 'react-native'; - -const FormInputField = (props: FormInputFieldProps) => { - const isIOS = Platform.OS === 'ios'; - const value = props.value ?? ''; - - const [isFocused, setIsFocused] = useState(false); - const [showPassword, setShowPassword] = useState(false); - - return ( - - {props.label} - - - setIsFocused(true)} - onBlur={() => setIsFocused(false)} - /> - - - {props.secondarylabel && ( - - - {props.secondarylabel} - - - )} - - - ); -}; - -export default FormInputField; diff --git a/apps/frontend/components/form/index.ts b/apps/frontend/components/form/index.ts index a733cab..947cc3b 100644 --- a/apps/frontend/components/form/index.ts +++ b/apps/frontend/components/form/index.ts @@ -1,4 +1,4 @@ export { default as FileUplaod } from './FileUpload'; -export { default as FormInputField } from './FormInputField'; export { default as InputField } from './InputField'; +export { default as SecondaryInputField } from './SecondaryInputField'; export { default as StepperInput } from './StepperInput'; diff --git a/apps/frontend/components/modals/ModalView.tsx b/apps/frontend/components/modals/ModalView.tsx index e24f2bb..aed6c07 100644 --- a/apps/frontend/components/modals/ModalView.tsx +++ b/apps/frontend/components/modals/ModalView.tsx @@ -1,43 +1,41 @@ import React from 'react'; -import { Dimensions, Pressable, Text } from 'react-native'; +import { Dimensions, Pressable, Text, View } from 'react-native'; import Animated, { Easing, FadeIn, FadeOut, SlideInDown, SlideOutDown } from 'react-native-reanimated'; -import { useSafeAreaInsets } from 'react-native-safe-area-context'; - -const screenHeight = Dimensions.get('window').height; - -const ModalView = ({ visible, onClose, title, children, maxHeight = '80%' }: ModalViewProps) => { - const insets = useSafeAreaInsets(); +const ModalView = ({ visible, onClose, title, children, maxHeight = 0.55 }: ModalViewProps) => { if (!visible) return null; return ( {/* Backdrop pressable covering entire screen */} - + {/* Bottom sheet content above backdrop */} - - {title} - + + + + + + {title} + {React.cloneElement(children as any, { style: [{ flex: 1 }, (children as any).props.style], contentContainerStyle: [ (children as any).props.contentContainerStyle, - { paddingBottom: 200 }, // optional extra space + { paddingBottom: 16 }, // optional extra space ], })} diff --git a/apps/frontend/components/modals/NewPayMethodModal.tsx b/apps/frontend/components/modals/NewPayMethodModal.tsx index 076fbac..d1cbd57 100644 --- a/apps/frontend/components/modals/NewPayMethodModal.tsx +++ b/apps/frontend/components/modals/NewPayMethodModal.tsx @@ -1,5 +1,7 @@ import { usePayMethodType } from '@/hooks'; -import { FlatList, Image, Text, TouchableHighlight, useColorScheme, View } from 'react-native'; +import { router } from 'expo-router'; +import { Dimensions, FlatList, Image, Text, TouchableHighlight, useColorScheme, View } from 'react-native'; +import { Portal } from 'react-native-portalize'; import { DividerX } from '../dividers'; import ModalView from './ModalView'; @@ -12,33 +14,49 @@ const NewPayMethodModal = (props: NewPayMethodModalProps) => { const isDark = useColorScheme() === 'dark'; const { payMethodTypes, getPayMethodTypeById, getPayMethodTypeLogoUrlById } = usePayMethodType(); + const modalMaxHeight = 0.55; + const listMaxHeight = modalMaxHeight * 0.7; + return ( - - item.id} - showsVerticalScrollIndicator={false} - contentContainerClassName='mt-4' - renderItem={({ item, index }) => { - const payMethodType = getPayMethodTypeById(item.id); - const payMethodTypeLogoUrl = getPayMethodTypeLogoUrlById(item.id); + + + item.id} + showsVerticalScrollIndicator={false} + style={{ maxHeight: Dimensions.get('screen').height * listMaxHeight }} + renderItem={({ item, index }) => { + const payMethodType = getPayMethodTypeById(item.id); + const payMethodTypeLogoUrl = getPayMethodTypeLogoUrlById(item.id); - return ( - console.log('Pressed', payMethodType?.name)} - > - - {payMethodType?.name} - - - - ); - }} - ItemSeparatorComponent={() => } - /> - + return ( + { + props.onClose(); + router.push({ + pathname: '/details', + params: { + payMethodTypeId: item.id, + payMethodTypeName: item.name, + payMethodTypeCategory: item.category, + }, + }); + }} + > + + {payMethodType?.name} + + + + ); + }} + ItemSeparatorComponent={() => } + ListFooterComponent={() => } + /> + + ); }; diff --git a/apps/frontend/components/sections/VerifyEmail.tsx b/apps/frontend/components/sections/VerifyEmail.tsx index 07cdbb8..d92f499 100644 --- a/apps/frontend/components/sections/VerifyEmail.tsx +++ b/apps/frontend/components/sections/VerifyEmail.tsx @@ -1,12 +1,12 @@ import { Strings } from '@/constants'; import { useKyc } from '@/hooks'; -import { FormInputField } from '../form'; +import { SecondaryInputField } from '../form'; const VerifyEmail = () => { const { kyc } = useKyc(); return ( - { @@ -12,7 +12,12 @@ const VerifyIdentity = () => { return ( <> - + @@ -23,7 +28,7 @@ const VerifyIdentity = () => { onSelect={(item) => updateKyc('countryId', item.id)} /> - { const { kyc } = useKyc(); return ( - 15.0.0", + "react-native": "> 0.50.0" + } + }, "node_modules/react-native-qrcode-svg": { "version": "6.3.15", "resolved": "https://registry.npmjs.org/react-native-qrcode-svg/-/react-native-qrcode-svg-6.3.15.tgz", diff --git a/apps/frontend/package.json b/apps/frontend/package.json index dc3104c..0636e88 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -51,6 +51,7 @@ "react-native": "0.79.5", "react-native-confirmation-code-field": "^8.0.1", "react-native-gesture-handler": "~2.24.0", + "react-native-portalize": "^1.0.7", "react-native-qrcode-svg": "^6.3.15", "react-native-reanimated": "~3.17.4", "react-native-safe-area-context": "5.4.0", diff --git a/apps/frontend/types/props.d.ts b/apps/frontend/types/props.d.ts index 7520071..33304c6 100644 --- a/apps/frontend/types/props.d.ts +++ b/apps/frontend/types/props.d.ts @@ -71,7 +71,7 @@ interface ModalViewProps { onClose: () => void; title: string; children?: ReactNode; - maxHeight?: number | `${number}%`; + maxHeight?: number; } // ==================== @@ -277,7 +277,7 @@ interface ListEmptyStateProps { ctaOnPresss?: () => void; } -interface FormInputFieldProps { +interface SecondaryInputFieldProps { label: string; value?: string; placeholder?: string;