import React, { useEffect, useState } from 'react'; import { CondoService } from '../services/mockDb'; import { ExtraordinaryExpense, Family, ExpenseItem, ExpenseShare } from '../types'; import { Plus, Calendar, FileText, CheckCircle2, Clock, Users, X, Save, Paperclip, Euro, Trash2, Eye, Briefcase } from 'lucide-react'; export const ExtraordinaryAdmin: React.FC = () => { const [expenses, setExpenses] = useState([]); const [families, setFamilies] = useState([]); const [loading, setLoading] = useState(true); const [showModal, setShowModal] = useState(false); const [showDetailsModal, setShowDetailsModal] = useState(false); const [selectedExpense, setSelectedExpense] = useState(null); // Form State const [formTitle, setFormTitle] = useState(''); const [formDesc, setFormDesc] = useState(''); const [formStart, setFormStart] = useState(''); const [formEnd, setFormEnd] = useState(''); const [formContractor, setFormContractor] = useState(''); const [formItems, setFormItems] = useState([{ description: '', amount: 0 }]); const [formShares, setFormShares] = useState([]); // Working state for shares const [formAttachments, setFormAttachments] = useState<{fileName: string, fileType: string, data: string}[]>([]); const [selectedFamilyIds, setSelectedFamilyIds] = useState([]); // Helper to track checkboxes useEffect(() => { loadData(); }, []); const loadData = async () => { setLoading(true); try { const [expList, famList] = await Promise.all([ CondoService.getExpenses(), CondoService.getFamilies() ]); setExpenses(expList); setFamilies(famList); } catch(e) { console.error(e); } finally { setLoading(false); } }; // Calculation Helpers const totalAmount = formItems.reduce((acc, item) => acc + (item.amount || 0), 0); const recalculateShares = (selectedIds: string[], manualMode = false) => { if (manualMode) return; // If manually editing, don't auto-calc const count = selectedIds.length; if (count === 0) { setFormShares([]); return; } const percentage = 100 / count; const newShares: ExpenseShare[] = selectedIds.map(fid => ({ familyId: fid, percentage: parseFloat(percentage.toFixed(2)), amountDue: parseFloat(((totalAmount * percentage) / 100).toFixed(2)), amountPaid: 0, status: 'UNPAID' })); // Adjust rounding error on last item if (newShares.length > 0) { const sumDue = newShares.reduce((a, b) => a + b.amountDue, 0); const diff = totalAmount - sumDue; if (diff !== 0) { newShares[newShares.length - 1].amountDue += diff; } } setFormShares(newShares); }; const handleFamilyToggle = (familyId: string) => { const newSelected = selectedFamilyIds.includes(familyId) ? selectedFamilyIds.filter(id => id !== familyId) : [...selectedFamilyIds, familyId]; setSelectedFamilyIds(newSelected); recalculateShares(newSelected); }; const handleShareChange = (index: number, field: 'percentage', value: number) => { const newShares = [...formShares]; newShares[index].percentage = value; newShares[index].amountDue = (totalAmount * value) / 100; setFormShares(newShares); }; const handleItemChange = (index: number, field: keyof ExpenseItem, value: any) => { const newItems = [...formItems]; // @ts-ignore newItems[index][field] = value; setFormItems(newItems); // Recalculate shares based on new total // We need a small delay or effect, but for simplicity let's force recalc next render or manual }; // Trigger share recalc when total changes (if not manual override mode - implementing simple auto mode here) useEffect(() => { recalculateShares(selectedFamilyIds); }, [totalAmount]); // eslint-disable-line react-hooks/exhaustive-deps const handleFileChange = async (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { const newAtts = []; for(let i=0; i((resolve) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result as string); reader.readAsDataURL(file); }); newAtts.push({ fileName: file.name, fileType: file.type, data: base64 }); } setFormAttachments([...formAttachments, ...newAtts]); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { await CondoService.createExpense({ title: formTitle, description: formDesc, startDate: formStart, endDate: formEnd, contractorName: formContractor, items: formItems, shares: formShares, attachments: formAttachments }); setShowModal(false); loadData(); // Reset form setFormTitle(''); setFormDesc(''); setFormItems([{description:'', amount:0}]); setSelectedFamilyIds([]); setFormShares([]); setFormAttachments([]); } catch(e) { alert('Errore creazione'); } }; const openDetails = async (expense: ExtraordinaryExpense) => { const fullDetails = await CondoService.getExpenseDetails(expense.id); setSelectedExpense(fullDetails); setShowDetailsModal(true); }; const openAttachment = async (expenseId: string, attId: string) => { try { const file = await CondoService.getExpenseAttachment(expenseId, attId); const win = window.open(); if (win) { if (file.fileType.startsWith('image/') || file.fileType === 'application/pdf') { win.document.write(``); } else { win.document.write(`Download ${file.fileName}`); } } } catch(e) { alert("Errore file"); } }; return (

Spese Straordinarie

Gestione lavori e appalti

{/* List */}
{expenses.map(exp => (
Lavori € {exp.totalAmount.toLocaleString()}

{exp.title}

{exp.description}

{exp.contractorName}
{new Date(exp.startDate).toLocaleDateString()}
))}
{/* CREATE MODAL */} {showModal && (

Crea Progetto Straordinario

{/* General Info */}
setFormTitle(e.target.value)} required /> setFormContractor(e.target.value)} required />