@imksh/create 1.0.24 → 1.0.25
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/package.json +1 -1
- package/templates/mern-react-native/client/src/vite-env.d.ts +1 -0
- package/templates/mern-react-native/mobile/babel.config.js +1 -0
- package/templates/mern-react-native/mobile/drizzle.config.ts +8 -0
- package/templates/mern-react-native/mobile/expo-env.d.ts +3 -0
- package/templates/mern-react-native/mobile/package.json +6 -0
- package/templates/mern-react-native/mobile/src/app/(auth)/_layout.tsx +12 -0
- package/templates/mern-react-native/mobile/src/app/(auth)/change-password.tsx +112 -0
- package/templates/mern-react-native/mobile/src/app/(auth)/edit-profile.tsx +160 -0
- package/templates/mern-react-native/mobile/src/app/(auth)/forgot-password.tsx +191 -0
- package/templates/mern-react-native/mobile/src/app/{login.tsx → (auth)/login.tsx} +69 -21
- package/templates/mern-react-native/mobile/src/app/(tabs)/index.tsx +18 -17
- package/templates/mern-react-native/mobile/src/app/(tabs)/profile.tsx +23 -60
- package/templates/mern-react-native/mobile/src/app/_layout.tsx +22 -4
- package/templates/mern-react-native/mobile/src/components/common/AnimatedHeader.tsx +328 -0
- package/templates/mern-react-native/mobile/src/components/common/LocationLoader.tsx +591 -0
- package/templates/mern-react-native/mobile/src/components/common/ScreenHeader.tsx +41 -17
- package/templates/mern-react-native/mobile/src/components/common/TabHeader.tsx +58 -0
- package/templates/mern-react-native/mobile/src/components/common/Typography.tsx +49 -30
- package/templates/mern-react-native/mobile/src/components/common/Welcome.tsx +2 -2
- package/templates/mern-react-native/mobile/src/components/ui/BottomModal.tsx +31 -20
- package/templates/mern-react-native/mobile/src/components/ui/ClassicTabBar.tsx +4 -3
- package/templates/mern-react-native/mobile/src/components/ui/CustomTabBar.tsx +108 -71
- package/templates/mern-react-native/mobile/src/components/ui/Sidebar.tsx +81 -56
- package/templates/mern-react-native/mobile/src/components/ui/buttons/Button.tsx +106 -37
- package/templates/mern-react-native/mobile/src/components/ui/buttons/IconButton.tsx +4 -2
- package/templates/mern-react-native/mobile/src/components/ui/data-display/Accordion.tsx +3 -2
- package/templates/mern-react-native/mobile/src/components/ui/data-display/Avatar.tsx +4 -3
- package/templates/mern-react-native/mobile/src/components/ui/data-display/Badge.tsx +45 -17
- package/templates/mern-react-native/mobile/src/components/ui/data-display/ImageViewer.tsx +19 -9
- package/templates/mern-react-native/mobile/src/components/ui/feedback/CircularProgress.tsx +5 -4
- package/templates/mern-react-native/mobile/src/components/ui/feedback/ProgressBar.tsx +4 -3
- package/templates/mern-react-native/mobile/src/components/ui/feedback/Skeleton.tsx +3 -0
- package/templates/mern-react-native/mobile/src/components/ui/feedback/Spinner.tsx +11 -3
- package/templates/mern-react-native/mobile/src/components/ui/inputs/Checkbox.tsx +3 -2
- package/templates/mern-react-native/mobile/src/components/ui/inputs/DatePicker.tsx +186 -0
- package/templates/mern-react-native/mobile/src/components/ui/inputs/ImagePickerModal.tsx +129 -0
- package/templates/mern-react-native/mobile/src/components/ui/inputs/Input.tsx +54 -14
- package/templates/mern-react-native/mobile/src/components/ui/inputs/LocationPicker.tsx +211 -0
- package/templates/mern-react-native/mobile/src/components/ui/inputs/OTPInput.tsx +32 -9
- package/templates/mern-react-native/mobile/src/components/ui/inputs/PasswordInput.tsx +2 -1
- package/templates/mern-react-native/mobile/src/components/ui/inputs/Radio.tsx +3 -2
- package/templates/mern-react-native/mobile/src/components/ui/inputs/SearchBar.tsx +41 -4
- package/templates/mern-react-native/mobile/src/components/ui/inputs/Slider.tsx +4 -3
- package/templates/mern-react-native/mobile/src/components/ui/inputs/Switch.tsx +3 -2
- package/templates/mern-react-native/mobile/src/components/ui/inputs/TextArea.tsx +2 -1
- package/templates/mern-react-native/mobile/src/components/ui/inputs/WebLocationPicker.tsx +321 -0
- package/templates/mern-react-native/mobile/src/components/ui/layout/Grid.tsx +52 -10
- package/templates/mern-react-native/mobile/src/components/ui/layout/Section.tsx +7 -8
- package/templates/mern-react-native/mobile/src/components/ui/navigation/Pagination.tsx +4 -3
- package/templates/mern-react-native/mobile/src/components/ui/navigation/ProgressStepper.tsx +6 -5
- package/templates/mern-react-native/mobile/src/components/ui/navigation/Tabs.tsx +30 -4
- package/templates/mern-react-native/mobile/src/config/api.ts +12 -1
- package/templates/mern-react-native/mobile/src/config/sidebar.config.ts +72 -0
- package/templates/mern-react-native/mobile/src/config/tabNavigation.ts +37 -7
- package/templates/mern-react-native/mobile/src/db/index.ts +9 -0
- package/templates/mern-react-native/mobile/src/db/schema.ts +14 -0
- package/templates/mern-react-native/mobile/src/hooks/useDebounce.ts +17 -0
- package/templates/mern-react-native/mobile/src/services/socket.service.ts +36 -0
- package/templates/mern-react-native/mobile/src/store/useAuthStore.ts +122 -27
- package/templates/mern-react-native/mobile/src/store/useNotificationStore.ts +53 -0
- package/templates/mern-react-native/mobile/src/types/auth.type.ts +14 -0
- package/templates/mern-react-native/mobile/tsconfig.json +1 -0
- package/templates/mern-ts/client/src/vite-env.d.ts +1 -0
- package/templates/react-native/babel.config.js +1 -0
- package/templates/react-native/drizzle.config.ts +8 -0
- package/templates/react-native/expo-env.d.ts +3 -0
- package/templates/react-native/package.json +6 -0
- package/templates/react-native/src/app/(auth)/_layout.tsx +12 -0
- package/templates/react-native/src/app/(auth)/change-password.tsx +112 -0
- package/templates/react-native/src/app/(auth)/edit-profile.tsx +160 -0
- package/templates/react-native/src/app/(auth)/forgot-password.tsx +191 -0
- package/templates/react-native/src/app/{login.tsx → (auth)/login.tsx} +69 -21
- package/templates/react-native/src/app/(tabs)/index.tsx +18 -17
- package/templates/react-native/src/app/(tabs)/profile.tsx +23 -60
- package/templates/react-native/src/app/_layout.tsx +22 -4
- package/templates/react-native/src/components/common/AnimatedHeader.tsx +328 -0
- package/templates/react-native/src/components/common/LocationLoader.tsx +591 -0
- package/templates/react-native/src/components/common/ScreenHeader.tsx +41 -17
- package/templates/react-native/src/components/common/TabHeader.tsx +58 -0
- package/templates/react-native/src/components/common/Typography.tsx +49 -30
- package/templates/react-native/src/components/common/Welcome.tsx +2 -2
- package/templates/react-native/src/components/ui/BottomModal.tsx +31 -20
- package/templates/react-native/src/components/ui/ClassicTabBar.tsx +4 -3
- package/templates/react-native/src/components/ui/CustomTabBar.tsx +108 -71
- package/templates/react-native/src/components/ui/Sidebar.tsx +81 -56
- package/templates/react-native/src/components/ui/buttons/Button.tsx +106 -37
- package/templates/react-native/src/components/ui/buttons/IconButton.tsx +4 -2
- package/templates/react-native/src/components/ui/data-display/Accordion.tsx +3 -2
- package/templates/react-native/src/components/ui/data-display/Avatar.tsx +4 -3
- package/templates/react-native/src/components/ui/data-display/Badge.tsx +45 -17
- package/templates/react-native/src/components/ui/data-display/ImageViewer.tsx +19 -9
- package/templates/react-native/src/components/ui/feedback/CircularProgress.tsx +5 -4
- package/templates/react-native/src/components/ui/feedback/ProgressBar.tsx +4 -3
- package/templates/react-native/src/components/ui/feedback/Skeleton.tsx +3 -0
- package/templates/react-native/src/components/ui/feedback/Spinner.tsx +11 -3
- package/templates/react-native/src/components/ui/inputs/Checkbox.tsx +3 -2
- package/templates/react-native/src/components/ui/inputs/DatePicker.tsx +186 -0
- package/templates/react-native/src/components/ui/inputs/ImagePickerModal.tsx +129 -0
- package/templates/react-native/src/components/ui/inputs/Input.tsx +54 -14
- package/templates/react-native/src/components/ui/inputs/LocationPicker.tsx +211 -0
- package/templates/react-native/src/components/ui/inputs/OTPInput.tsx +32 -9
- package/templates/react-native/src/components/ui/inputs/PasswordInput.tsx +2 -1
- package/templates/react-native/src/components/ui/inputs/Radio.tsx +3 -2
- package/templates/react-native/src/components/ui/inputs/SearchBar.tsx +41 -4
- package/templates/react-native/src/components/ui/inputs/Slider.tsx +4 -3
- package/templates/react-native/src/components/ui/inputs/Switch.tsx +3 -2
- package/templates/react-native/src/components/ui/inputs/TextArea.tsx +2 -1
- package/templates/react-native/src/components/ui/inputs/WebLocationPicker.tsx +321 -0
- package/templates/react-native/src/components/ui/layout/Grid.tsx +52 -10
- package/templates/react-native/src/components/ui/layout/Section.tsx +7 -8
- package/templates/react-native/src/components/ui/navigation/Pagination.tsx +4 -3
- package/templates/react-native/src/components/ui/navigation/ProgressStepper.tsx +6 -5
- package/templates/react-native/src/components/ui/navigation/Tabs.tsx +30 -4
- package/templates/react-native/src/config/api.ts +12 -1
- package/templates/react-native/src/config/sidebar.config.ts +72 -0
- package/templates/react-native/src/config/tabNavigation.ts +37 -7
- package/templates/react-native/src/db/index.ts +9 -0
- package/templates/react-native/src/db/schema.ts +14 -0
- package/templates/react-native/src/hooks/useDebounce.ts +17 -0
- package/templates/react-native/src/services/socket.service.ts +36 -0
- package/templates/react-native/src/store/useAuthStore.ts +122 -27
- package/templates/react-native/src/store/useNotificationStore.ts +53 -0
- package/templates/react-native/src/types/auth.type.ts +14 -0
- package/templates/react-native/tsconfig.json +1 -0
- package/templates/react-ts/src/vite-env.d.ts +1 -0
- package/templates/mern-react-native/mobile/.env.example +0 -2
- package/templates/mern-react-native/mobile/.vscode/extensions.json +0 -1
- package/templates/mern-react-native/mobile/.vscode/settings.json +0 -7
- package/templates/mern-react-native/mobile/README.md +0 -159
- package/templates/mern-react-native/mobile/docs/README.md +0 -17
- package/templates/mern-react-native/mobile/docs/components/buttons.md +0 -40
- package/templates/mern-react-native/mobile/docs/components/data-display.md +0 -44
- package/templates/mern-react-native/mobile/docs/components/feedback.md +0 -36
- package/templates/mern-react-native/mobile/docs/components/gestures.md +0 -60
- package/templates/mern-react-native/mobile/docs/components/inputs.md +0 -41
- package/templates/mern-react-native/mobile/docs/components/layout.md +0 -34
- package/templates/mern-react-native/mobile/docs/components/navigation.md +0 -31
- package/templates/mern-react-native/mobile/docs/features.md +0 -85
- package/templates/mern-react-native/mobile/docs/getting-started.md +0 -47
- package/templates/mern-react-native/mobile/src/components/common/HomeHeader.tsx +0 -43
- package/templates/mern-react-native/mobile/src/components/settings/SettingToggle.tsx +0 -26
- package/templates/mern-react-native/mobile/src/components/settings/SettingsOptions.tsx +0 -47
- package/templates/react-native/.env.example +0 -2
- package/templates/react-native/.vscode/extensions.json +0 -1
- package/templates/react-native/.vscode/settings.json +0 -7
- package/templates/react-native/README.md +0 -159
- package/templates/react-native/docs/README.md +0 -17
- package/templates/react-native/docs/components/buttons.md +0 -40
- package/templates/react-native/docs/components/data-display.md +0 -44
- package/templates/react-native/docs/components/feedback.md +0 -36
- package/templates/react-native/docs/components/gestures.md +0 -60
- package/templates/react-native/docs/components/inputs.md +0 -41
- package/templates/react-native/docs/components/layout.md +0 -34
- package/templates/react-native/docs/components/navigation.md +0 -31
- package/templates/react-native/docs/features.md +0 -85
- package/templates/react-native/docs/getting-started.md +0 -47
- package/templates/react-native/src/components/common/HomeHeader.tsx +0 -43
- package/templates/react-native/src/components/settings/SettingToggle.tsx +0 -26
- package/templates/react-native/src/components/settings/SettingsOptions.tsx +0 -47
|
@@ -1,28 +1,34 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useState, useCallback } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import { useAuthStore } from "
|
|
4
|
-
import { Txt } from "
|
|
5
|
-
import { Redirect } from "expo-router";
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import Tabs from "../components/ui/navigation/Tabs";
|
|
3
|
+
import { useAuthStore } from "../../store/useAuthStore";
|
|
4
|
+
import { Txt } from "../../components/common/Typography";
|
|
5
|
+
import { Redirect, router, useFocusEffect } from "expo-router";
|
|
6
|
+
import ScrollContainer from "../../components/ui/layout/ScrollContainer";
|
|
7
|
+
import Input from "../../components/ui/inputs/Input";
|
|
8
|
+
import Button from "../../components/ui/buttons/Button";
|
|
9
|
+
import Tabs from "../../components/ui/navigation/Tabs";
|
|
11
10
|
import Image from "@/components/ui/data-display/Image";
|
|
12
|
-
import logo from "
|
|
11
|
+
import logo from "../../../assets/images/logo/logo.png";
|
|
13
12
|
|
|
14
13
|
export default function LoginScreen() {
|
|
15
14
|
const {
|
|
16
15
|
login,
|
|
17
|
-
demoLogin,
|
|
18
16
|
signup,
|
|
19
17
|
sendOtp,
|
|
20
18
|
loading,
|
|
21
19
|
error,
|
|
22
20
|
user,
|
|
23
21
|
isCheckingAuth,
|
|
22
|
+
clearError,
|
|
23
|
+
demoLogin,
|
|
24
24
|
} = useAuthStore();
|
|
25
25
|
|
|
26
|
+
useFocusEffect(
|
|
27
|
+
useCallback(() => {
|
|
28
|
+
return () => clearError();
|
|
29
|
+
}, [clearError]),
|
|
30
|
+
);
|
|
31
|
+
|
|
26
32
|
const [mode, setMode] = useState("login");
|
|
27
33
|
const [showPassword, setShowPassword] = useState(false);
|
|
28
34
|
const [form, setForm] = useState({
|
|
@@ -32,6 +38,17 @@ export default function LoginScreen() {
|
|
|
32
38
|
otp: "",
|
|
33
39
|
});
|
|
34
40
|
const [otpSent, setOtpSent] = useState(false);
|
|
41
|
+
const [timer, setTimer] = useState(0);
|
|
42
|
+
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
let interval: ReturnType<typeof setInterval>;
|
|
45
|
+
if (timer > 0) {
|
|
46
|
+
interval = setInterval(() => {
|
|
47
|
+
setTimer((prev) => prev - 1);
|
|
48
|
+
}, 1000);
|
|
49
|
+
}
|
|
50
|
+
return () => clearInterval(interval);
|
|
51
|
+
}, [timer]);
|
|
35
52
|
|
|
36
53
|
const handleChange = (name: string, value: string) => {
|
|
37
54
|
setForm((prev) => ({ ...prev, [name]: value }));
|
|
@@ -44,7 +61,10 @@ export default function LoginScreen() {
|
|
|
44
61
|
} else {
|
|
45
62
|
if (!otpSent) {
|
|
46
63
|
ok = await sendOtp(form.email);
|
|
47
|
-
if (ok)
|
|
64
|
+
if (ok) {
|
|
65
|
+
setOtpSent(true);
|
|
66
|
+
setTimer(60);
|
|
67
|
+
}
|
|
48
68
|
} else {
|
|
49
69
|
ok = await signup(form.name, form.email, form.password, form.otp);
|
|
50
70
|
}
|
|
@@ -62,22 +82,23 @@ export default function LoginScreen() {
|
|
|
62
82
|
justifyContent: "center",
|
|
63
83
|
padding: 16,
|
|
64
84
|
}}
|
|
85
|
+
className="bg-base-100"
|
|
65
86
|
>
|
|
66
|
-
<View className="w-full p-6">
|
|
87
|
+
<View className="w-full p-6 ">
|
|
67
88
|
{/* Header */}
|
|
68
89
|
<View className="items-center mb-8 w-full">
|
|
69
90
|
<View className="w-16 h-16 rounded-2xl bg-primary/10 border border-primary/20 items-center justify-center mb-4">
|
|
70
91
|
<Image src={logo} height={40} width={40} />
|
|
71
92
|
</View>
|
|
72
93
|
<Txt
|
|
73
|
-
variant="
|
|
94
|
+
variant="xl"
|
|
74
95
|
className="text-2xl mb-1 text-center"
|
|
75
96
|
numberOfLines={1}
|
|
76
97
|
>
|
|
77
98
|
{mode === "login" ? "Welcome back" : "Create account"}
|
|
78
99
|
</Txt>
|
|
79
100
|
<Txt
|
|
80
|
-
variant="
|
|
101
|
+
variant="sm"
|
|
81
102
|
className="text-xs text-base-content/50 text-center px-2"
|
|
82
103
|
>
|
|
83
104
|
{mode === "login"
|
|
@@ -105,7 +126,7 @@ export default function LoginScreen() {
|
|
|
105
126
|
{/* Error */}
|
|
106
127
|
{error ? (
|
|
107
128
|
<View className="bg-error/10 border border-error/20 rounded-2xl p-3 mb-4">
|
|
108
|
-
<Txt variant="
|
|
129
|
+
<Txt variant="md" className="text-error text-xs text-center">
|
|
109
130
|
⚠️ {error}
|
|
110
131
|
</Txt>
|
|
111
132
|
</View>
|
|
@@ -141,6 +162,18 @@ export default function LoginScreen() {
|
|
|
141
162
|
secureTextEntry={!showPassword}
|
|
142
163
|
/>
|
|
143
164
|
|
|
165
|
+
{mode === "login" && (
|
|
166
|
+
<View className="items-end mt-1 mb-2">
|
|
167
|
+
<Txt
|
|
168
|
+
variant="md"
|
|
169
|
+
className="text-primary text-xs"
|
|
170
|
+
onPress={() => router.push("/(auth)/forgot-password")}
|
|
171
|
+
>
|
|
172
|
+
Forgot Password?
|
|
173
|
+
</Txt>
|
|
174
|
+
</View>
|
|
175
|
+
)}
|
|
176
|
+
|
|
144
177
|
{mode === "signup" && otpSent && (
|
|
145
178
|
<Input
|
|
146
179
|
leftIcon="key"
|
|
@@ -170,9 +203,24 @@ export default function LoginScreen() {
|
|
|
170
203
|
{mode === "login" && (
|
|
171
204
|
<View className="mt-2">
|
|
172
205
|
<Button
|
|
173
|
-
label="
|
|
174
|
-
onPress={demoLogin}
|
|
175
|
-
|
|
206
|
+
label="Demo Login"
|
|
207
|
+
onPress={() => demoLogin()}
|
|
208
|
+
isLoading={loading}
|
|
209
|
+
variant="outline"
|
|
210
|
+
isFullWidth
|
|
211
|
+
/>
|
|
212
|
+
</View>
|
|
213
|
+
)}
|
|
214
|
+
|
|
215
|
+
{mode === "signup" && otpSent && (
|
|
216
|
+
<View className="mt-2">
|
|
217
|
+
<Button
|
|
218
|
+
label={timer > 0 ? `Resend OTP in ${timer}s` : "Resend OTP"}
|
|
219
|
+
onPress={async () => {
|
|
220
|
+
const ok = await sendOtp(form.email);
|
|
221
|
+
if (ok) setTimer(60);
|
|
222
|
+
}}
|
|
223
|
+
disabled={timer > 0 || loading}
|
|
176
224
|
variant="outline"
|
|
177
225
|
isFullWidth
|
|
178
226
|
/>
|
|
@@ -183,12 +231,12 @@ export default function LoginScreen() {
|
|
|
183
231
|
{/* Footer */}
|
|
184
232
|
<View className="mt-8">
|
|
185
233
|
<Txt
|
|
186
|
-
variant="
|
|
234
|
+
variant="sm"
|
|
187
235
|
className="text-sm text-base-content/50 text-center"
|
|
188
236
|
>
|
|
189
237
|
{mode === "login" ? "New here? " : "Already have an account? "}
|
|
190
238
|
<Txt
|
|
191
|
-
variant="
|
|
239
|
+
variant="md"
|
|
192
240
|
className="text-primary text-sm"
|
|
193
241
|
onPress={() => {
|
|
194
242
|
setMode(mode === "login" ? "signup" : "login");
|
|
@@ -9,6 +9,7 @@ import { toast } from "@/utils/toast";
|
|
|
9
9
|
import ScrollContainer from "@/components/ui/layout/ScrollContainer";
|
|
10
10
|
import Container from "@/components/ui/layout/Container";
|
|
11
11
|
import Section from "@/components/ui/layout/Section";
|
|
12
|
+
import Divider from "@/components/ui/layout/Divider";
|
|
12
13
|
import { HStack, VStack } from "@/components/ui/layout/Stack";
|
|
13
14
|
|
|
14
15
|
import Button from "@/components/ui/buttons/Button";
|
|
@@ -79,7 +80,7 @@ const Index = () => {
|
|
|
79
80
|
>
|
|
80
81
|
<HStack justify="space-between" align="center">
|
|
81
82
|
<VStack>
|
|
82
|
-
<Txt variant="
|
|
83
|
+
<Txt variant="3xl" className="font-extrabold tracking-tight">
|
|
83
84
|
imksh-create
|
|
84
85
|
</Txt>
|
|
85
86
|
<Txt
|
|
@@ -115,12 +116,12 @@ const Index = () => {
|
|
|
115
116
|
<Badge label="SOFT" variant="primary" soft={true} />
|
|
116
117
|
</HStack>
|
|
117
118
|
<Txt
|
|
118
|
-
variant="
|
|
119
|
+
variant="4xl"
|
|
119
120
|
className="text-primary font-black leading-tight"
|
|
120
121
|
>
|
|
121
122
|
Stop configuring. Start building.
|
|
122
123
|
</Txt>
|
|
123
|
-
<Txt variant="
|
|
124
|
+
<Txt variant="base" className="text-primary/70 font-medium">
|
|
124
125
|
Skip the setup. Build your product. A complete boilerplate with auth, state management, navigation, and beautiful prebuilt components.
|
|
125
126
|
</Txt>
|
|
126
127
|
</VStack>
|
|
@@ -197,7 +198,7 @@ const Index = () => {
|
|
|
197
198
|
size={50}
|
|
198
199
|
/>
|
|
199
200
|
<VStack style={{ flex: 1 }}>
|
|
200
|
-
<Txt variant="
|
|
201
|
+
<Txt variant="md" className="font-bold">
|
|
201
202
|
Swipe me left!
|
|
202
203
|
</Txt>
|
|
203
204
|
<Txt
|
|
@@ -234,7 +235,7 @@ const Index = () => {
|
|
|
234
235
|
color={colors.accent}
|
|
235
236
|
style={{ marginBottom: 12 }}
|
|
236
237
|
/>
|
|
237
|
-
<Txt variant="
|
|
238
|
+
<Txt variant="2xl" className="text-accent text-center">
|
|
238
239
|
Double Tap or Swipe Up
|
|
239
240
|
</Txt>
|
|
240
241
|
<Txt
|
|
@@ -258,11 +259,11 @@ const Index = () => {
|
|
|
258
259
|
placeholder="Search components..."
|
|
259
260
|
/>
|
|
260
261
|
|
|
261
|
-
<
|
|
262
|
+
<Divider />
|
|
262
263
|
|
|
263
264
|
<HStack justify="space-between" align="center">
|
|
264
265
|
<VStack>
|
|
265
|
-
<Txt variant="
|
|
266
|
+
<Txt variant="md" className="font-bold">
|
|
266
267
|
Biometric Login
|
|
267
268
|
</Txt>
|
|
268
269
|
<Txt
|
|
@@ -275,11 +276,11 @@ const Index = () => {
|
|
|
275
276
|
<Switch checked={isEnabled} onChange={setIsEnabled} />
|
|
276
277
|
</HStack>
|
|
277
278
|
|
|
278
|
-
<
|
|
279
|
+
<Divider />
|
|
279
280
|
|
|
280
281
|
<VStack spacing={12}>
|
|
281
282
|
<HStack justify="space-between" align="center">
|
|
282
|
-
<Txt variant="
|
|
283
|
+
<Txt variant="md" className="font-bold">
|
|
283
284
|
Intensity
|
|
284
285
|
</Txt>
|
|
285
286
|
<Badge label={`${sliderVal}%`} variant="secondary" />
|
|
@@ -292,7 +293,7 @@ const Index = () => {
|
|
|
292
293
|
/>
|
|
293
294
|
</VStack>
|
|
294
295
|
|
|
295
|
-
<
|
|
296
|
+
<Divider style={{ marginTop: 8 }} />
|
|
296
297
|
|
|
297
298
|
{/* Text Input */}
|
|
298
299
|
<Input
|
|
@@ -301,7 +302,7 @@ const Index = () => {
|
|
|
301
302
|
leftIcon="mail-outline"
|
|
302
303
|
/>
|
|
303
304
|
|
|
304
|
-
<
|
|
305
|
+
<Divider />
|
|
305
306
|
|
|
306
307
|
{/* Selection Controls */}
|
|
307
308
|
<VStack spacing={16}>
|
|
@@ -341,7 +342,7 @@ const Index = () => {
|
|
|
341
342
|
]}
|
|
342
343
|
/>
|
|
343
344
|
<View className="py-6 items-center justify-center">
|
|
344
|
-
<Txt variant="
|
|
345
|
+
<Txt variant="base" className="text-base-content/60 italic">
|
|
345
346
|
Currently viewing {activeTab} content.
|
|
346
347
|
</Txt>
|
|
347
348
|
</View>
|
|
@@ -380,7 +381,7 @@ const Index = () => {
|
|
|
380
381
|
|
|
381
382
|
<Card elevation={1} className="rounded-3xl p-6 mt-4">
|
|
382
383
|
<HStack justify="space-between" align="center" className="mb-4">
|
|
383
|
-
<Txt variant="
|
|
384
|
+
<Txt variant="md" className="font-bold">
|
|
384
385
|
Background Sync
|
|
385
386
|
</Txt>
|
|
386
387
|
<Spinner size={24} />
|
|
@@ -399,14 +400,14 @@ const Index = () => {
|
|
|
399
400
|
<Section title="Information & FAQs" className="pb-20">
|
|
400
401
|
<VStack spacing={12}>
|
|
401
402
|
<Accordion title="How to use this library?">
|
|
402
|
-
<Txt variant="
|
|
403
|
+
<Txt variant="base">
|
|
403
404
|
Simply import the components from the `@/components/ui`
|
|
404
405
|
directory. They are fully typed, gesture-driven, and styled
|
|
405
406
|
with NativeWind.
|
|
406
407
|
</Txt>
|
|
407
408
|
</Accordion>
|
|
408
409
|
<Accordion title="Does it support dark mode?">
|
|
409
|
-
<Txt variant="
|
|
410
|
+
<Txt variant="base">
|
|
410
411
|
Yes! All components automatically respond to the device's
|
|
411
412
|
color scheme, utilizing the custom CSS variables defined in
|
|
412
413
|
global.css.
|
|
@@ -437,11 +438,11 @@ const Index = () => {
|
|
|
437
438
|
color={colors.primary}
|
|
438
439
|
/>
|
|
439
440
|
</View>
|
|
440
|
-
<Txt variant="
|
|
441
|
+
<Txt variant="3xl" className="text-center font-black">
|
|
441
442
|
Premium Modal
|
|
442
443
|
</Txt>
|
|
443
444
|
<Txt
|
|
444
|
-
variant="
|
|
445
|
+
variant="base"
|
|
445
446
|
className="text-center text-base-content/70 leading-relaxed px-4"
|
|
446
447
|
>
|
|
447
448
|
This highly responsive bottom sheet is gesture-driven. You can
|
|
@@ -3,10 +3,10 @@ import { useAuthStore } from "../../store/useAuthStore";
|
|
|
3
3
|
import { useColorScheme } from "nativewind";
|
|
4
4
|
import { Ionicons } from "@expo/vector-icons";
|
|
5
5
|
import { Txt } from "../../components/common/Typography";
|
|
6
|
-
import SettingsOptions from "../../components/settings/SettingsOptions";
|
|
7
|
-
import SettingToggle from "../../components/settings/SettingToggle";
|
|
8
6
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
9
7
|
import Avatar from "@/components/ui/data-display/Avatar";
|
|
8
|
+
import Button from "@/components/ui/buttons/Button";
|
|
9
|
+
import Switch from "@/components/ui/inputs/Switch";
|
|
10
10
|
|
|
11
11
|
const Profile = () => {
|
|
12
12
|
const { user, logout } = useAuthStore();
|
|
@@ -22,10 +22,6 @@ const Profile = () => {
|
|
|
22
22
|
await logout();
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const handleEditProfile = () => {
|
|
26
|
-
console.log("Edit profile clicked");
|
|
27
|
-
};
|
|
28
|
-
|
|
29
25
|
return (
|
|
30
26
|
<View className="flex-1 bg-base-100">
|
|
31
27
|
<View className="pt-16 pb-8 px-6 bg-primary/10 rounded-b-[40px] items-center border-b border-primary/20">
|
|
@@ -50,63 +46,30 @@ const Profile = () => {
|
|
|
50
46
|
</Txt>
|
|
51
47
|
</View>
|
|
52
48
|
</View>
|
|
53
|
-
<ScrollView className="flex-1 bg-base-100">
|
|
54
|
-
{/* Settings Section */}
|
|
55
|
-
<View className="px-6 py-8 pb-20">
|
|
56
|
-
<Txt
|
|
57
|
-
variant="h3"
|
|
58
|
-
className="mb-6 text-base-content/80 uppercase tracking-widest text-xs"
|
|
59
|
-
>
|
|
60
|
-
Account Settings
|
|
61
|
-
</Txt>
|
|
62
49
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
fun={() => {}}
|
|
76
|
-
check={false}
|
|
77
|
-
/>
|
|
78
|
-
|
|
79
|
-
<Txt
|
|
80
|
-
variant="h3"
|
|
81
|
-
className="mt-6 mb-6 text-base-content/80 uppercase tracking-widest text-xs"
|
|
82
|
-
>
|
|
83
|
-
Preferences
|
|
84
|
-
</Txt>
|
|
85
|
-
|
|
86
|
-
<SettingToggle
|
|
87
|
-
name="Dark Theme"
|
|
88
|
-
icon="moon-outline"
|
|
89
|
-
check={colorScheme === "dark"}
|
|
90
|
-
fun={handleToggleTheme}
|
|
91
|
-
/>
|
|
92
|
-
|
|
93
|
-
<SettingToggle
|
|
94
|
-
name="Push Notifications"
|
|
95
|
-
icon="notifications-outline"
|
|
96
|
-
check={true}
|
|
97
|
-
fun={() => {}}
|
|
98
|
-
/>
|
|
99
|
-
|
|
100
|
-
<View className="mt-8 mb-12">
|
|
101
|
-
<SettingsOptions
|
|
102
|
-
name="Log Out"
|
|
103
|
-
icon="log-out-outline"
|
|
104
|
-
message="Are you sure you want to log out from this device?"
|
|
105
|
-
fun={handleLogout}
|
|
106
|
-
check={false}
|
|
107
|
-
/>
|
|
50
|
+
<ScrollView className="flex-1 px-6 pt-6">
|
|
51
|
+
<View className="bg-base-200 rounded-2xl p-4 mb-6">
|
|
52
|
+
<View className="flex-row items-center justify-between py-2">
|
|
53
|
+
<View className="flex-row items-center">
|
|
54
|
+
<Ionicons
|
|
55
|
+
name={colorScheme === "dark" ? "moon" : "sunny"}
|
|
56
|
+
size={22}
|
|
57
|
+
color={colorScheme === "dark" ? "#fff" : "#000"}
|
|
58
|
+
/>
|
|
59
|
+
<Txt variant="base" className="ml-3 font-semibold">Dark Mode</Txt>
|
|
60
|
+
</View>
|
|
61
|
+
<Switch checked={colorScheme === "dark"} onChange={handleToggleTheme} />
|
|
108
62
|
</View>
|
|
109
63
|
</View>
|
|
64
|
+
|
|
65
|
+
<Button
|
|
66
|
+
label="Logout"
|
|
67
|
+
variant="error"
|
|
68
|
+
isFullWidth
|
|
69
|
+
leftIcon="log-out-outline"
|
|
70
|
+
onPress={handleLogout}
|
|
71
|
+
style={{ marginTop: 20, marginBottom: 40 }}
|
|
72
|
+
/>
|
|
110
73
|
</ScrollView>
|
|
111
74
|
</View>
|
|
112
75
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
|
-
import { Stack } from "expo-router";
|
|
2
|
+
import { Stack, useRouter, useSegments } from "expo-router";
|
|
3
3
|
import Toast from "react-native-toast-message";
|
|
4
4
|
import { useAuthStore } from "../store/useAuthStore";
|
|
5
5
|
import { useColorScheme } from "nativewind";
|
|
@@ -25,9 +25,12 @@ export default function RootLayout() {
|
|
|
25
25
|
InterExtraBold: require("../../assets/fonts/Inter_ExtraBold.ttf"),
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const { getMe, isCheckingAuth } = useAuthStore();
|
|
28
|
+
const { getMe, isCheckingAuth, loadCachedUser, user } = useAuthStore();
|
|
29
29
|
const { colorScheme, setColorScheme } = useColorScheme();
|
|
30
30
|
const colors = Colors[colorScheme ?? "light"];
|
|
31
|
+
|
|
32
|
+
const segments = useSegments();
|
|
33
|
+
const router = useRouter();
|
|
31
34
|
|
|
32
35
|
useEffect(() => {
|
|
33
36
|
if (fontsLoaded || fontError) {
|
|
@@ -36,7 +39,10 @@ export default function RootLayout() {
|
|
|
36
39
|
}, [fontsLoaded, fontError]);
|
|
37
40
|
|
|
38
41
|
useEffect(() => {
|
|
39
|
-
|
|
42
|
+
// Load cached user quickly, then fetch fresh in background
|
|
43
|
+
loadCachedUser().then(() => {
|
|
44
|
+
getMe();
|
|
45
|
+
});
|
|
40
46
|
|
|
41
47
|
// Load saved theme
|
|
42
48
|
AsyncStorage.getItem("theme").then((savedTheme) => {
|
|
@@ -47,7 +53,19 @@ export default function RootLayout() {
|
|
|
47
53
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
54
|
}, []);
|
|
49
55
|
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (isCheckingAuth) return;
|
|
58
|
+
|
|
59
|
+
const inAuthGroup = segments[0] === "(auth)";
|
|
50
60
|
|
|
61
|
+
if (!user && !inAuthGroup) {
|
|
62
|
+
// Redirect to the auth group
|
|
63
|
+
router.replace("/(auth)/login");
|
|
64
|
+
} else if (user && inAuthGroup) {
|
|
65
|
+
// Redirect away from auth
|
|
66
|
+
router.replace("/(tabs)");
|
|
67
|
+
}
|
|
68
|
+
}, [user, isCheckingAuth, segments]);
|
|
51
69
|
|
|
52
70
|
if (!fontsLoaded && !fontError) {
|
|
53
71
|
return null;
|
|
@@ -69,7 +87,7 @@ export default function RootLayout() {
|
|
|
69
87
|
>
|
|
70
88
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
71
89
|
<Stack.Screen
|
|
72
|
-
name="
|
|
90
|
+
name="(auth)"
|
|
73
91
|
options={{ headerShown: false, animation: "fade" }}
|
|
74
92
|
/>
|
|
75
93
|
</Stack>
|