BaaS_Driver_Android_App/app/auth/login.tsx

248 lines
6.8 KiB
TypeScript

import React, { useEffect } from "react";
import {
Text,
View,
TextInput,
StyleSheet,
TouchableOpacity,
TouchableWithoutFeedback,
Keyboard,
KeyboardAvoidingView,
StatusBar,
Linking,
} 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 { useNavigation } from "expo-router";
// type VerifyOTPNavigationProp = StackNavigationProp<
// RootStackParamList,
// "VerifyOTP"
// >;
// import OTPInputView from "@twotalltotems/react-native-otp-input";
//handleblue => when input field looses focus (mark as touched)
// handleBlur marks the field as touched, when field looses focus
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 navigation = useNavigation();
const phoneValidationSchema = Yup.object().shape({
phone: Yup.string()
.required("Phone number is required")
.matches(/^\d{10}$/, "Phone number must be exactly 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="padding">
<StatusBar barStyle="dark-content" backgroundColor="#F3F5F8" />
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.inner}>
<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.form}>
<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>
<View style={styles.contactContainer}>
<View style={{ flexDirection: "row" }}>
<Text>For any queries, </Text>
<TouchableOpacity onPress={makePhoneCall}>
<Text style={styles.link}>contact us.</Text>
</TouchableOpacity>
</View>
</View>
<TouchableOpacity
onPress={handleSubmit as unknown as () => void}
style={{
...styles.button,
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>
)}
</Formik>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
contactContainer: {
width: "100%",
alignItems: "center",
justifyContent: "center",
position: "absolute",
bottom: 110, // slightly above the "Send OTP" button
},
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,
},
inner: {
flex: 1,
justifyContent: "flex-start",
position: "relative",
},
form: {
height: "90%",
position: "relative",
},
button: {
height: 48,
borderRadius: 4,
alignItems: "center",
justifyContent: "center",
marginTop: 20,
width: "100%",
position: "absolute",
bottom: 50,
},
buttonText: {
color: "#FCFCFC",
fontFamily: "Inter",
fontSize: 14,
fontWeight: "bold",
lineHeight: 20,
},
container: {
flex: 1,
padding: 16,
backgroundColor: "#F3F5F8",
paddingTop: 0,
},
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",
},
});