Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-19 01:13:45 +00:00
co-authored by renee-png
parent 5a37fbbd54
commit 77afa0f788
+49 -34
View File
@@ -377,41 +377,56 @@ function InvoiceDetail() {
</tr>
</thead>
<tbody>
{g.items.map((it) => (
<tr key={it.id} className="border-t">
<td className="px-3 py-2 text-muted-foreground text-xs">{it.work_date ? formatDate(it.work_date) : "—"}</td>
<td className="px-3 py-2">
{canEdit && isDraft ? (
<Input className="h-8" defaultValue={it.description}
onBlur={(e) => e.target.value !== it.description && updateItem(it.id, { description: e.target.value })} />
) : (
<div>
<div>{it.description}</div>
{it.user?.full_name && <div className="text-[11px] text-muted-foreground italic">{it.user.full_name}</div>}
</div>
)}
</td>
<td className="px-3 py-2 text-right tabular-nums">
{canEdit && isDraft ? (
<Input className="h-8 text-right tabular-nums" defaultValue={Number(it.quantity)}
onBlur={(e) => Number(e.target.value) !== Number(it.quantity) && updateItem(it.id, { quantity: Number(e.target.value) })} />
) : Number(it.quantity).toFixed(2)}
</td>
<td className="px-3 py-2 text-right tabular-nums">
{canEdit && isDraft ? (
<Input className="h-8 text-right tabular-nums" defaultValue={Number(it.rate)}
onBlur={(e) => Number(e.target.value) !== Number(it.rate) && updateItem(it.id, { rate: Number(e.target.value) })} />
) : formatCurrency(it.rate)}
</td>
<td className="px-3 py-2 text-right tabular-nums font-medium">{formatCurrency(it.amount)}</td>
{canEdit && isDraft && (
<td className="px-2 py-2 text-right">
<Button variant="ghost" size="icon" className="h-7 w-7 text-muted-foreground hover:text-destructive" onClick={() => removeItem(it.id)}>
<Trash2 className="h-3.5 w-3.5" />
</Button>
{g.subsections.map((sub) => (
<FragmentSection key={sub.key}>
<tr className="bg-muted/20 border-t">
<td colSpan={4} className="px-3 py-1.5 text-[11px] uppercase tracking-wider font-semibold text-muted-foreground">
{sub.label}
</td>
)}
</tr>
<td className="px-3 py-1.5 text-right tabular-nums text-xs font-semibold text-muted-foreground">
{sub.billable ? formatCurrency(sub.subtotal) : "—"}
</td>
{canEdit && isDraft && <td />}
</tr>
{sub.items.map((it) => (
<tr key={it.id} className={`border-t ${!sub.billable ? "text-muted-foreground" : ""}`}>
<td className="px-3 py-2 text-xs">{it.work_date ? formatDate(it.work_date) : "—"}</td>
<td className="px-3 py-2">
{canEdit && isDraft ? (
<Input className="h-8" defaultValue={it.description}
onBlur={(e) => e.target.value !== it.description && updateItem(it.id, { description: e.target.value })} />
) : (
<div>
<div className={!sub.billable ? "italic" : ""}>{it.description}</div>
{it.user?.full_name && <div className="text-[11px] text-muted-foreground italic">{it.user.full_name}</div>}
</div>
)}
</td>
<td className="px-3 py-2 text-right tabular-nums">
{canEdit && isDraft ? (
<Input className="h-8 text-right tabular-nums" defaultValue={Number(it.quantity)}
onBlur={(e) => Number(e.target.value) !== Number(it.quantity) && updateItem(it.id, { quantity: Number(e.target.value) })} />
) : Number(it.quantity).toFixed(2)}
</td>
<td className="px-3 py-2 text-right tabular-nums">
{canEdit && isDraft ? (
<Input className="h-8 text-right tabular-nums" defaultValue={Number(it.rate)}
onBlur={(e) => Number(e.target.value) !== Number(it.rate) && updateItem(it.id, { rate: Number(e.target.value) })} />
) : formatCurrency(it.rate)}
</td>
<td className="px-3 py-2 text-right tabular-nums font-medium">
{sub.billable ? formatCurrency(it.amount) : "—"}
</td>
{canEdit && isDraft && (
<td className="px-2 py-2 text-right">
<Button variant="ghost" size="icon" className="h-7 w-7 text-muted-foreground hover:text-destructive" onClick={() => removeItem(it.id)}>
<Trash2 className="h-3.5 w-3.5" />
</Button>
</td>
)}
</tr>
))}
</FragmentSection>
))}
</tbody>
</table>