Skip to main content

Jobseeker Dashboard Enhancement & Boost CV Feature

Overview

This document covers three interconnected changes to the jobseeker experience:

  1. Dashboard Enhancement — Full rewrite of the jobseeker dashboard with KPIs, pipeline visualization, charts, and quality metrics
  2. Boost CV Feature — When a job's match score is below 70%, the "Apply" button is replaced with "Boost My CV" across all surfaces
  3. Boost CV Edit Context — Clicking "Boost My CV" navigates directly to the CV edit page with job-specific recommendations displayed

1. Dashboard Enhancement

File: components/reusable/dashboard/jobseeker/JobSeekerDashboardSlim.tsx

The dashboard was rewritten from a minimal 3-section layout into a comprehensive 7-section dashboard:

SectionDescription
Profile CompletionEnhanced card with circular progress, quick-win field suggestions, and next group suggestion
KPI Row4 colored stat cards using Kpi from ChartBits: Applications, Avg Match %, Profile Views, Recommended Jobs
Application PipelineHorizontal funnel: Submitted → In Review → Interview → Approved, with counts and percentages
Charts RowWeekly Recommendations Trend (AreaChart) + Match Score Distribution (BarChart)
Quality Metrics5 circular progress indicators: Profile Completion, Response Rate, Offer Rate, In Review %, Interview %
Recommended JobsExisting RecommendedGrid component with job cards
Upcoming DeadlinesTable of jobs with approaching due dates

Key Design Decisions

  • Reuses ChartBits utilities (Kpi, DefaultTooltip, COLORS, GRADIENTS) from the company dashboard for visual consistency
  • All data comes from the existing GET_JOBSEEKER_DASHBOARD query — no new GraphQL queries needed
  • Derived metrics (avg match, pipeline rates, trend data, match distribution) computed via useMemo
  • Uses Recharts (AreaChart, BarChart) for data visualization

File: app/jobseeker/dashboard/page.tsx

  • Added personalized hero with time-of-day greeting (Good Morning/Afternoon/Evening)
  • Improved loading skeleton to match new layout

2. Boost CV Feature (Match Score < 70%)

Threshold Logic

When a job's match score is below 70%, the user should improve their CV instead of applying directly. The "Apply" button is replaced with "Boost My CV" across three surfaces.

Affected Surfaces

A. Dashboard Cards (components/reusable/jobs/JobSeekerCard.tsx)

  • When matchScore < 70 and the card is on an authenticated page (not landing), the Apply button is replaced with a "Boost Your CV" button
  • Clicking it opens a modal showing:
    • Match percentage indicator
    • Parsed recommendations from matchDetails
    • Missing must-have skills
  • The modal's "Boost My CV" button navigates to the CV edit page with boost context

B. Jobs Listing Page (app/jobseeker/jobs/page.tsx)

  • Uses the TWResponsiveCard declarative card system
  • isLowMatch: boolean flag is added to UiJobData (set when matchScore < 70)
  • Card config in jobSeekerJobConfig.ts uses conditional visibility:
    { key: "apply", hideIf: "hasApplied", requireAll: ["!isLowMatch"] }
    { key: "boostCv", showIf: "isLowMatch", requireAll: ["!hasApplied"] }
  • boostCv action registered in actionConfigs.tsx with ResumeIcon and amber color

C. Job Detail Page (app/jobseeker/jobs/[jobId]/page.tsx + components/reusable/jobs/JobDetails.tsx)

  • JobDetailBody accepts matchScore prop
  • When matchScore < 70 (and not in withdraw mode), the bottom CTA shows "Boost My CV" (warning color) instead of "Apply Now"
  • The "Boost Your CV to Match This Role" section's button also triggers the boost navigation
  • Match score qualifications fetched via GET_USER_JOB_MATCH_SCORE lazy query

Match Data Parsing

Recommendations and missing skills are parsed from the match score response:

matchScoreData.getUserJobMatchScore
├── qualifications (preferred) OR details.unified_report
│ ├── recommendations: string[]
│ └── component_scores[]
│ └── find(c => c.component_name === "skills")
│ └── analysis[]
│ └── filter(!matched && is_must_have)
│ └── map(s => s.job_skill_name)

