Files
info-target-mobile/screens/create-ads/ui/CategorySelectorBottomSheet.tsx
Samandar Turgunboyev d747c72c8d complated
2026-02-17 10:46:57 +05:00

152 lines
3.9 KiB
TypeScript

import { useTheme } from '@/components/ThemeContext';
import {
BottomSheetBackdrop,
BottomSheetBackdropProps,
BottomSheetModal,
BottomSheetScrollView,
} from '@gorhom/bottom-sheet';
import { Image } from 'expo-image';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
export type Option = {
label: string;
value: string;
flag?: string;
};
type CategorySelectorProps = {
isOpen: boolean;
onClose: () => void;
selectedValue: string;
onSelect: (value: string) => void;
data: Option[];
};
export default function CategorySelectorBottomSheet({
isOpen,
onClose,
selectedValue,
onSelect,
data = [],
}: CategorySelectorProps) {
const { isDark } = useTheme();
const { t } = useTranslation();
const theme = {
background: isDark ? '#1e293b' : '#ffffff',
text: isDark ? '#f8fafc' : '#0f172a',
border: isDark ? '#334155' : '#e2e8f0',
selectedBg: '#2563eb',
selectedText: '#ffffff',
indicator: isDark ? '#cbd5e1' : '#94a3b8',
};
const bottomSheetRef = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ['60%', '85%'], []);
const renderBackdrop = useCallback(
(props: BottomSheetBackdropProps) => (
<BottomSheetBackdrop {...props} disappearsOnIndex={-1} appearsOnIndex={0} opacity={0.5} />
),
[]
);
useEffect(() => {
if (isOpen) {
bottomSheetRef.current?.present();
} else {
bottomSheetRef.current?.dismiss();
}
}, [isOpen]);
return (
<BottomSheetModal
ref={bottomSheetRef}
index={0}
snapPoints={snapPoints}
backdropComponent={renderBackdrop}
enablePanDownToClose
onDismiss={onClose}
handleIndicatorStyle={{ backgroundColor: theme.indicator, width: 50 }}
backgroundStyle={{
backgroundColor: theme.background,
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
}}
>
<View style={[styles.header, { borderBottomColor: theme.border }]}>
<Text style={[styles.title, { color: theme.text }]}>{t('Tanlang')}</Text>
</View>
<BottomSheetScrollView style={styles.content} contentContainerStyle={styles.contentContainer}>
{data.map((item) => (
<TouchableOpacity
key={item.value}
style={[
styles.optionRow,
{ borderBottomColor: theme.border },
selectedValue === item.value && { backgroundColor: theme.selectedBg },
]}
onPress={() => {
onSelect(item.value);
onClose();
}}
>
{item.flag ? (
<Image
source={{ uri: `https://flagcdn.com/24x18/${item.flag.toLowerCase()}.png` }}
style={{ width: 24, height: 18, borderRadius: 2 }}
/>
) : null}
<Text
style={[
styles.optionText,
{ color: selectedValue === item.value ? theme.selectedText : theme.text },
selectedValue === item.value && styles.optionTextSelected,
]}
>
{item.label}
</Text>
</TouchableOpacity>
))}
</BottomSheetScrollView>
</BottomSheetModal>
);
}
const styles = StyleSheet.create({
header: {
paddingVertical: 16,
paddingHorizontal: 20,
borderBottomWidth: 1,
alignItems: 'center',
},
title: {
fontSize: 18,
fontWeight: '700',
},
content: {
flex: 1,
},
contentContainer: {
paddingHorizontal: 8,
paddingBottom: 40,
},
optionRow: {
paddingVertical: 16,
paddingHorizontal: 20,
borderBottomWidth: 1,
flexDirection: 'row',
alignContent: 'center',
alignItems: 'center',
gap: 10,
},
optionText: {
fontSize: 16,
},
optionTextSelected: {
fontWeight: '600',
},
});