import { Briefcase, ClipboardList, RefreshCw, ShieldCheck, Users } from 'lucide-react' import { Link } from 'react-router-dom' import { ToolHeader } from '../../components/ToolHeader' import { Bar, Panel, Stat } from '../../components/ui' import { num } from '../../lib/format' import type { Alert, RMFunnelStage } from '../../lib/types' import { recruitBrand } from './brand' import { useAlerts, useRecommendations, useRecruitDashboard } from './queries' // REDEPLOYMENT GETS ITS OWN PANEL rather than a slot in the mixed alert feed. // // A contractor rolling off is the warmest and cheapest candidate a staffing firm has: already cleared, // already known to the client, already proven on the work. Buried in a feed truncated at six and sorted by // nothing in particular, it is the signal most likely to be missed, and missing it is how a firm loses a // billable person it already had. const REDEPLOYMENT = 'redeployment_due' // alertLink opens an alert onto the thing it is about, where that thing is a record this product has a screen // for. An alert a recruiter cannot act on from is a notification, not a worklist. function alertLink(a: Alert): string | null { if (a.subject_type === 'candidate' && a.subject_id) { return `/bench/candidate/${encodeURIComponent(a.subject_id)}` } return null } // AlertRow renders one alert, as a link when there is somewhere to go and as plain text otherwise, so a // non actionable alert never looks like a dead button. function AlertRow({ a }: { a: Alert }) { const to = alertLink(a) const body = (
{a.title}
{a.detail ? ({a.detail}
) : null}as of {d.as_of}
No candidates yet. The funnel fills as candidates are added and screened.
) : (No candidates on the bench yet.
) : (No slate members yet. Generate a slate in slateMATCH.
) : (Nothing screened yet.
) : (No open requirements yet.
) : ( // A list rather than a table. Federal requirement titles and agency names are long enough // that a three column table forced the agency to wrap onto three lines and left every row a // different height. The agency reads as a subtitle instead, so the title gets the full width.{j.title}
{j.customer_agency || 'n/a'}
No active users in this organization yet.
) : (| Recruiter | Screened | Decided | Approved |
|---|---|---|---|
| {r.full_name} | {r.screened} | {r.decided} | {r.approved} |
This is unavailable for your role.
) : rollingOff.length === 0 ? (Nobody is finishing an assignment in the next six weeks, or everybody who is has their next one already lined up. People with a next assignment booked are left out on purpose.
) : ( <>These people finish soon and have nothing booked after. They are already cleared, already known to the client, and already proven on the work, which makes them the cheapest placement available to you this month.
Alerts are unavailable for your role.
) : otherAlerts.length === 0 ? (No open alerts. The watch loop runs daily and posts clearance expiry, recompete and coverage findings here.
) : (Recommendations are unavailable for your role.
) : !recs.data || recs.data.recommendations.length === 0 ? (No recommendations yet. These are generated from open requirements and the current bench.
) : ({r.rationale}
{r.rationale_source === 'deterministic' ? (deterministic rationale
) : null}{p.title}
{p.reason}