wulf-pulse/.planning/phases/05-finance-restyle/05-CONTEXT.md

9.5 KiB
Raw Blame History

Phase 5: Finance Restyle - Context

Gathered: 2026-05-03 (auto mode) Status: Ready for planning

## Phase Boundary

Restyle app/mobile/finance/page.tsx to match the new mobile shell (Phase 2 + Phase 3/4 patterns). Replace squished wide tables with stacked card lists. Adopt the new Card and typography scale established in earlier phases. Same data, same sections, same API endpoint (/api/mobile/finance) — only the presentation changes.

In scope: page-body restyle, table→list conversion, Card/typography updates, spacing/overflow fixes, optional skeletons.

Out of scope: API/schema changes, new sections, sorting/filtering controls, new data sources, the QBO sync gear UI (keep as-is unless trivially affected by spacing fixes).

## Implementation Decisions

Card adoption

  • D-01: Use shadcn Card + CardContent (matching the pattern from KpiCardMobile). Replace the current bare <div> blocks for the four KPI summary tiles, the aging buckets, and any wrapper containers around the invoice/payment lists. Card = surface boundary; not every paragraph needs one.
  • D-02: Mirror Phase 3's KPI scale: text-xl font-semibold for the dollar amount, text-xs text-muted-foreground for the label, optional caption row in text-[10px] text-muted-foreground.

Typography scale (matches Phase 4 UI-SPEC)

  • D-03: Two font weights only — font-normal (400) and font-semibold (600). No font-medium. Reason: consistency with Phase 4 UI-SPEC dimension 4.
  • D-04: Three sizes — text-sm (14px) for primary lines, text-xs (12px) for secondary/labels, text-[10px] for IDs/dates/badges. Currency values use text-xl or text-2xl for the four KPI summary tiles only.
  • D-05: Currency formatted via the existing fmt$() helper — keep zero decimals (maximumFractionDigits: 0).

Tables → stacked lists

  • D-06: The two main "table-shaped" sections — Open/Overdue Invoices and Recent Payments — render as stacked card rows, not <table> elements. Each row is a small card (or border-b divided block) with a 2-line layout:
    • Line 1: customer name (left, text-sm font-semibold) + amount (right, text-sm font-semibold, currency)
    • Line 2: secondary metadata (left: invoice number / doc number / status chip / Xd overdue if applicable, text-xs text-muted-foreground) + date (right, text-xs text-muted-foreground)
  • D-07: Top Customers section also becomes a stacked card list with the same 2-line shape: customer name + total balance on line 1, invoice count on line 2.
  • D-08: Aging buckets (1-30 / 31-60 / 60+) become a 3-column compact card row at phone widths (similar to WorkerStatusRow from Phase 3) — no horizontal scroll. Each cell shows balance + count + label vertically.
  • D-09: Monthly revenue (monthly_revenue array, last 6 months) renders as a stacked list of Month → revenue → count rows. No chart. (DASH-04 precedent: no recharts on mobile.)

Spacing & layout

  • D-10: Page container uses the same shell inset as other mobile pages: px-4 py-4 space-y-6 (or whatever the phase 3/4 dashboards use). Sections separated by space-y-6 or visible section dividers.
  • D-11: Within a section: space-y-3 between rows. Inside a card: gap-3 for the 2-line internal layout.
  • D-12: No horizontal overflow at 360px viewport width (test target). All numeric columns truncate or wrap rather than push the layout.
  • D-13: Section headers use text-sm font-semibold (not larger), rendered above each card list. Optional count badge in text-xs text-muted-foreground.

Existing controls

  • D-14: Keep the existing RefreshCw "Refresh" / CloudDownload "Sync from QBO" controls in the header row. Reskin only — convert to icon buttons with aria-label per Phase 4 UI-SPEC dimension 1 conventions.
  • D-15: Keep the Open/Overdue tab toggle (tab state). Restyle as shadcn segmented buttons or a small chip pair. Don't add new tab options.
  • D-16: Keep the invoicesOpen / paymentsOpen collapsibles, but render them with shadcn Collapsible (matching the Phase 4 filter strip pattern).

Loading & error states

  • D-17: Skeleton state on initial load: 4 KPI tile skeletons + 1 aging row skeleton + 3 list-row skeletons. Reuse Skeleton from components/ui/skeleton.tsx. Keep a small inline spinner on Refresh.
  • D-18: Error → inline message in a destructive-tinted card with a "Retry" button. Use toast.error() for transient sync failures (per Phase 4 D-21 precedent).

