// AI Failure Detection modal (#1546) — opened from the printer card's AI badge. // Shows the live classification for this printer and the detection service's // last error, without leaving the Printers page (mirrors the HMS error modal). import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { X, ScanEye, AlertCircle, Settings } from 'lucide-react'; import { aiDetectionClass, hasVerdict, type AiDetection } from '../utils/aiDetection'; interface AiDetectionModalProps { printerName: string; detection?: AiDetection; // null = no error, or the viewer lacks settings:read (the backend withholds // error strings from non-settings users because they can embed config URLs) lastError: string | null; onClose: () => void; } export function AiDetectionModal({ printerName, detection, lastError, onClose }: AiDetectionModalProps) { const { t } = useTranslation(); const navigate = useNavigate(); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [onClose]); const cls = aiDetectionClass(detection); const statusColor = cls === 'failure' ? 'text-status-error' : cls === 'warning' ? 'text-status-warning' : cls === 'safe' ? 'text-status-ok' : cls === 'error' ? 'text-amber-600 dark:text-amber-400' : 'text-bambu-gray'; // This printer's own reason beats the service-wide one: with several printers // monitored, the global string is whichever failed most recently and may be // about someone else's printer entirely. const reason = detection?.error ?? lastError; return (
{t('printers.aiDetection.errorHint')}
} {!detection &&{t('printers.aiDetection.idleHint')}
}{reason}