Restyle JobDetailsDialog.tsx (04-job-workspace.png mockup) within its
existing dialog/tab structure -- the real app splits Correspondence,
Attachments, and Candidate Fit into separate tabs rather than the
mockup's single-screen 2x2 card grid, so this is a visual-language
pass over the existing IA, not a restructure:
- Header: bolder title (h5/800), heavier status chip, cleaner
no-underline tab styling.
- Every flat bordered "fake card" Box (11 instances across all tabs,
plus the 2 in the Overview strategy-snapshot panel) becomes a
floating shadow card with no border, matching every other screen
redesigned this session.
- The two genuinely AI-generation actions (Generate Strategy Snapshot,
and by extension the shared GradientButton component) get the
mockup's signature gradient CTA treatment; the confirm-gated
"Refresh AI summary" action stays a plain outlined button so the
gradient doesn't get diluted by a second use on the same tab.
Also fixes a real bug surfaced by actually using GradientButton for
the first time: its sx callback read theme.vars.customShadows, which
throws when a component renders without this app's ThemeProvider --
true in production always, but true in every test in this repo (none
of them wrap with a ThemeProvider), so every test touching a
GradientButton or one of these restyled boxes crashed. Fixed by using
a static shadow value instead of a theme.vars lookup in both the
component and this file, matching the fact that inline sx callbacks
execute against whatever theme is in context (unlike theme.components
styleOverrides, which only run when this app's real theme is actually
provided).
Verified: tsc clean, full suite green (65/65, including 4 test files
that render this exact dialog). Live check: booted the backend and
loaded the dashboard through a fresh Next.js dev server + cache
(cleared .next after chasing what turned out to be a stale console-log
history in the Browser pane tooling, not a real compile error) --
confirmed real data renders with no actual runtime errors.
Continuing the product/UX review's deferred items:
- Every top-level view now gets a one-line subtitle under its title
(Dashboard/Jobs/Kanban/Reminders/Correspondence/Gmail review) stating
what that specific view is for, instead of navigation being the only
signal of what each page does.
- Correspondence inbox and Gmail review queue cross-link to each other
instead of being two unexplained flat sidebar items -- kept both nav
entries (renaming/nesting risked breaking muscle memory) but made the
relationship between them explicit in the UI itself.
- Kanban board switches to a horizontal scroll-snap row on phone-width
viewports instead of stacking all 5 columns vertically, which meant
a lot of scrolling to see anything past "Applied".
- Match-score ring gets an aria-label with the actual percentage --
it was two nested decorative CircularProgress elements with no
accessible text. (Keyboard-accessible status changes on kanban cards
were already covered by the existing "..." menu -- no gap there.)
Implements the six "propose first" items from the product/UX review:
- "/" now redirects to /dashboard instead of the empty /jobs table --
a new user's first screen is now an overview with orientation, not
a data table with zero rows and four filter dropdowns.
- Jobs table gets a real first-time empty state (distinct from "no
results match your filters") pointing at Add Job and the bookmarklet,
instead of a bare "No jobs found."
- Match Score card and Candidate Fit tab now each get a one-line
caption explaining what they are and how they differ (deterministic
keyword coverage vs. AI opinion) -- they previously sat side by side
with no explanation of why there are two.
- Google sign-in hint now reflects self-serve signup when
Auth:AllowRegistration is on, instead of always implying you need an
existing linked account.
- Quick Search button now shows its keyboard shortcut (Ctrl+K / ⌘K)
inline instead of being undiscoverable.
Second UI-rework pass. The job workspace mockup's signature element is
a donut "coverage" ring for the deterministic CV match score; the app
had a linear progress bar instead. Replaced with a layered
CircularProgress ring (track + value arc, percentage centered) while
keeping every existing feature (band chip, matched/missing keyword
chips, section coverage) -- this is a pure visual upgrade to the
existing MatchScoreCard, not a feature reduction to match the mockup's
simpler single-panel layout.
Fixed match-score-panel.test.tsx's no-signal-state assertion, which
expected the removed inline "—" placeholder; restored it outside the
ring's conditional render.
When a job workspace opens, loads /status-suggestion and shows a
dismissible banner when a recent inbound email implies a status move
("This email looks like a move to Interview"). Applying it PATCHes the
status; nothing changes without the user's click.
- StatusSuggestion type + load-on-open effect + apply handler
- warning-toned banner shown above tab content on any tab
- EN/NB translations; README endpoint docs
- 2 frontend tests; full suite green (21 suites / 48 tests)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a MatchScoreCard at the top of the Candidate Fit tab that loads the
deterministic /match-score endpoint independently of the slow AI
narrative, so users see a reproducible score, matched/missing keyword
chips, and per-section coverage immediately.
- MatchScore types + cached, attachment-independent load effect
- graceful 'not enough signal' state
- EN/NB translations
- frontend panel test (matched/missing/section + degraded state)
- backend integration tests for GetMatchScore (happy path + missing CV)
- README endpoint reference
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>