diff --git a/pages/ExtraordinaryUser.tsx b/pages/ExtraordinaryUser.tsx index 99af64b..5ec3726 100644 --- a/pages/ExtraordinaryUser.tsx +++ b/pages/ExtraordinaryUser.tsx @@ -1,16 +1,22 @@ import React, { useEffect, useState } from 'react'; -import { CondoService } from '../services/mockDb'; +import { CondoService } from '../services/api'; import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js"; -import { Briefcase, Calendar, CheckCircle2, AlertCircle } from 'lucide-react'; +import { Briefcase, Calendar, CheckCircle2, AlertCircle, Eye, Paperclip, X, FileText, Download } from 'lucide-react'; +import { ExtraordinaryExpense } from '../types'; export const ExtraordinaryUser: React.FC = () => { - const [expenses, setExpenses] = useState([]); // Using any for composite object from specific API + const [expenses, setExpenses] = useState([]); const [loading, setLoading] = useState(true); const [paypalClientId, setPaypalClientId] = useState(''); const [successMsg, setSuccessMsg] = useState(''); const [hasFamily, setHasFamily] = useState(true); + // Details Modal State + const [showDetails, setShowDetails] = useState(false); + const [selectedExpense, setSelectedExpense] = useState(null); + const [loadingDetails, setLoadingDetails] = useState(false); + useEffect(() => { const load = async () => { try { @@ -50,6 +56,35 @@ export const ExtraordinaryUser: React.FC = () => { } catch(e) { alert("Errore registrazione pagamento"); } }; + const handleCardClick = async (expenseId: string) => { + setLoadingDetails(true); + try { + // Fetch full details including attachments + const fullDetails = await CondoService.getExpenseDetails(expenseId); + setSelectedExpense(fullDetails); + setShowDetails(true); + } catch (e) { + console.error(e); + alert("Impossibile caricare i dettagli."); + } finally { + setLoadingDetails(false); + } + }; + + 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 apertura file"); } + }; + if (loading) return
Caricamento spese...
; if (!hasFamily) { @@ -88,10 +123,16 @@ export const ExtraordinaryUser: React.FC = () => { const isPaid = exp.myShare.status === 'PAID'; return ( -
-
+
handleCardClick(exp.id)} + className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden flex flex-col cursor-pointer hover:shadow-md transition-all group" + > +
-

{exp.title}

+

+ {exp.title} +

{new Date(exp.startDate).toLocaleDateString()}

@@ -126,7 +167,7 @@ export const ExtraordinaryUser: React.FC = () => {
-
+
e.stopPropagation()}> {!isPaid && remaining > 0.01 && ( <> {paypalClientId ? ( @@ -168,6 +209,102 @@ export const ExtraordinaryUser: React.FC = () => { })}
)} + + {/* DETAILS MODAL */} + {showDetails && selectedExpense && ( +
+
+
+
+

{selectedExpense.title}

+

{selectedExpense.contractorName}

+
+ +
+ +
+ {/* Description */} +
+

Descrizione Lavori

+

+ {selectedExpense.description} +

+
+ + {/* Dates & Totals */} +
+
+

Inizio Lavori

+

+ {new Date(selectedExpense.startDate).toLocaleDateString()} +

+
+
+

Totale Progetto

+

+ € {selectedExpense.totalAmount.toLocaleString()} +

+
+
+ + {/* Items List */} +
+

Dettaglio Voci di Spesa

+
+ + + + + + + + + {selectedExpense.items.map((item, i) => ( + + + + + ))} + +
DescrizioneImporto
{item.description}€ {item.amount.toLocaleString()}
+
+
+ + {/* Attachments */} + {selectedExpense.attachments && selectedExpense.attachments.length > 0 && ( +
+

Documenti & Allegati

+
+ {selectedExpense.attachments.map(att => ( + + ))} +
+
+ )} +
+ +
+ +
+
+
+ )}
); };