3. Boost CV Edit Context

Problem

When a user clicks "Boost My CV", they should go directly to CV edit mode with the job-specific recommendations visible, so they know exactly what to improve.

Solution: sessionStorage + URL query param + lazy query

Flow

  1. Source page (job detail / listing / dashboard card) calls setBoostCvContext() to store recommendations in sessionStorage
  2. Navigation goes to /jobseeker/resume/edit/{activeCvId}?boost=true
  3. CV edit page reads ?boost=true, loads context from sessionStorage, displays a dismissible amber banner
  4. If the source only had a jobId (no detailed recommendations), the edit page fires a lazy query to GET_USER_JOB_MATCH_SCORE
  5. Context is cleared on unmount — truly temporary

Utility: lib/utils/cv/boostCvContext.ts

type BoostCvSessionData = {
jobId: string
jobTitle?: string
recommendations: string[]
missingSkills: string[]
matchScore?: number
}

setBoostCvContext(data) // Store in sessionStorage
getBoostCvContext() // Read from sessionStorage (returns null if absent)
clearBoostCvContext() // Remove from sessionStorage

Source Page Changes

FileChange
app/jobseeker/jobs/[jobId]/page.tsxhandleBoostCv() stores full context (recommendations, missingSkills, jobTitle, matchScore), navigates to edit page
components/reusable/jobs/JobDetails.tsxNew onBoostCv?: () => void prop; both Boost buttons delegate to parent handler
components/reusable/jobs/JobSeekerCard.tsxModal's "Boost My CV" button stores context from parsed matchDetails, navigates to edit page
app/jobseeker/jobs/page.tsxonBoostCvClick stores minimal context (jobId, title, matchScore), navigates to edit page

All sources fall back to /jobseeker/resume if user.activeCvId is not available (user needs to create/select a CV first).

CV Edit Page Changes (app/jobseeker/resume/edit/[cvId]/page.tsx)

  • Reads ?boost=true from URL search params
  • Reads BoostCvSessionData from sessionStorage on mount
  • If recommendations array is empty, fires GET_USER_JOB_MATCH_SCORE lazy query using the stored jobId
  • Parses match details into boostPointers (recommendations + missingSkills) via useMemo
  • Renders a dismissible amber banner above the ProfileForm:
    • Job title ("Boost your CV for: {title}")
    • Recommendations (bulleted list)
    • Missing skills (amber-bordered pills)
    • Dismiss button (clears sessionStorage)
  • Calls clearBoostCvContext() on component unmount
┌──────────────────────────────────────────────────────┐
│ 📄 Boost your CV for: "Senior React Developer" [X] │
│ │
│ RECOMMENDATIONS │
│ • Add more detail to your React experience │
│ • Highlight TypeScript proficiency │
│ │
│ MISSING SKILLS │
│ [GraphQL] [Docker] [AWS] │
└──────────────────────────────────────────────────────┘

Styled with bg-amber-50 border-amber-200 to match the existing boost section in the job detail page.


File Index

FileRole
lib/utils/cv/boostCvContext.tssessionStorage utility for boost context
components/reusable/jobs/JobDetails.tsxJob detail body with onBoostCv prop
components/reusable/jobs/JobSeekerCard.tsxDashboard/search job card with boost modal
app/jobseeker/jobs/page.tsxJobs listing page with card system
app/jobseeker/jobs/[jobId]/page.tsxJob detail page with boost handlers
app/jobseeker/resume/edit/[cvId]/page.tsxCV edit page with boost banner
app/jobseeker/dashboard/page.tsxDashboard page with hero
components/reusable/dashboard/jobseeker/JobSeekerDashboardSlim.tsxDashboard component
components/ux/TWResponsiveCard/cardBuilder/actions/actionConfigs.tsxboostCv action config
components/ux/TWResponsiveCard/cardBuilder/configs/jobSeekerJobConfig.tsConditional action visibility