244 lines
7.1 KiB
TypeScript
244 lines
7.1 KiB
TypeScript
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';
|
||
|
||
// 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 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;
|
||
|
||
setIsLoading(true);
|
||
// Simulate API request
|
||
setTimeout(() => {
|
||
setIsLoading(false);
|
||
navigation.navigate(RouteNames.Otp, { phone: mobileNumber });
|
||
}, 1500);
|
||
};
|
||
|
||
// 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={isLoading}
|
||
style={styles.loginButton}
|
||
/>
|
||
|
||
<TouchableOpacity onPress={handleSignUp} activeOpacity={0.8}>
|
||
<Text style={styles.footerText}>
|
||
Don’t have an account?{' '}
|
||
<Text style={styles.signUpLink}>Sign up</Text>
|
||
</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</ScrollView>
|
||
</KeyboardAvoidingView>
|
||
);
|
||
};
|
||
|
||
export default LoginScreen;
|