255 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react';
import {
View,
Text,
KeyboardAvoidingView,
Platform,
ScrollView,
TouchableOpacity,
Alert,
} from 'react-native';
import Svg, { Circle, Rect, Path, G } from 'react-native-svg';
import { getStyles } from './LoginScreen.styles';
import { CustomInput, PrimaryButton } from '@components';
import { useAppTheme } from '@theme';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { AuthStackParamList } from '@navigation/navigationTypes';
import { RouteNames } from '@utils/constants';
import {
loginWithPhone,
RootState,
useAppDispatch,
useAppSelector,
} from '@store';
// Premium SVG Mascot: Delivery boy on scooter
const DeliveryScooterSvg = () => {
return (
<View style={{ alignItems: 'center', marginVertical: 20 }}>
<Svg width="160" height="130" viewBox="0 0 160 130" fill="none">
{/* Background Accent Circles */}
<Circle cx="80" cy="65" r="55" fill="#E8F5EE" />
<Circle cx="120" cy="35" r="15" fill="#C8E6C9" opacity="0.6" />
{/* Scooter Wheels */}
<Circle
cx="45"
cy="100"
r="14"
fill="#37474F"
stroke="#FFFFFF"
strokeWidth="3"
/>
<Circle cx="45" cy="100" r="6" fill="#CFD8DC" />
<Circle
cx="115"
cy="100"
r="14"
fill="#37474F"
stroke="#FFFFFF"
strokeWidth="3"
/>
<Circle cx="115" cy="100" r="6" fill="#CFD8DC" />
{/* Scooter Body */}
{/* Main deck */}
<Path
d="M 45 100 L 115 100"
stroke="#78909C"
strokeWidth="6"
strokeLinecap="round"
/>
<Path d="M 45 95 L 90 95 L 95 80 L 50 80 Z" fill="#05824C" />
{/* Front steering column */}
<Path
d="M 115 100 L 110 65 L 105 55"
stroke="#78909C"
strokeWidth="5"
strokeLinecap="round"
/>
{/* Handlebars */}
<Path
d="M 100 55 L 112 55"
stroke="#37474F"
strokeWidth="4"
strokeLinecap="round"
/>
{/* Front Shield */}
<Path d="M 110 65 L 118 65 L 114 90 L 108 90 Z" fill="#05824C" />
{/* Delivery Box */}
<Rect x="30" y="52" width="28" height="28" rx="4" fill="#046B3E" />
<Rect x="34" y="56" width="20" height="20" rx="2" fill="#05824C" />
{/* Box Stripe */}
<Path d="M 30 66 L 58 66" stroke="#FFFFFF" strokeWidth="2" />
{/* Delivery Rider */}
{/* Torso/Jacket */}
<Path d="M 68 55 L 88 55 L 82 82 L 65 82 Z" fill="#05824C" />
{/* Backpack strap */}
<Path d="M 64 58 L 74 82" stroke="#37474F" strokeWidth="3" />
{/* Head / Helmet */}
<Circle cx="80" cy="38" r="9" fill="#FFCCBC" />
{/* Helmet */}
<Path d="M 70 36 C 70 26, 90 26, 90 36 Z" fill="#37474F" />
{/* Visor */}
<Path d="M 80 32 L 89 35 L 80 38 Z" fill="#00E5FF" />
{/* Arm stretching to handle */}
<Path
d="M 80 58 L 98 56"
stroke="#046B3E"
strokeWidth="4"
strokeLinecap="round"
/>
<Path
d="M 98 56 L 105 55"
stroke="#FFCCBC"
strokeWidth="3"
strokeLinecap="round"
/>
{/* Motion lines */}
<Path
d="M 10 70 L 22 70"
stroke="#05824C"
strokeWidth="2"
strokeLinecap="round"
opacity="0.8"
/>
<Path
d="M 5 80 L 15 80"
stroke="#05824C"
strokeWidth="2"
strokeLinecap="round"
opacity="0.6"
/>
<Path
d="M 12 90 L 20 90"
stroke="#05824C"
strokeWidth="2"
strokeLinecap="round"
opacity="0.8"
/>
</Svg>
</View>
);
};
export const LoginScreen: React.FC = () => {
const { colors } = useAppTheme();
const styles = getStyles(colors);
const navigation =
useNavigation<NativeStackNavigationProp<AuthStackParamList>>();
const [mobileNumber, setMobileNumber] = useState('');
// const [password, setPassword] = useState('');
// const [isLoading, setIsLoading] = useState(false);
const [errors, setErrors] = useState<{ mobile?: string }>({});
const dispatch = useAppDispatch();
const { loading } = useAppSelector((state: RootState) => state.auth);
const validate = () => {
const newErrors: { mobile?: string } = {};
if (!mobileNumber) {
newErrors.mobile = 'Mobile number is required';
} else if (mobileNumber.length < 9) {
newErrors.mobile = 'Please enter a valid mobile number';
}
// if (!password) {
// newErrors.password = 'Password is required';
// } else if (password.length < 4) {
// newErrors.password = 'Password must be at least 4 characters';
// }
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleLogin = () => {
if (!validate()) return;
dispatch(loginWithPhone(mobileNumber))
.unwrap()
.then(() => {
navigation.navigate(RouteNames.Otp, { phone: mobileNumber });
})
.catch((error: any) => {
Alert.alert('Error', error.message);
});
};
// const handleForgotPassword = () => {
// Alert.alert('Forgot Password', 'OTP verification will be sent to recover password.');
// };
const handleSignUp = () => {
Alert.alert('Sign Up', 'Redirecting to register partner profile...');
};
return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView
contentContainerStyle={styles.scrollContainer}
showsVerticalScrollIndicator={false}
>
<DeliveryScooterSvg />
<View style={styles.headerContainer}>
<Text style={styles.title}>Welcome Partner!</Text>
<Text style={styles.subtitle}>Login to continue</Text>
</View>
<View style={styles.formContainer}>
<CustomInput
label="Mobile number"
placeholder="+91 98765 43210"
keyboardType="phone-pad"
value={mobileNumber}
onChangeText={text => {
setMobileNumber(text);
if (errors.mobile) setErrors({ ...errors, mobile: undefined });
}}
error={errors.mobile}
/>
{/* <CustomInput
label="Password"
placeholder="Enter password"
isPassword
rightActionText="Forgot Password?"
onRightActionPress={handleForgotPassword}
value={password}
onChangeText={text => {
setPassword(text);
if (errors.password) setErrors({ ...errors, password: undefined });
}}
error={errors.password}
/> */}
<PrimaryButton
title="Login"
onPress={handleLogin}
isLoading={loading}
style={styles.loginButton}
/>
<TouchableOpacity onPress={handleSignUp} activeOpacity={0.8}>
<Text style={styles.footerText}>
Dont have an account?{' '}
<Text style={styles.signUpLink}>Sign up</Text>
</Text>
</TouchableOpacity>
</View>
</ScrollView>
</KeyboardAvoidingView>
);
};
export default LoginScreen;