Files
cpost-mobile/src/screens/auth/login/ui/index.tsx
Samandar Turgunboyev 34fb3e357a delete firebase
2025-09-04 19:13:14 +05:00

366 lines
13 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 { zodResolver } from '@hookform/resolvers/zod';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useMutation, useQuery } from '@tanstack/react-query';
import { authApi } from 'api/auth';
import { loginPayload } from 'api/auth/type';
import { Branch, branchApi } from 'api/branch';
import AppText from 'components/AppText';
import formatPhone from 'helpers/formatPhone';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import {
ActivityIndicator,
ImageBackground,
KeyboardAvoidingView,
Platform,
ScrollView,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import Logo from 'screens/../../assets/bootsplash/logo_512.png';
import { LoginFormType, loginSchema } from 'screens/auth/login/lib/form';
import LanguageSelector from 'screens/auth/select-language/SelectLang';
import ArrowDown from 'svg/ArrowDown';
import ArrowLeft from 'svg/ArrowLeft';
import ArrowUp from 'svg/ArrowUp';
import { useUserStore } from '../lib/userstore';
import { Loginstyle } from './styled';
const Filial = [
{ label: 'Toshkent shahar' },
{ label: 'Andijon viloyati' },
{ label: 'Samarqand viloyati' },
{ label: 'Toshkent viloyati' },
{ label: 'Xorazm viloyati' },
];
const Login = () => {
const { t } = useTranslation();
const passportNumberRef = useRef<TextInput>(null);
const [filialDropdownVisible, setFilialDropdownVisible] = useState(false);
const navigation = useNavigation<NativeStackNavigationProp<any>>();
const { setUser, setExpireTime } = useUserStore(state => state);
const [error, setError] = useState<string>();
const [rawPhone, setRawPhone] = useState('+998');
const { data: branchList } = useQuery({
queryKey: ['branchList'],
queryFn: branchApi.branchList,
});
// const [firebaseToken, setFirebseToken] = useState<{
// fcmToken: string;
// deviceId: string;
// deviceName: string;
// deviceType: string;
// } | null>();
// const app = getApp();
// const messaging = getMessaging(app);
// const getDeviceData = async () => {
// try {
// const fcmToken = await getToken(messaging);
// return {
// fcmToken,
// deviceId: await DeviceInfo.getUniqueId(),
// deviceName: await DeviceInfo.getDeviceName(),
// deviceType: await DeviceInfo.getDeviceType(),
// };
// } catch (e) {
// console.log('Xato:', e);
// return null;
// }
// };
// useEffect(() => {
// getDeviceData().then(data => {
// setFirebseToken(data);
// });
// }, []);
const { mutate, isPending } = useMutation({
mutationFn: (payload: loginPayload) => authApi.login(payload),
onSuccess: res => {
navigation.navigate('Login-Confirm');
setExpireTime(res.data.expireTime);
},
onError: err => {
setError('Xatolik yuz berdi');
console.dir(err);
},
});
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<LoginFormType>({
resolver: zodResolver(loginSchema),
defaultValues: {
phone: '',
passportSeriya: '',
passportNumber: '',
},
});
const onSubmit = (data: LoginFormType) => {
mutate({
branchId: data.branchId,
phoneNumber: data.phone,
passportSerial: `${data.passportSeriya.toUpperCase()}${
data.passportNumber
}`,
fcmToken: '',
deviceId: '',
deviceType: '',
deviceName: '',
});
// navigation.navigate('Login-Confirm');
setUser({
phoneNumber: data.phone,
});
};
const handleBackNavigation = useCallback(() => {
navigation.navigate('select-auth');
}, [navigation]);
const handlePhoneChange = useCallback((text: string) => {
const digits = text.replace(/\D/g, '');
const full = digits.startsWith('998') ? digits : `998${digits}`;
setRawPhone(`+${full}`);
setValue('phone', full, { shouldValidate: true });
}, []);
const keyboardBehavior = useMemo(
() => (Platform.OS === 'ios' ? 'padding' : 'height'),
[],
);
return (
<ImageBackground
source={Logo}
style={Loginstyle.background}
resizeMode="contain"
imageStyle={{
opacity: 0.1,
height: '100%',
width: '100%',
transform: [{ scale: 1 }],
}}
>
<SafeAreaView style={{ flex: 1 }}>
<View style={Loginstyle.langContainer}>
<TouchableOpacity onPress={handleBackNavigation}>
<ArrowLeft color={'#000'} />
</TouchableOpacity>
<LanguageSelector />
</View>
<KeyboardAvoidingView
style={Loginstyle.container}
behavior={keyboardBehavior}
>
<ScrollView style={{ flex: 1 }}>
<View style={Loginstyle.scrollContainer}>
<View style={Loginstyle.loginContainer}>
<AppText style={Loginstyle.title}>
{t('Tizimga kirish')}
</AppText>
<Controller
control={control}
name="phone"
render={({ field: { onChange } }) => {
const formatted = formatPhone(rawPhone);
return (
<View>
<AppText style={Loginstyle.label}>
{t('Telefon raqami')}
</AppText>
<TextInput
keyboardType="numeric"
placeholder="+998 90 123-45-67"
value={formatted}
onChangeText={handlePhoneChange}
style={Loginstyle.input}
placeholderTextColor="#D8DADC"
maxLength={19} // +998 90 123-45-67 bo'lishi uchun
/>
{errors.phone && (
<AppText style={Loginstyle.errorText}>
{t(errors.phone.message || '')}
</AppText>
)}
</View>
);
}}
/>
<View>
<AppText style={Loginstyle.label}>
{t('Passport seriya raqami')}
</AppText>
<View style={{ flexDirection: 'row' }}>
<Controller
control={control}
name="passportSeriya"
render={({ field: { onChange, value } }) => (
<TextInput
style={[Loginstyle.input, Loginstyle.seriyaInput]}
placeholder="AA"
maxLength={2}
autoCapitalize="characters"
value={value}
onChangeText={text => {
onChange(text);
if (text.length === 2) {
passportNumberRef.current?.focus();
}
}}
placeholderTextColor="#D8DADC"
/>
)}
/>
<Controller
control={control}
name="passportNumber"
render={({ field: { onChange, value } }) => (
<TextInput
ref={passportNumberRef}
style={[Loginstyle.input, Loginstyle.raqamInput]}
placeholder="1234567"
maxLength={7}
keyboardType="numeric"
value={value}
onChangeText={text => {
const onlyNumbers = text.replace(/[^0-9]/g, '');
onChange(onlyNumbers);
}}
placeholderTextColor="#D8DADC"
/>
)}
/>
</View>
{(errors.passportSeriya || errors.passportNumber) && (
<AppText style={Loginstyle.errorText}>
{t(errors.passportSeriya?.message || '') ||
t(errors.passportNumber?.message || '')}
</AppText>
)}
</View>
<Controller
control={control}
name="branchId"
render={({ field: { value } }) => (
<View style={{ position: 'relative' }}>
<AppText style={Loginstyle.label}>{t('Filial')}</AppText>
<View style={Loginstyle.input}>
<TouchableOpacity
style={Loginstyle.selector}
onPress={() =>
setFilialDropdownVisible(prev => !prev)
}
>
<AppText
style={
value
? { color: '#000' }
: Loginstyle.selectedText
}
>
{branchList?.find(e => e.id === value)?.name ||
t('Filialni tanlang...')}
</AppText>
{filialDropdownVisible ? (
<ArrowUp color={'#000'} />
) : (
<ArrowDown color={'#000'} />
)}
</TouchableOpacity>
</View>
{filialDropdownVisible && (
<View style={[Loginstyle.dropdown, { maxHeight: 200 }]}>
<ScrollView nestedScrollEnabled>
{branchList &&
branchList.map((item: Branch) => (
<TouchableOpacity
key={item.id}
style={Loginstyle.dropdownItem}
onPress={() => {
setValue('branchId', item.id);
setFilialDropdownVisible(false);
}}
>
<AppText style={Loginstyle.dropdownItemText}>
{item.name}
</AppText>
</TouchableOpacity>
))}
</ScrollView>
</View>
)}
{errors.branchId && (
<AppText style={Loginstyle.errorText}>
{t(errors.branchId.message || '')}
</AppText>
)}
{error && (
<AppText style={[Loginstyle.errorText]}>
{t(error)}
</AppText>
)}
</View>
)}
/>
<TouchableOpacity
onPress={handleSubmit(onSubmit)}
style={Loginstyle.button}
>
{isPending ? (
<ActivityIndicator color="#fff" />
) : (
<AppText style={Loginstyle.btnText}>
{t('Tizimga kirish')}
</AppText>
)}
</TouchableOpacity>
<View
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<AppText style={{ fontSize: 14, fontWeight: '500' }}>
{t('ID va kabinet yoqmi?')}
</AppText>
<TouchableOpacity
style={Loginstyle.dropdownItem}
onPress={() => navigation.navigate('Register')}
>
<AppText
style={{
color: '#28A7E8',
fontSize: 14,
fontWeight: '500',
}}
>
{t('Royxatdan otish')}
</AppText>
</TouchableOpacity>
</View>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
</SafeAreaView>
</ImageBackground>
);
};
export default Login;