80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
/**
|
|
* CritereCard — Sprint 3.6b.
|
|
*
|
|
* Carte critère enrichie : nom, score /5, commentaire, exemple, suggestion,
|
|
* astuce + badges des codes d'erreurs taxonomie correspondants.
|
|
*
|
|
* Visible pour Standard et Premium (gate `detailed_report`). Le floutage est
|
|
* géré par le parent via BlurredSection — CritereCard ne connaît pas le plan.
|
|
*
|
|
* Règle L : tokens Direction H exclusivement.
|
|
* Règle H : purement présentationnel — aucune logique plan ici.
|
|
*/
|
|
|
|
import ReactMarkdown from 'react-markdown'
|
|
import { Card } from '@/shared/ui/Card'
|
|
import { Badge } from '@/shared/ui/Badge'
|
|
import type { Critere, ErreurCode } from '@/entities/report/types'
|
|
|
|
interface Props {
|
|
critere: Critere
|
|
erreursCodes: ErreurCode[]
|
|
}
|
|
|
|
export function CritereCard({ critere, erreursCodes }: Props) {
|
|
return (
|
|
<Card variant="default" className="space-y-3 p-4">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<h3 className="text-sm font-semibold text-ink-1">{critere.nom}</h3>
|
|
<Badge variant="nclc" className="shrink-0 tabular-nums">
|
|
{critere.score}/5
|
|
</Badge>
|
|
</div>
|
|
|
|
{critere.commentaire && (
|
|
<div className="text-sm leading-relaxed text-ink-2">
|
|
<ReactMarkdown disallowedElements={['script', 'iframe']}>
|
|
{critere.commentaire}
|
|
</ReactMarkdown>
|
|
</div>
|
|
)}
|
|
|
|
{critere.exemple && (
|
|
<div className="space-y-1.5 rounded-md border border-line bg-canvas-2 p-3">
|
|
<p className="text-[11px] font-semibold uppercase tracking-widest text-ink-5">
|
|
Exemple tiré de votre texte
|
|
</p>
|
|
<p className="italic text-sm leading-relaxed text-ink-2">« {critere.exemple} »</p>
|
|
</div>
|
|
)}
|
|
|
|
{critere.suggestion && (
|
|
<div className="space-y-1.5 rounded-md border border-expria/30 bg-expria-50 p-3">
|
|
<p className="text-[11px] font-semibold uppercase tracking-widest text-expria">
|
|
Reformulation suggérée
|
|
</p>
|
|
<p className="text-sm leading-relaxed text-ink-1">{critere.suggestion}</p>
|
|
</div>
|
|
)}
|
|
|
|
{critere.astuce && (
|
|
<div className="flex gap-2 text-sm text-ink-3">
|
|
<span className="shrink-0 text-expria" aria-hidden="true">
|
|
💡
|
|
</span>
|
|
<span>{critere.astuce}</span>
|
|
</div>
|
|
)}
|
|
|
|
{erreursCodes.length > 0 && (
|
|
<div className="flex flex-wrap gap-1.5 border-t border-line pt-3">
|
|
{erreursCodes.map((e) => (
|
|
<Badge key={`${e.code}-${e.description ?? ''}`} variant="neutral">
|
|
{e.description ?? e.code.replace(/_/g, ' ')}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
)}
|
|
</Card>
|
|
)
|
|
}
|