Skip to content

fix(web): repair portal earnings chart, dead header search, bare 404#32

Merged
jeffgicharu merged 1 commit into
mainfrom
fix/live-walkthrough-ui-polish
May 18, 2026
Merged

fix(web): repair portal earnings chart, dead header search, bare 404#32
jeffgicharu merged 1 commit into
mainfrom
fix/live-walkthrough-ui-polish

Conversation

@jeffgicharu
Copy link
Copy Markdown
Owner

Context

Full click-through of the live app surfaced three customer-facing issues that undercut an otherwise polished product. All three are on high-traffic surfaces (the contractor's landing screen, the global header, and the not-found path).

1. Portal "Monthly Earnings" chart rendered as a broken solid block — HIGH

Before: On /portal/dashboard the "Monthly Earnings" card used a Recharts BarChart with no maxBarSize. When a contractor's paid invoices land in a single month (the common case for the demo contractor), the lone bar expands to fill the entire category band — a giant full-width indigo rectangle that reads as a rendering failure, not a chart. This is the first screen the contractor demo account sees after login.

After: The card now uses the exact same gradient AreaChart the admin "Monthly Revenue" card already uses. An area series degrades gracefully with one or two data points (a small line/area instead of a wall of color), and the two dashboards now share a single, consistent chart treatment.

Why this fix: The admin dashboard already had a chart that handled sparse data well. Rather than patch the bar chart with width caps and a hand-tuned Y domain, aligning the portal to the existing, proven treatment fixes the bug and removes a design inconsistency between the two dashboards.

2. Header search control was dead and unlabelled — MED

Before: The magnifying-glass in the top bar was a <button> with no onClick and no accessible name. Clicking it did nothing; assistive tech announced only "button". The mobile nav toggle was also unnamed.

After: The search control is now a real, context-aware Link — to the contractor directory for admins, to invoices inside the portal — both of which have working search. It has an aria-label/title, and the mobile nav toggle now has an accessible name too.

Why this fix: A visible control that does nothing is worse than no control. Routing to the existing searchable list is an honest, complete behaviour (no half-built search modal) and closes the accessibility gap.

3. 404 page was unbranded and mis-routed — LOW/MED

Before: Root not-found.tsx was bare centered text on a flat background with no logo, and its only action pointed at /dashboard — an auth-gated route that bounces logged-out visitors to login.

After: Rebranded to match the auth shell (logo mark + product name + gradient) and the primary action now points at /, which resolves correctly whether the visitor is logged in or out. The in-shell admin 404 got a matching card treatment.

Tests

  • src/components/layout/header.test.tsx — search link target per context (admin vs portal) + accessible mobile nav toggle.
  • src/app/not-found.test.tsx — branded content and a safe / primary action on both not-found pages.

vitest run (32 tests) green, tsc --noEmit clean, next build succeeds. No new lint findings (the two remaining warnings are pre-existing and on untouched lines).

Final visual verification is performed against the live site after deploy.

🤖 Generated with Claude Code

Three customer-facing UI issues found during a full walkthrough of the
live app:

- Portal "Monthly Earnings" rendered as a single full-width bar that
  swallowed the whole plot area whenever a contractor's paid invoices
  fell in one month — it read as a broken solid block. Switched it to
  the same gradient AreaChart the admin "Monthly Revenue" card already
  uses, so it degrades gracefully with sparse data and the two
  dashboards now share one chart treatment.
- The header magnifying-glass was a button with no handler and no
  accessible name — clicking it did nothing and screen readers
  announced only "button". Made it a real, context-aware link to the
  searchable directory (contractors for admins, invoices in the
  portal) and gave the mobile nav toggle an accessible name.
- The 404 page was unbranded bare text and pointed logged-out users at
  an auth-gated route. Rebranded it to match the auth shell and pointed
  the primary action at "/", which resolves correctly in any auth
  state.

Adds regression tests for the header search/menu affordances and the
not-found pages.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the application's UI and accessibility, specifically redesigning the 404 error pages and updating the dashboard's earnings visualization from a bar chart to an area chart. It also improves the Header component by adding dynamic search links for the contractor portal and better accessibility attributes. New tests were introduced for the 404 pages and the Header. Feedback focused on improving the precision of currency formatting in the dashboard chart to avoid misleading rounding and ensuring consistent shadow styling across components.

tickLine={false}
tickFormatter={(v: number) => v >= 1000 ? `$${(v / 1000).toFixed(0)}k` : `$${v}`}
width={48}
tickFormatter={(v: number) => (v >= 1000 ? `$${(v / 1000).toFixed(0)}k` : `$${v}`)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of toFixed(0) rounds currency values to the nearest thousand, which can be misleading for financial data (e.g., $1,500 would be displayed as $2k). Consider using toFixed(1) and removing the trailing zero to provide better precision while keeping the labels concise.

Suggested change
tickFormatter={(v: number) => (v >= 1000 ? `$${(v / 1000).toFixed(0)}k` : `$${v}`)}
tickFormatter={(v: number) => (v >= 1000 ? `$${(v / 1000).toFixed(1).replace(/\.0$/, '')}k` : `$${v}`)}

Unified contractor lifecycle platform
</p>
</Link>
<div className="rounded-2xl border border-slate-200 bg-white p-8 text-center shadow-card">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Inconsistent shadow utility. The rest of the application, including the admin 404 card in apps/web/src/app/(admin)/not-found.tsx, uses shadow-xs. Unless shadow-card is a specific custom utility intended for this branded page, consider using shadow-xs for visual consistency.

Suggested change
<div className="rounded-2xl border border-slate-200 bg-white p-8 text-center shadow-card">
<div className="rounded-2xl border border-slate-200 bg-white p-8 text-center shadow-xs">

@jeffgicharu jeffgicharu merged commit 1d1a950 into main May 18, 2026
19 checks passed
@jeffgicharu jeffgicharu deleted the fix/live-walkthrough-ui-polish branch May 18, 2026 22:34
@jeffgicharu
Copy link
Copy Markdown
Owner Author

Deployed to production (deploy run 26064392129, success) and verified on the live site at https://contractoros.jeffgicharu.com:

  • Portal Monthly Earnings — the full-width clipped block is gone; it now renders as the gradient AreaChart and degrades gracefully with a single data point, consistent with the admin Monthly Revenue card.
  • Header search — now an accessible link: admin context navigates to /contractors, portal context to /portal/invoices. Mobile nav toggle has an accessible name.
  • 404 — now branded with the auth shell treatment; primary action routes to / and resolves in any auth state.

Admin dashboard, contractors list, and portal pages re-checked post-deploy — no regressions from the shared Header change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant