app-expo-cli 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -5
- package/package.json +1 -1
- package/src/copy-template.js +19 -1
- package/src/install-deps.js +6 -0
- package/template/assets/fonts/Inter_18pt-Black.ttf +0 -0
- package/template/assets/fonts/Inter_18pt-BlackItalic.ttf +0 -0
- package/template/assets/icon/index.ts +146 -0
- package/template/assets/images/about_us.png +0 -0
- package/template/assets/images/index.ts +6 -0
- package/template/assets/images/logo.png +0 -0
- package/template/assets/images/privacy_policy.png +0 -0
- package/template/assets/images/terms_and_conditions.png +0 -0
- package/template/src/app/_layout.tsx +3 -3
- package/template/src/app/auth/change_pass.tsx +18 -15
- package/template/src/app/auth/change_pass_modal.tsx +32 -51
- package/template/src/app/auth/forgot.tsx +74 -88
- package/template/src/app/auth/index.tsx +161 -192
- package/template/src/app/auth/opt_verify.tsx +93 -103
- package/template/src/app/auth/register.tsx +198 -260
- package/template/src/app/auth/reset_pass.tsx +102 -105
- package/template/src/app/index.tsx +70 -7
- package/template/src/app/modals/confirmation_logout_modal.tsx +0 -5
- package/template/src/app/modals/success_modal.tsx +28 -48
- package/template/src/app/settings/about_us.tsx +1 -1
- package/template/src/app/settings/privacy_policy.tsx +1 -1
- package/template/src/app/settings/terms_and_conditions.tsx +1 -1
- package/template/src/lib/DateTimePicker/DateTimePicker.tsx +63 -0
- package/template/src/lib/Empty/EmptyCard.tsx +67 -0
- package/template/src/lib/Error/GlobalErrorBoundary.tsx +111 -0
- package/template/src/lib/animate/AniImage.tsx +32 -0
- package/template/src/lib/backHeader/BackButton.tsx +62 -0
- package/template/src/lib/backHeader/BackWithCoponent.tsx +112 -0
- package/template/src/lib/backHeader/BackWithHeader.tsx +46 -0
- package/template/src/lib/backHeader/BackWithTitle.tsx +53 -0
- package/template/src/lib/buttons/IButton.tsx +69 -0
- package/template/src/lib/buttons/IwtButton.tsx +199 -0
- package/template/src/lib/buttons/Or.tsx +27 -0
- package/template/src/lib/buttons/SimpleButton.tsx +45 -0
- package/template/src/lib/buttons/TButton.tsx +70 -0
- package/template/src/lib/cards/Card.tsx +175 -0
- package/template/src/lib/cards/OptionSelect.tsx +44 -0
- package/template/src/lib/cards/SearchCard.tsx +35 -0
- package/template/src/lib/editor/TextEditor.tsx +81 -0
- package/template/src/lib/expend/ExpendComponent.tsx +36 -0
- package/template/src/lib/imageViewer/ImageViwer.tsx +332 -0
- package/template/src/lib/imageZoomer/ImageZoomer.tsx +104 -0
- package/template/src/lib/inputs/CheckBox.tsx +86 -0
- package/template/src/lib/inputs/InputText.tsx +232 -0
- package/template/src/lib/loader/GLoading.tsx +26 -0
- package/template/src/lib/loading/MLoading.tsx +14 -0
- package/template/src/lib/loading/SLoading.tsx +14 -0
- package/template/src/lib/modals/ActionModal.tsx +97 -0
- package/template/src/lib/modals/BottomModal.tsx +224 -0
- package/template/src/lib/modals/ConfrimationModal.tsx +116 -0
- package/template/src/lib/modals/DateModal.tsx +152 -0
- package/template/src/lib/modals/NormalModal.tsx +73 -0
- package/template/src/lib/modals/SideModal.tsx +57 -0
- package/template/src/lib/modals/Toaster.tsx +256 -0
- package/template/src/lib/payment/PaymentCardForD.tsx +47 -0
- package/template/src/lib/progressBar/ProgressBar.tsx +64 -0
- package/template/src/lib/tailwind.js +9 -0
- package/template/src/lib/ui/Avatar.tsx +55 -0
- package/template/src/redux/api-config/baseApi.ts +0 -22
- package/template/src/redux/interface/interface.ts +11 -193
- package/template/src/redux/store.ts +2 -2
- package/template/src/app/home/_layout.tsx +0 -29
- package/template/src/app/home/drawer/_layout.tsx +0 -27
- package/template/src/app/home/tabs/_layout.tsx +0 -75
- package/template/src/app/home/tabs/index.tsx +0 -11
- package/template/src/app/modals/payment_modal.tsx +0 -105
- package/template/src/hooks/useCheckLocation.ts +0 -36
- package/template/src/hooks/useDocPicker.ts +0 -83
- package/template/src/hooks/useSuggestionLocation.ts +0 -36
- package/template/src/hooks/useUploadProgress.ts +0 -127
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Pressable, Text, View } from "react-native";
|
|
2
|
+
|
|
3
|
+
import IwtButton from "../buttons/IwtButton";
|
|
4
|
+
import { Modal } from "react-native-ui-lib";
|
|
5
|
+
import React from "react";
|
|
6
|
+
import TButton from "../buttons/TButton";
|
|
7
|
+
import tw from "../tailwind";
|
|
8
|
+
|
|
9
|
+
interface NormalModalProps {
|
|
10
|
+
visible?: boolean;
|
|
11
|
+
setVisible?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
12
|
+
layerContainerStyle?: any;
|
|
13
|
+
containerStyle?: any;
|
|
14
|
+
animationType?: "none" | "slide" | "fade";
|
|
15
|
+
confirmationPress?: () => void;
|
|
16
|
+
title?: string;
|
|
17
|
+
subTitle?: string;
|
|
18
|
+
titleStyle?: any;
|
|
19
|
+
subTitleStyle?: any;
|
|
20
|
+
icon?: React.ReactNode;
|
|
21
|
+
svg?: string;
|
|
22
|
+
buttonStyle?: any;
|
|
23
|
+
buttonTextStyle?: any;
|
|
24
|
+
buttonText?: string;
|
|
25
|
+
onButtonPress?: () => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const NormalModal = ({
|
|
29
|
+
setVisible,
|
|
30
|
+
visible,
|
|
31
|
+
containerStyle,
|
|
32
|
+
layerContainerStyle,
|
|
33
|
+
animationType,
|
|
34
|
+
confirmationPress,
|
|
35
|
+
buttonStyle,
|
|
36
|
+
buttonText,
|
|
37
|
+
buttonTextStyle,
|
|
38
|
+
icon,
|
|
39
|
+
onButtonPress,
|
|
40
|
+
subTitle,
|
|
41
|
+
subTitleStyle,
|
|
42
|
+
svg,
|
|
43
|
+
title,
|
|
44
|
+
titleStyle,
|
|
45
|
+
}: NormalModalProps) => {
|
|
46
|
+
return (
|
|
47
|
+
<Modal
|
|
48
|
+
transparent
|
|
49
|
+
// useKeyboardAvoidingView={false}
|
|
50
|
+
animationType={"fade"}
|
|
51
|
+
overlayBackgroundColor={"rgba(0, 0, 0, 0.2)"}
|
|
52
|
+
visible={visible}
|
|
53
|
+
onBackgroundPress={() => setVisible && setVisible(!visible)}
|
|
54
|
+
>
|
|
55
|
+
<View
|
|
56
|
+
style={[tw` justify-center items-center h-full`, layerContainerStyle]}
|
|
57
|
+
>
|
|
58
|
+
<Pressable
|
|
59
|
+
style={[
|
|
60
|
+
tw`bg-white w-[90%] p-4 rounded-lg`,
|
|
61
|
+
containerStyle,
|
|
62
|
+
tw`tablet:w-[35%]`,
|
|
63
|
+
]}
|
|
64
|
+
>
|
|
65
|
+
<View>
|
|
66
|
+
<View style={tw`self-center py-[10%] w-[80%]`}>
|
|
67
|
+
<Text
|
|
68
|
+
style={[
|
|
69
|
+
tw`text-center text-black500 text-lg font-RobotoMedium`,
|
|
70
|
+
titleStyle,
|
|
71
|
+
]}
|
|
72
|
+
>
|
|
73
|
+
{title}
|
|
74
|
+
</Text>
|
|
75
|
+
</View>
|
|
76
|
+
<View style={tw`flex-row justify-between px-2 pb-2`}>
|
|
77
|
+
<TButton
|
|
78
|
+
containerStyle={tw`w-[45%] h-12 p-0 m-0 bg-white border-gray-100 border items-center`}
|
|
79
|
+
titleStyle={tw`text-black600 text-sm font-NunitoSansMedium`}
|
|
80
|
+
title={"Cancel"}
|
|
81
|
+
onPress={() => setVisible && setVisible(false)}
|
|
82
|
+
/>
|
|
83
|
+
{svg ? (
|
|
84
|
+
<IwtButton
|
|
85
|
+
containerStyle={[
|
|
86
|
+
tw`w-[45%] h-12 p-0 m-0 bg-danger600 items-center`,
|
|
87
|
+
buttonStyle,
|
|
88
|
+
]}
|
|
89
|
+
titleStyle={[
|
|
90
|
+
tw`text-white text-sm font-NunitoSansMedium`,
|
|
91
|
+
buttonTextStyle,
|
|
92
|
+
]}
|
|
93
|
+
svg={svg}
|
|
94
|
+
title={buttonText}
|
|
95
|
+
onPress={confirmationPress}
|
|
96
|
+
/>
|
|
97
|
+
) : (
|
|
98
|
+
<TButton
|
|
99
|
+
containerStyle={tw`w-[45%] h-12 p-0 m-0 bg-danger600 items-center`}
|
|
100
|
+
titleStyle={[
|
|
101
|
+
tw`text-white text-sm font-NunitoSansMedium`,
|
|
102
|
+
buttonTextStyle,
|
|
103
|
+
]}
|
|
104
|
+
title={buttonText}
|
|
105
|
+
onPress={confirmationPress}
|
|
106
|
+
/>
|
|
107
|
+
)}
|
|
108
|
+
</View>
|
|
109
|
+
</View>
|
|
110
|
+
</Pressable>
|
|
111
|
+
</View>
|
|
112
|
+
</Modal>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export default React.memo(NormalModal);
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { Calendar } from "react-native-calendars";
|
|
4
|
+
import NormalModal from "./NormalModal";
|
|
5
|
+
import TButton from "../buttons/TButton";
|
|
6
|
+
import dayjs from "dayjs";
|
|
7
|
+
import tw from "../tailwind";
|
|
8
|
+
|
|
9
|
+
interface DateModalProps {
|
|
10
|
+
visible: boolean;
|
|
11
|
+
setVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
|
12
|
+
selectedDate: (dates: string[]) => void;
|
|
13
|
+
item?: any;
|
|
14
|
+
range?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const formatDate = (date: any) => dayjs(date).format("YYYY-MM-DD");
|
|
18
|
+
|
|
19
|
+
const DateModal = ({
|
|
20
|
+
setVisible,
|
|
21
|
+
visible,
|
|
22
|
+
item,
|
|
23
|
+
range,
|
|
24
|
+
selectedDate,
|
|
25
|
+
}: DateModalProps) => {
|
|
26
|
+
const [selectedDates, setSelectedDates] = useState<string[]>([]);
|
|
27
|
+
const bookedDates = new Set(item?.booked || []);
|
|
28
|
+
|
|
29
|
+
const handleDateSelect = (day: any) => {
|
|
30
|
+
const selectedDay = day.dateString;
|
|
31
|
+
|
|
32
|
+
if (!range) {
|
|
33
|
+
// Single date selection
|
|
34
|
+
setSelectedDates([selectedDay]);
|
|
35
|
+
selectedDate([selectedDay]);
|
|
36
|
+
setVisible(false);
|
|
37
|
+
} else {
|
|
38
|
+
// Multiple date selection (array)
|
|
39
|
+
setSelectedDates((prevDates) => {
|
|
40
|
+
if (prevDates.includes(selectedDay)) {
|
|
41
|
+
return prevDates.filter((date) => date !== selectedDay); // Deselect if already selected
|
|
42
|
+
} else if (!bookedDates.has(selectedDay)) {
|
|
43
|
+
return [...prevDates, selectedDay]; // Add new date if not booked
|
|
44
|
+
}
|
|
45
|
+
selectedDate(prevDates);
|
|
46
|
+
setVisible(false);
|
|
47
|
+
return prevDates;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const getMarkedDates = () => {
|
|
53
|
+
let marked: Record<string, any> = {};
|
|
54
|
+
|
|
55
|
+
// Mark booked dates as disabled
|
|
56
|
+
if (item?.booked) {
|
|
57
|
+
item.booked.forEach((date: string) => {
|
|
58
|
+
marked[date] = {
|
|
59
|
+
disabled: true,
|
|
60
|
+
disableTouchEvent: true,
|
|
61
|
+
customStyles: {
|
|
62
|
+
container: tw`bg-red-500 rounded-full`,
|
|
63
|
+
text: tw`text-white font-bold`,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Mark selected dates
|
|
70
|
+
selectedDates.forEach((date) => {
|
|
71
|
+
marked[date] = {
|
|
72
|
+
customStyles: {
|
|
73
|
+
container: tw`bg-sky-600 rounded-full`,
|
|
74
|
+
text: tw`text-white font-bold`,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Highlight today's date
|
|
80
|
+
const today = formatDate(new Date());
|
|
81
|
+
if (!marked[today]) {
|
|
82
|
+
marked[today] = {
|
|
83
|
+
customStyles: {
|
|
84
|
+
container: tw`bg-primary rounded-full`,
|
|
85
|
+
text: {
|
|
86
|
+
color: "white",
|
|
87
|
+
fontWeight: "bold",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return marked;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<NormalModal
|
|
98
|
+
animationType="fade"
|
|
99
|
+
visible={visible}
|
|
100
|
+
setVisible={setVisible}
|
|
101
|
+
layerContainerStyle={tw`justify-center items-center flex-1 px-[4%] `}
|
|
102
|
+
containerStyle={tw`rounded-2xl bg-white`}
|
|
103
|
+
>
|
|
104
|
+
<Calendar
|
|
105
|
+
theme={theme}
|
|
106
|
+
markingType="custom"
|
|
107
|
+
markedDates={getMarkedDates()}
|
|
108
|
+
onDayPress={handleDateSelect}
|
|
109
|
+
/>
|
|
110
|
+
{range && (
|
|
111
|
+
<TButton
|
|
112
|
+
disabled={selectedDates.length === 0}
|
|
113
|
+
title="Done"
|
|
114
|
+
containerStyle={tw`mt-4`}
|
|
115
|
+
onPress={() => {
|
|
116
|
+
selectedDate(selectedDates);
|
|
117
|
+
setVisible(false);
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
</NormalModal>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default DateModal;
|
|
126
|
+
|
|
127
|
+
const theme = {
|
|
128
|
+
stylesheet: {
|
|
129
|
+
calendar: {
|
|
130
|
+
header: {
|
|
131
|
+
dayHeader: {
|
|
132
|
+
fontWeight: "600",
|
|
133
|
+
color: "#48BFE3",
|
|
134
|
+
},
|
|
135
|
+
monthText: {
|
|
136
|
+
textAlign: "left",
|
|
137
|
+
fontWeight: "bold",
|
|
138
|
+
fontSize: 18,
|
|
139
|
+
marginLeft: 10,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
"stylesheet.day.basic": {
|
|
145
|
+
today: tw`bg-primary rounded-full`,
|
|
146
|
+
todayText: tw`text-white`,
|
|
147
|
+
},
|
|
148
|
+
"stylesheet.day.single": {
|
|
149
|
+
base: tw`border border-red-500`,
|
|
150
|
+
text: tw`text-red-500 font-bold`,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ScrollView, TouchableWithoutFeedback, View } from "react-native";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Modal } from "react-native-ui-lib";
|
|
5
|
+
import tw from "../tailwind";
|
|
6
|
+
|
|
7
|
+
interface NormalModalProps {
|
|
8
|
+
visible?: boolean;
|
|
9
|
+
setVisible?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
10
|
+
layerContainerStyle?: any;
|
|
11
|
+
containerStyle?: any;
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
animationType?: "none" | "slide" | "fade";
|
|
14
|
+
scrollable?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const NormalModal = ({
|
|
18
|
+
setVisible,
|
|
19
|
+
visible,
|
|
20
|
+
containerStyle,
|
|
21
|
+
children,
|
|
22
|
+
layerContainerStyle,
|
|
23
|
+
scrollable,
|
|
24
|
+
animationType,
|
|
25
|
+
}: NormalModalProps) => {
|
|
26
|
+
return (
|
|
27
|
+
<Modal
|
|
28
|
+
transparent
|
|
29
|
+
useGestureHandlerRootView
|
|
30
|
+
presentationStyle="overFullScreen"
|
|
31
|
+
shouldRasterizeIOS
|
|
32
|
+
enableModalBlur={false}
|
|
33
|
+
useKeyboardAvoidingView
|
|
34
|
+
animationType={"fade"}
|
|
35
|
+
overlayBackgroundColor={"rgba(0, 0, 0, 0.5)"}
|
|
36
|
+
visible={visible}
|
|
37
|
+
onBackgroundPress={() => setVisible && setVisible(false)} // Ensure it toggles correctly
|
|
38
|
+
>
|
|
39
|
+
<TouchableWithoutFeedback onPress={() => setVisible && setVisible(false)}>
|
|
40
|
+
<View
|
|
41
|
+
style={[
|
|
42
|
+
tw`flex-1 justify-center items-center `,
|
|
43
|
+
layerContainerStyle,
|
|
44
|
+
]}
|
|
45
|
+
>
|
|
46
|
+
<TouchableWithoutFeedback>
|
|
47
|
+
<View
|
|
48
|
+
style={[
|
|
49
|
+
tw`bg-secondary bg-opacity-10 w-full p-4 rounded-xl`,
|
|
50
|
+
containerStyle,
|
|
51
|
+
tw`tablet:w-[35%]`,
|
|
52
|
+
]}
|
|
53
|
+
>
|
|
54
|
+
{scrollable ? (
|
|
55
|
+
<ScrollView
|
|
56
|
+
nestedScrollEnabled
|
|
57
|
+
keyboardShouldPersistTaps="always"
|
|
58
|
+
showsVerticalScrollIndicator={false}
|
|
59
|
+
>
|
|
60
|
+
{children}
|
|
61
|
+
</ScrollView>
|
|
62
|
+
) : (
|
|
63
|
+
children
|
|
64
|
+
)}
|
|
65
|
+
</View>
|
|
66
|
+
</TouchableWithoutFeedback>
|
|
67
|
+
</View>
|
|
68
|
+
</TouchableWithoutFeedback>
|
|
69
|
+
</Modal>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default React.memo(NormalModal);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { useRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { _HIGHT } from "@/utils/utils";
|
|
4
|
+
import { ScrollView } from "react-native";
|
|
5
|
+
import RBSheet from "react-native-raw-bottom-sheet";
|
|
6
|
+
|
|
7
|
+
interface BottomSheetProps {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
scrollable?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface UseBottomModalResult {
|
|
13
|
+
open: () => void;
|
|
14
|
+
close: () => void;
|
|
15
|
+
BottomModal: React.FC<BottomSheetProps>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const useBottomModal = (): UseBottomModalResult => {
|
|
19
|
+
// Keep the reference stable and ensure it's always available
|
|
20
|
+
const ref = useRef<RBSheet>(null);
|
|
21
|
+
|
|
22
|
+
const open = () => {
|
|
23
|
+
if (ref.current) {
|
|
24
|
+
ref.current.open();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const close = () => {
|
|
29
|
+
if (ref.current) {
|
|
30
|
+
ref.current.close();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const BottomModal: React.FC<BottomSheetProps> = ({
|
|
35
|
+
children,
|
|
36
|
+
scrollable = false,
|
|
37
|
+
}) => (
|
|
38
|
+
<RBSheet
|
|
39
|
+
ref={ref}
|
|
40
|
+
draggable
|
|
41
|
+
height={_HIGHT * 0.6}
|
|
42
|
+
customStyles={{
|
|
43
|
+
container: {
|
|
44
|
+
borderTopLeftRadius: 10,
|
|
45
|
+
borderTopRightRadius: 10,
|
|
46
|
+
},
|
|
47
|
+
draggableIcon: {
|
|
48
|
+
width: 30,
|
|
49
|
+
},
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
{scrollable ? <ScrollView>{children}</ScrollView> : children}
|
|
53
|
+
</RBSheet>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return { open, close, BottomModal };
|
|
57
|
+
};
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
forwardRef,
|
|
4
|
+
useContext,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
9
|
+
import {
|
|
10
|
+
Dimensions,
|
|
11
|
+
Pressable,
|
|
12
|
+
Text,
|
|
13
|
+
TouchableOpacity,
|
|
14
|
+
View,
|
|
15
|
+
} from "react-native";
|
|
16
|
+
|
|
17
|
+
import { Modal } from "react-native-ui-lib";
|
|
18
|
+
import tw from "../tailwind";
|
|
19
|
+
|
|
20
|
+
// import LottieView from 'lottie-react-native';
|
|
21
|
+
|
|
22
|
+
// import { FontSize } from '../../../utils/utils';
|
|
23
|
+
|
|
24
|
+
// Define the ref object type
|
|
25
|
+
export interface PopUpModalRef {
|
|
26
|
+
open: (data: PopUpModalProps) => void;
|
|
27
|
+
close: () => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Define the component's props type
|
|
31
|
+
export interface PopUpModalProps {
|
|
32
|
+
title?: string;
|
|
33
|
+
titleStyle?: any;
|
|
34
|
+
icon?: JSX.Element;
|
|
35
|
+
lottify?: string;
|
|
36
|
+
containerStyle?: any;
|
|
37
|
+
iconComponent?: JSX.Element;
|
|
38
|
+
multipleBTNStyle?: any;
|
|
39
|
+
multipleButton?: Array<{
|
|
40
|
+
onPress?: () => void;
|
|
41
|
+
text?: string;
|
|
42
|
+
buttonText?: string;
|
|
43
|
+
buttonTextStyle?: any;
|
|
44
|
+
buttonStyle?: any;
|
|
45
|
+
}>;
|
|
46
|
+
onPress?: () => void;
|
|
47
|
+
svgIcon?: any;
|
|
48
|
+
content?: string;
|
|
49
|
+
contentStyle?: any;
|
|
50
|
+
buttonStyle?: any;
|
|
51
|
+
btnDisplay?: boolean;
|
|
52
|
+
buttonTextStyle?: any;
|
|
53
|
+
buttonText?: string;
|
|
54
|
+
fullWidth?: boolean;
|
|
55
|
+
fullHeight?: boolean;
|
|
56
|
+
direction?: "down" | "up" | "left" | "right";
|
|
57
|
+
iconComponentStyle?: any;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { width, height } = Dimensions.get("window");
|
|
61
|
+
|
|
62
|
+
const PopUpModal = forwardRef<PopUpModalRef, PopUpModalProps>(
|
|
63
|
+
({ direction }, ref) => {
|
|
64
|
+
const [visible, setVisible] = useState(false);
|
|
65
|
+
const [modalContent, setModalContent] = useState<PopUpModalProps>();
|
|
66
|
+
|
|
67
|
+
useImperativeHandle(ref, () => ({
|
|
68
|
+
open(data) {
|
|
69
|
+
setModalContent(data);
|
|
70
|
+
setVisible(true);
|
|
71
|
+
},
|
|
72
|
+
close() {
|
|
73
|
+
setVisible(false);
|
|
74
|
+
},
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Modal
|
|
79
|
+
transparent
|
|
80
|
+
animationType="fade"
|
|
81
|
+
overlayBackgroundColor="rgba(0, 0, 0, 0.5)" // Semi-transparent background
|
|
82
|
+
visible={visible}
|
|
83
|
+
useKeyboardAvoidingView
|
|
84
|
+
// statusBarTranslucent
|
|
85
|
+
onDismiss={() => setVisible(false)}
|
|
86
|
+
onBackgroundPress={() => setVisible(false)} // Close modal on background press
|
|
87
|
+
>
|
|
88
|
+
<Pressable
|
|
89
|
+
onPress={() => {
|
|
90
|
+
setVisible(false);
|
|
91
|
+
}}
|
|
92
|
+
style={tw`flex-1 justify-center items-center`}
|
|
93
|
+
>
|
|
94
|
+
<Pressable
|
|
95
|
+
style={[
|
|
96
|
+
tw`bg-white p-5 rounded-xl gap-2`,
|
|
97
|
+
modalContent?.containerStyle,
|
|
98
|
+
]}
|
|
99
|
+
>
|
|
100
|
+
{modalContent?.icon && <View>{modalContent?.icon}</View>}
|
|
101
|
+
{/* {modalContent?.lottify && (
|
|
102
|
+
<View>
|
|
103
|
+
<LottieView
|
|
104
|
+
autoPlay
|
|
105
|
+
loop={true}
|
|
106
|
+
source={modalContent?.lottify}
|
|
107
|
+
style={{
|
|
108
|
+
height: height * 0.08,
|
|
109
|
+
aspectRatio: 1,
|
|
110
|
+
}}
|
|
111
|
+
/>
|
|
112
|
+
</View>
|
|
113
|
+
)} */}
|
|
114
|
+
{modalContent?.iconComponent && (
|
|
115
|
+
<View
|
|
116
|
+
style={[
|
|
117
|
+
tw`justify-center items-center`,
|
|
118
|
+
modalContent.iconComponentStyle,
|
|
119
|
+
]}
|
|
120
|
+
>
|
|
121
|
+
{modalContent?.iconComponent}
|
|
122
|
+
</View>
|
|
123
|
+
)}
|
|
124
|
+
{modalContent?.svgIcon && (
|
|
125
|
+
<View style={tw`justify-center items-center`}>
|
|
126
|
+
{modalContent?.svgIcon}
|
|
127
|
+
</View>
|
|
128
|
+
)}
|
|
129
|
+
{modalContent?.title && (
|
|
130
|
+
<Text
|
|
131
|
+
style={[
|
|
132
|
+
tw`text-center text-black text-lg`,
|
|
133
|
+
modalContent.titleStyle,
|
|
134
|
+
]}
|
|
135
|
+
>
|
|
136
|
+
{modalContent.title}
|
|
137
|
+
</Text>
|
|
138
|
+
)}
|
|
139
|
+
{modalContent?.content && (
|
|
140
|
+
<Text
|
|
141
|
+
style={[
|
|
142
|
+
tw`text-center text-black font-normal text-base `,
|
|
143
|
+
modalContent.contentStyle,
|
|
144
|
+
]}
|
|
145
|
+
>
|
|
146
|
+
{modalContent.content}
|
|
147
|
+
</Text>
|
|
148
|
+
)}
|
|
149
|
+
{!modalContent?.multipleButton && !modalContent?.btnDisplay && (
|
|
150
|
+
<View
|
|
151
|
+
style={[
|
|
152
|
+
tw`bg-cyan-800 justify-center items-center bg-opacity-75 rounded-lg`,
|
|
153
|
+
modalContent?.buttonStyle,
|
|
154
|
+
]}
|
|
155
|
+
>
|
|
156
|
+
<TouchableOpacity
|
|
157
|
+
style={tw` w-full h-10 justify-center items-center`}
|
|
158
|
+
activeOpacity={0.5}
|
|
159
|
+
onPress={modalContent?.onPress}
|
|
160
|
+
>
|
|
161
|
+
<Text
|
|
162
|
+
style={[
|
|
163
|
+
tw`text-white font-bold`,
|
|
164
|
+
modalContent?.buttonTextStyle,
|
|
165
|
+
]}
|
|
166
|
+
>
|
|
167
|
+
{modalContent?.buttonText || "Okay"}
|
|
168
|
+
</Text>
|
|
169
|
+
</TouchableOpacity>
|
|
170
|
+
</View>
|
|
171
|
+
)}
|
|
172
|
+
{modalContent?.multipleButton && (
|
|
173
|
+
<View style={[tw`flex-row gap-3`, modalContent.multipleBTNStyle]}>
|
|
174
|
+
{modalContent?.multipleButton.map((item, index) => (
|
|
175
|
+
<View
|
|
176
|
+
key={index}
|
|
177
|
+
style={[
|
|
178
|
+
tw` bg-black600 justify-center items-center rounded-xl`,
|
|
179
|
+
item?.buttonStyle,
|
|
180
|
+
]}
|
|
181
|
+
>
|
|
182
|
+
<TouchableOpacity
|
|
183
|
+
style={tw`h-10 w-full justify-center items-center`}
|
|
184
|
+
activeOpacity={0.5}
|
|
185
|
+
onPress={item?.onPress}
|
|
186
|
+
>
|
|
187
|
+
<Text
|
|
188
|
+
style={[
|
|
189
|
+
tw`text-white font-bold`,
|
|
190
|
+
item?.buttonTextStyle,
|
|
191
|
+
]}
|
|
192
|
+
>
|
|
193
|
+
{item?.buttonText || "Okay"}
|
|
194
|
+
</Text>
|
|
195
|
+
</TouchableOpacity>
|
|
196
|
+
</View>
|
|
197
|
+
))}
|
|
198
|
+
</View>
|
|
199
|
+
)}
|
|
200
|
+
</Pressable>
|
|
201
|
+
</Pressable>
|
|
202
|
+
{/* </BlurView> */}
|
|
203
|
+
</Modal>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
export default PopUpModal;
|
|
209
|
+
|
|
210
|
+
interface ToastContextType {
|
|
211
|
+
showToast: (data: PopUpModalProps) => void;
|
|
212
|
+
closeToast: () => void;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const ToastContext = createContext<ToastContextType | undefined>(undefined);
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Hook to use the toast context.
|
|
219
|
+
* @throws {Error} if called outside of a ToastProvider
|
|
220
|
+
* @returns {ToastContextType} the toast context
|
|
221
|
+
*/
|
|
222
|
+
export const useToast = (): ToastContextType => {
|
|
223
|
+
const context = useContext(ToastContext);
|
|
224
|
+
if (!context) {
|
|
225
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
226
|
+
}
|
|
227
|
+
return context;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Context provider for managing toast notifications.
|
|
232
|
+
* @param children React node representing the children components.
|
|
233
|
+
*/
|
|
234
|
+
export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
235
|
+
children,
|
|
236
|
+
}) => {
|
|
237
|
+
const ref = useRef<PopUpModalRef>(null);
|
|
238
|
+
|
|
239
|
+
const showToast = (data: PopUpModalProps) => {
|
|
240
|
+
if (ref.current) {
|
|
241
|
+
ref.current.open(data);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
const closeToast = () => {
|
|
245
|
+
if (ref.current) {
|
|
246
|
+
ref.current.close();
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<ToastContext.Provider value={{ showToast, closeToast }}>
|
|
252
|
+
{children}
|
|
253
|
+
<PopUpModal ref={ref} />
|
|
254
|
+
</ToastContext.Provider>
|
|
255
|
+
);
|
|
256
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Text, TextInput, View } from "react-native";
|
|
2
|
+
|
|
3
|
+
import { Icon } from "@/assets/Icon";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { SvgXml } from "react-native-svg";
|
|
6
|
+
import tw from "../tailwind";
|
|
7
|
+
|
|
8
|
+
const PaymentCardForD = () => {
|
|
9
|
+
return (
|
|
10
|
+
<View style={tw`px-5 mt-5 gap-3`}>
|
|
11
|
+
<Text style={tw`text-white text-xl font-DegularDisplayRegular`}>
|
|
12
|
+
Card information
|
|
13
|
+
</Text>
|
|
14
|
+
<View style={tw``}>
|
|
15
|
+
<View
|
|
16
|
+
style={tw`flex-row items-center px-4 border border-t-secondary border-r-secondary border-l-secondary h-14 rounded-t-lg`}
|
|
17
|
+
>
|
|
18
|
+
<TextInput
|
|
19
|
+
placeholder="Card number"
|
|
20
|
+
placeholderTextColor={"#A9A9A9"}
|
|
21
|
+
style={tw`flex-1 font-DegularDisplayRegular text-white text-lg `}
|
|
22
|
+
/>
|
|
23
|
+
<SvgXml xml={Icon?.card} />
|
|
24
|
+
</View>
|
|
25
|
+
<View style={tw`flex-1 flex-row `}>
|
|
26
|
+
<TextInput
|
|
27
|
+
placeholder="MM/YY"
|
|
28
|
+
placeholderTextColor={"#A9A9A9"}
|
|
29
|
+
style={tw`border w-1/2 rounded-bl-lg border-secondary h-14 px-4 font-DegularDisplayRegular text-white text-lg`}
|
|
30
|
+
/>
|
|
31
|
+
<View
|
|
32
|
+
style={tw`flex-row rounded-br-lg items-center border w-1/2 border-secondary h-14 px-4 `}
|
|
33
|
+
>
|
|
34
|
+
<TextInput
|
|
35
|
+
placeholder="CVC"
|
|
36
|
+
placeholderTextColor={"#A9A9A9"}
|
|
37
|
+
style={tw`flex-1 font-DegularDisplayRegular text-white text-lg `}
|
|
38
|
+
/>
|
|
39
|
+
<SvgXml xml={Icon?.cvc} />
|
|
40
|
+
</View>
|
|
41
|
+
</View>
|
|
42
|
+
</View>
|
|
43
|
+
</View>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default PaymentCardForD;
|