feat: Add bulk AI analyzer component to process product data and generate insights.

This commit is contained in:
Michael committed 2026-02-23 00:40:49 +01:00
1 parent 8c02771e46
commit 17498dcc10
4 files changed
+47 -8

No files matched your search

@@ -12,15 +12,18 @@ interface AiInsightBlockProps {
}
export function AiInsightBlock({ row }: AiInsightBlockProps) {
const { insights, analyzeProduct } = useAiCopilotStore();
const setDraftGamme = useGridStore(state => state.setDraftGamme);
const insight = insights[row.codein];
const insight = useAiCopilotStore((s) => s.insights[row.codein]);
const analyzeProduct = useAiCopilotStore((s) => s.analyzeProduct);
const setLoading = useAiCopilotStore((s) => s.setLoading);
const setDraftGamme = useGridStore((s) => s.setDraftGamme);
const status = insight?.status ?? "idle";
const handleAnalyze = () => {
if (status === "loading") return;
// Vider la recommandation actuelle avant de relancer l'IA
// Reset Visuel Immédiat
setLoading(row.codein);
setDraftGamme(row.codein, "Aucune");
const regScore = Object.values(row.sales12m || {}).filter(v => v > 0).length;
@@ -14,6 +14,7 @@ interface AiCopilotState {
insights: Record<string, AiInsight>;
setInsight: (codein: string, insight: string, isDuplicate?: boolean) => void;
setLoading: (codein: string) => void;
batchSetLoading: (codeins: string[]) => void;
setError: (codein: string, error: string) => void;
analyzeProduct: (payload: {
codein: string;
@@ -56,6 +57,16 @@ export const useAiCopilotStore = create<AiCopilotState>()(
}));
},
batchSetLoading: (codeins) => {
set((s) => {
const nextInsights = { ...s.insights };
codeins.forEach(codein => {
nextInsights[codein] = { codein, insight: "", status: "loading" };
});
return { insights: nextInsights };
});
},
setError: (codein, error) => {
set((s) => ({
insights: {
@@ -12,8 +12,9 @@ export function BulkAiAnalyzer() {
const [progress, setProgress] = useState({ current: 0, total: 0, message: "", errors: 0 });
const isCancelledRef = useRef(false);
const batchSetDraftGamme = useGridStore((s) => s.batchSetDraftGamme);
const setDraftGamme = useGridStore((s) => s.setDraftGamme);
const { setInsight, setLoading, setError } = useAiCopilotStore();
const { setInsight, batchSetLoading, setError } = useAiCopilotStore();
const handleStop = () => {
isCancelledRef.current = true;
@@ -111,6 +112,14 @@ export function BulkAiAnalyzer() {
const totalItems = productPayloads.length;
setProgress({ current: 0, total: totalItems, message: "Initialisation...", errors: 0 });
// Reset global ATOMIQUE et IMMÉDIAT
const codeins = productPayloads.map(p => p.codein);
batchSetLoading(codeins);
const gammeChanges: Record<string, GammeCode> = {};
codeins.forEach(c => gammeChanges[c] = "Aucune");
batchSetDraftGamme(gammeChanges);
const CONCURRENCY = 3;
const remaining = [...productPayloads];
@@ -120,9 +129,6 @@ export function BulkAiAnalyzer() {
const payload = remaining.shift();
if (!payload) break;
setLoading(payload.codein);
setDraftGamme(payload.codein, "Aucune");
try {
let res: Response | null = null;
for (let i = 0; i < 3; i++) {
+19
View File
@@ -25,6 +25,7 @@ interface GridState {
setDisplayDensity: (density: "compact" | "normal" | "comfortable") => void;
setActiveGridQuery: (query: string) => void;
restoreSnapshot: (changes: Record<string, GammeCode>) => void;
batchSetDraftGamme: (changes: Record<string, GammeCode>) => void;
}
function computeSummary(rows: ProductRow[], drafts: Record<string, GammeCode>): GridSummary {
@@ -105,6 +106,24 @@ export const useGridStore = create<GridState>()(
restoreSnapshot: (changes) => {
set({ draftChanges: changes, summary: computeSummary(get().rows, changes) });
},
batchSetDraftGamme: (newChanges) => {
const { rows, draftChanges: oldDrafts } = get();
const updatedDrafts = { ...oldDrafts };
Object.entries(newChanges).forEach(([codein, gamme]) => {
const originalRow = rows.find(r => r.codein === codein);
const originalGamme = originalRow?.codeGamme;
if (gamme === originalGamme) {
delete updatedDrafts[codein];
} else {
updatedDrafts[codein] = gamme;
}
});
set({ draftChanges: updatedDrafts, summary: computeSummary(rows, updatedDrafts) });
},
}),
{
name: "collectflow-grid-storage",