Empty state

  • D-19: When data.summary.total_ar is 0 and the open-invoices list is empty, render a neutral "No outstanding AR" message. Don't show empty tables. Other zero-data sections (zero recent payments, zero monthly revenue) gracefully render "—" or hide the section.

What NOT to change

  • D-20: API route (app/api/mobile/finance/route.ts) is unchanged.
  • D-21: Data shape (FinanceData interface) is unchanged. The page consumes the existing fields.
  • D-22: No new sections, no new data sources, no new state libraries.
  • D-23: Sticky shell HeaderBar is provided by app/mobile/layout.tsx (Phase 2). No changes there.

Claude's Discretion

  • Exact spacing within rows (match existing density)
  • Whether to extract a small FinanceRow component (probably yes for DRY, but it's an internal helper — no public export needed)
  • Skeleton visual pattern
  • Whether the QBO sync timestamp displays inline or in a tooltip

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Phase spec

  • docs/superpowers/specs/2026-05-03-mobile-shell-design.md §6.3 (Finance) — Card/typography adoption, table→list conversion
  • .planning/REQUIREMENTS.md (FIN-01, FIN-02) — locked acceptance criteria

Project conventions

  • CLAUDE.md — Pulse stack rules (no SWR/react-query, no ORM, fetch-from-clients pattern), /mobile/* boundary, kebab-case files
  • DESIGN.md — token usage, navigation IA
  • ARCHITECTURE.md — runtime context (no impact this phase)

Prior phase contracts (typography/Card scale to mirror)

  • .planning/phases/02-mobile-shell/02-CONTEXT.md — shell decisions
  • .planning/phases/03-dashboard-restyle/03-01-SUMMARY.md — KpiCardMobile pattern (the 2×2 KPI grid uses the same scale this phase adopts)
  • .planning/phases/04-tickets-restyle/04-UI-SPEC.md — typography contract (2 weights, 3 sizes), color tokens, spacing scale; mirror in Phase 5 UI-SPEC

Existing code (entry points)

  • app/mobile/finance/page.tsx — current 309-line page being restyled
  • app/api/mobile/finance/route.ts — unchanged, just consumed
  • components/mobile/KpiCardMobile.tsx — Phase 3 KPI card pattern; reuse if the four summary tiles fit cleanly, otherwise mirror its structure
  • components/ui/{card,collapsible,skeleton}.tsx — shadcn primitives

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • KpiCardMobile from Phase 3 — direct fit for the four summary tiles (Total AR / Current / Overdue / Paid MTD). May need a tone="attention" for the overdue tile (red left border).
  • Skeleton from shadcn (components/ui/skeleton.tsx)
  • Collapsible from shadcn (already installed; used in Phase 4 filter strip)
  • shadcn primitives: Card, Button, Switch (for tab toggle if chosen)
  • lucide-react icons already imported (RefreshCw, TrendingUp, AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, CloudDownload)
  • fmt$() and fmtDate() helpers in the page file — keep them

Established Patterns

  • 'use client' + useState + useEffect + fetch('/api/mobile/finance') — keep this pattern; do not introduce SWR/react-query (CLAUDE.md rule)
  • import type from API route file for response shape (Phase 3/4 precedent)
  • Currency rendering: Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }) — already in the file

Integration Points

  • Page docks under app/mobile/layout.tsx shell (Phase 2). Sticky HeaderBar
    • bottom nav already render — this page just controls the scroll body.
  • BottomNav active-tab detection uses pathname.startsWith('/mobile/finance') — no changes needed.
  • The QBO sync endpoint (/api/qbo/sync) is consumed read-only here for the "last sync" timestamp — keep current behavior.

</code_context>

## Specific Ideas
  • Mirror Phase 3 visually: same 2×2 KPI tile look for the four summary stats (Total AR / Current / Overdue / Paid MTD). The "Paid MTD" tile may show YTD as caption (text-[10px]).
  • Match Phase 4 UI-SPEC's 2-weight, 3-size typography rule so dimension 4 passes when the UI checker runs on this phase.
  • Stacked card rows for invoices/payments should feel like the Tickets list rows (Phase 4) but without the priority left-stripe — Finance has no priority taxonomy, just dollar amounts.
## Deferred Ideas
  • Sortable invoice list (by amount, date, days-overdue) — not in FIN-* scope
  • Multi-currency support — out of scope (codebase is USD-only)
  • Drill-down into per-customer payment history — would be a new mobile surface, separate phase
  • Inline payment posting from mobile — read-only mobile principle (PROJECT.md Out of Scope)
  • A real chart for monthly revenue — explicit no-chart precedent (DASH-04)
  • Customer search / filter within Top Customers — not in FIN-* scope

Phase: 05-finance-restyle Context gathered: 2026-05-03