import AuthHeader from '@/components/ui/AuthHeader'; import { formatPhone, normalizeDigits } from '@/constants/formatPhone'; import { products_api } from '@/screens/home/lib/api'; import BottomSheet, { BottomSheetBackdrop, BottomSheetFlatList, BottomSheetTextInput, } from '@gorhom/bottom-sheet'; import { useMutation, useQuery } from '@tanstack/react-query'; import { AxiosError } from 'axios'; import { Image } from 'expo-image'; import { LinearGradient } from 'expo-linear-gradient'; import { useRouter } from 'expo-router'; import { Building2, CheckIcon, Globe, Hash, Search, ShieldCheck, User, UserPlus, } from 'lucide-react-native'; import React, { useCallback, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ActivityIndicator, KeyboardAvoidingView, Platform, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { auth_api } from '../login/lib/api'; import PhonePrefix from '../login/ui/PhonePrefix'; import { useRegister } from './lib/useRegisterStore'; function getHeaderInfo(personType: string | null) { switch (personType) { case 'yatt': return { label: 'YATT', icon: , gradient: ['#10b981', '#059669'] as [string, string], }; case 'band': return { label: "O'zini o'zi band qilgan", icon: , gradient: ['#3b82f6', '#2563eb'] as [string, string], }; case 'legal_entity': return { label: 'Yuridik shaxs', icon: , gradient: ['#f59e0b', '#d97706'] as [string, string], }; default: return { label: "Ro'yxatdan o'tish", icon: , gradient: ['#10b981', '#059669'] as [string, string], }; } } export default function RegisterFormScreen() { const router = useRouter(); const { personType, phone, setPhone, referal, setReferal, jshshr, setJshshr, passportSeries, setPassportSeries, passportNumber, setPassportNumber, inn, setInn, info, setInfo, directorInfo, setDirectorInfo, } = useRegister(); const { t } = useTranslation(); const [loading, setLoading] = React.useState(false); const [directorJshshr, setDirectorJshshr] = React.useState(''); const [directorLoading, setDirectorLoading] = React.useState(false); const [directorInfoError, setErrorDirectorInfo] = useState(null); // Country select const [selectedCountry, setSelectedCountry] = useState('UZ'); const [countrySearch, setCountrySearch] = useState(''); const countrySheetRef = useRef(null); const snapPoints = useMemo(() => ['60%', '90%'], []); const { data: countryResponse, isLoading: countryLoading } = useQuery({ queryKey: ['country-detail'], queryFn: async () => products_api.getStates(), select: (res) => res.data?.data || [], }); const openCountrySheet = useCallback(() => { setTimeout(() => { countrySheetRef.current?.snapToIndex(0); }, 100); }, []); const closeCountrySheet = useCallback(() => { countrySheetRef.current?.close(); setTimeout(() => setCountrySearch(''), 300); }, []); const renderBackdrop = useCallback( (props: any) => ( ), [] ); const selectedCountryName = useMemo(() => { if (!selectedCountry) return t('Tanlang'); return ( countryResponse?.find((c: any) => c.flag?.toUpperCase() === selectedCountry)?.name || t('Tanlang') ); }, [selectedCountry, countryResponse, t]); const filteredCountries = useMemo(() => { if (!countrySearch.trim()) return countryResponse || []; const q = countrySearch.toLowerCase().trim(); return (countryResponse || []).filter((c: any) => c.name?.toLowerCase().includes(q)); }, [countryResponse, countrySearch]); const headerInfo = getHeaderInfo(personType); const isYattOrBand = personType === 'yatt' || personType === 'band'; const isLegal = personType === 'legal_entity'; const { mutate: fetchInfo } = useMutation({ mutationFn: (body: { value: string; type: string; passport_series?: string; passport_number?: string; }) => auth_api.get_info(body), onSuccess: (res) => { setInfo(res.data.data); setLoading(false); // INN o'zgarganda director ma'lumotlarini tozalash setDirectorJshshr(''); setDirectorInfo(null); setErrorDirectorInfo(null); }, onError: () => { setInfo(null); setLoading(false); setDirectorJshshr(''); setDirectorInfo(null); setErrorDirectorInfo(null); }, }); const { mutate: fetchDirectorInfo } = useMutation({ mutationFn: (body: { value: string }) => auth_api.get_director_info(body), onSuccess: (res) => { const directorData = res.data; // ------------------------------------------------------- // INN TEKSHIRUVI // Director response strukturasi: // data.entity.name.rows = [{ inn: "123456789", ... }, ...] // Shu rows ichida joriy inn bor-yo'qligini tekshiramiz // ------------------------------------------------------- const rows: Array<{ inn: string }> = directorData?.data?.entity?.name?.rows ?? []; const innMatch = rows.some((row) => row.inn === inn); if (!innMatch) { // Director bu tashkilotga tegishli emas setDirectorInfo(null); setErrorDirectorInfo(t("Bu direktor ko'rsatilgan tashkilotga tegishli emas")); setDirectorLoading(false); return; } // INN mos keldi — director ma'lumotini saqlash setDirectorInfo(directorData); setDirectorLoading(false); setErrorDirectorInfo(null); }, onError: (error: AxiosError) => { const err = error.response?.data as { status: boolean; data: { detail: string; error: { message: string }; status_code: number; }; }; setDirectorInfo(null); setErrorDirectorInfo(err?.data?.detail ?? t('Xatolik yuz berdi')); setDirectorLoading(false); }, }); const handleJshshrChange = useCallback( (text: string) => { const v = normalizeDigits(text).slice(0, 14); setJshshr(v); if (v.length === 14) { setLoading(true); if (personType) { fetchInfo({ value: v, type: personType }); } } }, [setJshshr, fetchInfo, personType] ); const handleInnChange = useCallback( (text: string) => { const v = normalizeDigits(text).slice(0, 9); setInn(v); if (v.length === 9) { setLoading(true); if (personType) { fetchInfo({ value: v, type: personType }); } } }, [setInn, fetchInfo, personType] ); const handlePassportSeriesChange = useCallback( (text: string) => { const v = text .toUpperCase() .replace(/[^A-Z]/g, '') .slice(0, 2); setPassportSeries(v); if (personType && passportNumber.length === 7 && jshshr.length === 14) { setLoading(true); fetchInfo({ type: personType, passport_number: passportNumber, passport_series: v, value: jshshr, }); } }, [setPassportSeries, passportNumber, jshshr, personType, fetchInfo] ); const handlePassportNumberChange = useCallback( (text: string) => { const v = normalizeDigits(text).slice(0, 7); setPassportNumber(v); if (personType && passportSeries.length === 2 && jshshr.length === 14) { setLoading(true); fetchInfo({ type: personType, passport_number: v, passport_series: passportSeries, value: jshshr, }); } }, [setPassportNumber, passportSeries, jshshr, personType, fetchInfo] ); const handleDirectorJshshrChange = useCallback( (text: string) => { const v = normalizeDigits(text).slice(0, 14); setDirectorJshshr(v); setDirectorInfo(null); setErrorDirectorInfo(null); if (v.length === 14) { setDirectorLoading(true); fetchDirectorInfo({ value: v }); } }, [fetchDirectorInfo] ); const hasValidName = Boolean(info?.name || info?.fullName); const hasValidInfo = Boolean(info?.lastname || info?.firstname || info?.middlename); const isValid = (() => { const phoneValid = phone.length === 9; const referalValid = referal.length > 0; const countryValid = Boolean(selectedCountry && selectedCountry !== 'all'); if (isYattOrBand) { return ( phoneValid && referalValid && countryValid && jshshr.length === 14 && passportSeries.length === 2 && passportNumber.length === 7 && info ); } if (isLegal) { return ( phoneValid && referalValid && countryValid && inn.length === 9 && info && directorJshshr.length === 14 && directorInfo // faqat INN mos kelganda to'ldiriladi ); } return false; })(); const handleContinue = () => { // Director to'liq ismi directorInfo dan olinadi const directorFullName = isLegal ? (directorInfo?.data?.entrepreneur?.rows[0]?.entrepreneur ?? '') : `${info?.firstname ?? ''} ${info?.lastname ?? ''} ${info?.middlename ?? ''}`.trim(); const countryObj = countryResponse?.find((c: any) => c.flag?.toUpperCase() === selectedCountry); router.push({ pathname: '/(auth)/select-category', params: { phone, stir: isLegal ? inn : jshshr, person_type: personType ?? '', passport_series: passportSeries, passport_number: passportNumber, director_full_name: directorFullName, referal: referal, first_name: info?.firstname ?? '', last_name: info?.lastname ?? '', middle_name: info?.middlename ?? '', country: countryObj?.name ?? '', country_id: selectedCountry, }, }); }; return ( {headerInfo.icon} {t(headerInfo.label)} {isYattOrBand ? t("JSHSHR va passport ma'lumotlarini kiriting") : t('INN raqamini kiriting')} {/* ---- Davlat (Country) ---- */} {/* {t('Davlat')} {countryLoading ? ( ) : ( <> {selectedCountryName} )} */} {/* ---- YATT / BAND ---- */} {isYattOrBand && ( <> {t('JSHSHR')} {loading && jshshr.length >= 14 && ( )} {t('Passport seriya va raqami')} )} {/* ---- LEGAL ENTITY: INN ---- */} {isLegal && ( {t('INN')} {loading && inn.length >= 9 && ( )} )} {/* ---- LEGAL ENTITY: Kompaniya ma'lumoti ---- */} {isLegal && info && (hasValidName ? ( {t('Tashkilot')} {info.fullName || info.name} ) : hasValidInfo ? ( {t('Tashkilot')} {info.firstname} {info.lastname} {info.middlename} ) : ( {t('Tashkilot topilmadi')} ))} {/* ---- LEGAL ENTITY: Direktor JSHSHR — faqat info kelganda ko'rinadi ---- */} {isLegal && info && ( {t('Direktor JSHSHR')} {directorLoading && directorJshshr.length >= 14 && ( )} {/* ---- Direktor ma'lumoti (INN mos kelgan holda) ---- */} {directorInfo && ( {t('Direktor')} {directorInfo?.data?.entrepreneur?.rows[0]?.entrepreneur} )} {/* ---- Xato: INN mos kelmasa yoki server xatosi ---- */} {directorInfoError && ( {directorInfoError} )} )} {/* ---- Referal ---- */} {t('Referal')} {/* ---- Telefon ---- */} {t('Telefon raqami')} setPhone(normalizeDigits(t).slice(0, 9))} testID="phone-input" /> {/* ---- YATT/BAND info ---- */} {!isLegal && info && (hasValidName ? ( {info.fullName || info.name} ) : hasValidInfo ? ( {info.firstname} {info.lastname} {info.middlename} ) : ( {t('Foydalanuvchi topilmadi')} ))} {/* ---- Davom etish tugmasi ---- */} {t('Davom etish')} {/* ---- Country BottomSheet ---- */} {t('Davlat')} {/* Search input */} item.id?.toString()} contentContainerStyle={styles.listContainer} showsVerticalScrollIndicator={false} keyboardShouldPersistTaps="handled" ListEmptyComponent={ {t('Natija topilmadi')} } renderItem={({ item }: { item: any }) => { const isSelected = item.flag?.toUpperCase() === selectedCountry; const flagCode = item.flag ? item.flag.toLowerCase() : ''; return ( { setSelectedCountry(item.flag?.toUpperCase()); closeCountrySheet(); }} activeOpacity={0.7} > {flagCode ? ( ) : ( )} {item.name} {isSelected && ( )} ); }} /> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0f172a', }, scrollContent: { flexGrow: 1, paddingHorizontal: 24, paddingBottom: 40, paddingTop: 10, }, header: { alignItems: 'center', marginBottom: 28, }, iconContainer: { marginBottom: 16, }, iconGradient: { width: 72, height: 72, borderRadius: 22, alignItems: 'center', justifyContent: 'center', shadowColor: '#10b981', shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.3, shadowRadius: 12, elevation: 8, }, title: { fontSize: 26, fontWeight: '800' as const, color: '#ffffff', marginBottom: 8, letterSpacing: 0.5, }, subtitle: { fontSize: 14, color: '#94a3b8', textAlign: 'center', lineHeight: 20, paddingHorizontal: 10, }, card: { backgroundColor: '#ffffff', borderRadius: 28, padding: 24, shadowColor: '#000', shadowOffset: { width: 0, height: 10 }, shadowOpacity: 0.3, shadowRadius: 20, elevation: 10, }, formGap: { gap: 16, }, label: { fontWeight: '700' as const, color: '#475569', marginBottom: 6, fontSize: 14, }, input: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#f8fafc', borderRadius: 14, paddingHorizontal: 12, height: 52, borderWidth: 1, borderColor: '#e2e8f0', gap: 8, }, bottomSheetBg: { backgroundColor: '#ffffff', borderTopLeftRadius: 24, borderTopRightRadius: 24, shadowColor: '#000', shadowOffset: { width: 0, height: -2 }, shadowOpacity: 0.1, shadowRadius: 8, elevation: 5, }, handleIndicator: { width: 40, height: 4, borderRadius: 2, backgroundColor: '#cbd5e1', }, sheetHeader: { paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, borderBottomColor: '#e2e8f0', }, sheetTitle: { fontSize: 18, fontWeight: '700', color: '#0f172a', }, listContainer: { padding: 16, paddingBottom: 40, }, listItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 14, borderRadius: 12, marginBottom: 8, borderWidth: 1, backgroundColor: '#ffffff', borderColor: '#e2e8f0', }, selectedListItem: { backgroundColor: '#eff6ff', borderColor: '#3b82f6', }, listItemText: { fontSize: 15, fontWeight: '500', color: '#1e293b', }, selectedListItemText: { color: '#2563eb', fontWeight: '600', }, checkmark: { width: 24, height: 24, borderRadius: 12, backgroundColor: '#dbeafe', justifyContent: 'center', alignItems: 'center', }, searchContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#f1f5f9', borderRadius: 12, marginHorizontal: 16, marginVertical: 12, paddingHorizontal: 12, gap: 8, height: 44, borderWidth: 1, borderColor: '#e2e8f0', }, searchInput: { flex: 1, fontSize: 15, color: '#1e293b', paddingVertical: 0, }, emptyList: { alignItems: 'center', paddingVertical: 32, }, emptyListText: { fontSize: 14, color: '#94a3b8', fontWeight: '500', }, textInput: { flex: 1, fontSize: 15, color: '#1e293b', }, passportRow: { flexDirection: 'row', gap: 10, }, passportSeries: { width: 100, flex: undefined, }, passportNumber: { flex: 1, }, infoBox: { backgroundColor: '#f0fdf4', padding: 14, borderRadius: 14, borderWidth: 1, borderColor: '#bbf7d0', }, infoLabel: { fontSize: 11, fontWeight: '600' as const, color: '#059669', marginBottom: 2, textTransform: 'uppercase', letterSpacing: 0.5, }, infoText: { fontWeight: '700' as const, color: '#166534', fontSize: 14, }, errorBox: { backgroundColor: '#fef2f2', padding: 14, borderRadius: 14, borderWidth: 1, borderColor: '#fecaca', }, errorText: { fontWeight: '700' as const, color: '#dc2626', fontSize: 14, }, btn: { height: 54, backgroundColor: '#2563eb', borderRadius: 16, alignItems: 'center', justifyContent: 'center', shadowColor: '#2563eb', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 6, }, disabled: { opacity: 0.45, }, btnText: { color: '#fff', fontWeight: '800' as const, fontSize: 16, }, footer: { marginTop: 20, alignItems: 'center', }, footerText: { color: '#94a3b8', fontSize: 14, fontWeight: '600' as const, }, decorCircle1: { position: 'absolute', top: -150, right: -100, width: 400, height: 400, borderRadius: 200, backgroundColor: 'rgba(59, 130, 246, 0.1)', }, decorCircle2: { position: 'absolute', bottom: -100, left: -150, width: 350, height: 350, borderRadius: 175, backgroundColor: 'rgba(16, 185, 129, 0.08)', }, inputDisabled: { backgroundColor: '#f1f5f9', // disabled bo'lganda fon rangi borderColor: '#e2e8f0', // disabled bo'lganda border rangi }, });