Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / frontend/src/components/ScreeningResults.tsx |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | frontend/src/components/ScreeningResults.tsx |
| Original SHA-256 | d6e3eb09d781c529bc48bfbb7e578c9929284672d4cb2027ea5fde707b4aa13c |
| Git blob SHA | e997fbe274b6e05cf4126c04faa57920558078d4 |
| Reading-copy SHA-256 | d6e3eb09d781c529bc48bfbb7e578c9929284672d4cb2027ea5fde707b4aa13c |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / frontend/src/components/ScreeningResults.tsx | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / frontend/src/components/ScreeningResults.tsx | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓326 lines · 12.9 KB
import type { ReactNode } from 'react'
import {
AlertTriangle,
Award,
BadgeCheck,
Briefcase,
CalendarClock,
CheckCircle2,
Clock,
Crown,
FileText,
MapPin,
ShieldCheck,
Target,
TrendingUp,
} from 'lucide-react'
import type { CandidateListView, RequirementListView, ScreenView } from '../lib/types'
import { bandColor, clearanceLabel, num, stateColor } from '../lib/format'
import { Badge, CheckRow, Panel, ScoreRow } from './ui'
import { Gauge } from './Gauge'
function winColor(code: string): string {
return code === 'high'
? 'var(--color-ok)'
: code === 'medium'
? 'var(--color-warn)'
: 'var(--color-risk)'
}
export function ScreeningResults({
view,
candidate,
requirement,
hideHeader = false,
}: {
view: ScreenView
candidate: CandidateListView
requirement: RequirementListView
hideHeader?: boolean
}) {
const mr = view.mission_readiness
const ci = view.clearance_intelligence
const wi = view.win_impact
const matched = view.match.matched_skills.filter((m) => m.matched)
return (
<div className="space-y-4">
{/* SECTION A, Candidate Summary */}
{!hideHeader && (
<Panel className="flex flex-wrap items-center justify-between gap-4 p-4">
<div className="flex items-center gap-4">
<div className="grid size-14 place-items-center rounded-xl bg-blue/25 text-xl font-bold text-blue-soft">
{candidate.full_name
.split(' ')
.map((p) => p[0])
.slice(0, 2)
.join('')}
</div>
<div>
<div className="flex items-center gap-2">
<h2 className="text-xl font-bold">{candidate.full_name}</h2>
<span style={{ color: 'var(--color-gold)' }}>
<BadgeCheck size={18} />
</span>
</div>
<div className="mt-0.5 flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted">
<span className="flex items-center gap-1.5">
<Briefcase size={14} /> {requirement.title}
</span>
<span className="flex items-center gap-1.5">
<Clock size={14} /> {candidate.years_experience} yrs
</span>
{candidate.location && (
<span className="flex items-center gap-1.5">
<MapPin size={14} /> {candidate.location}
</span>
)}
<span className="flex items-center gap-1.5">
<ShieldCheck size={14} /> {clearanceLabel[candidate.clearance_level] ?? candidate.clearance_level}
</span>
</div>
</div>
</div>
<div className="flex items-center gap-2">
<Badge color={candidate.available ? 'var(--color-ok)' : 'var(--color-warn)'} subtle>
{candidate.available ? 'Available Now' : 'Not Available'}
</Badge>
<button className="flex items-center gap-1.5 rounded-lg border border-line/70 px-3 py-1.5 text-sm font-semibold text-muted hover:text-ink">
<FileText size={14} /> Export Report
</button>
</div>
</Panel>
)}
<div className="grid grid-cols-1 gap-4 lg:grid-cols-12">
{/* SECTION B, Mission Readiness gauge */}
<Panel className="lg:col-span-4 grid place-items-center py-6">
<Gauge value={num(mr.score)} color={bandColor(mr.band)} status={mr.status} />
<p className="mt-3 max-w-[18rem] text-center text-sm text-muted">{view.match.explanation}</p>
</Panel>
{/* SECTION C + D, Requirement summary + qualification breakdown */}
<div className="lg:col-span-5 space-y-4">
<Panel title="Requirement">
<div className="flex items-center justify-between">
<div>
<div className="text-base font-bold">{requirement.title}</div>
<div className="text-sm text-muted">
{requirement.customer_agency ?? 'No specific customer'} ·{' '}
{clearanceLabel[requirement.required_level] ?? requirement.required_level} required
</div>
</div>
{requirement.key_personnel && (
<Badge color="var(--color-gold)" subtle>
<Crown size={12} /> Key Personnel
</Badge>
)}
</div>
</Panel>
<Panel title="Qualification Breakdown" hint="why the score was generated">
<div className="space-y-3">
{mr.categories.map((cat) => (
<ScoreRow
key={cat.name}
name={cat.name}
weight={cat.weight}
score={cat.score}
color={stateColor(cat.state)}
/>
))}
</div>
<div className="mt-3 space-y-1 border-t border-line/60 pt-2.5">
<div className="text-[11px] font-bold uppercase tracking-wider text-muted">Evidence</div>
{view.match.trace.map((t) => (
<p key={t.component} className="text-xs leading-relaxed text-faint">
<span className="font-semibold text-muted">{t.component}</span> ({t.weight}): {t.rationale}
</p>
))}
<p className="pt-1 text-[11px] text-faint">
Weight profile <span className="font-semibold text-muted">{view.match.weight_profile_version}</span>, applied by the scoring engine and recorded with this result.
</p>
</div>
</Panel>
</div>
{/* SECTION H (Win) + Clearance Intelligence */}
<div className="lg:col-span-3 space-y-4">
<Panel title="Win Impact™">
<div className="text-2xl font-extrabold" style={{ color: winColor(wi.level_code) }}>
{wi.level}
</div>
<div className="mt-0.5 text-xs text-faint">
Staffing strength {num(wi.staffing_strength).toFixed(0)}%
</div>
<ul className="mt-2.5 space-y-1.5">
{(wi.reasons ?? []).map((r) => (
<li key={r} className="flex items-start gap-1.5 text-sm text-ink">
<CheckCircle2 size={15} style={{ color: 'var(--color-ok)' }} className="mt-0.5 shrink-0" />
{r}
</li>
))}
</ul>
</Panel>
<Panel title="Clearance Intelligence">
<div className="flex items-center justify-between">
<span className="text-lg font-bold">{ci.current}</span>
<Badge color={ci.expired ? 'var(--color-risk)' : 'var(--color-ok)'} subtle>
{ci.expired ? 'Expired' : ci.status}
</Badge>
</div>
<div className={`mt-1 text-[11px] ${ci.verified ? 'font-semibold text-ok' : 'text-faint'}`}>
{ci.verified ? '✓ ' : ''}
{ci.provenance_label}
{ci.verified_at ? ` ${ci.verified_at}` : ''}
</div>
<div className="mt-2.5 flex flex-wrap gap-1.5">
{ci.sci_eligible && <Tag>SCI Eligible</Tag>}
{ci.ci_poly_eligible && <Tag>CI Poly Eligible</Tag>}
{ci.full_scope_poly && <Tag>Full Scope Poly</Tag>}
{ci.recent_classified_support && <Tag>Recent Classified Support</Tag>}
</div>
<dl className="mt-3 space-y-1.5 text-sm">
{typeof ci.investigation_age_months === 'number' && (
<Row icon={<CalendarClock size={14} />} k="Investigation age" v={`${ci.investigation_age_months} mo`} />
)}
{ci.expires_at && <Row icon={<Clock size={14} />} k="Expires" v={ci.expires_at} />}
</dl>
</Panel>
</div>
</div>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
{/* SECTION E, Top Matching Skills */}
<Panel title="Top Matching Skills">
{matched.length === 0 ? (
<p className="text-sm text-faint">No specific skills required for this requirement.</p>
) : (
<div className="space-y-2.5">
{matched.map((m) => (
<div key={m.required_skill} className="flex items-center justify-between">
<span className="flex items-center gap-2 text-sm">
<Target size={14} style={{ color: 'var(--color-blue-soft)' }} />
{m.required_skill}
</span>
<Badge color={m.exact ? 'var(--color-ok)' : 'var(--color-blue)'} subtle>
{m.exact ? 'Exact' : `Semantic ${(num(m.similarity) * 100).toFixed(0)}%`}
</Badge>
</div>
))}
</div>
)}
</Panel>
{/* SECTION F, Gaps to Review */}
<Panel title="Gaps to Review">
{view.battle_card.gaps.length === 0 ? (
<p className="flex items-center gap-2 text-sm" style={{ color: 'var(--color-ok)' }}>
<CheckCircle2 size={16} /> No mandatory gaps identified.
</p>
) : (
<ul className="space-y-1.5">
{view.battle_card.gaps.map((g) => (
<li key={g} className="flex items-start gap-2 text-sm text-warn">
<AlertTriangle size={15} className="mt-0.5 shrink-0" />
{g}
</li>
))}
</ul>
)}
</Panel>
{/* SECTION H, Battle Card */}
<Panel title="Candidate Battle Card™">
<div className="grid grid-cols-2 gap-4">
<div>
<div className="mb-1.5 text-[11px] font-bold uppercase tracking-wider text-muted">Strengths</div>
<ul className="space-y-1">
{view.battle_card.strengths.length === 0 && <li className="text-sm text-faint">n/a</li>}
{view.battle_card.strengths.map((s) => (
<li key={s} className="flex items-start gap-1.5 text-sm">
<CheckCircle2 size={14} style={{ color: 'var(--color-ok)' }} className="mt-0.5 shrink-0" />
{s}
</li>
))}
</ul>
</div>
<div>
<div className="mb-1.5 text-[11px] font-bold uppercase tracking-wider text-muted">Risks</div>
<ul className="space-y-1">
{view.battle_card.gaps.length === 0 && <li className="text-sm text-faint">None</li>}
{view.battle_card.gaps.map((g) => (
<li key={g} className="flex items-start gap-1.5 text-sm">
<AlertTriangle size={14} style={{ color: 'var(--color-warn)' }} className="mt-0.5 shrink-0" />
{g}
</li>
))}
</ul>
</div>
</div>
</Panel>
{/* Contract Readiness */}
<Panel title="Contract Readiness">
<div className="space-y-1.5">
{view.contract_readiness.areas.map((a) => (
<CheckRow key={a.area} ok={a.met} label={a.area} />
))}
</div>
{view.contract_readiness.risks.length > 0 && (
<div className="mt-3 border-t border-line/60 pt-2.5">
<div className="mb-1.5 text-[11px] font-bold uppercase tracking-wider text-muted">Risk Areas</div>
<ul className="space-y-1">
{view.contract_readiness.risks.map((r) => (
<li key={r.message} className="flex items-start gap-1.5 text-sm text-warn">
<AlertTriangle size={14} className="mt-0.5 shrink-0" />
{r.message}
</li>
))}
</ul>
</div>
)}
</Panel>
</div>
{/* SECTION I, Recommended Next Actions */}
<Panel title="Recommended Next Actions">
<div className="flex flex-wrap gap-2.5">
{view.next_steps.map((step, i) => (
<button
key={step.action}
className={`group flex items-center gap-2 rounded-lg px-4 py-2.5 text-sm font-semibold transition-colors ${
i === 0
? 'bg-gradient-to-r from-blue to-navy-700 text-white hover:brightness-110'
: 'border border-line/70 text-muted hover:text-ink'
}`}
title={step.reason}
>
{i === 0 ? <TrendingUp size={15} /> : <Award size={15} />}
{step.action}
</button>
))}
</div>
</Panel>
</div>
)
}
function Tag({ children }: { children: ReactNode }) {
return (
<span className="rounded-md border border-line/70 bg-navy-800/60 px-2 py-0.5 text-[11px] font-medium text-blue-soft">
{children}
</span>
)
}
function Row({ icon, k, v }: { icon: ReactNode; k: string; v: string }) {
return (
<div className="flex items-center justify-between">
<span className="flex items-center gap-1.5 text-muted">
{icon} {k}
</span>
<span className="font-semibold tabular-nums">{v}</span>
</div>
)
}