Commit Graph

128 Commits

Author SHA1 Message Date
Krao Hasanee bcdb177244 fix: report billing counts only sent/paid invoices as Invoiced
Draft invoices and orphaned invoice line items (invoice deleted → null)
no longer count as Invoiced on the billing report, matching what the
Finances page shows as issued. Not-invoiced/invoiced/paid buckets still
sum to total version rows. No-op on current data (no drafts/orphans);
guards future drafts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:17:19 -04:00
Krao Hasanee 91045a1897 redesign: rename Project→Client, finance single-card + filters, mobile tasks, sticky headers
- Rename "Project" → "Client" across UI (labels + /projects→/clients routes with redirect); normalize company-meaning labels to "Company"
- Finance tabs: merge dual cards into one per tab, add header column filters (expenses/subs/invoices), overview as 3-section card, move +Expense/+Invoice to card right edge
- Tasks: responsive mobile stats grid, progressive column hiding (min Status+Name+Assigned), sidebar mobile footer (profile/theme/signout)
- Hide Company column for single-company users; +Task shows disabled Company field instead of hiding
- Sticky table headers site-wide with opaque card background
- Pin dev server to port 5173

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:39:54 -04:00
Krao Hasanee c91e292066 redesign: Layout2 design-system + dashboard/tasks rework + perf
Design system (Layout2):
- Solid token-driven theme (no animated grid); single-source tokens for bg,
  cards (bg/border/radius), popups, fonts (Inter), and full semantic +
  data-viz color palette. Swept ~168 hardcoded colors to tokens.

Dashboard:
- Reflow: To Do + Calendar row (fixed right rail) over Activity / In-Progress /
  Team Performance; CSS height-match (To Do = Calendar); responsive stacking.
- 'Tasks Not Started' -> 'To Do' card with R#/Assigned columns; compact money fmt.

Tasks page:
- Combined tabs into Tasks + Completed with a Status column.
- Column-header sort + filter (Status, R#/new-vs-revision, Project, Task Type,
  Company) via portaled, scrollable FilterDropdown; removed toolbar filters and
  the projects side panel; headers stay visible when empty; renamed to 'Tasks'.

Perf:
- FK/filter index migration; removed redundant client/external scope waterfall
  (rely on RLS); parallel follow-up queries.

Mobile:
- Responsive grids; mobile topbar = hamburger only, blends with bg, proper offset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 10:08:40 -04:00
Krao Hasanee c5f020cf44 fix: project auto-complete trigger + reject reason must persist before flipping status
- Add sync_project_status trigger so projects flip active<->completed with their tasks; backfill existing rows.
- handleSubmitReject now aborts (and alerts) if the rejection-reason submission fails to save, instead of silently flipping status to in_progress and logging a reason-less rejection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 15:04:01 -04:00
Krao Hasanee 8eacd86b04 fix: invoice integrity — atomic numbering, safe delete, single create path
- Invoice numbers now come from DB function next_invoice_number()
  (max+1 per year under advisory lock) with a unique index; the old
  row-count method reused numbers after deletes and raced concurrent
  creates, which broke public pay links
- Remove dead standalone TeamCreateInvoice page; the TeamInvoices
  modal is the single create path (page had already drifted)
- Invoice delete now asks for confirmation and only un-bills tasks/
  submissions not billed on another invoice
- Created invoice shows correct "sent" status in list without reload
- Invoice/due dates computed at save time, not module load
- Reopening a paid invoice clears stale stripe_fee
- Stripe webhook markPaid is idempotent (no double receipts)
- subcontractor_invoice_items.version_number column stores billing
  version explicitly; description parsing kept as legacy fallback
