import AuthHeader from '@/components/ui/AuthHeader'; import { decryptToken } from '@/constants/crypto'; import { formatPhone, normalizeDigits } from '@/constants/formatPhone'; import { formatText, formatTextToLatin } from '@/constants/formatText'; 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 { Image } from 'expo-image'; import { LinearGradient } from 'expo-linear-gradient'; import { useRouter } from 'expo-router'; import { CheckIcon, ChevronDown, Globe, Hash, Search, UserPlus } from 'lucide-react-native'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ActivityIndicator, Keyboard, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import { SafeAreaView } from 'react-native-safe-area-context'; import { auth_api, GetInfo } from '../login/lib/api'; import PhonePrefix from '../login/ui/PhonePrefix'; import { UseLoginForm } from '../login/ui/UseLoginForm'; interface CoordsData { lat: number; lon: number; polygon: [number, number][][]; } export default function RegisterFormScreen() { const router = useRouter(); const { t } = useTranslation(); const { phone, setPhone } = UseLoginForm(); const countrySheetRef = useRef(null); const snapPoints = useMemo(() => ['60%', '90%'], []); const [selectedCountry, setSelectedCountry] = useState('UZ'); const [countrySearch, setCountrySearch] = useState(''); const [stir, setStir] = useState(''); const [info, setInfo] = useState(null); const [loading, setLoading] = useState(false); const [referal, setReferal] = useState(''); const [error, setError] = useState(null) const [district, setDistrict] = useState(null) const [region, setRegion] = useState(null) const [token, setTokens] = useState<{ name: string, value: string } | null>(null) const [directorTinInput, setDirectorTinInput] = useState(''); const { data } = useQuery({ queryKey: ["tokens"], queryFn: async () => auth_api.get_tokens(), select(data) { return data.data.data.results }, }) useEffect(() => { if (data?.length) { const token = data[0] const tokenValue = decryptToken(token.value) if (tokenValue) { setTokens({ name: token.key, value: tokenValue }) } } }, [data]) const { mutate } = useMutation({ mutationFn: (stir: string) => auth_api.get_info({ value: stir, token: token?.value || "", tokenName: token?.name || "" }), onSuccess: (res) => { setInfo(res.data); setLoading(false); setError(null) setDistrict(res.data.address) }, onError: () => { setInfo(null); setLoading(false); setError("Foydalanuvchi topilmadi") }, }); const { data: districts } = useQuery({ queryKey: ["discrit"], queryFn: async () => auth_api.get_district({ token: token?.value || "", tokenName: token?.name || "" }), enabled: !!token, }) const { data: regions } = useQuery({ queryKey: ["regions"], queryFn: async () => auth_api.get_region({ token: token?.value || "", tokenName: token?.name || "" }), enabled: !!token, }) const { data: countryResponse, isLoading: countryLoading } = useQuery({ queryKey: ['country-detail'], queryFn: async () => products_api.getStates(), select: (res) => res.data?.data || [], }); const getRegionDistrictFromAddress = async (address: string) => { try { const encoded = encodeURIComponent(address + ", Uzbekistan"); const res = await fetch( `https://nominatim.openstreetmap.org/search?q=${encoded}&format=json&addressdetails=1&limit=1`, { headers: { 'Accept-Language': 'uz', 'User-Agent': 'MyApp/1.0 (turgunboyevsamandar4@gamil.com)' } } ); const data = await res.json(); if (data.length > 0) { const addr = data[0].address; return { district: addr.county || addr.district || addr.suburb, region: addr.state, }; } } catch (e) { } return null; }; useEffect(() => { if (district) { const dis = formatText(district)?.split(" ")[0].toLocaleUpperCase() let reg = null if (dis) { reg = districts?.data.find((item) => item.name.includes(dis)) }; if (reg) { const region = regions?.data.find((item) => item.regionId == reg.regionId) setRegion(region?.name || "") } } }, [district]) const [districtId, setDistrictId] = useState(null); const [regionId, setRegionId] = useState(null); useEffect(() => { if (!district || !countryResponse?.length) return; const resolve = async () => { const geo = await getRegionDistrictFromAddress(district.split(" ")[0]); const searchRegion = geo?.region || region; const searchDistrict = geo?.district || district for (const country of countryResponse) { const regionName = formatTextToLatin(searchRegion)?.split(" ")[0]; let foundRegion = null if (regionName) { foundRegion = country.region.find((r: any) => formatTextToLatin(r.name)?.includes(regionName) ); } if (foundRegion) { setRegionId(foundRegion.id); setDistrictId(null); return; } for (const reg of country.region || []) { const dis = formatTextToLatin(searchDistrict)?.split(" ")[0].toUpperCase(); let foundDistrict = null if (dis) { foundDistrict = reg.districts.find((d: any) => { return formatTextToLatin(d.name)?.toUpperCase().includes(dis.slice(0, 4)) } ); }; if (foundDistrict) { setDistrictId(foundDistrict.id); setRegionId(null); return; } } } }; resolve(); }, [district, countryResponse]); useEffect(() => { if (info === null || (stir.length === 9 && info.name && info.fullName)) { setError(null) } else if (info?.name === null || info?.fullName === null) { setError("Sizning shaxsiy ma'lumotlaringiz topilmadi") } else if (!info?.selfEmployment && !info?.isItd) { setError("Siz o'zini o'zi band qilgan yoki yakka tartibdagi tadbirkorlik bo'lishingiz kerak") } }, [info]) const hasDirectorTin = info?.directorPinfl && String(info.directorPinfl).length > 0; const isDirectorTinValid = !hasDirectorTin || directorTinInput === String(info.directorPinfl); const hasValidName = Boolean(info?.name || info?.fullName); 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 openCountrySheet = useCallback(() => { Keyboard.dismiss(); setTimeout(() => { countrySheetRef.current?.snapToIndex(0); }, 100); }, []); const selectedCountryName = useMemo(() => { if (!selectedCountry) return t('Tanlang'); return ( countryResponse?.find((c: any) => c.flag?.toUpperCase() === selectedCountry)?.name || t('Tanlang') ); }, [selectedCountry, countryResponse, t]); const renderBackdrop = useCallback( (props: any) => ( ), [] ); const closeCountrySheet = useCallback(() => { countrySheetRef.current?.close(); setTimeout(() => setCountrySearch(''), 300); }, []); const valid = phone.length === 9 && (stir.length === 9 || stir.length === 14) && info && hasValidName && isDirectorTinValid && error === null; return ( <> { Keyboard.dismiss(); return false; }} > {t('Ro\'yxatdan o\'tish')} {t('Davlat')} {countryLoading ? ( ) : ( <> {selectedCountryName} )} {t('STIR')} { const v = normalizeDigits(text).slice(0, 14); setStir(v); if (v.length === 9 || v.length === 14) { setLoading(true); mutate(v); setRegionId(null) setDistrictId(null) setRegion(null) setDistrict(null) } }} /> {loading && } {t('Referal')} {t('Telefon raqami')} setPhone(normalizeDigits(t))} /> {hasDirectorTin && ( {t('Direktor STIR')} setDirectorTinInput(normalizeDigits(t))} /> {directorTinInput.length === 14 && !isDirectorTinValid && ( {t('Direktor STIR noto‘g‘ri')} )} )} {error !== null ? {t(error)} : info && hasValidName && {info.fullName || info.name} } { if (error === null) { router.push({ pathname: '/(auth)/select-category', params: { phone, first_name: stir.length === 9 ? info?.director : info?.fullName, last_name: stir.length === 9 ? info?.director : info?.fullName, company_name: info?.name, district: districtId !== null ? districtId : regionId, address: districtId !== null ? districtId : regionId, director_full_name: stir.length === 9 ? info?.director : info?.fullName, stir, referal, person_type: stir.length === 9 ? 'legal_entity' : info?.selfEmployment ? 'band' : info?.isItd ? 'ytt' : 'ytt', }, }) } }} > {t('Davom etish')} {t('Davlat')} 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({ keyboardScroll: { flex: 1, backgroundColor: '#0f172a', }, container: { flex: 1, backgroundColor: '#0f172a', minHeight: '100%', }, 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, marginTop: 10, 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, }, 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', borderColor: '#e2e8f0', }, info: { padding: 12, borderRadius: 12, fontWeight: '700', backgroundColor: '#f0fdf4', }, error: { color: '#dc2626', fontSize: 12, marginTop: 4, fontWeight: '600', }, notFound: { backgroundColor: '#fef2f2', padding: 12, borderRadius: 12, fontWeight: '700', color: '#dc2626', borderWidth: 1, borderColor: '#fecaca', }, });