Checkpoint: Transformation des cellules Service, Type d'achat et Ventilation en menus déroulants éditables directement dans la liste des factures. Les modifications sont sauvegardées automatiquement avec notification de succès.

This commit is contained in:
Manus
2026-02-11 09:11:07 -05:00
parent e217ac06ce
commit 69ba92b12a
2 changed files with 70 additions and 3 deletions

View File

@@ -37,6 +37,8 @@ export default function Invoices() {
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [invoiceToDelete, setInvoiceToDelete] = useState<number | null>(null);
const { data: invoices, isLoading } = trpc.invoices.list.useQuery();
const { data: departments } = trpc.departments.getByUser.useQuery();
const { data: allocations } = trpc.accountingAllocations.getByUser.useQuery();
const utils = trpc.useUtils();
const exportExcelMutation = trpc.sftp.exportToExcel.useMutation({
@@ -101,6 +103,16 @@ export default function Invoices() {
},
});
const updateFieldMutation = trpc.invoices.update.useMutation({
onSuccess: () => {
toast.success("Facture mise à jour");
utils.invoices.list.invalidate();
},
onError: (error) => {
toast.error(error.message || "Erreur lors de la mise à jour");
},
});
const filteredInvoices = invoices?.filter((inv) => {
// Filter by search query
if (searchQuery) {
@@ -365,9 +377,56 @@ export default function Invoices() {
? `${parseFloat(invoice.totalAmount as string).toFixed(2)}`
: "-"}
</TableCell>
<TableCell className="text-sm">{invoice.serviceConcerne || "-"}</TableCell>
<TableCell className="text-sm">{invoice.typeAchat || "-"}</TableCell>
<TableCell className="text-sm">{invoice.ventilationComptable || "-"}</TableCell>
<TableCell className="text-sm">
<select
value={invoice.serviceConcerne || ""}
onChange={(e) => {
updateFieldMutation.mutate({
id: invoice.id,
data: { serviceConcerne: e.target.value || undefined },
});
}}
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-</option>
{departments?.map((dept) => (
<option key={dept.id} value={dept.name}>{dept.name}</option>
))}
</select>
</TableCell>
<TableCell className="text-sm">
<select
value={invoice.typeAchat || ""}
onChange={(e) => {
updateFieldMutation.mutate({
id: invoice.id,
data: { typeAchat: e.target.value as "CAPEX" | "OPEX" | undefined },
});
}}
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-</option>
<option value="CAPEX">CAPEX</option>
<option value="OPEX">OPEX</option>
</select>
</TableCell>
<TableCell className="text-sm">
<select
value={invoice.ventilationComptable || ""}
onChange={(e) => {
updateFieldMutation.mutate({
id: invoice.id,
data: { ventilationComptable: e.target.value || undefined },
});
}}
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-</option>
{allocations?.map((alloc) => (
<option key={alloc.id} value={alloc.name}>{alloc.name}</option>
))}
</select>
</TableCell>
<TableCell>{getQualityBadge(invoice.qualityScore)}</TableCell>
<TableCell>{getExportStatusBadge(invoice.exportStatus || "not_exported")}</TableCell>
<TableCell>