Targeting queue - scored case file
flair-targeting-queue/ · 5 files
componentskill: design-taste-frontendtabledensepublic-recordscompliancesearchdashboard
Brief
The prompt that produced this. Re-run it to generate more in the same taste.
- Aesthetic
- administrative density - DSFR-sober, tabular, high-contrast, unornamented, scannable, decision-oriented
- Reference
- FLAIR targeting console, file de ciblage
- Intent
- let an agent narrow several hundred scored dossiers to the handful worth opening, without the ranking ever reading as a verdict
- Guardrails
- always keep the score beside the amount it is claimed to justify, sort and filter without hiding how many rows were dropped, name the decision already recorded on a dossier, use native select and search controlsnever present a score as evidence or as a decision, show a case without its rank and source identifiers, colour a row by risk alone, paginate away the filtered count
Install
pnpm dlx shadcn@latest add http://localhost:3040/r/flair-targeting-queue.json
Source
Meta block and library type import stripped - this is what pastes cleanly elsewhere.
'use client'
import { useState } from 'react'
import type { CasesFile, Decision, FlairCase } from './lib'
import { TargetingQueue } from './targeting-queue'
/**
* Six dossiers is enough to exercise every branch the table has: both target
* types, all four score bands, multi-typology rows, and one dossier already
* decided against.
*/
const data: CasesFile = {
meta: { population: { foyers: 412_800, entreprises: 63_140, cas_retenus: 1_284 } },
cas: [
{
id: 'FLR-2026-00418',
rang: 1,
type: 'particulier',
score: 92,
montant_estime: 148_300,
typologies: ['REVENUS_OCCULTES', 'COMPTE_ETRANGER_NON_DECLARE'],
identite: { nom: 'Valcour', prenom: 'Noémie', commune: 'Rennes', departement: '35' },
},
{
id: 'FLR-2026-00461',
rang: 2,
type: 'entreprise',
score: 81,
montant_estime: 96_750,
typologies: ['TVA_MINOREE', 'CHARGES_FICTIVES'],
identite: { nom: 'Atelier Brunel SAS', commune: 'Lyon', departement: '69' },
},
{
id: 'FLR-2026-00503',
rang: 3,
type: 'particulier',
score: 64,
montant_estime: 41_200,
typologies: ['LOCATION_NON_DECLAREE'],
identite: { nom: 'Ferrand', prenom: 'Bastien', commune: 'Annecy', departement: '74' },
},
{
id: 'FLR-2026-00547',
rang: 4,
type: 'entreprise',
score: 58,
montant_estime: 33_900,
typologies: ['DOMICILIATION_FICTIVE'],
identite: { nom: 'Nord Logistique SARL', commune: 'Lille', departement: '59' },
},
{
id: 'FLR-2026-00612',
rang: 5,
type: 'particulier',
score: 37,
montant_estime: 12_460,
typologies: ['REVENUS_OCCULTES'],
identite: { nom: 'Okonkwo', prenom: 'Adaeze', commune: 'Nantes', departement: '44' },
},
{
id: 'FLR-2026-00688',
rang: 6,
type: 'particulier',
score: 19,
montant_estime: 4_180,
typologies: ['LOCATION_NON_DECLAREE'],
identite: { nom: 'Perreault', prenom: 'Yann', commune: 'Brest', departement: '29' },
},
],
}
const decisions: Decision[] = [
{
uid: 'd-1',
caseId: 'FLR-2026-00461',
action: 'retenir',
matricule: 'A-4471',
dateIso: '2026-07-28T09:14:00Z',
},
{
uid: 'd-2',
caseId: 'FLR-2026-00688',
action: 'ecarter',
matricule: 'A-2210',
dateIso: '2026-07-27T16:02:00Z',
},
]
export default function FlairTargetingQueue() {
const [ouvert, setOuvert] = useState<FlairCase | null>(null)
return (
<main className="min-h-[100dvh] bg-[#F6F6F6] p-4 text-[#161616] sm:p-8">
<div className="mx-auto max-w-7xl">
<TargetingQueue data={data} decisions={decisions} onSelect={setOuvert} />
{/* The real console opens a case file here; the design only needs to
prove the row is a live target and says which one was hit. */}
<p aria-live="polite" className="mt-4 text-[#3A3A3A] text-sm">
{ouvert
? `Fiche demandée : ${ouvert.id} — ${ouvert.identite.nom}`
: 'Aucune fiche ouverte.'}
</p>
</div>
</main>
)
}