mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
Grille (navigateur) - « Rafraîchir » ne passe plus par l'URL : le paramètre _refresh restait mémorisé et chaque retour par le menu forçait un recalcul serveur complet (migration du store pour nettoyer les valeurs déjà enregistrées). - Lignes reçues regroupées toutes les 300 ms au lieu de reconstruire tout le tableau à chaque paquet de 150 (chargement quadratique). - Sélection indexée par code article (getRowId) : après un filtre, l'action groupée visait d'autres produits. Seules les lignes affichées comptent. - Recherche : un passage par ligne au lieu d'un par colonne ; formateurs de nombres partagés (lib/format.ts) ; colonnes mensuelles mémorisées ; plus de transition-all sur les lignes positionnées par transform. - exceljs, jspdf et xlsx chargés au clic seulement. Grille (serveur) - Requêtes Qlik et snapshot lancées en parallèle de la phase SQL. - Cache mémoire borné (LRU) ; calcul en cours réutilisé même en forcé ; flux interrompu quand le client part. - Après un enregistrement, les gammes sont reportées dans le cache et dans grid_rows au lieu d'invalider (recalcul de ~40 s évité). Données et API - lib/ff-cache.ts : cache mémoire 30 min des lectures FF (stock, hit-parade, CA mensuel, fournisseurs, dernière réception, publicités), vidé en fin de synchro nocturne ; erreurs jamais gardées. - Pool PostgreSQL unique (globalThis), réglage sans workers parallèles posé une fois par connexion au lieu d'une transaction autour de chaque requête. - Délai maximal sur tous les appels à l'API FF. - Index session_snapshots ; commandes : plus de double rechargement ; synchro : saisies regroupées ; paramètres : configuration lue une fois ; journal de capture en ajout seul, rien de formaté sans capture ouverte. Corrections - Historique : l'échec de chargement s'affiche (au lieu de « Aucun snapshot »). - Sessions et validations enregistrent le magasin affiché, plus « TOTAL ». - Publicités : libellé du statut « passées ». Plan complet : docs/plan-optimisation-webui.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AcA129WzGTH6zxPHFBGWmn
71 lines
3.0 KiB
TypeScript
71 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import { useGridStore } from "@/features/grid/store/use-grid-store";
|
|
import { Loader2, RefreshCw, CheckCircle, AlertCircle } from "lucide-react";
|
|
import { useQlikSyncJob } from "@/features/qlik-sync/use-qlik-sync-job";
|
|
|
|
interface SyncQlikButtonProps {
|
|
/** Code fournisseur affiché (pour sync ciblée) */
|
|
codeFournisseur?: string;
|
|
/** Date ISO de dernière maj Qlik pour ce fournisseur (max des lignes) */
|
|
lastUpdate?: string | null;
|
|
}
|
|
|
|
/** Date + heure de dernière synchro, ou "jamais". */
|
|
function formatLastUpdate(iso?: string | null): string {
|
|
if (!iso) return "jamais";
|
|
const d = new Date(iso);
|
|
if (isNaN(d.getTime())) return "jamais";
|
|
return d.toLocaleString("fr-FR", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
}
|
|
|
|
/**
|
|
* Bouton admin : synchronise depuis Qlik les métriques réseau du fournisseur affiché
|
|
* (POST /api/qlik/sync?fournisseur=…) puis recharge la grille. Affiche la dernière maj.
|
|
*
|
|
* Toute la mécanique de job (POST puis polling GET, reprise après reload) vit
|
|
* dans `useQlikSyncJob`, partagée avec la fiche produit.
|
|
*/
|
|
export function SyncQlikButton({ codeFournisseur, lastUpdate }: SyncQlikButtonProps) {
|
|
/** Recharge la grille en ignorant le cache serveur (la barre de résumé suit). */
|
|
const requestRefresh = useGridStore((s) => s.requestRefresh);
|
|
|
|
const { status, message, start } = useQlikSyncJob({
|
|
target: { mode: "fournisseur", fournisseur: codeFournisseur },
|
|
onSuccess: requestRefresh,
|
|
});
|
|
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<span
|
|
className="text-[10px] leading-tight text-right whitespace-nowrap hidden lg:block"
|
|
style={{ color: status === "error" ? "var(--accent-error)" : "var(--text-muted)" }}
|
|
title={message || undefined}
|
|
>
|
|
{status === "error"
|
|
? message
|
|
: status === "running"
|
|
? (message || `Extraction Qlik…`)
|
|
: `MAJ Qlik · ${formatLastUpdate(lastUpdate)}`}
|
|
</span>
|
|
<button
|
|
onClick={start}
|
|
disabled={status === "running"}
|
|
className="btn-action btn-action-secondary flex items-center gap-1.5 disabled:opacity-60"
|
|
title={message || `Synchroniser les données réseau Qlik · MAJ ${formatLastUpdate(lastUpdate)}`}
|
|
>
|
|
{status === "running" ? (
|
|
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
|
) : status === "success" ? (
|
|
<CheckCircle className="w-3.5 h-3.5 text-emerald-500" />
|
|
) : status === "error" ? (
|
|
<AlertCircle className="w-3.5 h-3.5 text-rose-500" />
|
|
) : (
|
|
<RefreshCw className="w-3.5 h-3.5" />
|
|
)}
|
|
{status === "running" ? "Sync en cours…" : "Sync Qlik"}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|