import AuthHeader from '@/components/ui/AuthHeader'; import { decryptToken } from '@/constants/crypto'; 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 { 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'; import { useResolveLocation } from './lib/useResolveLocation'; 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 [token, setTokens] = useState<{ name: string, value: string } | null>(null); const [directorTinInput, setDirectorTinInput] = useState(''); // ─── Token ─────────────────────────────────────────────────────────────────── 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]); // ─── Location resolver hook ─────────────────────────────────────────────────── const { location, resolve: resolveLocation, reset: resetLocation, } = useResolveLocation({ token: token?.value ?? null, tokenName: token?.name ?? null, }); console.log("location", location.district?.id); // ─── STIR info mutation ─────────────────────────────────────────────────────── 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); if (res.data?.address) { resolveLocation(res.data.address); } }, onError: () => { setInfo(null); setLoading(false); setError("Foydalanuvchi topilmadi"); resetLocation(); }, }); // ─── Country list ───────────────────────────────────────────────────────────── const { data: countryResponse, isLoading: countryLoading } = useQuery({ queryKey: ['country-detail'], queryFn: async () => products_api.getStates(), select: (res) => res.data?.data || [], }); // ─── Validation helpers ─────────────────────────────────────────────────────── 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 valid = phone.length === 9 && (stir.length === 9 || stir.length === 14) && info && hasValidName && isDirectorTinValid && error === null; // ─── Country sheet ──────────────────────────────────────────────────────────── 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); }, []); // ─── Render ─────────────────────────────────────────────────────────────────── return ( <> { Keyboard.dismiss(); return false; }} > {t("Ro'yxatdan o'tish")} {/* Country */} {t('Davlat')} {countryLoading ? ( ) : ( <> {selectedCountryName} )} {/* STIR */} {t('STIR')} { const v = normalizeDigits(text).slice(0, 14); setStir(v); if (v.length === 9 || v.length === 14) { setLoading(true); resetLocation(); mutate(v); } }} /> {loading && } {/* Referal */} {t('Referal')} {/* Phone */} {t('Telefon raqami')} setPhone(normalizeDigits(t))} /> {/* Director TIN */} {hasDirectorTin && ( {t('Direktor STIR')} setDirectorTinInput(normalizeDigits(t))} /> {directorTinInput.length === 14 && !isDirectorTinValid && ( {t("Direktor STIR noto'g'ri")} )} )} {/* Info / Error */} {error !== null ? ( {t(error)} ) : ( info && hasValidName && ( {info.fullName || info.name} ) )} {/* Submit */} { 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: location.district?.id, address: location.district?.id, director_full_name: stir.length === 9 ? info?.director : info?.fullName, stir, referal, person_type: stir.length === 9 ? 'legal_entity' : info?.selfEmployment ? 'band' : 'ytt', }, }); } }} > {t('Davom etish')} {/* Country BottomSheet */} {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, }, 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, }, inputDisabled: { backgroundColor: '#f1f5f9', borderColor: '#e2e8f0', }, textInput: { flex: 1, fontSize: 15, color: '#1e293b', }, 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', }, 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)', }, 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', }, });