import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Clock3, Download, HardDrive, Upload } from 'lucide-react'; import { createPortal } from 'react-dom'; import { exportBackupToPath, importAnyBackupFromPath, pickBackupExportPath, pickBackupImportPath, } from '../../utils/export/backup'; import { showToast } from '../../utils/ui/toast'; type BackupMode = 'full' | 'library' | 'config'; type BackupAction = 'export' | 'import'; export function BackupSection() { const { t } = useTranslation(); const [exporting, setExporting] = useState(false); const [importing, setImporting] = useState(false); const [mode, setMode] = useState('full'); const [busyAction, setBusyAction] = useState(null); const waitForPaint = async () => { await new Promise(resolve => window.setTimeout(resolve, 0)); }; const busy = exporting || importing; const handleExport = async () => { const exportMode = mode; const path = await pickBackupExportPath(exportMode); if (!path) return; setBusyAction('export'); setExporting(true); try { await waitForPaint(); await exportBackupToPath(exportMode, path); const successKey = exportMode === 'full' ? 'settings.backupFullExportSuccess' : exportMode === 'library' ? 'settings.backupLibraryExportSuccess' : 'settings.backupSuccess'; showToast(t(successKey), 3000, 'info'); } catch (e) { console.error('Export failed', e); const errorKey = mode === 'full' ? 'settings.backupFullImportError' : mode === 'library' ? 'settings.backupLibraryImportError' : 'settings.backupImportError'; showToast(t(errorKey), 4000, 'error'); } finally { setExporting(false); setBusyAction(null); } }; const handleImport = async () => { if (!window.confirm(t('settings.backupImportAnyConfirm'))) return; const path = await pickBackupImportPath(); if (!path) return; setBusyAction('import'); setImporting(true); try { await waitForPaint(); const importedKind = await importAnyBackupFromPath(path); if (importedKind === 'full') { showToast(t('settings.backupFullImportSuccess'), 3000, 'info'); } else if (importedKind === 'databases') { showToast(t('settings.backupLibraryImportSuccess'), 3000, 'info'); } else if (importedKind === 'config') { showToast(t('settings.backupImportSuccess'), 3000, 'info'); } } catch (e) { console.error('Import failed', e); showToast(t('settings.backupImportError'), 4000, 'error'); } finally { setImporting(false); setBusyAction(null); } }; const modeTitle = mode === 'full' ? t('settings.backupModeFull') : mode === 'library' ? t('settings.backupModeLibrary') : t('settings.backupModeConfig'); const modeDesc = mode === 'full' ? t('settings.backupFullDesc') : mode === 'library' ? t('settings.backupLibraryExportDesc') : t('settings.backupExportDesc'); const exportLabel = mode === 'full' ? t('settings.backupFullExport') : mode === 'library' ? t('settings.backupLibraryExport') : t('settings.backupExport'); const importLabel = t('settings.backupImportAny'); const overlayTitle = busyAction === 'import' ? t('settings.backupOverlayImportTitle') : t('settings.backupOverlayExportTitle'); const overlayHint = t('settings.backupOverlayHint'); const busyOverlay = busy && typeof document !== 'undefined' ? createPortal(
{overlayTitle}
{overlayHint}
, document.body, ) : null; return (

{t('settings.backupTitle')}

{(['full', 'library', 'config'] as BackupMode[]).map(candidate => ( ))}
{modeTitle}
{modeDesc}
{busyOverlay}
); }