mirror of
https://github.com/Stef-00012/Zipline-Android-App.git
synced 2025-05-11 10:25:59 +02:00
118 lines
No EOL
4.6 KiB
TypeScript
118 lines
No EOL
4.6 KiB
TypeScript
import { styles } from "@/styles/components/select";
|
|
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
|
|
import React, { useState } from "react";
|
|
import { Text, View, TouchableOpacity, FlatList, Modal } from "react-native";
|
|
import CheckBox from "./CheckBox";
|
|
|
|
export interface SelectProps {
|
|
data: Array<{
|
|
label: string;
|
|
value: string;
|
|
[key: string]: string | number | boolean | null;
|
|
}>;
|
|
placeholder: string;
|
|
onSelect: (selectedItem: SelectProps["data"][0], index: number) => void;
|
|
showScrollIndicator?: boolean;
|
|
disabled?: boolean;
|
|
defaultValue?: SelectProps["data"][0];
|
|
maxHeight?: number;
|
|
multiple?: boolean;
|
|
}
|
|
|
|
export default function Select({
|
|
data,
|
|
placeholder,
|
|
showScrollIndicator,
|
|
defaultValue,
|
|
onSelect,
|
|
disabled = false,
|
|
maxHeight = 200,
|
|
multiple = false
|
|
}: SelectProps) {
|
|
const [selectedItems, setSelectedItems] = useState<SelectProps["data"]>(multiple ? [] : defaultValue ? [defaultValue] : []);
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
const handleSelect = (item: SelectProps["data"][0], index: number) => {
|
|
if (multiple) {
|
|
setSelectedItems(prevItems => {
|
|
const isSelected = prevItems.some(selectedItem => selectedItem.value === item.value);
|
|
if (isSelected) {
|
|
return prevItems.filter(selectedItem => selectedItem.value !== item.value);
|
|
}
|
|
|
|
return [...prevItems, item];
|
|
});
|
|
} else {
|
|
setSelectedItems([item]);
|
|
setIsOpen(false);
|
|
}
|
|
onSelect(item, index);
|
|
};
|
|
|
|
return (
|
|
<View>
|
|
<TouchableOpacity
|
|
style={styles.selectButton}
|
|
onPress={() => setIsOpen(!isOpen)}
|
|
disabled={disabled}
|
|
>
|
|
<Text style={{
|
|
...styles.selectText,
|
|
...(selectedItems.length && styles.selectedText)
|
|
}}>
|
|
{selectedItems.length ? selectedItems.map(item => item.label).join(', ') : placeholder}
|
|
</Text>
|
|
<MaterialIcons
|
|
name={isOpen ? "keyboard-arrow-up" : "keyboard-arrow-down"}
|
|
size={32}
|
|
color={styles.selectText.color}
|
|
/>
|
|
</TouchableOpacity>
|
|
|
|
{isOpen && (
|
|
<Modal
|
|
transparent={true}
|
|
animationType="fade"
|
|
visible={isOpen}
|
|
onRequestClose={() => setIsOpen(false)}
|
|
>
|
|
<TouchableOpacity
|
|
style={{
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
}}
|
|
onPress={() => setIsOpen(false)}
|
|
>
|
|
<View style={{ ...styles.select, width: '90%', maxHeight: maxHeight, borderRadius: 10 }}>
|
|
<FlatList
|
|
data={data}
|
|
style={{borderRadius: 10}}
|
|
keyExtractor={(item, index) => index.toString()}
|
|
showsVerticalScrollIndicator={showScrollIndicator}
|
|
renderItem={({ item, index }) => (
|
|
<TouchableOpacity
|
|
style={{
|
|
...styles.menuItem,
|
|
...(selectedItems.some(selectedItem => selectedItem.value === item.value) && styles.menuItemSelected),
|
|
}}
|
|
onPress={() => handleSelect(item, index)}
|
|
>
|
|
{multiple && (
|
|
<CheckBox
|
|
value={selectedItems.some(selectedItem => selectedItem.value === item.value)}
|
|
onValueChange={() => handleSelect(item, index)}
|
|
/>
|
|
)}
|
|
<Text style={styles.menuItemText}>{item.label}</Text>
|
|
</TouchableOpacity>
|
|
)}
|
|
/>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
)}
|
|
</View>
|
|
);
|
|
} |