AUDIT / src /components /BgTaskRecoveryBanner.tsx
Arypulka98's picture
feat(audit): deploy full backend cluster node
aea470f verified
Raw
History Blame Contribute Delete
2.19 kB
/**
* BgTaskRecoveryBanner.tsx — Banner di recovery per task backend in sospeso.
*
* Appare al boot se un task era ancora in esecuzione sul backend HF Space
* quando il telefono si è spento. Mostra stato e permette di riaprire la chat.
* Mobile-first, posizionato in fondo allo schermo sopra la chat bar.
*/
import { usePendingTaskRecovery } from "@/lib/usePendingTaskRecovery";
export default function BgTaskRecoveryBanner() {
const { task, status, dismiss } = usePendingTaskRecovery();
if (!task || status === "idle" || status === "checking") return null;
const config = {
running: {
bg: "bg-blue-600/90",
icon: "⚡",
label: "Task in esecuzione sul server",
sub: "L'agente sta lavorando — riapri la chat per seguire i progressi",
},
done: {
bg: "bg-emerald-600/90",
icon: "✅",
label: "Task completato",
sub: "L'agente ha finito mentre eri offline — riapri la chat per vedere il risultato",
},
error: {
bg: "bg-red-600/90",
icon: "⚠️",
label: "Task interrotto",
sub: "Il task ha incontrato un errore — riapri la chat per i dettagli",
},
not_found: null,
} as const;
const cfg = config[status as keyof typeof config];
if (!cfg) return null;
return (
<div
className={`fixed bottom-20 left-3 right-3 z-50 rounded-xl shadow-2xl
${cfg.bg} backdrop-blur-sm text-white px-4 py-3
flex items-start gap-3 animate-in slide-in-from-bottom-4 duration-300`}
role="status"
aria-live="polite"
>
<span className="text-2xl mt-0.5 shrink-0">{cfg.icon}</span>
<div className="flex-1 min-w-0">
<p className="font-semibold text-sm leading-tight">{cfg.label}</p>
<p className="text-xs text-white/80 mt-0.5 leading-snug">{cfg.sub}</p>
<p className="text-xs text-white/60 mt-1 truncate">
Goal: {task.goal}
</p>
</div>
<button
onClick={dismiss}
className="shrink-0 text-white/70 hover:text-white transition-colors p-1 -mr-1"
aria-label="Chiudi"
>
</button>
</div>
);
}