Checkpoint: Simplification de la classification IA dans l'onglet Veille Stratégique : suppression de la catégorie médico-sociale (Handicap, PA, Enfance, etc.), remplacement de "Générale" par "Informationnelle", classification IA réduite au seul type de veille (réglementaire/concurrentielle/technologique/informationnelle). Migration BDD des données generale → informationnelle. 0 erreur TypeScript, 21 tests passés.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"version": "b19031d9",
|
||||
"timestamp": 1781681307542
|
||||
"version": "7708bf54",
|
||||
"timestamp": 1781683337686
|
||||
}
|
||||
@@ -61,7 +61,7 @@ import { cn } from "@/lib/utils";
|
||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
type FeedType = "veille" | "aap";
|
||||
type TypeVeille = "reglementaire" | "concurrentielle" | "technologique" | "generale";
|
||||
type TypeVeille = "reglementaire" | "concurrentielle" | "technologique" | "informationnelle";
|
||||
type CategorieAap = "Handicap" | "PA" | "Enfance" | "Précarité" | "Sanitaire" | "Autre";
|
||||
|
||||
interface AutoRule {
|
||||
@@ -89,11 +89,11 @@ const TYPE_VEILLE_LABELS: Record<TypeVeille, string> = {
|
||||
reglementaire: "Réglementaire",
|
||||
concurrentielle: "Concurrentielle",
|
||||
technologique: "Technologique",
|
||||
generale: "Générale",
|
||||
informationnelle: "Informationnelle",
|
||||
};
|
||||
|
||||
const CATEGORIE_AAP_OPTIONS: CategorieAap[] = ["Handicap", "PA", "Enfance", "Précarité", "Sanitaire", "Autre"];
|
||||
const TYPE_VEILLE_OPTIONS: TypeVeille[] = ["reglementaire", "concurrentielle", "technologique", "generale"];
|
||||
const TYPE_VEILLE_OPTIONS: TypeVeille[] = ["reglementaire", "concurrentielle", "technologique", "informationnelle"];
|
||||
|
||||
const INTERVAL_OPTIONS = [
|
||||
{ value: 30, label: "30 minutes" },
|
||||
|
||||
@@ -46,7 +46,7 @@ import { cn } from "@/lib/utils";
|
||||
import { format } from "date-fns";
|
||||
import { fr } from "date-fns/locale";
|
||||
|
||||
type TypeVeille = "reglementaire" | "concurrentielle" | "technologique" | "generale";
|
||||
type TypeVeille = "reglementaire" | "concurrentielle" | "technologique" | "informationnelle";
|
||||
|
||||
interface VeilleItem {
|
||||
id: number;
|
||||
@@ -62,7 +62,6 @@ interface VeilleItem {
|
||||
datePublication: Date | null;
|
||||
importedAt: Date;
|
||||
iaRelevant: boolean | null;
|
||||
iaCategorie: string | null;
|
||||
iaClassifiedBy: "ia" | "rules" | null;
|
||||
iaReason: string | null;
|
||||
iaResume: string | null;
|
||||
@@ -72,28 +71,28 @@ const TYPE_LABELS: Record<TypeVeille, string> = {
|
||||
reglementaire: "Réglementaire",
|
||||
concurrentielle: "Concurrentielle",
|
||||
technologique: "Technologique",
|
||||
generale: "Générale",
|
||||
informationnelle: "Informationnelle",
|
||||
};
|
||||
|
||||
const TYPE_COLORS: Record<string, string> = {
|
||||
reglementaire: "bg-blue-100 text-blue-800 border-blue-200",
|
||||
concurrentielle: "bg-purple-100 text-purple-800 border-purple-200",
|
||||
technologique: "bg-emerald-100 text-emerald-800 border-emerald-200",
|
||||
generale: "bg-amber-100 text-amber-800 border-amber-200",
|
||||
informationnelle: "bg-amber-100 text-amber-800 border-amber-200",
|
||||
};
|
||||
|
||||
const TYPE_ACCENT: Record<string, string> = {
|
||||
reglementaire: "border-l-blue-500",
|
||||
concurrentielle: "border-l-purple-500",
|
||||
technologique: "border-l-emerald-500",
|
||||
generale: "border-l-amber-500",
|
||||
informationnelle: "border-l-amber-500",
|
||||
};
|
||||
|
||||
const TYPE_HEADER_BG: Record<string, string> = {
|
||||
reglementaire: "from-blue-50 to-blue-100/30 border-blue-200",
|
||||
concurrentielle: "from-purple-50 to-purple-100/30 border-purple-200",
|
||||
technologique: "from-emerald-50 to-emerald-100/30 border-emerald-200",
|
||||
generale: "from-amber-50 to-amber-100/30 border-amber-200",
|
||||
informationnelle: "from-amber-50 to-amber-100/30 border-amber-200",
|
||||
};
|
||||
|
||||
const PAGE_SIZE = 24;
|
||||
@@ -151,15 +150,7 @@ function VeilleDetailDialog({
|
||||
|
||||
{/* Métadonnées en grille */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
|
||||
{item.categorie && (
|
||||
<div className="flex items-start gap-2 p-3 rounded-lg bg-muted/40 border border-border/50">
|
||||
<Tag size={14} className="text-muted-foreground mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<p className="text-[10px] uppercase tracking-wide text-muted-foreground font-medium">Catégorie</p>
|
||||
<p className="text-sm font-medium text-foreground">{item.categorie}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{item.niveau && (
|
||||
<div className="flex items-start gap-2 p-3 rounded-lg bg-violet-50 border border-violet-200">
|
||||
<Layers size={14} className="text-violet-500 mt-0.5 shrink-0" />
|
||||
@@ -314,7 +305,6 @@ export default function VeilleDashboard() {
|
||||
const totalPages = Math.ceil(total / PAGE_SIZE);
|
||||
|
||||
const filterOptions = [
|
||||
{ key: "categorie", label: "Catégorie", options: filtersQuery.data?.categories ?? [] },
|
||||
{ key: "niveau", label: "Niveau", options: filtersQuery.data?.niveaux ?? [] },
|
||||
{ key: "territoire", label: "Territoire", options: filtersQuery.data?.territoires ?? [] },
|
||||
{ key: "dateFrom", label: "Date depuis", type: "date" as const },
|
||||
@@ -334,7 +324,7 @@ export default function VeilleDashboard() {
|
||||
)}
|
||||
</div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Suivi réglementaire, concurrentiel, technologique et général
|
||||
Suivi réglementaire, concurrentiel, technologique et informationnel
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -460,7 +450,6 @@ function VeilleListView({ items, onDetail, readIds }: { items: VeilleItem[]; onD
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground w-8">#</th>
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground">Titre</th>
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground w-32">Type</th>
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground w-28">Catégorie</th>
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground w-24">Niveau</th>
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground w-36">Territoire</th>
|
||||
<th className="text-left px-4 py-3 font-semibold text-muted-foreground w-28">Date</th>
|
||||
@@ -487,9 +476,6 @@ function VeilleListView({ items, onDetail, readIds }: { items: VeilleItem[]; onD
|
||||
{TYPE_LABELS[item.typeVeille as TypeVeille] || item.typeVeille}
|
||||
</Badge>
|
||||
</td>
|
||||
<td className="px-4 py-3 text-xs">
|
||||
<span className="text-muted-foreground">{item.categorie || "—"}</span>
|
||||
</td>
|
||||
<td className="px-4 py-3 text-muted-foreground text-xs">{item.niveau || "—"}</td>
|
||||
<td className="px-4 py-3 text-muted-foreground text-xs">{item.territoire || "—"}</td>
|
||||
<td className="px-4 py-3 text-muted-foreground text-xs whitespace-nowrap">{formatDate(item.datePublication) || "—"}</td>
|
||||
@@ -562,8 +548,7 @@ function VeilleGridView({ items, onDetail, readIds }: { items: VeilleItem[]; onD
|
||||
<CardContent className="px-4 pb-4 space-y-2">
|
||||
{(item.iaResume || item.resume) && <p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">{item.iaResume || item.resume}</p>}
|
||||
<div className="flex flex-wrap gap-1.5 pt-1">
|
||||
{item.categorie && <span className="inline-flex items-center gap-1 text-xs text-muted-foreground"><Tag size={10} />{item.categorie}</span>}
|
||||
{item.territoire && (
|
||||
{item.territoire && (
|
||||
<span className="inline-flex items-center gap-1 text-xs px-1.5 py-0.5 rounded bg-teal-50 text-teal-700 border border-teal-200">
|
||||
<MapPin size={10} />{item.territoire}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user