/* ============================================================ Progress — single master/detail view of GET /job/stats/fetch. Left: searchable/filterable job index (paged). Right: selected job pipeline breakdown. Days-open is computed client-side from created_at. ============================================================ */ import { useEffect, useMemo, useState } from 'react' import { useSearchParams } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import PageHeader from '../ui/PageHeader' import { Badge, EmptyState, Icon, SkeletonRows } from '../ui/primitives' import { qk } from '../lib/queryKeys' import { friendlyAuthError } from '../lib/errors' import * as jobStatsApi from '../api/jobStats' const PAGE_SIZE = 10 const STAGES = [ { key: 'shortlist', label: 'Shortlisted', tone: 'blue' }, { key: 'screened', label: 'Screened', tone: 'purple' }, { key: 'assessment', label: 'Assessment', tone: 'amber' }, { key: 'interviewed', label: 'Interviewed', tone: 'indigo' }, { key: 'offered', label: 'Offered', tone: 'teal' }, { key: 'onHold', label: 'On hold', tone: 'amber' }, { key: 'rejected', label: 'Rejected', tone: 'red' }, { key: 'hired', label: 'Hired', tone: 'teal' }, ] function sumField(jobs, key) { return jobs.reduce((total, job) => total + (Number(job[key]) || 0), 0) } function statusTone(status) { const value = String(status || '').toLowerCase() if (value === 'open') return 'success' if (value === 'on_hold' || value === 'on hold') return 'warning' return 'muted' } function Metric({ value, label, accent = false }) { return (
{value} {label}
) } function JobRow({ job, active, onSelect }) { return (