import { useState } from "react"; import { AlertCircle, X, Copy, Check, ChevronDown, ChevronUp } from "lucide-react"; import type { ActionError } from "../../shared/types"; import { useT } from "../i18n"; const PREVIEW_CHAR_LIMIT = 180; function ToastItem({ err, onDismiss }: { err: ActionError; onDismiss: (id: string) => void }) { const { t } = useT(); const [copied, setCopied] = useState(false); const [expanded, setExpanded] = useState(false); const shortName = err.uid.split("/").pop() || err.uid; const project = err.uid.includes("/") ? err.uid.split("/")[0] : null; const isLong = err.error.length > PREVIEW_CHAR_LIMIT; const visibleError = expanded || !isLong ? err.error : err.error.slice(0, PREVIEW_CHAR_LIMIT) + "…"; const copy = async () => { let ok = false; try { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(err.error); ok = true; } else { const ta = document.createElement("textarea"); ta.value = err.error; ta.style.position = "fixed"; ta.style.opacity = "0"; document.body.appendChild(ta); ta.select(); ok = document.execCommand("copy"); document.body.removeChild(ta); } } catch {} if (ok) { setCopied(true); setTimeout(() => setCopied(false), 1500); } }; return (
{t("toast.actionFailed").replace("{action}", err.action)}
{shortName} {project && {project}}
          {visibleError}
        
{isLong && ( )}
); } interface ActionErrorToastProps { errors: ActionError[]; onDismiss: (id: string) => void; onClearAll: () => void; } export function ActionErrorToast({ errors, onDismiss, onClearAll }: ActionErrorToastProps) { const { t } = useT(); if (errors.length === 0) return null; return (
{errors.length > 1 && ( )} {errors.map((err) => ( ))}
); }