app-expo-cli 1.0.0

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.
Files changed (46) hide show
  1. package/bin/index.js +3 -0
  2. package/bun.lock +82 -0
  3. package/package.json +26 -0
  4. package/src/copy-template.js +156 -0
  5. package/src/create-expo.js +10 -0
  6. package/src/index.js +39 -0
  7. package/src/install-deps.js +22 -0
  8. package/src/utils/logger.js +29 -0
  9. package/tailwind.config.js +69 -0
  10. package/template/src/app/_layout.tsx +61 -0
  11. package/template/src/app/auth/_layout.tsx +41 -0
  12. package/template/src/app/auth/change_pass.tsx +138 -0
  13. package/template/src/app/auth/change_pass_modal.tsx +74 -0
  14. package/template/src/app/auth/forgot.tsx +124 -0
  15. package/template/src/app/auth/index.tsx +274 -0
  16. package/template/src/app/auth/opt_verify.tsx +145 -0
  17. package/template/src/app/auth/register.tsx +334 -0
  18. package/template/src/app/auth/reset_pass.tsx +152 -0
  19. package/template/src/app/common/image.tsx +202 -0
  20. package/template/src/app/common/openurl.tsx +42 -0
  21. package/template/src/app/home/_layout.tsx +29 -0
  22. package/template/src/app/home/drawer/_layout.tsx +27 -0
  23. package/template/src/app/home/tabs/_layout.tsx +75 -0
  24. package/template/src/app/home/tabs/index.tsx +11 -0
  25. package/template/src/app/index.tsx +11 -0
  26. package/template/src/app/modals/confirmation_logout_modal.tsx +78 -0
  27. package/template/src/app/modals/payment_modal.tsx +105 -0
  28. package/template/src/app/modals/success_modal.tsx +72 -0
  29. package/template/src/app/modals/toaster.tsx +31 -0
  30. package/template/src/app/settings/_layout.tsx +19 -0
  31. package/template/src/app/settings/about_us.tsx +61 -0
  32. package/template/src/app/settings/privacy_policy.tsx +61 -0
  33. package/template/src/app/settings/terms_and_conditions.tsx +60 -0
  34. package/template/src/hooks/useCheckLocation.ts +36 -0
  35. package/template/src/hooks/useDocPicker.ts +83 -0
  36. package/template/src/hooks/useImgePicker.ts +70 -0
  37. package/template/src/hooks/useSuggestionLocation.ts +36 -0
  38. package/template/src/hooks/useUploadProgress.ts +127 -0
  39. package/template/src/redux/api-config/baseApi.ts +89 -0
  40. package/template/src/redux/api-slices/authSlices.ts +175 -0
  41. package/template/src/redux/interface/common.ts +19 -0
  42. package/template/src/redux/interface/interface.ts +196 -0
  43. package/template/src/redux/interface/tag-types.ts +13 -0
  44. package/template/src/redux/service/demo.ts +27 -0
  45. package/template/src/redux/store.ts +17 -0
  46. package/template/src/utils/utils.ts +27 -0
