166 lines
8.1 KiB
TypeScript
166 lines
8.1 KiB
TypeScript
import { Machine } from '@/types/types';
|
|
import api from '@/utils/api';
|
|
import { ChevronDown, Search, X } from 'lucide-react-native';
|
|
import React, { useState, useEffect, useMemo } from 'react';
|
|
import { Modal, FlatList, Text, TextInput, TouchableOpacity, View, Keyboard, KeyboardEvent, Platform } from 'react-native';
|
|
|
|
interface MachineFilterProps {
|
|
selectedMachineId: any;
|
|
onMachineSelect: (machineId: any) => void;
|
|
textColor?: string;
|
|
}
|
|
|
|
export default function MachineFilter({ selectedMachineId, onMachineSelect, textColor }: MachineFilterProps) {
|
|
const [showPicker, setShowPicker] = useState(false);
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
const [machines, setMachines] = useState<Machine[]>([]);
|
|
|
|
useEffect(() => {
|
|
const fetchMachines = async () => {
|
|
try {
|
|
const res = await api.get('/machine-attendance/get-machines');
|
|
if (res.data?.success) {
|
|
setMachines(res.data.machines || []);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching machines:', err);
|
|
}
|
|
};
|
|
fetchMachines();
|
|
}, []);
|
|
|
|
// Keyboard height listener
|
|
useEffect(() => {
|
|
const showSubscription = Keyboard.addListener(
|
|
Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow',
|
|
(e: KeyboardEvent) => setKeyboardHeight(e.endCoordinates.height)
|
|
);
|
|
const hideSubscription = Keyboard.addListener(
|
|
Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide',
|
|
() => setKeyboardHeight(0)
|
|
);
|
|
|
|
return () => {
|
|
showSubscription.remove();
|
|
hideSubscription.remove();
|
|
};
|
|
}, []);
|
|
|
|
// Reset search query every time modal is opened
|
|
useEffect(() => {
|
|
if (showPicker) {
|
|
setSearchQuery('');
|
|
}
|
|
}, [showPicker]);
|
|
|
|
const filteredMachines = useMemo(() => {
|
|
if (!showPicker) return [];
|
|
if (!searchQuery.trim()) return machines;
|
|
const lowerQuery = searchQuery.toLowerCase();
|
|
return machines.filter(s => s.label.toLowerCase().includes(lowerQuery));
|
|
}, [machines, searchQuery, showPicker]);
|
|
|
|
const selectedMachineLabel = selectedMachineId
|
|
? machines.find(s => s.id === selectedMachineId)?.label || 'Macchina Selezionata'
|
|
: 'Tutte le macchine';
|
|
|
|
return (
|
|
<View className="mb-8">
|
|
<Text className={`text-lg font-bold ${textColor || 'text-gray-700'} mb-3`}>Macchina</Text>
|
|
<View className="flex-row items-center gap-3">
|
|
<TouchableOpacity
|
|
onPress={() => setShowPicker(true)}
|
|
className="flex-1 flex-row items-center justify-between bg-white px-5 py-4 rounded-2xl border border-gray-200 shadow-sm"
|
|
>
|
|
<Text className={`font-medium text-base flex-1 mr-2 ${selectedMachineId ? 'text-gray-800' : 'text-gray-500'}`} numberOfLines={1}>
|
|
{selectedMachineLabel}
|
|
</Text>
|
|
<ChevronDown size={20} color="#6b7280" pointerEvents="none" />
|
|
</TouchableOpacity>
|
|
|
|
{selectedMachineId !== null && (
|
|
<TouchableOpacity
|
|
onPress={() => onMachineSelect(null)}
|
|
className="bg-gray-50 p-4 rounded-2xl border border-gray-200 shadow-sm justify-center items-center"
|
|
>
|
|
<X size={22} color="#4b5563" pointerEvents="none" />
|
|
</TouchableOpacity>
|
|
)}
|
|
</View>
|
|
|
|
{/* Nested Place Picker Modal */}
|
|
<Modal visible={showPicker} transparent={true} animationType="fade" onRequestClose={() => setShowPicker(false)}>
|
|
<TouchableOpacity
|
|
activeOpacity={1}
|
|
onPress={() => setShowPicker(false)}
|
|
className="flex-1 bg-black/50 justify-end"
|
|
style={{ paddingBottom: keyboardHeight }}
|
|
>
|
|
<View className="bg-white rounded-t-3xl p-5 max-h-[70%]" onStartShouldSetResponder={() => true}>
|
|
<View className="flex-row justify-between items-center mb-4 border-b border-gray-100 pb-4">
|
|
<Text className="text-xl font-bold text-gray-800">Seleziona Macchina</Text>
|
|
<TouchableOpacity onPress={() => setShowPicker(false)} className="p-2 bg-gray-100 rounded-full active:bg-gray-200">
|
|
<X size={20} color="#4b5563" pointerEvents="none" />
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
{/* Search Bar */}
|
|
<View className="bg-gray-100 flex-row items-center px-4 py-3 rounded-2xl mb-4 border border-gray-200 focus:border-[#1071C2]">
|
|
<Search size={20} color="#9ca3af" />
|
|
<TextInput
|
|
className="flex-1 ml-3 text-base text-gray-800"
|
|
placeholder="Cerca macchina..."
|
|
value={searchQuery}
|
|
onChangeText={setSearchQuery}
|
|
placeholderTextColor="#9ca3af"
|
|
autoCorrect={false}
|
|
/>
|
|
{searchQuery.length > 0 && (
|
|
<TouchableOpacity onPress={() => setSearchQuery('')} className="p-1">
|
|
<X size={18} color="#6b7280" />
|
|
</TouchableOpacity>
|
|
)}
|
|
</View>
|
|
|
|
<FlatList
|
|
showsVerticalScrollIndicator={false}
|
|
contentContainerStyle={{ paddingBottom: 30 }}
|
|
keyboardShouldPersistTaps="handled"
|
|
data={filteredMachines}
|
|
keyExtractor={(item) => item.id.toString()}
|
|
ListHeaderComponent={() => (
|
|
searchQuery.trim() === '' ? (
|
|
<TouchableOpacity
|
|
className={`py-4 px-4 rounded-xl flex-row justify-between items-center mb-2 ${selectedMachineId === null ? 'bg-blue-50' : ''}`}
|
|
onPress={() => { onMachineSelect(null); setShowPicker(false); }}
|
|
>
|
|
<Text className={`text-lg ${selectedMachineId === null ? 'font-bold text-[#1071C2]' : 'text-gray-700'}`}>
|
|
Tutte le macchine
|
|
</Text>
|
|
</TouchableOpacity>
|
|
) : null
|
|
)}
|
|
ListEmptyComponent={() => (
|
|
<View className="py-8 items-center">
|
|
<Text className="text-gray-500 font-medium text-center">Nessuna macchina trovata per "{searchQuery}"</Text>
|
|
</View>
|
|
)}
|
|
renderItem={({ item }) => (
|
|
<TouchableOpacity
|
|
className={`py-4 px-4 rounded-xl flex-row justify-between items-center mb-2 ${selectedMachineId === item.id ? 'bg-blue-50' : ''}`}
|
|
onPress={() => { onMachineSelect(item.id); setShowPicker(false); }}
|
|
>
|
|
<Text className={`text-lg ${selectedMachineId === item.id ? 'font-bold text-[#1071C2]' : 'text-gray-700'}`}>
|
|
{item.label}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
)}
|
|
/>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
</View>
|
|
);
|
|
}
|