- Drop unused buildInvoiceStatusByKey/deriveVersionStatus

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 10:02:28 -04:00
Krao Hasanee aff3d98929 fix: fourge_error revisions always bill $0 to client
Fourge's own error revisions should never be charged to the client.
getRevisionChargeQuantity now returns 0 for revision_type=fourge_error
regardless of version number. Applied at all 4 invoice picker call sites.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 23:09:53 -04:00
Krao Hasanee 1784af909d fix: invoice picker skips review-shadow rows for service_type/pricing
Review-shadow submissions are type=initial with blank service_type; the
picker grabbed the first initial found, hitting a shadow -> null service ->
$0 price. New pickInitialServiceType() skips shadows and prefers a real
service_type. Fixes Harlingen sites showing $0 on invoice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 22:29:42 -04:00
Krao Hasanee 4ef73d193d fix: invoice delete un-bills only, never overwrites task work status
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:35:45 -05:00
Krao Hasanee 6b9f008fff fix: report Version Status collapses Approved into Completed
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:33:34 -05:00
Krao Hasanee c891f53d2a feat: add Sub Billing column to billing report (sub invoiced/paid per version)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:32:42 -05:00
Krao Hasanee 12c9a1a093 fix: report Version Status shows work state only, billing leak collapsed to approved
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:24:37 -05:00
Krao Hasanee 1cbf06a6c0 fix: revert per-version rows; reset stuck revision tasks in DB
Tasks/projects page: reverted back to one row per task (work status only,
no billing state on that page). Per-version R## tracking lives in invoicing
only (invoice_items, sub invoice form).

DB fix: 7 Public Storage tasks had pending revision versions (R01/R02)
with no delivery but were stuck as 'paid' from old invoice lifecycle sync.
Reset to 'not_started' so they appear in the Revisions tab for work:
  68664, 68666, 68721 (R02), 68808, 68809 (R02), 68810 (R02), 68811 (R02)

Removed unused invoiceItems state/fetch from Tasks + ProjectDetail.
invoiceVersionRules helpers retained for invoicing use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:47:21 -05:00
Krao Hasanee 5b2d5b65a4 feat: per-version R## tracking and billing separation
Each revision (R00, R01, R02) is now an independent trackable unit:

invoiceVersionRules: add deriveVersionStatus, buildInvoiceStatusByKey,
  parseVersionFromItemDescription for per-version status derivation

