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.
- package/bin/index.js +3 -0
- package/bun.lock +82 -0
- package/package.json +26 -0
- package/src/copy-template.js +156 -0
- package/src/create-expo.js +10 -0
- package/src/index.js +39 -0
- package/src/install-deps.js +22 -0
- package/src/utils/logger.js +29 -0
- package/tailwind.config.js +69 -0
- package/template/src/app/_layout.tsx +61 -0
- package/template/src/app/auth/_layout.tsx +41 -0
- package/template/src/app/auth/change_pass.tsx +138 -0
- package/template/src/app/auth/change_pass_modal.tsx +74 -0
- package/template/src/app/auth/forgot.tsx +124 -0
- package/template/src/app/auth/index.tsx +274 -0
- package/template/src/app/auth/opt_verify.tsx +145 -0
- package/template/src/app/auth/register.tsx +334 -0
- package/template/src/app/auth/reset_pass.tsx +152 -0
- package/template/src/app/common/image.tsx +202 -0
- package/template/src/app/common/openurl.tsx +42 -0
- package/template/src/app/home/_layout.tsx +29 -0
- package/template/src/app/home/drawer/_layout.tsx +27 -0
- package/template/src/app/home/tabs/_layout.tsx +75 -0
- package/template/src/app/home/tabs/index.tsx +11 -0
- package/template/src/app/index.tsx +11 -0
- package/template/src/app/modals/confirmation_logout_modal.tsx +78 -0
- package/template/src/app/modals/payment_modal.tsx +105 -0
- package/template/src/app/modals/success_modal.tsx +72 -0
- package/template/src/app/modals/toaster.tsx +31 -0
- package/template/src/app/settings/_layout.tsx +19 -0
- package/template/src/app/settings/about_us.tsx +61 -0
- package/template/src/app/settings/privacy_policy.tsx +61 -0
- package/template/src/app/settings/terms_and_conditions.tsx +60 -0
- package/template/src/hooks/useCheckLocation.ts +36 -0
- package/template/src/hooks/useDocPicker.ts +83 -0
- package/template/src/hooks/useImgePicker.ts +70 -0
- package/template/src/hooks/useSuggestionLocation.ts +36 -0
- package/template/src/hooks/useUploadProgress.ts +127 -0
- package/template/src/redux/api-config/baseApi.ts +89 -0
- package/template/src/redux/api-slices/authSlices.ts +175 -0
- package/template/src/redux/interface/common.ts +19 -0
- package/template/src/redux/interface/interface.ts +196 -0
- package/template/src/redux/interface/tag-types.ts +13 -0
- package/template/src/redux/service/demo.ts +27 -0
- package/template/src/redux/store.ts +17 -0
- package/template/src/utils/utils.ts +27 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Image, Text, View } from "react-native";
|
|
2
|
+
import { router, useGlobalSearchParams } from "expo-router";
|
|
3
|
+
|
|
4
|
+
import AppBgWrapper from "@/src/components/common/AppBgWrapper";
|
|
5
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
6
|
+
import { ImageAssets } from "@/assets/images/image";
|
|
7
|
+
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
|
|
8
|
+
import { OtpInput } from "react-native-otp-entry";
|
|
9
|
+
import React from "react";
|
|
10
|
+
import TButton from "@/src/lib/buttons/TButton";
|
|
11
|
+
import tw from "@/src/lib/tailwind";
|
|
12
|
+
import { useEmailVerifyMutation } from "@/src/redux/apiSlices/authSlices";
|
|
13
|
+
|
|
14
|
+
const Otp_verify = () => {
|
|
15
|
+
// Define validation schema using Yup
|
|
16
|
+
|
|
17
|
+
const [Otp, setOtp] = React.useState("");
|
|
18
|
+
const [email, setEmail] = React.useState("");
|
|
19
|
+
|
|
20
|
+
const [emailVerify, { isLoading }] = useEmailVerifyMutation();
|
|
21
|
+
|
|
22
|
+
const params = useGlobalSearchParams();
|
|
23
|
+
|
|
24
|
+
console.log(params);
|
|
25
|
+
|
|
26
|
+
const handleVerify = async (value: any) => {
|
|
27
|
+
try {
|
|
28
|
+
const verifyInfo = {
|
|
29
|
+
email: params?.email,
|
|
30
|
+
code: value,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
console.log(verifyInfo);
|
|
34
|
+
const res = await emailVerify(verifyInfo).unwrap();
|
|
35
|
+
if (res?.success) {
|
|
36
|
+
if (params?.forgot) {
|
|
37
|
+
router?.push(`/auth/reset_pass?email=${params?.email}`);
|
|
38
|
+
} else if (params?.account) {
|
|
39
|
+
console.log(res);
|
|
40
|
+
await AsyncStorage.setItem("token", res?.data?.token);
|
|
41
|
+
router?.replace(`/auth/location_access`);
|
|
42
|
+
} else {
|
|
43
|
+
router?.push(`/auth`);
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
router.push(`/modals/toaster?content=${res?.message}`);
|
|
47
|
+
}
|
|
48
|
+
} catch (error: any) {
|
|
49
|
+
router.push(`/modals/toaster?content=${error?.message}`);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
React.useLayoutEffect(() => {
|
|
54
|
+
if (params?.email) {
|
|
55
|
+
setEmail(params?.email as any);
|
|
56
|
+
}
|
|
57
|
+
}, [params?.email]);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<AppBgWrapper>
|
|
61
|
+
<KeyboardAwareScrollView
|
|
62
|
+
style={tw`z-10 flex-1`}
|
|
63
|
+
contentContainerStyle={tw`items-center justify-center flex-1`}
|
|
64
|
+
>
|
|
65
|
+
<View style={tw`z-10 flex-1 items-center justify-center gap-8 p-5 `}>
|
|
66
|
+
<View style={tw`justify-center items-center gap-2`}>
|
|
67
|
+
<Image
|
|
68
|
+
source={ImageAssets.logo}
|
|
69
|
+
style={tw`h-30 aspect-square mb-5`}
|
|
70
|
+
resizeMode="contain"
|
|
71
|
+
/>
|
|
72
|
+
<View style={tw`items-center justify-center gap-2`}>
|
|
73
|
+
<Text
|
|
74
|
+
style={tw`text-white font-InterSemiBold text-2xl -tracking-[1px]`}
|
|
75
|
+
>
|
|
76
|
+
Enter OTP
|
|
77
|
+
</Text>
|
|
78
|
+
<Text
|
|
79
|
+
style={tw`text-white text-base text-center font-InterRegular -tracking-[1px]`}
|
|
80
|
+
>
|
|
81
|
+
We’ve sent you a 4 digit OTP to {`\n`}{" "}
|
|
82
|
+
{(email as any)?.split("@")[0]?.slice(0, 3) +
|
|
83
|
+
"****@" +
|
|
84
|
+
(email as any)?.split("@")[1]}
|
|
85
|
+
</Text>
|
|
86
|
+
</View>
|
|
87
|
+
</View>
|
|
88
|
+
|
|
89
|
+
<View style={tw` w-full items-center `}>
|
|
90
|
+
<View style={tw` w-full items-center`}>
|
|
91
|
+
{/* OTP Fields */}
|
|
92
|
+
<View style={tw` mb-4`}>
|
|
93
|
+
<OtpInput
|
|
94
|
+
numberOfDigits={4}
|
|
95
|
+
focusColor={tw.color("primary")}
|
|
96
|
+
autoFocus={false}
|
|
97
|
+
hideStick={true}
|
|
98
|
+
placeholder="-"
|
|
99
|
+
blurOnFilled={true}
|
|
100
|
+
disabled={false}
|
|
101
|
+
type="numeric"
|
|
102
|
+
secureTextEntry={false}
|
|
103
|
+
focusStickBlinkingDuration={500}
|
|
104
|
+
onTextChange={async (text) => {
|
|
105
|
+
// setValue(text);
|
|
106
|
+
setOtp(text);
|
|
107
|
+
}}
|
|
108
|
+
// onFocus={() => console.log("Focused")}
|
|
109
|
+
// onBlur={() => console.log("Blurred")}
|
|
110
|
+
// onTextChange={(text) => console.log(text)}
|
|
111
|
+
onFilled={async (text) => {
|
|
112
|
+
console.log(`OTP is ${text}`);
|
|
113
|
+
// router.push("/home/tabs");
|
|
114
|
+
handleVerify(text);
|
|
115
|
+
}}
|
|
116
|
+
textInputProps={{
|
|
117
|
+
accessibilityLabel: "One-Time Password",
|
|
118
|
+
}}
|
|
119
|
+
theme={{
|
|
120
|
+
containerStyle: tw`rounded-full px-2 gap-2.5 mb-4`,
|
|
121
|
+
pinCodeContainerStyle: tw`h-20 w-20 justify-center border-0 items-center bg-secondary rounded-2xl `,
|
|
122
|
+
pinCodeTextStyle: tw`text-white text-2xl font-InterSemiBold `,
|
|
123
|
+
placeholderTextStyle: tw`text-white text-2xl font-InterSemiBold `,
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
126
|
+
</View>
|
|
127
|
+
{/* Verify Button */}
|
|
128
|
+
<TButton
|
|
129
|
+
isLoading={isLoading}
|
|
130
|
+
title="Verify"
|
|
131
|
+
onPress={() => {
|
|
132
|
+
// router.push("/auth/reset_pass");
|
|
133
|
+
handleVerify(Otp);
|
|
134
|
+
}}
|
|
135
|
+
containerStyle={tw`w-full`}
|
|
136
|
+
/>
|
|
137
|
+
</View>
|
|
138
|
+
</View>
|
|
139
|
+
</View>
|
|
140
|
+
</KeyboardAwareScrollView>
|
|
141
|
+
</AppBgWrapper>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default Otp_verify;
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import * as Yup from "yup";
|
|
2
|
+
|
|
3
|
+
import { Image, Text, TouchableOpacity, View } from "react-native";
|
|
4
|
+
import {
|
|
5
|
+
useGoogleLoginMutation,
|
|
6
|
+
useSignUpMutation,
|
|
7
|
+
} from "@/src/redux/apiSlices/authSlices";
|
|
8
|
+
|
|
9
|
+
import AppBgWrapper from "@/src/components/common/AppBgWrapper";
|
|
10
|
+
import BackButton from "@/src/lib/backHeader/BackButton";
|
|
11
|
+
import CheckBox from "@/src/lib/inputs/CheckBox";
|
|
12
|
+
import { Formik } from "formik";
|
|
13
|
+
import { Icon } from "@/assets/icons/Icon";
|
|
14
|
+
import { ImageAssets } from "@/assets/images/image";
|
|
15
|
+
import InputText from "@/src/lib/inputs/InputText";
|
|
16
|
+
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
|
|
17
|
+
import Or from "@/src/lib/buttons/Or";
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { SvgXml } from "react-native-svg";
|
|
20
|
+
import TButton from "@/src/lib/buttons/TButton";
|
|
21
|
+
import { router } from "expo-router";
|
|
22
|
+
import tw from "@/src/lib/tailwind";
|
|
23
|
+
|
|
24
|
+
const Register = () => {
|
|
25
|
+
const [showPassword, setShowPassword] = React.useState(false);
|
|
26
|
+
const [showPasswordTwo, setShowPasswordTwo] = React.useState(false);
|
|
27
|
+
|
|
28
|
+
const [checked, setChecked] = React.useState(false);
|
|
29
|
+
|
|
30
|
+
const [register, { isLoading }] = useSignUpMutation();
|
|
31
|
+
const [loginWithGoogle, googleResults] = useGoogleLoginMutation();
|
|
32
|
+
|
|
33
|
+
const handleRegister = async (values: any) => {
|
|
34
|
+
try {
|
|
35
|
+
// delete values?.confirmPassword;
|
|
36
|
+
// create new data without confirm password
|
|
37
|
+
const sendData = {
|
|
38
|
+
email: values.email,
|
|
39
|
+
password: values.password,
|
|
40
|
+
confirmPassword: values.confirmPassword,
|
|
41
|
+
name: values.name,
|
|
42
|
+
display_name: values.display_name,
|
|
43
|
+
gender: values.gender,
|
|
44
|
+
};
|
|
45
|
+
const res = await register(sendData).unwrap();
|
|
46
|
+
if (res?.success) {
|
|
47
|
+
router.push(`/auth/opt_verify?email=${values.email}&account=true`);
|
|
48
|
+
}
|
|
49
|
+
console.log(res);
|
|
50
|
+
} catch (error: any) {
|
|
51
|
+
// console.log(error);
|
|
52
|
+
router.push(`/modals/toaster?content=${error?.message}&time=4000`);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleLoginWithGoogle = async () => {
|
|
57
|
+
try {
|
|
58
|
+
const response = await loginWithGoogle({}).unwrap();
|
|
59
|
+
// console.log(response);
|
|
60
|
+
if (response?.success) {
|
|
61
|
+
// router.push("/home/tabs");
|
|
62
|
+
router.replace(`/auth/google_login?url=${`${response?.data}`}`);
|
|
63
|
+
} else {
|
|
64
|
+
router.push(`/modals/toaster?content=${response?.message}`);
|
|
65
|
+
}
|
|
66
|
+
} catch (error: any) {
|
|
67
|
+
router.push(`/modals/toaster?content=${error?.message}`);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Define validation schema using Yup
|
|
72
|
+
const loginValidationSchema = Yup.object().shape({
|
|
73
|
+
email: Yup.string()
|
|
74
|
+
.email("Please enter a valid email")
|
|
75
|
+
.required("Email is required"),
|
|
76
|
+
password: Yup.string()
|
|
77
|
+
.min(6, ({ min }) => `Password must be at least ${min} characters`)
|
|
78
|
+
.required("Password is required"),
|
|
79
|
+
confirmPassword: Yup.string()
|
|
80
|
+
.min(6, ({ min }) => `Password must be at least ${min} characters`)
|
|
81
|
+
.required("Password is required")
|
|
82
|
+
.oneOf([Yup.ref("password")], "Passwords do not match"),
|
|
83
|
+
// show match password to confirm password
|
|
84
|
+
|
|
85
|
+
name: Yup.string().required("Fullname is required"),
|
|
86
|
+
display_name: Yup.string().required("Display name is required"),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<AppBgWrapper>
|
|
91
|
+
<KeyboardAwareScrollView style={tw`z-10 `}>
|
|
92
|
+
<BackButton
|
|
93
|
+
onPress={() => router.dismiss()}
|
|
94
|
+
containerStyle={tw`absolute top-0`}
|
|
95
|
+
/>
|
|
96
|
+
<View style={tw`flex-1 items-center justify-center p-5`}>
|
|
97
|
+
<View style={tw`justify-center items-center gap-2`}>
|
|
98
|
+
<Image
|
|
99
|
+
source={ImageAssets.logo}
|
|
100
|
+
style={tw`h-28 aspect-square `}
|
|
101
|
+
resizeMode="contain"
|
|
102
|
+
/>
|
|
103
|
+
<View style={tw`items-center justify-center gap-1`}>
|
|
104
|
+
<Text
|
|
105
|
+
style={tw`text-white font-InterSemiBold text-2xl -tracking-[1px]`}
|
|
106
|
+
>
|
|
107
|
+
Create a new account
|
|
108
|
+
</Text>
|
|
109
|
+
<Text
|
|
110
|
+
style={tw`text-white text-base font-InterRegular -tracking-[1px]`}
|
|
111
|
+
>
|
|
112
|
+
Please input your details to sign up
|
|
113
|
+
</Text>
|
|
114
|
+
</View>
|
|
115
|
+
</View>
|
|
116
|
+
|
|
117
|
+
{/* Formik Wrapper */}
|
|
118
|
+
<Formik
|
|
119
|
+
initialValues={{
|
|
120
|
+
email: "",
|
|
121
|
+
password: "",
|
|
122
|
+
confirmPassword: "",
|
|
123
|
+
name: "",
|
|
124
|
+
display_name: "",
|
|
125
|
+
gender: "male",
|
|
126
|
+
}}
|
|
127
|
+
validationSchema={loginValidationSchema}
|
|
128
|
+
onSubmit={handleRegister}
|
|
129
|
+
>
|
|
130
|
+
{({
|
|
131
|
+
handleChange,
|
|
132
|
+
handleBlur,
|
|
133
|
+
handleSubmit,
|
|
134
|
+
values,
|
|
135
|
+
errors,
|
|
136
|
+
touched,
|
|
137
|
+
isValid,
|
|
138
|
+
setFieldValue,
|
|
139
|
+
}) => (
|
|
140
|
+
<View style={tw`w-full py-8 gap-6`}>
|
|
141
|
+
<View style={tw`gap-3`}>
|
|
142
|
+
<InputText
|
|
143
|
+
svgFirstIcon={Icon.user}
|
|
144
|
+
textInputProps={{
|
|
145
|
+
placeholder: "Your Full Name",
|
|
146
|
+
placeholderTextColor: "#A9A9A9",
|
|
147
|
+
}}
|
|
148
|
+
value={values.name}
|
|
149
|
+
onChangeText={handleChange("name")}
|
|
150
|
+
onBlur={handleBlur("name")}
|
|
151
|
+
touched={touched.name}
|
|
152
|
+
errorText={errors.name}
|
|
153
|
+
/>
|
|
154
|
+
<InputText
|
|
155
|
+
svgFirstIcon={Icon.display_name}
|
|
156
|
+
textInputProps={{
|
|
157
|
+
placeholder: "Enter your display name",
|
|
158
|
+
placeholderTextColor: "#A9A9A9",
|
|
159
|
+
}}
|
|
160
|
+
value={values.display_name}
|
|
161
|
+
onChangeText={handleChange("display_name")}
|
|
162
|
+
onBlur={handleBlur("display_name")}
|
|
163
|
+
touched={touched.display_name}
|
|
164
|
+
errorText={errors.display_name}
|
|
165
|
+
/>
|
|
166
|
+
<InputText
|
|
167
|
+
svgFirstIcon={Icon.email}
|
|
168
|
+
textInputProps={{
|
|
169
|
+
placeholder: "Email",
|
|
170
|
+
placeholderTextColor: "#A9A9A9",
|
|
171
|
+
}}
|
|
172
|
+
value={values.email}
|
|
173
|
+
onChangeText={handleChange("email")}
|
|
174
|
+
onBlur={handleBlur("email")}
|
|
175
|
+
touched={touched.email}
|
|
176
|
+
errorText={errors.email}
|
|
177
|
+
/>
|
|
178
|
+
<View style={tw` px-4`}>
|
|
179
|
+
<Text style={tw`text-white font-InterRegular mb-2 `}>
|
|
180
|
+
Gender
|
|
181
|
+
</Text>
|
|
182
|
+
<View style={tw`flex-row items-center gap-3`}>
|
|
183
|
+
<TouchableOpacity
|
|
184
|
+
onPress={() => setFieldValue("gender", "male")}
|
|
185
|
+
style={
|
|
186
|
+
values.gender === "male"
|
|
187
|
+
? tw`px-4 py-2 rounded-full bg-blue-500`
|
|
188
|
+
: tw`px-4 py-2 rounded-full bg-[#3D3D3D]`
|
|
189
|
+
}
|
|
190
|
+
>
|
|
191
|
+
<Text style={tw`text-white`}>Male</Text>
|
|
192
|
+
</TouchableOpacity>
|
|
193
|
+
<TouchableOpacity
|
|
194
|
+
onPress={() => setFieldValue("gender", "female")}
|
|
195
|
+
style={
|
|
196
|
+
values.gender === "female"
|
|
197
|
+
? tw`px-4 py-2 rounded-full bg-blue-500`
|
|
198
|
+
: tw`px-4 py-2 rounded-full bg-[#3D3D3D]`
|
|
199
|
+
}
|
|
200
|
+
>
|
|
201
|
+
<Text style={tw`text-white`}>Female</Text>
|
|
202
|
+
</TouchableOpacity>
|
|
203
|
+
</View>
|
|
204
|
+
</View>
|
|
205
|
+
<InputText
|
|
206
|
+
svgFirstIcon={Icon.lock}
|
|
207
|
+
textInputProps={{
|
|
208
|
+
placeholder: "Password",
|
|
209
|
+
placeholderTextColor: "#A9A9A9",
|
|
210
|
+
secureTextEntry: !showPassword,
|
|
211
|
+
}}
|
|
212
|
+
svgSecondIcon={!showPassword ? Icon.eyeOff : Icon.eye}
|
|
213
|
+
svgSecondOnPress={() => setShowPassword(!showPassword)}
|
|
214
|
+
value={values.password}
|
|
215
|
+
onChangeText={handleChange("password")}
|
|
216
|
+
onBlur={handleBlur("password")}
|
|
217
|
+
touched={touched.password}
|
|
218
|
+
errorText={errors.password}
|
|
219
|
+
/>
|
|
220
|
+
<InputText
|
|
221
|
+
svgFirstIcon={Icon.lock}
|
|
222
|
+
textInputProps={{
|
|
223
|
+
placeholder: "Confirm Password",
|
|
224
|
+
placeholderTextColor: "#A9A9A9",
|
|
225
|
+
secureTextEntry: !showPasswordTwo,
|
|
226
|
+
}}
|
|
227
|
+
svgSecondIcon={!showPasswordTwo ? Icon.eyeOff : Icon.eye}
|
|
228
|
+
svgSecondOnPress={() =>
|
|
229
|
+
setShowPasswordTwo(!showPasswordTwo)
|
|
230
|
+
}
|
|
231
|
+
value={values.confirmPassword}
|
|
232
|
+
onChangeText={handleChange("confirmPassword")}
|
|
233
|
+
onBlur={handleBlur("confirmPassword")}
|
|
234
|
+
touched={touched.confirmPassword}
|
|
235
|
+
errorText={errors.confirmPassword}
|
|
236
|
+
/>
|
|
237
|
+
</View>
|
|
238
|
+
|
|
239
|
+
<View style={tw`flex-row justify-between items-center`}>
|
|
240
|
+
<View style={tw`flex-row items-center`}>
|
|
241
|
+
<CheckBox
|
|
242
|
+
checked={checked}
|
|
243
|
+
onPress={() => setChecked(!checked)}
|
|
244
|
+
containerStyle={tw`items-center flex-1`}
|
|
245
|
+
titleComponent={
|
|
246
|
+
<View style={tw` flex-row items-center gap-1`}>
|
|
247
|
+
<Text
|
|
248
|
+
style={tw`text-white font-InterRegular text-[13px]`}
|
|
249
|
+
>
|
|
250
|
+
Agree to
|
|
251
|
+
</Text>
|
|
252
|
+
<Text
|
|
253
|
+
onPress={() =>
|
|
254
|
+
router.push("/settings/terms_and_conditions")
|
|
255
|
+
}
|
|
256
|
+
style={tw`text-blue-500 underline font-InterRegular text-[13px]`}
|
|
257
|
+
>
|
|
258
|
+
Terms & conditions
|
|
259
|
+
</Text>
|
|
260
|
+
<Text
|
|
261
|
+
style={tw`text-white font-InterRegular text-[13px]`}
|
|
262
|
+
>
|
|
263
|
+
and
|
|
264
|
+
</Text>
|
|
265
|
+
<Text
|
|
266
|
+
onPress={() =>
|
|
267
|
+
router.push("/settings/privacy_policy")
|
|
268
|
+
}
|
|
269
|
+
style={tw` text-blue-500 underline font-InterRegular text-[13px]`}
|
|
270
|
+
>
|
|
271
|
+
Privacy policy
|
|
272
|
+
</Text>
|
|
273
|
+
<Text
|
|
274
|
+
style={tw`text-white font-InterRegular text-[13px]`}
|
|
275
|
+
>
|
|
276
|
+
.
|
|
277
|
+
</Text>
|
|
278
|
+
</View>
|
|
279
|
+
}
|
|
280
|
+
/>
|
|
281
|
+
</View>
|
|
282
|
+
</View>
|
|
283
|
+
|
|
284
|
+
{/* Submit button calls handleSubmit from Formik */}
|
|
285
|
+
<TButton
|
|
286
|
+
isLoading={isLoading}
|
|
287
|
+
title="Sign Up"
|
|
288
|
+
onPress={() => {
|
|
289
|
+
handleSubmit();
|
|
290
|
+
// router.push("/auth/opt_verify");
|
|
291
|
+
}}
|
|
292
|
+
disabled={!isValid || !checked}
|
|
293
|
+
/>
|
|
294
|
+
|
|
295
|
+
<Or title="Or continue with" />
|
|
296
|
+
<View style={tw`flex-row justify-center items-center gap-5`}>
|
|
297
|
+
<TouchableOpacity
|
|
298
|
+
onPress={handleLoginWithGoogle}
|
|
299
|
+
style={tw`w-16 h-16 rounded-full bg-[#3D3D3D] items-center justify-center`}
|
|
300
|
+
>
|
|
301
|
+
<SvgXml xml={Icon.google} />
|
|
302
|
+
</TouchableOpacity>
|
|
303
|
+
{/* <TouchableOpacity
|
|
304
|
+
style={tw`w-16 h-16 rounded-full bg-[#3D3D3D] items-center justify-center`}
|
|
305
|
+
>
|
|
306
|
+
<SvgXml xml={Icon.apple} />
|
|
307
|
+
</TouchableOpacity> */}
|
|
308
|
+
</View>
|
|
309
|
+
|
|
310
|
+
<View style={tw`flex-row justify-center mt-6`}>
|
|
311
|
+
<Text style={tw`text-white`}>Already have an account?</Text>
|
|
312
|
+
<TouchableOpacity
|
|
313
|
+
onPress={() => {
|
|
314
|
+
router.replace("/auth");
|
|
315
|
+
}}
|
|
316
|
+
style={tw`flex-row items-center gap-3`}
|
|
317
|
+
>
|
|
318
|
+
<Text style={tw`text-[#339DFF] underline ml-1`}>
|
|
319
|
+
Sign In
|
|
320
|
+
</Text>
|
|
321
|
+
<SvgXml xml={Icon.play} />
|
|
322
|
+
</TouchableOpacity>
|
|
323
|
+
</View>
|
|
324
|
+
</View>
|
|
325
|
+
)}
|
|
326
|
+
</Formik>
|
|
327
|
+
{/* End of Formik Wrapper */}
|
|
328
|
+
</View>
|
|
329
|
+
</KeyboardAwareScrollView>
|
|
330
|
+
</AppBgWrapper>
|
|
331
|
+
);
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
export default Register;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as Yup from "yup";
|
|
2
|
+
|
|
3
|
+
import { Image, Text, View } from "react-native";
|
|
4
|
+
import { router, useGlobalSearchParams } from "expo-router";
|
|
5
|
+
|
|
6
|
+
import AppBgWrapper from "@/src/components/common/AppBgWrapper";
|
|
7
|
+
import BackButton from "@/src/lib/backHeader/BackButton";
|
|
8
|
+
import { Formik } from "formik";
|
|
9
|
+
import { Icon } from "@/assets/icons/Icon";
|
|
10
|
+
import { ImageAssets } from "@/assets/images/image";
|
|
11
|
+
import InputText from "@/src/lib/inputs/InputText";
|
|
12
|
+
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
|
|
13
|
+
import React from "react";
|
|
14
|
+
import TButton from "@/src/lib/buttons/TButton";
|
|
15
|
+
import tw from "@/src/lib/tailwind";
|
|
16
|
+
import { useResetPasswordMutation } from "@/src/redux/apiSlices/authSlices";
|
|
17
|
+
|
|
18
|
+
const Rest_pass = () => {
|
|
19
|
+
const [showPassword, setShowPassword] = React.useState(false);
|
|
20
|
+
const [showPasswordTwo, setShowPasswordTwo] = React.useState(false);
|
|
21
|
+
const [resetPassword, { isLoading }] = useResetPasswordMutation();
|
|
22
|
+
const { email } = useGlobalSearchParams();
|
|
23
|
+
const handleResetPassword = async (values: any) => {
|
|
24
|
+
try {
|
|
25
|
+
values.email = email;
|
|
26
|
+
|
|
27
|
+
const res = await resetPassword(values).unwrap();
|
|
28
|
+
if (res?.success) {
|
|
29
|
+
router.push(
|
|
30
|
+
"/auth/change_pass_modal?title=You’re All Set!&subtitle=Your password has been changed successfully!&buttonTitle=Back to login&route=/auth"
|
|
31
|
+
);
|
|
32
|
+
} else {
|
|
33
|
+
router.push(`/modals/toaster?content=${res?.message}`);
|
|
34
|
+
}
|
|
35
|
+
} catch (error: any) {
|
|
36
|
+
router.push(`/modals/toaster?content=${error?.message}`);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Define validation schema using Yup
|
|
41
|
+
const loginValidationSchema = Yup.object().shape({
|
|
42
|
+
new_password: Yup.string()
|
|
43
|
+
.min(6, ({ min }) => `Password must be at least ${min} characters`)
|
|
44
|
+
.required("Password is required"),
|
|
45
|
+
c_password: Yup.string()
|
|
46
|
+
.min(6, ({ min }) => `Password must be at least ${min} characters`)
|
|
47
|
+
.required("Password is required")
|
|
48
|
+
.oneOf([Yup.ref("new_password")], "Passwords do not match"),
|
|
49
|
+
// show match password to confirm password
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<AppBgWrapper>
|
|
54
|
+
<BackButton
|
|
55
|
+
onPress={() => router.dismiss()}
|
|
56
|
+
containerStyle={tw`absolute top-5`}
|
|
57
|
+
/>
|
|
58
|
+
<KeyboardAwareScrollView
|
|
59
|
+
style={tw`z-10 flex-1`}
|
|
60
|
+
contentContainerStyle={tw`items-center justify-center flex-1`}
|
|
61
|
+
>
|
|
62
|
+
<View style={tw`z-10 flex-1 items-center justify-center p-5`}>
|
|
63
|
+
<View style={tw`justify-center items-center gap-2`}>
|
|
64
|
+
<Image
|
|
65
|
+
source={ImageAssets.logo}
|
|
66
|
+
style={tw`h-30 aspect-square mb-5`}
|
|
67
|
+
resizeMode="contain"
|
|
68
|
+
/>
|
|
69
|
+
<View style={tw`items-center justify-center gap-2`}>
|
|
70
|
+
<Text
|
|
71
|
+
style={tw`text-white font-InterSemiBold text-2xl -tracking-[1px]`}
|
|
72
|
+
>
|
|
73
|
+
Reset Password
|
|
74
|
+
</Text>
|
|
75
|
+
<Text
|
|
76
|
+
style={tw`text-white text-base text-center font-InterRegular -tracking-[1px]`}
|
|
77
|
+
>
|
|
78
|
+
Enter a new password for your account
|
|
79
|
+
</Text>
|
|
80
|
+
</View>
|
|
81
|
+
</View>
|
|
82
|
+
|
|
83
|
+
{/* Formik Wrapper */}
|
|
84
|
+
<Formik
|
|
85
|
+
initialValues={{ new_password: "", c_password: "" }}
|
|
86
|
+
validationSchema={loginValidationSchema}
|
|
87
|
+
onSubmit={handleResetPassword}
|
|
88
|
+
>
|
|
89
|
+
{({
|
|
90
|
+
handleChange,
|
|
91
|
+
handleBlur,
|
|
92
|
+
handleSubmit,
|
|
93
|
+
values,
|
|
94
|
+
errors,
|
|
95
|
+
touched,
|
|
96
|
+
isValid,
|
|
97
|
+
}) => (
|
|
98
|
+
<View style={tw`w-full py-8 gap-6`}>
|
|
99
|
+
<View style={tw`gap-3`}>
|
|
100
|
+
<InputText
|
|
101
|
+
svgFirstIcon={Icon.lock}
|
|
102
|
+
textInputProps={{
|
|
103
|
+
placeholder: "New Password",
|
|
104
|
+
placeholderTextColor: "#A9A9A9",
|
|
105
|
+
secureTextEntry: !showPassword,
|
|
106
|
+
}}
|
|
107
|
+
svgSecondIcon={showPassword ? Icon.eye : Icon.eyeOff}
|
|
108
|
+
svgSecondOnPress={() => setShowPassword(!showPassword)}
|
|
109
|
+
value={values.new_password}
|
|
110
|
+
onChangeText={handleChange("new_password")}
|
|
111
|
+
onBlur={handleBlur("new_password")}
|
|
112
|
+
touched={touched.new_password}
|
|
113
|
+
errorText={errors.new_password}
|
|
114
|
+
/>
|
|
115
|
+
<InputText
|
|
116
|
+
svgFirstIcon={Icon.lock}
|
|
117
|
+
textInputProps={{
|
|
118
|
+
placeholder: "Confirm New Password",
|
|
119
|
+
placeholderTextColor: "#A9A9A9",
|
|
120
|
+
secureTextEntry: !showPasswordTwo,
|
|
121
|
+
}}
|
|
122
|
+
svgSecondIcon={showPasswordTwo ? Icon.eye : Icon.eyeOff}
|
|
123
|
+
svgSecondOnPress={() =>
|
|
124
|
+
setShowPasswordTwo(!showPasswordTwo)
|
|
125
|
+
}
|
|
126
|
+
value={values.c_password}
|
|
127
|
+
onChangeText={handleChange("c_password")}
|
|
128
|
+
onBlur={handleBlur("c_password")}
|
|
129
|
+
touched={touched.c_password}
|
|
130
|
+
errorText={errors.c_password}
|
|
131
|
+
/>
|
|
132
|
+
</View>
|
|
133
|
+
|
|
134
|
+
{/* Submit button calls handleSubmit from Formik */}
|
|
135
|
+
<TButton
|
|
136
|
+
isLoading={isLoading}
|
|
137
|
+
title="Change password"
|
|
138
|
+
onPress={() => {
|
|
139
|
+
handleSubmit();
|
|
140
|
+
}}
|
|
141
|
+
disabled={!isValid}
|
|
142
|
+
/>
|
|
143
|
+
</View>
|
|
144
|
+
)}
|
|
145
|
+
</Formik>
|
|
146
|
+
</View>
|
|
147
|
+
</KeyboardAwareScrollView>
|
|
148
|
+
</AppBgWrapper>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default Rest_pass;
|