9.5 KiB
Phase 5: Finance Restyle - Context
Gathered: 2026-05-03 (auto mode) Status: Ready for planning
## Phase BoundaryRestyle 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 DecisionsCard adoption
- D-01: Use shadcn
Card+CardContent(matching the pattern fromKpiCardMobile). 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-semiboldfor the dollar amount,text-xs text-muted-foregroundfor the label, optional caption row intext-[10px] text-muted-foreground.
Typography scale (matches Phase 4 UI-SPEC)
- D-03: Two font weights only —
font-normal(400) andfont-semibold(600). Nofont-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 usetext-xlortext-2xlfor 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 (orborder-bdivided 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 overdueif applicable,text-xs text-muted-foreground) + date (right,text-xs text-muted-foreground)
- Line 1: customer name (left,
- 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
WorkerStatusRowfrom Phase 3) — no horizontal scroll. Each cell shows balance + count + label vertically. - D-09: Monthly revenue (
monthly_revenuearray, last 6 months) renders as a stacked list ofMonth → revenue → countrows. 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 byspace-y-6or visible section dividers. - D-11: Within a section:
space-y-3between rows. Inside a card:gap-3for 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 intext-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 witharia-labelper Phase 4 UI-SPEC dimension 1 conventions. - D-15: Keep the Open/Overdue tab toggle (
tabstate). Restyle as shadcn segmented buttons or a small chip pair. Don't add new tab options. - D-16: Keep the
invoicesOpen/paymentsOpencollapsibles, but render them with shadcnCollapsible(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
Skeletonfromcomponents/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_aris 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 (
FinanceDatainterface) 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
FinanceRowcomponent (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 filesDESIGN.md— token usage, navigation IAARCHITECTURE.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 restyledapp/api/mobile/finance/route.ts— unchanged, just consumedcomponents/mobile/KpiCardMobile.tsx— Phase 3 KPI card pattern; reuse if the four summary tiles fit cleanly, otherwise mirror its structurecomponents/ui/{card,collapsible,skeleton}.tsx— shadcn primitives
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
KpiCardMobilefrom Phase 3 — direct fit for the four summary tiles (Total AR / Current / Overdue / Paid MTD). May need atone="attention"for the overdue tile (red left border).Skeletonfrom shadcn (components/ui/skeleton.tsx)Collapsiblefrom shadcn (already installed; used in Phase 4 filter strip)- shadcn primitives:
Card,Button,Switch(for tab toggle if chosen) lucide-reacticons already imported (RefreshCw, TrendingUp, AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, CloudDownload)fmt$()andfmtDate()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 typefrom 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.tsxshell (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.
- 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