-
-
Notifications
You must be signed in to change notification settings - Fork 73
Open
Labels
Description
Summary
Build the resume scorer UI as a page at /resume-scorer with React components that call the FastAPI backend through the BFF proxy routes.
Dependencies
- [Resume Scorer] Next.js BFF proxy routes for FastAPI backend #995 (BFF proxy routes + frontend client library)
Implementation
1. Page
File: src/pages/resume-scorer.tsx
- Protected page — redirect to
/loginif not authenticated (same pattern asresume-translator.tsx) - Uses the main layout wrapper
- Sections:
- Header with title and description
- Upload + input form (left column)
- Analysis criteria table (right column)
- Results (full width, below form)
- Benchmark comparison (below results)
2. Components
Directory: src/components/resume-scorer/
| Component | Purpose |
|---|---|
ResumeUploadForm.tsx |
File upload (PDF/DOCX/TXT), job title input, optional JD textarea, analyze button. Calls parseResumeFile() then analyzeResume() from the client lib. |
OverallScore.tsx |
Large centered score (0-100), summary text, color-coded (green/amber/red) |
DimensionBreakdown.tsx |
Grid of 7 ScoreGauge components (4 cols desktop, 2 mobile) |
ScoreGauge.tsx |
Single dimension: label, number, progress bar. Color by threshold. |
StrengthsAndImprovements.tsx |
Two-column layout. Strengths (navy border cards), Improvements (issue + recommendation + example) |
SkillTags.tsx |
Reusable tag component with variants: found (navy), missing (outline), semantic (blue) |
JdMatchSection.tsx |
JD match percentage, matched vs missing skill columns |
RedFlagSection.tsx |
Flags (red), warnings (amber), risk score badge, experience quality bars |
BenchmarkComparison.tsx |
Category selector (from /categories), sample size selector, compare button, results table |
AnalysisHistory.tsx |
Sidebar list of last 10 analyses from /history. Click to re-view. |
CostEstimate.tsx |
Token count, estimated cost, rate limit remaining |
DownloadReport.tsx |
Button to download full JSON report |
3. State management
Use React hooks — no context needed for a single page:
const [isAnalyzing, setIsAnalyzing] = useState(false);
const [results, setResults] = useState<AnalyzeResponse | null>(null);
const [error, setError] = useState<string | null>(null);
async function handleAnalyze() {
setIsAnalyzing(true);
setError(null);
try {
// Step 1: Parse file if uploaded
let resumeText = pastedText;
if (file) {
const parsed = await parseResumeFile(file);
resumeText = parsed.text;
}
// Step 2: Analyze
const result = await analyzeResume({ resume_text: resumeText, job_title: jobTitle, job_description: jd });
setResults(result);
} catch (err) {
if (err.status === 429) setError("Rate limit reached. Please wait and try again.");
else setError("Analysis failed. Please try again.");
} finally {
setIsAnalyzing(false);
}
}4. Loading states
- File upload: "Extracting text..."
- Analysis: animated progress with steps ("Parsing work history...", "Analyzing resume...", "Computing scores...")
- Use
framer-motionfor score count-up animation on gauges
5. Design
- Follow existing
tw-prefix convention for all Tailwind classes - VWC brand colors: Navy
#091f40, Red, Gold, Cream - Radix UI primitives for Select, Dialog, Tabs
- Responsive: stack on mobile, side-by-side on desktop
- Match the clean, professional aesthetic of the rest of the app
6. Error handling
- Network errors: "Service unavailable, try again"
- 429 rate limit: show remaining count, cooldown timer
- Invalid file: "Unsupported format" or "File too large"
- Gemini failure: "Analysis failed after retries, please try again"
- Wrap page in error boundary
Acceptance Criteria
-
/resume-scorerpage renders with upload form - File upload handles PDF, DOCX, TXT via BFF proxy
- Analysis results show all 7 dimension scores with gauges
- JD match section appears when job description is provided
- Red flags and experience analysis display correctly
- Benchmark comparison fetches categories from API and shows comparison
- Analysis history shows past results
- Download report button generates JSON
- Rate limit status displayed, 429 handled gracefully
- Fully responsive (mobile + desktop)
- Protected by authentication
- All components use
tw-prefix and VWC brand colors - Score animations with framer-motion
Reactions are currently unavailable