import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, ScrollView, TouchableOpacity, RefreshControl } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useRouter } from 'expo-router'; import { StatusBar } from 'expo-status-bar'; import { Filter, ReceiptText } from 'lucide-react-native'; import api from '@/utils/api'; import { useAlert } from '@/components/AlertComponent'; import LoadingScreen from '@/components/LoadingScreen'; import FilterModal from '@/components/FilterModal'; import InvoiceCard from '@/components/InvoiceCard'; import { InvoiceItem, Place } from '@/types/types'; export default function InvoiceScreen() { const router = useRouter(); const alert = useAlert(); const [invoices, setInvoices] = useState([]); const [isLoading, setIsLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); // Filters state const [showFilterModal, setShowFilterModal] = useState(false); const [places, setPlaces] = useState([]); const [filterRange, setFilterRange] = useState<{ startDate: string | null; endDate: string | null }>({ startDate: null, endDate: null }); const [filterPlace, setFilterPlace] = useState(null); const [filterSupplier, setFilterSupplier] = useState(null); const activeFiltersCount = (filterRange.startDate ? 1 : 0) + (filterPlace ? 1 : 0) + (filterSupplier ? 1 : 0); const fetchPlaces = async () => { try { const response = await api.get('/place/get-places'); if (response.data?.success) { setPlaces(response.data.places || []); } } catch (error) { console.error('Errore nel recupero dei cantieri:', error); } }; const fetchInvoices = async (currentRange = filterRange, currentPlace = filterPlace, currentSupplier = filterSupplier) => { try { if (!refreshing) setIsLoading(true); const rangeParam = currentRange.startDate ? currentRange : null; const placeCode = currentPlace ? places.find(p => p.id === currentPlace)?.code : null; const params = { date: rangeParam, place: placeCode, supplier: currentSupplier }; const response = await api.post('/invoice-supplier/list', { params }); if (response.data?.success) { // The backend already returns data matching InvoiceItem mostly setInvoices(response.data.result || []); } } catch (error) { console.error('Error fetching invoices:', error); alert.showAlert('error', 'Errore', 'Impossibile recuperare la lista delle fatture.'); } finally { setIsLoading(false); setRefreshing(false); } }; useEffect(() => { fetchPlaces(); fetchInvoices(); }, []); const onRefresh = () => { setRefreshing(true); fetchInvoices(); }; // Stable reference: keeps InvoiceCard memoization effective across page re-renders const handleInvoicePress = useCallback((id: number) => { router.push(`/invoice/${id}`); }, [router]); const handleApplyFilters = (range: any, place: any, supplier: any) => { setFilterRange(range); setFilterPlace(place); setFilterSupplier(supplier); setShowFilterModal(false); fetchInvoices(range, place, supplier); }; const handleResetFilters = () => { const emptyRange = { startDate: null, endDate: null }; setFilterRange(emptyRange); setFilterPlace(null); setFilterSupplier(null); setShowFilterModal(false); fetchInvoices(emptyRange, null, null); }; if (isLoading && !refreshing) { return ; } return ( {/* Header */} Elenco delle fatture Fatture {/* List */} } > {invoices.length === 0 ? ( Nessuna fattura trovata ) : ( invoices.map((invoice) => ( )))} {/* FAB Filter */} setShowFilterModal(true)} className="absolute bottom-8 right-6 w-16 h-16 bg-[#1071C2] rounded-full shadow-lg items-center justify-center active:scale-90" > {activeFiltersCount > 0 && ( {activeFiltersCount} )} setShowFilterModal(false)} onApply={handleApplyFilters} onReset={handleResetFilters} /> ); }