import React, { useEffect, useState, useMemo } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { CondoService } from '../services/mockDb'; import { Family, Payment, AppSettings, MonthStatus, PaymentStatus } from '../types'; import { ArrowLeft, CheckCircle2, AlertCircle, Plus, Calendar, CreditCard, TrendingUp } from 'lucide-react'; const MONTH_NAMES = [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ]; export const FamilyDetail: React.FC = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const [family, setFamily] = useState(null); const [payments, setPayments] = useState([]); const [settings, setSettings] = useState(null); const [loading, setLoading] = useState(true); const [selectedYear, setSelectedYear] = useState(new Date().getFullYear()); const [availableYears, setAvailableYears] = useState([]); const [showAddModal, setShowAddModal] = useState(false); const [newPaymentMonth, setNewPaymentMonth] = useState(new Date().getMonth() + 1); const [newPaymentAmount, setNewPaymentAmount] = useState(0); const [isSubmitting, setIsSubmitting] = useState(false); useEffect(() => { if (!id) return; const loadData = async () => { setLoading(true); try { const [famList, famPayments, appSettings, years] = await Promise.all([ CondoService.getFamilies(), CondoService.getPaymentsByFamily(id), CondoService.getSettings(), CondoService.getAvailableYears() ]); const foundFamily = famList.find(f => f.id === id); if (foundFamily) { setFamily(foundFamily); setPayments(famPayments); setSettings(appSettings); setNewPaymentAmount(appSettings.defaultMonthlyQuota); setAvailableYears(years); setSelectedYear(appSettings.currentYear); } else { navigate('/'); } } catch (e) { console.error("Error loading family details", e); } finally { setLoading(false); } }; loadData(); }, [id, navigate]); const monthlyStatus: MonthStatus[] = useMemo(() => { const now = new Date(); const currentRealYear = now.getFullYear(); const currentRealMonth = now.getMonth(); return Array.from({ length: 12 }, (_, i) => { const monthNum = i + 1; const payment = payments.find(p => p.forMonth === monthNum && p.forYear === selectedYear); let status = PaymentStatus.UPCOMING; if (payment) { status = PaymentStatus.PAID; } else { if (selectedYear < currentRealYear) { status = PaymentStatus.UNPAID; } else if (selectedYear === currentRealYear) { if (i < currentRealMonth) status = PaymentStatus.UNPAID; else if (i === currentRealMonth) status = PaymentStatus.PENDING; else status = PaymentStatus.UPCOMING; } else { status = PaymentStatus.UPCOMING; } } return { monthIndex: i, status, payment }; }); }, [payments, selectedYear]); const chartData = useMemo(() => { return monthlyStatus.map(m => ({ label: MONTH_NAMES[m.monthIndex].substring(0, 3), fullLabel: MONTH_NAMES[m.monthIndex], amount: m.payment ? m.payment.amount : 0, isPaid: m.status === PaymentStatus.PAID, isFuture: m.status === PaymentStatus.UPCOMING })); }, [monthlyStatus]); const maxChartValue = useMemo(() => { const max = Math.max(...chartData.map(d => d.amount)); const baseline = settings?.defaultMonthlyQuota || 100; return max > 0 ? Math.max(max * 1.2, baseline) : baseline; }, [chartData, settings]); const handleAddPayment = async (e: React.FormEvent) => { e.preventDefault(); if (!family || !id) return; setIsSubmitting(true); try { const payment = await CondoService.addPayment({ familyId: id, amount: newPaymentAmount, forMonth: newPaymentMonth, forYear: selectedYear, datePaid: new Date().toISOString() }); setPayments([...payments, payment]); if (!availableYears.includes(selectedYear)) { setAvailableYears([...availableYears, selectedYear].sort((a,b) => b-a)); } setShowAddModal(false); } catch (e) { console.error("Failed to add payment", e); } finally { setIsSubmitting(false); } }; if (loading) return
Caricamento dettagli...
; if (!family) return
Famiglia non trovata.
; return (
{/* Header Responsive */}

{family.name}

Interno: {family.unitNumber}
{/* Stats Summary - Stack on mobile */}

Mesi Saldati

{monthlyStatus.filter(m => m.status === PaymentStatus.PAID).length} / 12

Mesi Insoluti

{monthlyStatus.filter(m => m.status === PaymentStatus.UNPAID).length}

Totale Versato

€ {payments.filter(p => p.forYear === selectedYear).reduce((acc, curr) => acc + curr.amount, 0).toLocaleString()}

{/* Monthly Grid */}

Dettaglio {selectedYear}

{monthlyStatus.map((month) => (
{MONTH_NAMES[month.monthIndex]} {month.status === PaymentStatus.PAID && ( Saldato )} {month.status === PaymentStatus.UNPAID && ( Insoluto )} {month.status === PaymentStatus.PENDING && ( In Scadenza )} {month.status === PaymentStatus.UPCOMING && ( Futuro )}
{month.payment ? (

Importo: € {month.payment.amount}

{new Date(month.payment.datePaid).toLocaleDateString()}

) : (

Nessun pagamento

{month.status === PaymentStatus.UNPAID && ( )}
)}
))}
{/* Payment Trend Chart (Scrollable) */}

Andamento

Versato
Mancante
{chartData.map((data, index) => { const heightPercentage = Math.max((data.amount / maxChartValue) * 100, 4); return (
{data.amount > 0 && (
)} {data.amount === 0 && !data.isFuture && (
)}
0 ? 'text-slate-700' : 'text-slate-400' }`}> {data.label}
); })}
{/* Add Payment Modal */} {showAddModal && (

Registra Pagamento

setNewPaymentAmount(parseFloat(e.target.value))} className="w-full border border-slate-300 rounded-xl p-3 focus:ring-2 focus:ring-blue-500 outline-none text-lg font-medium" />
)}
); }; const BuildingIcon = ({className}:{className?:string}) => ( );