import { useState } from 'react'; import { useMutation, useQueryClient, useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { Bell, Trash2, Settings2, Edit2, Send, Loader2, CheckCircle, XCircle, Moon, Clock, ChevronDown, ChevronUp, Calendar } from 'lucide-react'; import { api } from '../api/client'; import { formatDateOnly, parseUTCDate } from '../utils/date'; import type { NotificationProvider, NotificationProviderUpdate } from '../api/client'; import { Card, CardContent } from './Card'; import { Button } from './Button'; import { ConfirmModal } from './ConfirmModal'; import { Toggle } from './Toggle'; interface NotificationProviderCardProps { provider: NotificationProvider; onEdit: (provider: NotificationProvider) => void; } export function NotificationProviderCard({ provider, onEdit }: NotificationProviderCardProps) { const { t } = useTranslation(); const queryClient = useQueryClient(); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [isExpanded, setIsExpanded] = useState(false); const [testResult, setTestResult] = useState<{ success: boolean; message: string } | null>(null); // Fetch printers for linking const { data: printers } = useQuery({ queryKey: ['printers'], queryFn: api.getPrinters, }); const linkedPrinter = printers?.find(p => p.id === provider.printer_id); // Update mutation const updateMutation = useMutation({ mutationFn: (data: NotificationProviderUpdate) => api.updateNotificationProvider(provider.id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['notification-providers'] }); }, }); // Delete mutation const deleteMutation = useMutation({ mutationFn: () => api.deleteNotificationProvider(provider.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['notification-providers'] }); }, }); // Test mutation const testMutation = useMutation({ mutationFn: () => api.testNotificationProvider(provider.id), onSuccess: (result) => { setTestResult(result); queryClient.invalidateQueries({ queryKey: ['notification-providers'] }); }, onError: (err: Error) => { setTestResult({ success: false, message: err.message }); }, }); // Format time for display const formatTime = (time: string | null) => { if (!time) return ''; return time; }; return ( <> {/* Header Row */}

{provider.name}

{t(`notifications.providerTypes.${provider.provider_type}`, provider.provider_type)}

{/* Quick enable/disable toggle + Status indicator */}
{provider.last_success && ( {t('notifications.lastSuccess', { date: formatDateOnly(provider.last_success) })} )} {/* Only show error if it's more recent than last success */} {provider.last_error && provider.last_error_at && ( !provider.last_success || (parseUTCDate(provider.last_error_at)?.getTime() || 0) > (parseUTCDate(provider.last_success)?.getTime() || 0) ) && ( {t('notifications.error')} )} updateMutation.mutate({ enabled: checked })} />
{provider.enabled && (<> {/* Linked Printer */} {linkedPrinter && (
{t('notifications.printer')} {linkedPrinter.name}
)} {!linkedPrinter && !provider.printer_id && (
{t('notifications.allPrinters')}
)} {/* Event summary - show all event tags */}
{provider.on_print_start && ( {t('notifications.start')} )} {provider.on_plate_not_empty && ( {t('notifications.plateCheck')} )} {provider.on_print_complete && ( {t('notifications.complete')} )} {provider.on_print_failed && ( {t('notifications.failed')} )} {provider.on_print_stopped && ( {t('notifications.stopped')} )} {provider.on_print_progress && ( {t('notifications.progress')} )} {provider.on_printer_offline && ( {t('notifications.offline')} )} {provider.on_printer_error && ( {t('notifications.error')} )} {provider.on_filament_low && ( {t('notifications.lowFilament')} )} {provider.on_maintenance_due && ( {t('notifications.maintenance')} )} {provider.on_ams_humidity_high && ( {t('notifications.amsHumidity')} )} {provider.on_ams_temperature_high && ( {t('notifications.amsTemp')} )} {provider.on_ams_ht_humidity_high && ( {t('notifications.amsHtHumidity')} )} {provider.on_ams_ht_temperature_high && ( {t('notifications.amsHtTemp')} )} {provider.on_bed_cooled && ( {t('notifications.bedCooled')} )} {provider.on_first_layer_complete && ( {t('notifications.firstLayer')} )} {provider.on_print_missing_spool_assignment && ( {t('notifications.missingSpoolAssignmentLabel')} )} {provider.on_stock_reorder_alert && ( {t('notifications.stockReorderAlert')} )} {provider.on_stock_break_alert && ( {t('notifications.stockBreakAlert')} )} {provider.quiet_hours_enabled && ( {t('notifications.quiet')} )} {provider.daily_digest_enabled && ( {t('notifications.digest', { time: provider.daily_digest_time })} )}
{/* Test Button */}
{/* Test Result */} {testResult && (
{testResult.success ? ( ) : ( )} {testResult.message}
)} )} {/* Toggle Settings Panel */} {/* Expanded Settings */} {isExpanded && (
{/* Enabled Toggle */}

{t('notifications.enabled')}

{t('notifications.sendFromProvider')}

updateMutation.mutate({ enabled: checked })} />
{/* Print Lifecycle Events */}

{t('notifications.printEvents')}

{t('notifications.printStarted')}

updateMutation.mutate({ on_print_start: checked })} />

{t('notifications.plateNotEmpty')}

{t('notifications.plateNotEmptyDescription')}

updateMutation.mutate({ on_plate_not_empty: checked })} />

