// components/form/Select.tsx import React, { useState } from 'react'; import { View, TouchableOpacity, StyleSheet, Modal, ScrollView } from 'react-native'; import { Feather } from '@expo/vector-icons'; import { ThemedText } from '@/components/ThemedText'; import { useColorScheme } from '@/hooks/useColorScheme'; import { spacing } from '@/styles/sharedStyles'; export interface SelectOption { label: string; value: string; } interface SelectProps { label?: string; value: string | string[]; onValueChange: (value: string | string[]) => void; items: SelectOption[]; placeholder?: string; required?: boolean; multiple?: boolean; error?: string; } export function Select({ label, value, onValueChange, items, placeholder = 'Select...', required, multiple, error }: SelectProps) { const { colors } = useColorScheme(); const [isOpen, setIsOpen] = useState(false); const selectedLabels = React.useMemo(() => { if (multiple && Array.isArray(value)) { return value .map(v => items.find(item => item.value === v)?.label) .filter(Boolean) .join(', '); } return items.find(item => item.value === value)?.label; }, [value, items, multiple]); const handleSelect = (selectedValue: string) => { if (multiple) { const currentValue = Array.isArray(value) ? value : []; const newValue = currentValue.includes(selectedValue) ? currentValue.filter(v => v !== selectedValue) : [...currentValue, selectedValue]; onValueChange(newValue); } else { onValueChange(selectedValue); setIsOpen(false); } }; return ( {label && ( {label} {required && *} )} setIsOpen(true)} > {selectedLabels || placeholder} setIsOpen(false)} > setIsOpen(false)}> {label || 'Select'} {multiple && ( setIsOpen(false)}> Done )} {items.map((item) => { const isSelected = multiple ? Array.isArray(value) && value.includes(item.value) : value === item.value; return ( handleSelect(item.value)} > {item.label} {isSelected && ( )} ); })} {error && ( {error} )} ); } const styles = StyleSheet.create({ container: { gap: spacing.small, }, labelContainer: { flexDirection: 'row', }, label: { fontSize: 16, fontWeight: '500', }, select: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: spacing.medium, borderRadius: 8, borderWidth: 1, }, selectText: { fontSize: 16, }, errorText: { fontSize: 14, }, modalOverlay: { flex: 1, justifyContent: 'flex-end', }, modalContent: { maxHeight: '80%', borderTopLeftRadius: 20, borderTopRightRadius: 20, }, modalHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: spacing.medium, borderBottomWidth: 1, }, modalTitle: { fontSize: 18, fontWeight: '600', }, option: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: spacing.medium, borderBottomWidth: StyleSheet.hairlineWidth, }, optionText: { fontSize: 16, }, });