fix: remove cards from invoice popups, match original flat layout

Replace SubcontractorInvoiceDetailView (card-based) with flat layout
matching the original sub-invoice popup: meta strip + raw table + notes.

- InvoiceDetailPopup: add metaContent/metaActions/metaCols props + export POPUP_FIELD_LABEL
- New InvoicePopupTable: flat sortable 5-col table, no card wrapper
- All 4 popups (client, team invoice, team sub-invoice, external): use
  flat meta strip (4-col grid, borderBottom) and InvoicePopupTable
- Sub-invoice + external: Submitted | Paid/Created | Items | Total
- Client invoice: Date | Due | Status | Total
- Team invoice: Date | Due | Company | Email | Total (+ stripe if paid)
  with Edit Dates button in metaActions slot

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Krao Hasanee
2026-06-08 14:01:59 -04:00
parent 6e4e99c33c
commit 0945b548c1
6 changed files with 191 additions and 151 deletions
+13 -31
View File
@@ -10,8 +10,8 @@ import { supabase } from '../../lib/supabase';
import { generateInvoicePDF, generateReceiptPDF } from '../../lib/invoice';
import { useAuth } from '../../context/AuthContext';
import { useSortable } from '../../hooks/useSortable';
import InvoiceDetailPopup from '../../components/InvoiceDetailPopup';
import SubcontractorInvoiceDetailView from '../../components/SubcontractorInvoiceDetailView';
import InvoiceDetailPopup, { POPUP_FIELD_LABEL } from '../../components/InvoiceDetailPopup';
import InvoicePopupTable from '../../components/InvoicePopupTable';
const statusColor = { draft: 'not_started', sent: 'in_progress', paid: 'client_approved' };
const invoiceStatusLabel = (status) => {
@@ -97,13 +97,22 @@ function ClientInvoiceModal({ invoice, onClose }) {
return '';
});
const F = POPUP_FIELD_LABEL;
return (
<InvoiceDetailPopup
title={invoice.invoice_number}
subtitle={company?.name || invoice.bill_to}
subtitle={invoice.bill_to || company?.name}
headerRight={<StatusBadge status={statusColor[invoice.status] || 'not_started'} label={`${invoiceStatusLabel(invoice.status)}${isOverdue ? ' · Overdue' : ''}`} />}
onClose={onClose}
blockClose={Boolean(downloading)}
metaContent={<>
<div><div style={F}>Invoice Date</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{invoice.invoice_date ? new Date(invoice.invoice_date).toLocaleDateString() : '—'}</div></div>
<div><div style={F}>Due Date</div><div style={{ fontSize: 13, color: isOverdue ? 'var(--danger)' : 'var(--text-primary)' }}>{invoice.due_date ? new Date(invoice.due_date).toLocaleDateString() : '—'}</div></div>
<div><div style={F}>Status</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}><StatusBadge status={statusColor[invoice.status] || 'not_started'} label={invoiceStatusLabel(invoice.status)} /></div></div>
<div><div style={F}>Total</div><div style={{ fontSize: 18, fontWeight: 500, color: 'var(--accent)', lineHeight: 1.1 }}>${total.toFixed(2)}</div></div>
{invoice.paid_at && <div><div style={F}>Paid On</div><div style={{ fontSize: 13, color: 'var(--success, #16a34a)' }}>{new Date(invoice.paid_at).toLocaleDateString()}</div></div>}
{company?.id && <div><div style={F}>Bill To</div><div style={{ fontSize: 13 }}><Link to={`/company/${company.id}`} className="dashboard-inline-link" onClick={onClose}>{company.name}</Link></div></div>}
</>}
footerActions={<>
{invoice.status === 'sent' && <button className="btn btn-outline" onClick={openPay}>Pay Invoice</button>}
<LoadingButton className="btn btn-outline" loading={downloading === 'invoice'} disabled={Boolean(downloading)} loadingText="Generating…" onClick={handleDownloadInvoice}>Download Invoice</LoadingButton>
@@ -111,34 +120,7 @@ function ClientInvoiceModal({ invoice, onClose }) {
<button className="btn btn-outline" onClick={onClose}>Close</button>
</>}
>
<SubcontractorInvoiceDetailView
leftCardTitle="Bill To"
leftCardBody={<>
<div style={{ fontSize: 15, fontWeight: 400 }}>{invoice.bill_to || company?.name || '—'}</div>
{company?.id && (
<div style={{ marginTop: 12 }}>
<Link to={`/company/${company.id}`} className="btn btn-outline btn-sm" onClick={onClose}>View Company</Link>
</div>
)}
</>}
rightCardTitle="Invoice Details"
rightCardBody={
<div className="invoice-detail-meta-grid">
<div className="invoice-detail-meta-item"><label>Invoice Date</label><p>{invoice.invoice_date ? new Date(invoice.invoice_date).toLocaleDateString() : '—'}</p></div>
<div className="invoice-detail-meta-item"><label>Due Date</label><p style={{ color: isOverdue ? 'var(--danger)' : 'inherit' }}>{invoice.due_date ? new Date(invoice.due_date).toLocaleDateString() : '—'}</p></div>
<div className="invoice-detail-meta-item"><label>Terms</label><p>Net 30</p></div>
<div className="invoice-detail-meta-item"><label>Status</label><p><StatusBadge status={statusColor[invoice.status] || 'not_started'} label={invoiceStatusLabel(invoice.status)} /></p></div>
<div className="invoice-detail-meta-item"><label>Total</label><p style={{ fontSize: 18, fontWeight: 400, color: 'var(--accent)' }}>${total.toFixed(2)}</p></div>
{invoice.paid_at && <div className="invoice-detail-meta-item"><label>Paid On</label><p style={{ color: 'var(--success, #16a34a)' }}>{new Date(invoice.paid_at).toLocaleDateString()}</p></div>}
</div>
}
sortKey={sortKey}
sortDir={sortDir}
onSort={toggle}
items={tableItems}
notes={invoice.notes}
total={total}
/>
<InvoicePopupTable sortKey={sortKey} sortDir={sortDir} onSort={toggle} items={tableItems} notes={invoice.notes} />
</InvoiceDetailPopup>
);
}