{t('notifications.printCompleted')}

updateMutation.mutate({ on_print_complete: checked })} />

{t('notifications.bedCooledLabel')}

{t('notifications.bedCooledDescription')}

updateMutation.mutate({ on_bed_cooled: checked })} />

{t('notifications.firstLayerCompleteLabel')}

{t('notifications.firstLayerCompleteDescription')}

updateMutation.mutate({ on_first_layer_complete: checked })} />

{t('notifications.missingSpoolAssignmentLabel')}

{t('notifications.missingSpoolAssignmentDescription')}

updateMutation.mutate({ on_print_missing_spool_assignment: checked })} />

{t('notifications.printFailed')}

updateMutation.mutate({ on_print_failed: checked })} />

{t('notifications.printStopped')}

updateMutation.mutate({ on_print_stopped: checked })} />

{t('notifications.progressMilestones')}

{t('notifications.progressMilestonesDescription')}

updateMutation.mutate({ on_print_progress: checked })} />
{/* Printer Status Events */}

{t('notifications.printerStatus')}

{t('notifications.printerOffline')}

updateMutation.mutate({ on_printer_offline: checked })} />

{t('notifications.printerError')}

updateMutation.mutate({ on_printer_error: checked })} />

{t('notifications.lowFilamentLabel')}

updateMutation.mutate({ on_filament_low: checked })} />

{t('notifications.maintenanceDue')}

{t('notifications.maintenanceDueDescription')}

updateMutation.mutate({ on_maintenance_due: checked })} />
{/* AMS Environmental Alarms (regular AMS) */}

{t('notifications.amsAlarms')}

{t('notifications.amsHumidityHigh')}

{t('notifications.amsHumidityHighDescription')}

updateMutation.mutate({ on_ams_humidity_high: checked })} />

{t('notifications.amsTemperatureHigh')}

{t('notifications.amsTemperatureHighDescription')}

updateMutation.mutate({ on_ams_temperature_high: checked })} />
{/* AMS-HT Environmental Alarms */}

{t('notifications.amsHtAlarms')}

{t('notifications.amsHtHumidityHigh')}

{t('notifications.amsHtHumidityHighDescription')}

updateMutation.mutate({ on_ams_ht_humidity_high: checked })} />

{t('notifications.amsHtTemperatureHigh')}

{t('notifications.amsHtTemperatureHighDescription')}

updateMutation.mutate({ on_ams_ht_temperature_high: checked })} />
{/* Inventory Stock Alerts */}

{t('notifications.inventoryAlerts')}

{t('notifications.stockReorderAlert')}

{t('notifications.stockReorderAlertDescription')}

updateMutation.mutate({ on_stock_reorder_alert: checked })} />

{t('notifications.stockBreakAlert')}

{t('notifications.stockBreakAlertDescription')}

updateMutation.mutate({ on_stock_break_alert: checked })} />
{/* Print Queue Events */}

{t('notifications.printQueue')}

{t('notifications.jobAdded')}

{t('notifications.jobAddedDescription')}

updateMutation.mutate({ on_queue_job_added: checked })} />

{t('notifications.jobAssigned')}

{t('notifications.jobAssignedDescription')}

updateMutation.mutate({ on_queue_job_assigned: checked })} />

{t('notifications.jobStarted')}

{t('notifications.jobStartedDescription')}

updateMutation.mutate({ on_queue_job_started: checked })} />

{t('notifications.jobWaiting')}

{t('notifications.jobWaitingDescription')}

updateMutation.mutate({ on_queue_job_waiting: checked })} />

{t('notifications.jobSkipped')}

{t('notifications.jobSkippedDescription')}

updateMutation.mutate({ on_queue_job_skipped: checked })} />

{t('notifications.jobFailed')}

{t('notifications.jobFailedDescription')}

updateMutation.mutate({ on_queue_job_failed: checked })} />

{t('notifications.queueComplete')}

{t('notifications.queueCompleteDescription')}

updateMutation.mutate({ on_queue_completed: checked })} />
{/* Quiet Hours */}

{t('notifications.quietHours')}

updateMutation.mutate({ quiet_hours_enabled: checked })} />
{provider.quiet_hours_enabled && (

{t('notifications.noNotificationsDuring')}

{formatTime(provider.quiet_hours_start) || '22:00'} - {formatTime(provider.quiet_hours_end) || '07:00'}

{t('notifications.editProviderToChangeQuietHours')}

)}
{/* Daily Digest */}

{t('notifications.dailyDigest')}

updateMutation.mutate({ daily_digest_enabled: checked })} />
{provider.daily_digest_enabled && (

{t('notifications.batchNotifications')}

{t('notifications.sendAt', { time: formatTime(provider.daily_digest_time) || '08:00' })}

{t('notifications.editProviderToChangeDigestTime')}

)}
{/* Action Buttons */}
)}
{/* Delete Confirmation */} {showDeleteConfirm && ( { deleteMutation.mutate(); setShowDeleteConfirm(false); }} onCancel={() => setShowDeleteConfirm(false)} /> )} ); }