feat(ui): instant match-score panel on the Candidate Fit tab
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>
This commit is contained in:
@@ -867,6 +867,20 @@ export const translations = {
|
||||
jobDetailsFollowUpSent: "Follow-up sent and logged.",
|
||||
jobDetailsFollowUpSendFailed: "Failed to send follow-up.",
|
||||
jobDetailsHowYouMatch: "How you match",
|
||||
matchScoreTitle: "Match score",
|
||||
matchScoreLoading: "Scoring your CV against this role…",
|
||||
matchScoreBand_Strong: "Strong match",
|
||||
matchScoreBand_Partial: "Partial match",
|
||||
matchScoreBand_Low: "Low match",
|
||||
matchScoreBand_Unknown: "Not enough signal",
|
||||
matchScoreKeywordsCovered: "{matched}/{total} keywords",
|
||||
matchScoreNoSignal: "Add more CV detail or a fuller job description to get a reliable score.",
|
||||
matchScoreDeterministicHint: "Deterministic keyword coverage — no AI, so the score is stable and repeatable.",
|
||||
matchScoreMatched: "Matched keywords",
|
||||
matchScoreMissing: "Missing keywords",
|
||||
matchScoreNoneYet: "No matches found yet.",
|
||||
matchScoreAllCovered: "Every keyword is covered.",
|
||||
matchScoreSectionCoverage: "Where your CV covers this role",
|
||||
jobDetailsStrategySnapshot: "Strategy snapshot",
|
||||
jobDetailsGenerateStrategySnapshot: "Generate strategy snapshot",
|
||||
jobDetailsStrategySnapshotEmpty: "Generate a snapshot to see fit, positioning, and immediate priorities in one place.",
|
||||
@@ -1784,6 +1798,20 @@ export const translations = {
|
||||
jobDetailsFollowUpSent: "Oppfølging sendt og loggført.",
|
||||
jobDetailsFollowUpSendFailed: "Kunne ikke sende oppfølging.",
|
||||
jobDetailsHowYouMatch: "Slik matcher du",
|
||||
matchScoreTitle: "Match-score",
|
||||
matchScoreLoading: "Vurderer CV-en mot denne stillingen…",
|
||||
matchScoreBand_Strong: "Sterk match",
|
||||
matchScoreBand_Partial: "Delvis match",
|
||||
matchScoreBand_Low: "Lav match",
|
||||
matchScoreBand_Unknown: "For lite grunnlag",
|
||||
matchScoreKeywordsCovered: "{matched}/{total} nøkkelord",
|
||||
matchScoreNoSignal: "Legg til mer CV-innhold eller en fyldigere stillingstekst for en pålitelig score.",
|
||||
matchScoreDeterministicHint: "Deterministisk nøkkelorddekning — ingen AI, så scoren er stabil og repeterbar.",
|
||||
matchScoreMatched: "Treff på nøkkelord",
|
||||
matchScoreMissing: "Manglende nøkkelord",
|
||||
matchScoreNoneYet: "Ingen treff ennå.",
|
||||
matchScoreAllCovered: "Alle nøkkelord er dekket.",
|
||||
matchScoreSectionCoverage: "Hvor CV-en dekker denne rollen",
|
||||
jobDetailsStrategySnapshot: "Strategioversikt",
|
||||
jobDetailsGenerateStrategySnapshot: "Generer strategioversikt",
|
||||
jobDetailsStrategySnapshotEmpty: "Generer en oversikt for å se match, posisjonering og viktigste prioriteringer på ett sted.",
|
||||
|
||||
Reference in New Issue
Block a user