Tasks.jsx + ProjectDetail.jsx:
  - Fetch invoice_items joined with invoice.status (team only)
  - allRows/rows now flatMap per version (one row per R##)
  - Status derived from: invoice_items > past version > task.status
  - R00 paid shows as paid; R01 in_progress shows separately
  - tr keys use rowKey (taskId:version) to avoid duplicate key warnings

Invoice lifecycle (TeamInvoiceDetail, TeamInvoices, TeamCreateInvoice):
  - Remove task.status sync on invoice paid/sent/created
  - Keep invoiced:true flag for double-billing prevention
  - Task work status (not_started → client_approved) stays work-flow only

ProjectDetail completion bar uses task.status === client_approved only
  (no longer polluted by invoiced/paid status from invoice sync)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:36:36 -05:00
Krao Hasanee da0e5d5c39 fix: guard task status updates on invoice lifecycle transitions
Prevent overwriting task status when task has moved to a new revision
cycle after being invoiced. Now uses .eq('status', guardStatus) to only
update tasks still at the expected prior state:
- invoice creation: only update tasks at client_approved → invoiced
- mark sent: only client_approved → invoiced
- mark paid: only invoiced → paid
- reopen: only paid → client_approved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:22:18 -05:00
Krao Hasanee 8b0cb31bc6 fix: hide counter on All tab in projects table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:48:16 -04:00
Krao Hasanee 4faf0e80b6 fix: hide counter on All tabs; reduce card-bg alpha ~20%
- Tasks + ProjectDetail: skip count badge when tab.id === 'all'
- card-bg 0.07 → 0.055, card-bg-2 0.12 → 0.09

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:46:02 -04:00
Krao Hasanee 623dcb7983 fix: subcontractor PDF quality, footer on all pages, header gap
- Canvas 3x scale + JPEG 0.97 (matches main invoice quality)
- Footer drawn on every page canvas
- Continuation header gap increased (headerH+28 → +50 with label)
- Pagination pre-calculated before rendering (no mid-render addPage)
- 'PO Date' label → 'Invoice Date'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:17:20 -04:00
Krao Hasanee 48c8fbb7ff style: white-based card-bg 0.07, blur 12px→20px for less transparency
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:06:56 -04:00
Krao Hasanee 1dd7ca1922 style: card-bg dark-based alpha to match Safari panel look
rgba(255,255,255,0.06) with backdrop blur renders lighter in Chrome.
rgba(0,0,0,0.35) gives consistent dark panel across all browsers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:01:23 -04:00
Krao Hasanee fa8ade83d6 fix: subcontractor PDF title + multi-page support
- 'PURCHASE ORDER' → 'SUBCONTRACTOR INVOICE'
- Items loop now calls addPage() when hitting safeBottom (792-80pt)
- Continuation pages get header with invoice number + '(continued)'
- Summary/Notes sections also page-break if needed
- Footer text updated to match invoice context
- Footer line position dynamic (tracks y), not hardcoded at 704

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 15:58:42 -04:00
Krao Hasanee e450f1b0d1 style: increase card-bg alpha to match Safari rendering
0.02 → 0.06 dark theme, card-bg-2 0.08 → 0.10

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 15:54:59 -04:00
Krao Hasanee e3b2df6e2c fix: restore popupOverlayStyle import in ExternalMyInvoices
Removed during popup refactor but still used by +Invoice form popup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 14:16:11 -04:00
Krao Hasanee e8513125b9 fix: lock company/email fields on sent/paid invoices
Company dropdown and Email To input only editable on draft invoices.
Sent and paid invoices show read-only text values instead.
Applied to both popup (embedded) and standalone page views.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 14:03:58 -04:00
Krao Hasanee 0945b548c1 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>
2026-06-08 14:01:59 -04:00
Krao Hasanee 6e4e99c33c feat: unify all invoice popups to shared InvoiceDetailPopup shell
All invoice popup modals (team invoice, sub-invoice team, client invoice,
external sub-invoice) now share InvoiceDetailPopup + SubcontractorInvoiceDetailView.
Same overlay, header, scroll body, footer action row — just different data per role.

- New InvoiceDetailPopup component (overlay shell, header, scrollable body, footer)
- SubcontractorInvoiceDetailView: respects item._inferredType if pre-set
- ClientInvoiceModal: uses shared components, adds sortable headers
- TeamInvoiceDetailPanel embedded: uses shared components, keeps edit-dates/email/company
- TeamInvoices sub-invoice popup: uses shared components, cleans descriptions
- ExternalMyInvoices popup: uses shared components, fixes detailSort vars (was unused)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 13:46:08 -04:00
Krao Hasanee 04e0911e9f fix: crash bugs in TeamInvoices + faster load
Bug fixes:
- TeamInvoices: add useAuth import/currentUser (invoice-create crash)
- TeamInvoices: setChartYear -> setExportYear (year-dropdown crash)
- TeamDashboard: drop redundant setState-in-effect (cascading renders)
- Companies: delete dead _UnusedClientCompanies (illegal hook calls)
- annotate intentional empty PDF-fallback catches

Load speed:
- preconnect/dns-prefetch to Supabase origin
- lazy-load heic-to in Converters: page chunk 2737KB -> 9KB
- split recharts into its own 'charts' vendor chunk

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:59:11 -04:00
Krao Hasanee 85625f4d95 fix: delivery zip downloads from correct deliveries storage bucket
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 23:59:34 -04:00
Krao Hasanee 71a8ed1b43 docs: document team performance calculation logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 23:44:44 -04:00
Krao Hasanee 2c387c074f feat: performance dashboard counts per delivery, submission tab shows deliveries, task row hover fix
- Team performance: count each delivery record individually (sent_by + version_number), not per task — R00/R01/R02 by different people all count separately
- Performance uses deliveries table directly, EST timezone bucketing, month-gated tabs
- TaskDetail Submissions tab: reads from deliveries table, shows R## version, sent_by, sent_at
- Submit for Review: writes to deliveries + delivery_files (deliveries bucket), stores version_number
- Revision request popup: uses FileAttachment drag-drop component
- Task table: only Name and Project columns highlight on hover
- deliveries.version_number column added and backfilled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 22:21:58 -04:00
Krao Hasanee 96e90561b9 feat: expense/invoice popups, task row hover fix, delivery submissions
- Expense detail popup: 80vw×80vh, inline editing, save gated on dirty state, Download Receipt in footer
- Add expense form: same layout with FileAttachment drag-drop on right
- New invoice popup: 80vw×80vh inline form replacing navigate-away page
- Tasks table: suppress row hover background, only Name/Project table-links highlight
- TaskDetail Submissions tab: reads from deliveries table, shows R## version, sent_by, message
- Submit for Review: writes to deliveries + delivery_files (deliveries bucket)
- deliveries.version_number column added and backfilled from revision history
- Port 4173 for dev server

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 21:41:02 -04:00
Krao Hasanee 65f10036d8 fix: divider line under breadcrumbs on folder tab and filesharing 2026-06-02 15:18:03 -04:00
Krao Hasanee aae5214cde fix: context menu via createPortal, renders at viewport coords 2026-06-02 15:15:54 -04:00
Krao Hasanee 36f1179c04 fix: remove toolbar divider border 2026-06-02 14:48:56 -04:00
Krao Hasanee 8b6e2739ae fix: remove up-folder row, context menu flips up when near bottom 2026-06-02 14:48:24 -04:00
Krao Hasanee 144bda426b feat: FileBrowser matches FileSharing — no inline row buttons, context menu copy/cut/paste/rename/delete, selection Download+Delete panel, drag hint 2026-06-02 14:43:05 -04:00
Krao Hasanee 959dd571d2 fix: submissions tab row gap matches revisions (20px) 2026-06-02 14:36:13 -04:00
Krao Hasanee e912f82520 feat: review popup drag-drop attachments, .md styling 2026-06-02 14:33:50 -04:00
Krao Hasanee 894ec323f2 fix: use type=initial for all submissions, single unified type 2026-06-02 14:30:53 -04:00
Krao Hasanee 585fc7500c fix: Submissions tab includes legacy initial-type submissions 2026-06-02 14:29:37 -04:00
Krao Hasanee d222d8b573 feat: review popup notes+attachments, Submissions tab 2026-06-02 14:28:59 -04:00
Krao Hasanee 0d4b1f8096 feat: place-in-review attachment popup, remove-from-review button 2026-06-02 14:25:32 -04:00
Krao Hasanee ae093a9b1c fix: proxy file uploads server-side via action=upload, fixes CORS for all roles 2026-06-02 14:19:59 -04:00
Krao Hasanee e11ef45140 fix: FileBrowser upload uses auth query param, no CORS preflight for external users 2026-06-02 14:12:24 -04:00
Krao Hasanee 770bb1c05b fix: upload source=srv, expense detail popup, invoice/expense filters, pie charts, date timezone fixes 2026-06-02 14:08:11 -04:00
Krao Hasanee 1f09ce0a1d feat: expense year filter, newest-first default sort for expenses + invoices 2026-06-02 12:13:10 -04:00
Krao Hasanee 490e4f4bbf fix: stat cards use comma-formatted numbers 2026-06-02 11:11:08 -04:00
Krao Hasanee 4fce77abb9 fix: net profit deducts stripe fees from chart calculation 2026-06-02 10:49:11 -04:00
Krao Hasanee 573c4a69fa fix: expense date timezone, receipt popup blocker 2026-06-02 10:47:58 -04:00
Krao Hasanee 30838e8da3 fix: stat cards show full dollar amounts under $100k, k-suffix only at $100k+ 2026-06-02 10:41:05 -04:00
Krao Hasanee 958f451836 fix: client file sharing access denied + task/project default tabs
- FileSharing: rootPath for clients strips /Clients/ prefix — API resolveClientPath expects /{company} not /Clients/{company}
- Tasks: default to To Do tab (not_started) instead of All Tasks
- Projects: default to Active tab instead of All Projects

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 20:35:13 -04:00