Skip to content

[Resume Scorer] Next.js frontend page and React components #996

@jeromehardaway

Description

@jeromehardaway

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

Implementation

1. Page

File: src/pages/resume-scorer.tsx

  • Protected page — redirect to /login if not authenticated (same pattern as resume-translator.tsx)
  • Uses the main layout wrapper
  • Sections:
    1. Header with title and description
    2. Upload + input form (left column)
    3. Analysis criteria table (right column)
    4. Results (full width, below form)
    5. 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-motion for 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-scorer page 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions