mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
feat: Add AI Copilot Zustand store for managing and persisting product insights.
This commit is contained in:
1 parent
86df5d6f29
commit
99954fb001
2 files changed
+26
-10
No files matched your search
@@ -13,6 +13,7 @@ interface AiInsight {
|
||||
interface AiCopilotState {
|
||||
insights: Record<string, AiInsight>;
|
||||
setInsight: (codein: string, insight: string, isDuplicate?: boolean) => void;
|
||||
batchSetInsights: (entries: { codein: string; insight: string }[]) => void;
|
||||
setLoading: (codein: string) => void;
|
||||
batchSetLoading: (codeins: string[]) => void;
|
||||
setError: (codein: string, error: string) => void;
|
||||
@@ -76,6 +77,16 @@ export const useAiCopilotStore = create<AiCopilotState>()(
|
||||
}));
|
||||
},
|
||||
|
||||
batchSetInsights: (entries) => {
|
||||
set((s) => {
|
||||
const nextInsights = { ...s.insights };
|
||||
entries.forEach(({ codein, insight }) => {
|
||||
nextInsights[codein] = { codein, insight, status: "done" };
|
||||
});
|
||||
return { insights: nextInsights };
|
||||
});
|
||||
},
|
||||
|
||||
setLoading: (codein) => {
|
||||
set((s) => ({
|
||||
insights: {
|
||||
|
||||
@@ -20,7 +20,7 @@ export function BulkAiAnalyzer() {
|
||||
|
||||
const batchSetDraftGamme = useGridStore((s) => s.batchSetDraftGamme);
|
||||
const setDraftGamme = useGridStore((s) => s.setDraftGamme);
|
||||
const { setInsight, batchSetLoading, setError } = useAiCopilotStore();
|
||||
const { setInsight, batchSetInsights, batchSetLoading, setError } = useAiCopilotStore();
|
||||
|
||||
const prevSupplierRef = useRef(supplierCode);
|
||||
useEffect(() => {
|
||||
@@ -61,9 +61,10 @@ export function BulkAiAnalyzer() {
|
||||
const zChanges: Record<string, GammeCode> = {};
|
||||
zeroSalesRows.forEach(r => { zChanges[r.codein] = "Z"; });
|
||||
batchSetDraftGamme(zChanges);
|
||||
zeroSalesRows.forEach(r => {
|
||||
setInsight(r.codein, "Aucune vente sur 12 mois — produit classé Z automatiquement.");
|
||||
});
|
||||
batchSetInsights(zeroSalesRows.map(r => ({
|
||||
codein: r.codein,
|
||||
insight: "Aucune vente sur 12 mois — produit classé Z automatiquement.",
|
||||
})));
|
||||
}
|
||||
|
||||
// Construire les payloads uniquement pour les produits avec ventes
|
||||
@@ -129,9 +130,10 @@ export function BulkAiAnalyzer() {
|
||||
const zChanges: Record<string, GammeCode> = {};
|
||||
deadStockRows.forEach(r => { zChanges[r.codein] = "Z"; });
|
||||
batchSetDraftGamme(zChanges);
|
||||
deadStockRows.forEach(r => {
|
||||
setInsight(r.codein, `CA < 100€ (${(r.totalCa ?? 0).toFixed(0)}€) et quantité < 30 (${r.totalQuantite} uté) — stock mort absolu, classé Z automatiquement.`);
|
||||
});
|
||||
batchSetInsights(deadStockRows.map(r => ({
|
||||
codein: r.codein,
|
||||
insight: `CA < 100€ (${(r.totalCa ?? 0).toFixed(0)}€) et quantité < 30 (${r.totalQuantite} uté) — stock mort absolu, classé Z automatiquement.`,
|
||||
})));
|
||||
}
|
||||
const deadStockCodes = new Set(deadStockRows.map(r => r.codein));
|
||||
|
||||
@@ -145,12 +147,15 @@ export function BulkAiAnalyzer() {
|
||||
const aChanges: Record<string, GammeCode> = {};
|
||||
top20Rows.forEach(r => { aChanges[r.codein] = "A"; });
|
||||
batchSetDraftGamme(aChanges);
|
||||
top20Rows.forEach(r => {
|
||||
batchSetInsights(top20Rows.map(r => {
|
||||
const rkCa = r.rankingCa != null ? `${r.rankingCa}e CA` : "";
|
||||
const rkQte = r.rankingQte != null ? `${r.rankingQte}e Qté` : "";
|
||||
const total = r.totalRankedProducts ? ` / ${r.totalRankedProducts.toLocaleString("fr-FR")} produits` : "";
|
||||
setInsight(r.codein, `Top 20 réseau (${[rkCa, rkQte].filter(Boolean).join(", ")}${total}) — classé A automatiquement.`);
|
||||
});
|
||||
return {
|
||||
codein: r.codein,
|
||||
insight: `Top 20 réseau (${[rkCa, rkQte].filter(Boolean).join(", ")}${total}) — classé A automatiquement.`,
|
||||
};
|
||||
}));
|
||||
}
|
||||
const top20Codes = new Set(top20Rows.map(r => r.codein));
|
||||
|
||||
|
||||
Reference in new issue
Block a user