/** * Settings — backup / restore configuration. */ import { apiKey } from '../core/state.js'; import { API_BASE, fetchWithAuth } from '../core/api.js'; import { Modal } from '../core/modal.js'; import { showToast, showConfirm } from '../core/ui.js'; import { t } from '../core/i18n.js'; // Simple modal (no form / no dirty check needed) const settingsModal = new Modal('settings-modal'); export function openSettingsModal() { document.getElementById('settings-error').style.display = 'none'; settingsModal.open(); } export function closeSettingsModal() { settingsModal.forceClose(); } // ─── Backup ──────────────────────────────────────────────── export async function downloadBackup() { try { const resp = await fetchWithAuth('/system/backup', { timeout: 30000 }); if (!resp.ok) { const err = await resp.json().catch(() => ({})); throw new Error(err.detail || `HTTP ${resp.status}`); } const blob = await resp.blob(); const disposition = resp.headers.get('Content-Disposition') || ''; const match = disposition.match(/filename="(.+?)"/); const filename = match ? match[1] : 'ledgrab-backup.json'; const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = filename; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(a.href); showToast(t('settings.backup.success'), 'success'); } catch (err) { console.error('Backup download failed:', err); showToast(t('settings.backup.error') + ': ' + err.message, 'error'); } } // ─── Restore ─────────────────────────────────────────────── export async function handleRestoreFileSelected(input) { const file = input.files[0]; input.value = ''; if (!file) return; const confirmed = await showConfirm(t('settings.restore.confirm')); if (!confirmed) return; try { const formData = new FormData(); formData.append('file', file); const resp = await fetch(`${API_BASE}/system/restore`, { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}` }, body: formData, }); if (!resp.ok) { const err = await resp.json().catch(() => ({})); throw new Error(err.detail || `HTTP ${resp.status}`); } const data = await resp.json(); showToast(data.message || t('settings.restore.success'), 'success'); settingsModal.forceClose(); if (data.restart_scheduled) { showRestartOverlay(); } } catch (err) { console.error('Restore failed:', err); showToast(t('settings.restore.error') + ': ' + err.message, 'error'); } } // ─── Restart overlay ─────────────────────────────────────── function showRestartOverlay() { const overlay = document.createElement('div'); overlay.id = 'restart-overlay'; overlay.style.cssText = 'position:fixed;inset:0;z-index:100000;display:flex;flex-direction:column;' + 'align-items:center;justify-content:center;background:rgba(0,0,0,0.85);color:#fff;font-size:1.2rem;'; overlay.innerHTML = '
' + `