BaaS_Driver_Android_App/app/auth/login.tsx

253 lines
7.0 KiB
TypeScript

import React, { useEffect } from "react";
import {
Text,
View,
TextInput,
StyleSheet,
TouchableOpacity,
TouchableWithoutFeedback,
Keyboard,
KeyboardAvoidingView,
Linking,
Platform,
} from "react-native";
import { useRouter } from "expo-router";
import { Formik } from "formik";
import * as Yup from "yup";
import { sendOTP, clearSendOTPError } from "../../store/authSlice";
import { useDispatch } from "react-redux";
import { AppDispatch } from "../../store";
import { useSelector } from "react-redux";
import { RootState } from "../../store";
import { AUTH_STATUSES } from "@/constants/types";
import { useTranslation } from "react-i18next";
import { SUPPORT } from "@/constants/config";
import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function WelcomeScreen() {
const {
status,
otpId,
phone: phoneNumber,
sendOTPError,
} = useSelector((state: RootState) => state.auth);
const { t } = useTranslation();
const dispatch = useDispatch<AppDispatch>();
const router = useRouter();
const insets = useSafeAreaInsets();
// const navigation = useNavigation();
const phoneValidationSchema = Yup.object().shape({
phone: Yup.string()
.required(t("onboarding.phone-number-is-required"))
.matches(/^\d{10}$/, t("onboarding.must-be-10-digits")),
});
useEffect(() => {
if (status === AUTH_STATUSES.SUCCESS && otpId) {
router.push({
pathname: "/auth/verifyOtp",
params: { otpId, phoneNumber },
});
}
}, [status, otpId, router]);
const makePhoneCall = () => {
Linking.openURL(`tel:${SUPPORT.PHONE}`);
};
return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === "ios" ? "padding" : "height"}
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 0}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={[styles.inner, { paddingBottom: insets.bottom }]}>
<Text style={styles.title}>{t("onboarding.welcome")}</Text>
<Formik
initialValues={{ phone: "" }}
onSubmit={(values) => dispatch(sendOTP({ phone: values.phone }))}
validationSchema={phoneValidationSchema}
>
{({
handleChange,
handleBlur,
handleSubmit,
values,
errors,
touched,
}) => (
<View style={styles.formContainer}>
<View style={styles.inputContainer}>
<Text style={styles.label}>
{t("onboarding.enter-mobile-number")}
</Text>
<TextInput
style={{
...styles.input,
color: values.phone ? "black" : "#949CAC",
}}
onChangeText={(text) => {
handleChange("phone")(text);
if (sendOTPError) {
dispatch(clearSendOTPError());
}
}}
onBlur={handleBlur("phone")}
value={values.phone}
keyboardType="numeric"
placeholder={t("onboarding.enter-registered-mobile-number")}
placeholderTextColor={"#949CAC"}
/>
<View style={styles.errorContainer}>
{touched.phone && errors.phone && (
<Text style={styles.error}>{errors.phone}</Text>
)}
{sendOTPError && (
<Text style={styles.error}>{sendOTPError}</Text>
)}
</View>
{/* ✅ Send OTP button placed just below input box */}
<TouchableOpacity
onPress={handleSubmit as unknown as () => void}
style={{
...styles.button,
marginTop: 16,
marginBottom: 16,
backgroundColor:
values.phone.length === 10 &&
!errors.phone &&
status !== AUTH_STATUSES.LOADING
? "#008761"
: "#B0B7C5",
}}
disabled={
values.phone.length !== 10 ||
!!errors.phone ||
status === AUTH_STATUSES.LOADING
}
>
<Text style={styles.buttonText}>
{t("onboarding.send-otp")}
</Text>
</TouchableOpacity>
<View style={styles.contactContainer}>
<View style={{ flexDirection: "row" }}>
<Text>{t("onboarding.for-any-queries")}</Text>
<TouchableOpacity onPress={makePhoneCall}>
<Text style={styles.link}>
{t("onboarding.contact-us")}
</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
)}
</Formik>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: "#F3F5F8",
},
inner: {
flex: 1,
},
formContainer: {
flex: 1,
justifyContent: "space-between",
},
inputContainer: {
flex: 1,
},
bottomSection: {
width: "100%",
},
contactContainer: {
width: "100%",
alignItems: "center",
justifyContent: "center",
marginBottom: 16,
},
link: {
fontSize: 14,
fontWeight: "500",
lineHeight: 20,
color: "#1249ED",
},
errorContainer: {
flexDirection: "column",
gap: 8,
marginTop: 8,
},
error: {
color: "#D51D10",
fontFamily: "Inter",
fontSize: 12,
fontWeight: "bold",
lineHeight: 20,
},
button: {
height: 48,
borderRadius: 4,
alignItems: "center",
justifyContent: "center",
width: "100%",
},
buttonText: {
color: "#FCFCFC",
fontFamily: "Inter",
fontSize: 14,
fontWeight: "bold",
lineHeight: 20,
},
title: {
fontSize: 28,
fontWeight: "bold",
marginBottom: 16,
color: "#1A1C1E",
fontStyle: "normal",
lineHeight: 36,
letterSpacing: -0.56,
width: "70%",
},
label: {
fontSize: 14,
marginBottom: 8,
color: "#252A34",
fontFamily: "Inter",
fontStyle: "normal",
fontWeight: "normal",
lineHeight: 20,
},
input: {
borderRadius: 4,
borderTopColor: "#D8DDE7",
borderBottomColor: "#D8DDE7",
borderLeftColor: "#D8DDE7",
borderRightColor: "#D8DDE7",
height: 40,
borderColor: "gray",
borderWidth: 1,
paddingHorizontal: 8,
fontSize: 14,
overflow: "hidden",
fontFamily: "Inter",
fontStyle: "normal",
lineHeight: 20,
fontWeight: "bold",
backgroundColor: "#ffffff",
},
});