import { useTheme } from '@/components/ThemeContext'; import { products_api } from '@/screens/home/lib/api'; import BottomSheet, { BottomSheetBackdrop, BottomSheetFlatList, BottomSheetScrollView, } from '@gorhom/bottom-sheet'; import { useMutation, useQuery } from '@tanstack/react-query'; import { AxiosError } from 'axios'; import { Image } from 'expo-image'; import { CheckIcon, ChevronRight, XIcon } from 'lucide-react-native'; import React, { Dispatch, SetStateAction, useCallback, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ActivityIndicator, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import CategorySelect from './CategorySelect'; interface FilterUIProps { back: () => void; onApply?: (data: any) => void; setStep: (value: 'filter' | 'items') => void; setFiltered: Dispatch>; } interface Category { id: number; name: string; code: string; external_id: string | null; level: number; is_leaf: boolean; icon_name: string | null; } interface Country { id: number; name: string; region: Region[]; } interface Region { id: number; name: string; districts: District[]; } interface District { id: number; name: string; } type SheetType = 'country' | 'region' | 'district' | 'category' | null; export default function FilterUI({ back, onApply, setStep, setFiltered }: FilterUIProps) { const { isDark } = useTheme(); const { t } = useTranslation(); const bottomSheetRef = useRef(null); const snapPoints = useMemo(() => ['60%', '85%'], []); const [activeSheet, setActiveSheet] = useState(null); const [selectedCategories, setSelectedCategories] = useState(null); const [selectedCountry, setSelectedCountry] = useState('all'); const [selectedRegion, setSelectedRegion] = useState('all'); const [selectedDistrict, setSelectedDistrict] = useState('all'); const { data: countryResponse, isLoading } = useQuery({ queryKey: ['country-detail'], queryFn: async () => products_api.getStates(), select: (res) => res.data?.data || [], }); const { mutate, isPending } = useMutation({ mutationFn: (params: any) => products_api.businessAbout(params), onSuccess: (data) => { setStep('items'); setFiltered(data.data.data.results); }, onError: (error: AxiosError) => console.log(error), }); const handleApply = () => { const countryObj = countryResponse?.find((c) => c.id?.toString() === selectedCountry); const regionObj = countryObj?.region.find((r) => r.id?.toString() === selectedRegion); const districtObj = regionObj?.districts.find((d) => d.id?.toString() === selectedDistrict); mutate({ country: countryObj?.name || '', region: regionObj?.name || '', district: districtObj?.name || '', types: selectedCategories ? selectedCategories.id : undefined, }); }; const regions = useMemo(() => { if (selectedCountry === 'all') return []; const country = countryResponse?.find((c) => c.id?.toString() === selectedCountry); return country?.region || []; }, [countryResponse, selectedCountry]); const districts = useMemo(() => { if (selectedRegion === 'all') return []; const region = regions.find((r) => r.id?.toString() === selectedRegion); return region?.districts || []; }, [regions, selectedRegion]); const openSheet = useCallback((type: SheetType) => { setActiveSheet(type); setTimeout(() => { bottomSheetRef.current?.snapToIndex(0); }, 100); }, []); const closeSheet = useCallback(() => { bottomSheetRef.current?.close(); setTimeout(() => setActiveSheet(null), 300); }, []); const renderBackdrop = useCallback( (props: any) => ( ), [] ); const getSelectedLabel = useCallback( (type: SheetType) => { switch (type) { case 'country': if (selectedCountry === 'all') return t('Barchasi'); return ( countryResponse?.find((c) => c.id?.toString() === selectedCountry)?.name || t('Tanlang') ); case 'region': if (selectedRegion === 'all') return t('Barchasi'); return regions.find((r) => r.id?.toString() === selectedRegion)?.name || t('Tanlang'); case 'district': if (selectedDistrict === 'all') return t('Barchasi'); return districts.find((d) => d.id?.toString() === selectedDistrict)?.name || t('Tanlang'); case 'category': return selectedCategories?.name || t('Tanlang'); default: return t('Tanlang'); } }, [ selectedCountry, selectedRegion, selectedDistrict, selectedCategories, countryResponse, regions, districts, t, ] ); const FilterButton = useCallback( ({ label, value, onPress, disabled = false, }: { label: string; value: string; onPress: () => void; disabled?: boolean; }) => ( {label} {value} ), [isDark] ); const renderListItem = useCallback( ({ item, onSelect, selectedId, }: { item: any; onSelect: (id: string) => void; selectedId: string; }) => { const isSelected = selectedId === (item.id?.toString() || 'all'); const flagCode = item.flag ? item.flag.toLowerCase() : ''; // "uz" return ( onSelect(item.id?.toString() || 'all')} activeOpacity={0.7} > {item.flag && ( )} {item.name} {isSelected && ( )} ); }, [isDark] ); const renderSheetContent = useCallback(() => { if (activeSheet === 'category') { return ( ); } let data: any[] = []; let onSelect: (id: string) => void = () => { }; let selectedId = ''; switch (activeSheet) { case 'country': data = [{ id: 'all', name: t('Barchasi') }, ...(countryResponse || [])]; onSelect = (id) => { setSelectedCountry(id); setSelectedRegion('all'); setSelectedDistrict('all'); closeSheet(); }; selectedId = selectedCountry; break; case 'region': data = [{ id: 'all', name: t('Barchasi') }, ...regions]; onSelect = (id) => { setSelectedRegion(id); setSelectedDistrict('all'); closeSheet(); }; selectedId = selectedRegion; break; case 'district': data = [{ id: 'all', name: t('Barchasi') }, ...districts]; onSelect = (id) => { setSelectedDistrict(id); closeSheet(); }; selectedId = selectedDistrict; break; } return ( item.id?.toString() || 'all'} contentContainerStyle={styles.listContainer} showsVerticalScrollIndicator={false} bounces={true} overScrollMode="always" renderItem={({ item }: { item: any }) => renderListItem({ item, onSelect, selectedId })} /> ); }, [ activeSheet, selectedCategories, countryResponse, regions, districts, selectedCountry, selectedRegion, selectedDistrict, t, closeSheet, renderListItem, ]); const getSheetTitle = useCallback(() => { switch (activeSheet) { case 'country': return t('Davlat'); case 'region': return t('Viloyat'); case 'district': return t('Tuman'); case 'category': return t('Sohalar'); default: return ''; } }, [activeSheet, t]); if (isLoading) { return ( ); } return ( {/* Header */} {t('Filter')} {/* Filter Options */} openSheet('country')} /> openSheet('region')} disabled={selectedCountry === 'all' || regions.length === 0} /> openSheet('district')} disabled={selectedRegion === 'all' || districts.length === 0} /> openSheet('category')} /> {/* Apply Button */} {isPending ? ( ) : ( {t("Natijalarni ko'rish")} )} {/* Bottom Sheet */} setActiveSheet(null)} backdropComponent={renderBackdrop} backgroundStyle={[styles.bottomSheetBackground, isDark ? styles.darkBg : styles.lightBg]} handleIndicatorStyle={[ styles.handleIndicator, isDark ? styles.darkHandleIndicator : styles.lightHandleIndicator, ]} android_keyboardInputMode="adjustResize" keyboardBehavior="interactive" keyboardBlurBehavior="restore" > {getSheetTitle()} {renderSheetContent()} ); } const styles = StyleSheet.create({ container: { flex: 1, }, darkBg: { backgroundColor: '#0f172a', }, lightBg: { backgroundColor: '#f8fafc', }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, }, headerTitle: { fontSize: 20, fontWeight: '700', }, closeBtn: { padding: 8, borderRadius: 8, borderWidth: 1, }, darkCloseBtn: { backgroundColor: '#1e293b', borderColor: '#334155', }, lightCloseBtn: { backgroundColor: '#ffffff', borderColor: '#e2e8f0', }, content: { flex: 1, padding: 20, gap: 12, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, filterBtn: { padding: 16, borderRadius: 12, borderWidth: 1, shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.05, shadowRadius: 2, elevation: 1, }, darkFilterBtn: { backgroundColor: '#1e293b', borderColor: '#334155', }, lightFilterBtn: { backgroundColor: '#ffffff', borderColor: '#e2e8f0', }, disabledBtn: { opacity: 0.5, }, filterBtnContent: { flexDirection: 'column', gap: 8, // 4 o'rniga 8 qildim }, filterLabel: { fontSize: 13, fontWeight: '600', marginBottom: 2, // 4 o'rniga 2 qildim }, filterValueContainer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 8, // ChevronRight va text orasida gap }, filterValue: { fontSize: 15, fontWeight: '500', flex: 1, }, darkText: { color: '#f1f5f9', }, lightText: { color: '#0f172a', }, darkValueText: { color: '#cbd5e1', }, lightValueText: { color: '#64748b', }, disabledText: { opacity: 0.5, }, applyBtnWrapper: { padding: 20, borderTopWidth: 1, }, applyBtn: { backgroundColor: '#3b82f6', padding: 16, borderRadius: 12, alignItems: 'center', shadowColor: '#3b82f6', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.3, shadowRadius: 4, elevation: 5, }, applyBtnDisabled: { opacity: 0.7, }, applyBtnText: { color: '#ffffff', fontWeight: '700', fontSize: 16, }, bottomSheetBackground: { 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, }, darkHandleIndicator: { backgroundColor: '#475569', }, lightHandleIndicator: { backgroundColor: '#cbd5e1', }, sheetHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, }, sheetTitle: { fontSize: 18, fontWeight: '700', }, sheetCloseBtn: { padding: 4, }, listContainer: { padding: 16, paddingBottom: 40, }, scrollViewContent: { padding: 16, paddingBottom: 40, }, listItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 16, borderRadius: 12, marginBottom: 8, borderWidth: 1, }, darkListItem: { backgroundColor: '#1e293b', borderColor: '#334155', }, lightListItem: { backgroundColor: '#ffffff', borderColor: '#e2e8f0', }, selectedListItem: { backgroundColor: '#3b82f6', borderColor: '#3b82f6', }, listItemText: { fontSize: 15, fontWeight: '500', }, selectedListItemText: { color: '#ffffff', fontWeight: '600', }, checkmark: { width: 24, height: 24, borderRadius: 12, backgroundColor: '#ffffff', justifyContent: 'center', alignItems: 'center', }, checkmarkText: { color: '#3b82f6', fontSize: 16, fontWeight: '700', }, });