@@ -0,0 +1,202 @@
1
+ import { router, useGlobalSearchParams } from "expo-router";
2
+ import React, { useRef } from "react";
3
+ import {
4
+ Dimensions,
5
+ StyleSheet,
6
+ Text,
7
+ TouchableOpacity,
8
+ View,
9
+ } from "react-native";
10
+ import {
11
+ GestureHandlerRootView,
12
+ PanGestureHandler,
13
+ PinchGestureHandler,
14
+ TapGestureHandler,
15
+ } from "react-native-gesture-handler";
16
+ import Animated, {
17
+ useAnimatedGestureHandler,
18
+ useAnimatedStyle,
19
+ useSharedValue,
20
+ withSpring,
21
+ withTiming,
22
+ } from "react-native-reanimated";
23
+
24
+ import tw from "@/src/lib/tailwind";
25
+ import { SvgXml } from "react-native-svg";
26
+
27
+ const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("window");
28
+ const AnimatedImage = Animated.createAnimatedComponent(Animated.Image);
29
+
30
+ const clamp = (value: number, min: number, max: number) => {
31
+ "worklet";
32
+ return Math.min(Math.max(value, min), max);
33
+ };
34
+
35
+ const ImageModal = () => {
36
+ const { url }: { url?: string } = useGlobalSearchParams();
37
+
38
+ console.log(url);
39
+
40
+ const scale = useSharedValue(1);
41
+ const translateX = useSharedValue(0);
42
+ const translateY = useSharedValue(0);
43
+
44
+ const pinchRef = useRef(null);
45
+ const panRef = useRef(null);
46
+ const doubleTapRef = useRef(null);
47
+
48
+ const pinchHandler = useAnimatedGestureHandler({
49
+ onStart: (_, ctx: any) => {
50
+ ctx.startScale = scale.value;
51
+ },
52
+ onActive: (event, ctx: any) => {
53
+ scale.value = clamp(ctx.startScale * event.scale, 0.8, 4);
54
+ },
55
+ onEnd: () => {
56
+ if (scale.value < 1) scale.value = withTiming(1);
57
+ if (scale.value > 4) scale.value = withTiming(4);
58
+
59
+ // Adjust translation after pinch to stay in bounds
60
+ const maxX = (SCREEN_WIDTH * scale.value - SCREEN_WIDTH) / 2;
61
+ const maxY = (SCREEN_HEIGHT * scale.value - SCREEN_HEIGHT) / 2;
62
+
63
+ translateX.value = withTiming(clamp(translateX.value, -maxX, maxX));
64
+ translateY.value = withTiming(clamp(translateY.value, -maxY, maxY));
65
+ },
66
+ });
67
+
68
+ const panHandler = useAnimatedGestureHandler({
69
+ onStart: (_, ctx: any) => {
70
+ ctx.startX = translateX.value;
71
+ ctx.startY = translateY.value;
72
+ },
73
+ onActive: (event, ctx: any) => {
74
+ const maxX = (SCREEN_WIDTH * scale.value - SCREEN_WIDTH) / 2;
75
+ const maxY = (SCREEN_HEIGHT * scale.value - SCREEN_HEIGHT) / 2;
76
+
77
+ translateX.value = clamp(ctx.startX + event.translationX, -maxX, maxX);
78
+ translateY.value = clamp(ctx.startY + event.translationY, -maxY, maxY);
79
+ },
80
+ onEnd: () => {
81
+ const maxX = (SCREEN_WIDTH * scale.value - SCREEN_WIDTH) / 2;
82
+ const maxY = (SCREEN_HEIGHT * scale.value - SCREEN_HEIGHT) / 2;
83
+
84
+ translateX.value = withSpring(clamp(translateX.value, -maxX, maxX));
85
+ translateY.value = withSpring(clamp(translateY.value, -maxY, maxY));
86
+ },
87
+ });
88
+
89
+ const doubleTapHandler = useAnimatedGestureHandler({
90
+ onActive: () => {
91
+ if (scale.value > 1.5) {
92
+ scale.value = withTiming(1);
93
+ translateX.value = withTiming(0);
94
+ translateY.value = withTiming(0);
95
+ } else {
96
+ scale.value = withTiming(2);
97
+ }
98
+ },
99
+ });
100
+
101
+ const animatedStyle = useAnimatedStyle(() => ({
102
+ transform: [
103
+ { translateX: translateX.value },
104
+ { translateY: translateY.value },
105
+ { scale: scale.value },
106
+ ],
107
+ }));
108
+
109
+ return (
110
+ <GestureHandlerRootView style={styles.flex}>
111
+ {/* Close Button */}
112
+ <TouchableOpacity
113
+ onPress={() => router.dismiss()}
114
+ style={tw`flex-row items-center gap-3 absolute bottom-4 right-4 z-50`}
115
+ >
116
+ <View
117
+ style={[
118
+ tw`bg-[#3D3D3D] w-12 h-12 justify-center items-center rounded-full `,
119
+ ]}
120
+ >
121
+ <SvgXml
122
+ xml={`<svg width="12" height="18" viewBox="0 0 12 18" fill="none" xmlns="http://www.w3.org/2000/svg">
123
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M0.477124 9.99984L9.69575 18L12 16.0003L3.9335 9L12 1.99969L9.69575 0L0.477124 8.00016C0.171621 8.26536 0 8.625 0 9C0 9.375 0.171621 9.73464 0.477124 9.99984Z" fill="white"/>
124
+ </svg>
125
+
126
+
127
+
128
+ `}
129
+ />
130
+ </View>
131
+ </TouchableOpacity>
132
+
133
+ {/* Gesture Handlers */}
134
+ <PanGestureHandler
135
+ onGestureEvent={panHandler}
136
+ minPointers={1}
137
+ maxPointers={2}
138
+ ref={panRef}
139
+ >
140
+ <Animated.View style={styles.flex}>
141
+ <PinchGestureHandler
142
+ onGestureEvent={pinchHandler}
143
+ ref={pinchRef}
144
+ simultaneousHandlers={[panRef, doubleTapRef]}
145
+ >
146
+ <Animated.View style={styles.flex}>
147
+ <TapGestureHandler
148
+ onGestureEvent={doubleTapHandler}
149
+ numberOfTaps={2}
150
+ ref={doubleTapRef}
151
+ maxDelayMs={300}
152
+ >
153
+ <Animated.View style={styles.imageWrapper}>
154
+ {url ? (
155
+ <AnimatedImage
156
+ source={{ uri: url }}
157
+ style={[styles.image, animatedStyle]}
158
+ resizeMode="contain"
159
+ />
160
+ ) : (
161
+ <View style={styles.placeholder}>
162
+ <Text style={tw`text-white`}>No image URL provided</Text>
163
+ </View>
164
+ )}
165
+ </Animated.View>
166
+ </TapGestureHandler>
167
+ </Animated.View>
168
+ </PinchGestureHandler>
169
+ </Animated.View>
170
+ </PanGestureHandler>
171
+ </GestureHandlerRootView>
172
+ );
173
+ };
174
+
175
+ const styles = StyleSheet.create({
176
+ flex: { flex: 1, backgroundColor: tw.color("base") },
177
+ closeRow: {
178
+ position: "absolute",
179
+ top: 50,
180
+ left: 0,
181
+ right: 0,
182
+ zIndex: 10,
183
+ flexDirection: "row",
184
+ justifyContent: "flex-start",
185
+ paddingHorizontal: 10,
186
+ },
187
+ imageWrapper: {
188
+ width: "100%",
189
+ height: "100%",
190
+ alignItems: "center",
191
+ justifyContent: "center",
192
+ },
193
+ image: { width: "100%", height: "100%", backgroundColor: "transparent" },
194
+ placeholder: {
195
+ width: "100%",
196
+ height: "100%",
197
+ justifyContent: "center",
198
+ alignItems: "center",
199
+ },
200
+ });
201
+
202
+ export default ImageModal;
@@ -0,0 +1,42 @@
1
+ import { Text, TouchableOpacity, View } from "react-native";
2
+ import { router, useGlobalSearchParams } from "expo-router";
3
+
4
+ import React from "react";
5
+ import { SvgXml } from "react-native-svg";
6
+ import WebView from "react-native-webview";
7
+ import tw from "@/src/lib/tailwind";
8
+
9
+ const OpenUrl = () => {
10
+ const params = useGlobalSearchParams();
11
+ return (
12
+ <View style={tw`flex-1 bg-base`}>
13
+ <TouchableOpacity
14
+ onPress={() => router.dismiss()}
15
+ style={tw`flex-row items-center gap-3 absolute bottom-4 right-4 z-50`}
16
+ >
17
+ <View
18
+ style={[
19
+ tw`bg-[#3D3D3D] w-12 h-12 justify-center items-center rounded-full `,
20
+ ]}
21
+ >
22
+ <SvgXml
23
+ xml={`<svg width="12" height="18" viewBox="0 0 12 18" fill="none" xmlns="http://www.w3.org/2000/svg">
24
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M0.477124 9.99984L9.69575 18L12 16.0003L3.9335 9L12 1.99969L9.69575 0L0.477124 8.00016C0.171621 8.26536 0 8.625 0 9C0 9.375 0.171621 9.73464 0.477124 9.99984Z" fill="white"/>
25
+ </svg>
26
+
27
+
28
+
29
+ `}
30
+ />
31
+ </View>
32
+ </TouchableOpacity>
33
+ {params?.url ? (
34
+ <WebView source={{ uri: params?.url } as any} style={{ flex: 1 }} />
35
+ ) : (
36
+ <Text>no url</Text>
37
+ )}
38
+ </View>
39
+ );
40
+ };
41
+
42
+ export default OpenUrl;
@@ -0,0 +1,29 @@
1
+ import { Stack } from "expo-router";
2
+
3
+ export const unstable_settings = {
4
+ initialRouteName: "index",
5
+ };
6
+
7
+ export default function RootLayout() {
8
+ // const { top, bottom } = useSafeAreaInsets();
9
+ return (
10
+ <Stack
11
+ screenOptions={{
12
+ headerShown: false,
13
+ // statusBarAnimation: "fade",
14
+ statusBarStyle: "light",
15
+ }}
16
+ >
17
+ <Stack.Screen name="tabs" options={{}} />
18
+ <Stack.Screen name="other_user" options={{}} />
19
+ <Stack.Screen name="post_vibe" options={{}} />
20
+ <Stack.Screen name="post_music" options={{}} />
21
+ <Stack.Screen name="post_podcast" options={{}} />
22
+ <Stack.Screen name="create_mood" options={{}} />
23
+ <Stack.Screen name="view_post" options={{}} />
24
+ <Stack.Screen name="report" options={{}} />
25
+ <Stack.Screen name="report_details" options={{}} />
26
+ <Stack.Screen name="appeal" options={{}} />
27
+ </Stack>
28
+ );
29
+ }
@@ -0,0 +1,27 @@
1
+ import { Drawer } from "expo-router/drawer";
2
+
3
+ function CustomDrawerContent(props) {
4
+ return (
5
+ <DrawerContentScrollView {...props}>
6
+ <DrawerItemList {...props} />
7
+ <DrawerItem
8
+ label="Help"
9
+ onPress={() => Linking.openURL("https://mywebsite.com/help")}
10
+ />
11
+ </DrawerContentScrollView>
12
+ );
13
+ }
14
+
15
+ export default function Layout() {
16
+ return (
17
+ <Drawer>
18
+ <Drawer.Screen
19
+ name="index" // This is the name of the page and must match the url from root
20
+ options={{
21
+ drawerLabel: "Home",
22
+ title: "overview",
23
+ }}
24
+ />
25
+ </Drawer>
26
+ );
27
+ }
@@ -0,0 +1,75 @@
1
+ import { Text, View } from "react-native";
2
+
3
+ import { Tabs } from "expo-router";
4
+
5
+ // Define your route params
6
+
7
+ // Props type for MyTabBar
8
+ function MyTabBar({ state, descriptors, navigation }) {
9
+ return (
10
+ <View style={{ flexDirection: "row" }}>
11
+ {state.routes.map((route, index) => {
12
+ const { options } = descriptors[route.key];
13
+ const label =
14
+ options.tabBarLabel !== undefined
15
+ ? options.tabBarLabel
16
+ : options.title !== undefined
17
+ ? options.title
18
+ : route.name;
19
+
20
+ const isFocused = state.index === index;
21
+
22
+ const onPress = () => {
23
+ const event = navigation.emit({
24
+ type: "tabPress",
25
+ target: route.key,
26
+ canPreventDefault: true,
27
+ });
28
+
29
+ if (!isFocused && !event.defaultPrevented) {
30
+ navigation.navigate(route.name, route.params);
31
+ }
32
+ };
33
+
34
+ const onLongPress = () => {
35
+ navigation.emit({
36
+ type: "tabLongPress",
37
+ target: route.key,
38
+ });
39
+ };
40
+
41
+ return (
42
+ <PlatformPressable
43
+ key={route.key}
44
+ href={buildHref(route.name, route.params)}
45
+ accessibilityState={isFocused ? { selected: true } : {}}
46
+ accessibilityLabel={options.tabBarAccessibilityLabel}
47
+ testID={options.tabBarButtonTestID}
48
+ onPress={onPress}
49
+ onLongPress={onLongPress}
50
+ style={{ flex: 1 }}
51
+ >
52
+ <Text style={{ color: isFocused ? colors.primary : colors.text }}>
53
+ {label}
54
+ </Text>
55
+ </PlatformPressable>
56
+ );
57
+ })}
58
+ </View>
59
+ );
60
+ }
61
+
62
+ export default function Layout() {
63
+ return (
64
+ <Tabs
65
+ screenOptions={{
66
+ headerShown: false,
67
+ tabBarHideOnKeyboard: true,
68
+ lazy: true,
69
+ }}
70
+ tabBar={(props: any) => <MyTabBar {...props} />}
71
+ >
72
+ <Tabs.Screen name="index" />
73
+ </Tabs>
74
+ );
75
+ }
@@ -0,0 +1,11 @@
1
+ import { Text, View } from "react-native";
2
+
3
+ const Home = () => {
4
+ return (
5
+ <View>
6
+ <Text>index</Text>
7
+ </View>
8
+ );
9
+ };
10
+
11
+ export default Home;
@@ -0,0 +1,11 @@
1
+ import { Text, View } from "react-native";
2
+
3
+ import tw from "../lib/tailwind";
4
+
5
+ export default function Index() {
6
+ return (
7
+ <View style={tw``}>
8
+ <Text style={tw``}>Edit app/index.tsx to edit this screen.</Text>
9
+ </View>
10
+ );
11
+ }
@@ -0,0 +1,78 @@
1
+ import { router, useGlobalSearchParams } from "expo-router";
2
+ import { Pressable, Text, View } from "react-native";
3
+
4
+ import TButton from "@/src/lib/buttons/TButton";
5
+ import tw from "@/src/lib/tailwind";
6
+ import AsyncStorage from "@react-native-async-storage/async-storage";
7
+
8
+ const ConfirmationModal = () => {
9
+ const params = useGlobalSearchParams();
10
+
11
+ const handleUnfollow = async () => {
12
+ try {
13
+ await AsyncStorage.removeItem("token");
14
+ router.canDismiss() && router.dismissAll();
15
+ router.replace("/auth");
16
+ } catch (error) {
17
+ console.log(error);
18
+ }
19
+ };
20
+
21
+ return (
22
+ <Pressable
23
+ onPress={() => {
24
+ router.dismiss();
25
+ }}
26
+ style={tw`flex-1 bg-black/45 items-center justify-center`}
27
+ >
28
+ <View
29
+ style={tw`w-[90%] bg-black/85 border border-secondary rounded-xl overflow-hidden items-center justify-center p-4`}
30
+ >
31
+ <View style={tw`items-center gap-5 w-full py-4`}>
32
+ {/* <Text style={tw`text-white text-xl font-InterBold text-center`}>
33
+ {subject || "subject"}
34
+ </Text> */}
35
+ {/* <SvgXml xml={Icon.unfriend} width={80} height={80} /> */}
36
+
37
+ <View style={tw`gap-2 w-full items-center`}>
38
+ <Text style={tw`text-white text-2xl font-InterBold text-center`}>
39
+ Are you sure ?
40
+ </Text>
41
+ <Text
42
+ style={tw`text-gray-400 text-xs font-InterRegular text-center `}
43
+ >
44
+ If want you to logout from the app. {"\n"} then press sure!
45
+ otherwise press cancel
46
+ </Text>
47
+ </View>
48
+
49
+ <View style={tw`flex-row gap-3`}>
50
+ <TButton
51
+ offGradient
52
+ containerStyle={tw`w-[45%] self-center bg-black border border-secondary rounded-xl h-13`}
53
+ titleStyle={tw`text-sm font-InterSemiBold`}
54
+ onPress={() => {
55
+ router?.dismiss();
56
+ }}
57
+ title={"Cancel"}
58
+ />
59
+ <TButton
60
+ containerStyle={tw`w-[45%] self-center h-13`}
61
+ titleStyle={tw`text-sm font-InterSemiBold`}
62
+ gradinLayoutStyle={tw`rounded-xl`}
63
+ onPress={() => {
64
+ router?.dismiss();
65
+ // router.push("/profile_setup");
66
+ // route && router.push(route);
67
+ handleUnfollow();
68
+ }}
69
+ title={"Sure"}
70
+ />
71
+ </View>
72
+ </View>
73
+ </View>
74
+ </Pressable>
75
+ );
76
+ };
77
+
78
+ export default ConfirmationModal;
@@ -0,0 +1,105 @@
1
+ import { _HIGHT, _WIDTH } from "@/src/utils/utils";
2
+ import { router, useGlobalSearchParams } from "expo-router";
3
+ import { Alert, View } from "react-native";
4
+
5
+ import ModalHeader from "@/src/components/ModalHeader";
6
+ import tw from "@/src/lib/tailwind";
7
+ import React from "react";
8
+ import { WebView } from "react-native-webview";
9
+
10
+ const userAgent =
11
+ "Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36";
12
+
13
+ // --- This JavaScript will try to force the loaded website's background to black ---
14
+ // This is useful if the website itself doesn't have a dark mode.
15
+
16
+ // --- Main Purchase Screen Component ---
17
+ const PurchaseScreen = () => {
18
+ const [data, setData] = React.useState<any>(null);
19
+
20
+ const handlePurchase = (values: any) => {
21
+ // console.log("Payment Details:", values);
22
+ Alert.alert("Payment Successful", "Your plan has been purchased.");
23
+ router.dismiss();
24
+ };
25
+
26
+ const param = useGlobalSearchParams();
27
+
28
+ React.useLayoutEffect(() => {
29
+ try {
30
+ const parsedData = JSON?.parse(
31
+ Array.isArray(param.data) ? param.data[0] : param.data || "{}"
32
+ );
33
+ setData(parsedData);
34
+ } catch (e) {
35
+ console.error("Failed to parse data:", e);
36
+ setData({}); // Set to empty object on error
37
+ }
38
+ }, [param.data]);
39
+
40
+ // console.log(data);
41
+
42
+ return (
43
+ <View style={tw`flex-1 bg-black/60 justify-end items-center w-full`}>
44
+ <View
45
+ style={[
46
+ // Changed bg-base to bg-black to make the modal background dark
47
+ tw`bg-black rounded-t-2xl`,
48
+ {
49
+ height: _HIGHT * 0.9,
50
+ width: _WIDTH,
51
+ },
52
+ ]}
53
+ >
54
+ {/* Header */}
55
+ <ModalHeader title="Payment" onPress={() => router.dismiss()} />
56
+ {data?.session_url || data?.url ? (
57
+ <WebView
58
+ // Changed bg-base to bg-black and added flex-1
59
+ // This makes the WebView's own background black and ensures it fills the space
60
+ style={tw`bg-black flex-1`}
61
+ source={
62
+ param.type === "subscription"
63
+ ? {
64
+ uri: data?.session_url,
65
+ }
66
+ : {
67
+ uri: data?.url,
68
+ }
69
+ }
70
+ startInLoadingState={true}
71
+ userAgent={userAgent}
72
+ javaScriptEnabled={true}
73
+ domStorageEnabled={true}
74
+ forceDarkOn={true} // You already had this, which is correct!
75
+ // --- Injected JavaScript ---
76
+ // This runs the code from `forceDarkJS` to force the website content
77
+ // to have a black background, just in case forceDarkOn isn't enough.
78
+ // injectedJavaScript={forceDarkJS}
79
+ // Run this on the first load
80
+ onMessage={() => {}} // Required for injectedJavaScript to run on first load
81
+ directionalLockEnabled
82
+ sharedCookiesEnabled={true}
83
+ thirdPartyCookiesEnabled={true}
84
+ originWhitelist={["*"]}
85
+ onNavigationStateChange={(navState) => {
86
+ if (navState.url.includes("success")) {
87
+ handlePurchase(data);
88
+ }
89
+ if (navState.url.includes("cancel")) {
90
+ router.dismiss();
91
+ }
92
+ }}
93
+ />
94
+ ) : (
95
+ // Added a fallback view in case session_url is missing
96
+ <View style={tw`flex-1 items-center justify-center bg-black`}>
97
+ {/* You could put a loading spinner or error message here */}
98
+ </View>
99
+ )}
100
+ </View>
101
+ </View>
102
+ );
103
+ };
104
+
105
+ export default PurchaseScreen;
@@ -0,0 +1,72 @@
1
+ import { router, useGlobalSearchParams } from "expo-router";
2
+ import { Platform, Pressable, Text, View } from "react-native";
3
+
4
+ import { Icon } from "@/assets/icons/Icon";
5
+ import TButton from "@/src/lib/buttons/TButton";
6
+ import tw from "@/src/lib/tailwind";
7
+ import { BlurView } from "expo-blur";
8
+ import React from "react";
9
+ import { SvgXml } from "react-native-svg";
10
+
11
+ const Success_modal = () => {
12
+ const params = useGlobalSearchParams();
13
+ // ?title='You’re All Set!'&subtitle='Your password has been changed successfully!'&buttonTitle='Back to login'&route='/auth
14
+ // const { title, subtitle, buttonTitle, route }: any = params;
15
+ const CommonContent = () => {
16
+ return (
17
+ <View style={tw`items-center gap-5 w-full`}>
18
+ <SvgXml width={80} height={80} xml={Icon.check2} />
19
+
20
+ <View style={tw`gap-2 w-full items-center`}>
21
+ <Text style={tw`text-white text-2xl font-semibold text-center`}>
22
+ {params?.message || "Email sent successfully"}
23
+ </Text>
24
+ </View>
25
+
26
+ <TButton
27
+ containerStyle={tw`w-full mt-3 h-13 self-center `}
28
+ gradinLayoutStyle={tw`rounded-xl`}
29
+ onPress={() => {
30
+ router?.dismiss();
31
+ // router.push("/home/tabs/account");
32
+ if (params?.route as string) {
33
+ router.push(params?.route as any);
34
+ } else {
35
+ router?.dismiss();
36
+ }
37
+ }}
38
+ title={(params?.b_text as string) || "Done"}
39
+ />
40
+ </View>
41
+ );
42
+ };
43
+
44
+ return (
45
+ <Pressable
46
+ onPress={() => {
47
+ router.dismiss();
48
+ }}
49
+ style={tw`flex-1 bg-black/45 items-center justify-center`}
50
+ >
51
+ {Platform.OS === "ios" ? (
52
+ <BlurView
53
+ style={tw`w-[90%] rounded-xl overflow-hidden items-center justify-center p-6 pb-8`}
54
+ tint="dark"
55
+ blurReductionFactor={5}
56
+ intensity={100}
57
+ experimentalBlurMethod="dimezisBlurView"
58
+ >
59
+ <CommonContent />
60
+ </BlurView>
61
+ ) : (
62
+ <View
63
+ style={tw`w-[90%] bg-black/85 border border-secondary rounded-xl overflow-hidden items-center justify-center p-6 pb-8`}
64
+ >
65
+ <CommonContent />
66
+ </View>
67
+ )}
68
+ </Pressable>
69
+ );
70
+ };
71
+
72
+ export default Success_modal;
@@ -0,0 +1,31 @@
1
+ import { Text, View } from "react-native";
2
+ import { router, useGlobalSearchParams, usePathname } from "expo-router";
3
+
4
+ import React from "react";
5
+ import tw from "@/src/lib/tailwind";
6
+
7
+ const Taster = () => {
8
+ const params = useGlobalSearchParams();
9
+ const pathname = usePathname(); // current route path
10
+
11
+ React.useEffect(() => {
12
+ const currentPath = pathname; // save the path when modal loads
13
+
14
+ const timer = setTimeout(() => {
15
+ // check if user still on this modal page
16
+ if (router.canGoBack() && pathname === currentPath) {
17
+ router.dismiss();
18
+ }
19
+ }, Number(params?.time) || 2000);
20
+
21
+ return () => clearTimeout(timer);
22
+ }, [params?.time, pathname]);
23
+
24
+ return (
25
+ <View style={tw`p-4 bg-gray-900`}>
26
+ <Text style={tw`text-white`}>{params?.content}</Text>
27
+ </View>
28
+ );
29
+ };
30
+
31
+ export default Taster;