import { useMemo } from 'react' import { Link, useSearchParams } from 'react-router-dom' import { useQueries, useQuery } from '@tanstack/react-query' import { ArrowLeft, Loader2, Trophy } from 'lucide-react' import { screenApi } from './api' import { screenBrand } from './brand' import { Badge, Panel } from '../../components/ui' import { ToolHeader } from '../../components/ToolHeader' import { Gauge } from '../../components/Gauge' import { bandColor, num } from '../../lib/format' import type { ScreenView } from '../../lib/types' // Side by side comparison of up to three candidates against one requirement. Each column is the // SAME explainable screen the single evaluation page shows, fetched through the same endpoint, so // the numbers can never disagree between views. export function ScreenCompare() { const [params] = useSearchParams() const requirementId = params.get('req') ?? '' const candidateIds = useMemo( () => (params.get('c') ?? '').split(',').filter(Boolean).slice(0, 3), [params], ) const requirement = useQuery({ queryKey: ['screenmatch', 'requirement', requirementId], queryFn: () => screenApi.requirement(requirementId), enabled: !!requirementId, }) const screens = useQueries({ queries: candidateIds.map((cid) => ({ queryKey: ['screenmatch', 'compare', cid, requirementId], queryFn: async () => ({ candidate: await screenApi.candidate(cid), view: await screenApi.screen(cid, requirementId), }), enabled: !!requirementId, })), }) const loaded = screens.filter((s) => s.data).map((s) => s.data!) const bestTotal = loaded.length ? Math.max(...loaded.map((s) => num(s.view.match.total_score))) : 0 return (
Back to Screening Queue {!requirementId || candidateIds.length < 2 ? (

Pick two or three candidates in the Screening Queue and choose Compare.

) : ( <> {requirement.data && (
Comparing against
{requirement.data.title}
)}
{screens.map((s, i) => (
{s.isLoading && ( Scoring… )} {s.isError && (

{(s.error as Error).message}

)} {s.data && ( 1} /> )}
))}
)}
) } function CompareColumn({ name, view, best }: { name: string; view: ScreenView; best: boolean }) { const m = view.match return (

{name}

{best && ( Strongest fit )}
{m.trace.map((t) => (
{t.component} {num(t.raw).toFixed(0)}
))}
Gaps
{m.gap_summary.length === 0 ? (

No mandatory gaps.

) : (
    {m.gap_summary.map((g) => (
  • {g}
  • ))}
)}

Weight profile {m.weight_profile_version}

) }