134 lines
3.8 KiB
TypeScript

import React, { useState } from 'react';
import {
View,
Text,
TouchableOpacity,
Modal,
FlatList,
TextInput,
SafeAreaView,
Platform,
StatusBar,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { useTheme } from '@theme';
import { getStyles } from './formPicker.styles';
import { FormPickerProps, FormPickerOption } from './formPicker.props';
export const FormPicker: React.FC<FormPickerProps> = ({
label,
value,
onValueChange,
options,
required = false,
placeholder = 'Select...',
searchable = false,
}) => {
const { theme: colors } = useTheme();
const styles = getStyles(colors);
const [modalVisible, setModalVisible] = useState(false);
const [query, setQuery] = useState('');
const selectedOption = options.find(opt => opt.value === value);
const filtered = searchable
? options.filter(opt =>
opt.label.toLowerCase().includes(query.toLowerCase()),
)
: options;
const handleSelect = (opt: FormPickerOption) => {
onValueChange(opt.value);
setModalVisible(false);
setQuery('');
};
return (
<View style={styles.container}>
<Text style={styles.label}>
{label}
{required && <Text style={styles.required}> *</Text>}
</Text>
<TouchableOpacity
style={styles.pickerContainer}
activeOpacity={0.7}
onPress={() => setModalVisible(true)}>
<Text
style={[styles.pickerText, !selectedOption && styles.placeholder]}>
{selectedOption?.label || placeholder}
</Text>
<Icon name="chevron-down" size={18} color={colors.textSecondary} />
</TouchableOpacity>
<Modal
visible={modalVisible}
animationType="slide"
transparent
onRequestClose={() => setModalVisible(false)}>
<TouchableOpacity
style={styles.backdrop}
activeOpacity={1}
onPress={() => setModalVisible(false)}
/>
<SafeAreaView style={styles.sheet}>
{/* Header */}
<View style={styles.sheetHeader}>
<Text style={styles.sheetTitle}>{label}</Text>
<TouchableOpacity onPress={() => setModalVisible(false)}>
<Icon name="close" size={22} color={colors.text} />
</TouchableOpacity>
</View>
{/* Search */}
{searchable && (
<View style={styles.searchWrapper}>
<Icon
name="search-outline"
size={16}
color={colors.textSecondary}
style={styles.searchIcon}
/>
<TextInput
style={styles.searchInput}
placeholder="Search..."
placeholderTextColor={colors.textMuted}
value={query}
onChangeText={setQuery}
autoFocus
/>
</View>
)}
{/* Options */}
<FlatList
data={filtered}
keyExtractor={item => item.value}
ItemSeparatorComponent={() => <View style={styles.separator} />}
renderItem={({ item }) => {
const isSelected = item.value === value;
return (
<TouchableOpacity
style={styles.optionRow}
activeOpacity={0.6}
onPress={() => handleSelect(item)}>
<Text
style={[
styles.optionText,
isSelected && styles.optionTextSelected,
]}>
{item.label}
</Text>
{isSelected && (
<Icon name="checkmark" size={18} color={colors.icon} />
)}
</TouchableOpacity>
);
}}
/>
</SafeAreaView>
</Modal>
</View>
);
};