'use client'; import { useState, useEffect } from 'react'; import { useAppStore } from '../store/useAppStore'; import { useI18n } from '../lib/useI18n'; import { getSnapshots, createSnapshot, restoreSnapshot, deleteSnapshot } from '../lib/snapshots'; export default function SnapshotManager({ onRestored }) { const { showSnapshots: open, setShowSnapshots } = useAppStore(); const onClose = () => setShowSnapshots(false); const { t } = useI18n(); const [snapshots, setSnapshots] = useState([]); const [loading, setLoading] = useState(true); const [selectedId, setSelectedId] = useState(null); const [isRestoring, setIsRestoring] = useState(false); const [isCreating, setIsCreating] = useState(false); const loadData = async () => { setLoading(true); const data = await getSnapshots(); setSnapshots(data); if (data.length > 0 && !selectedId) { setSelectedId(data[0].id); } setLoading(false); }; useEffect(() => { if (open) { loadData(); } }, [open]); if (!open) return null; const handleCreateManual = async () => { const label = prompt(t('snapshot.promptLabel'), t('snapshot.promptDefault')); if (!label) return; setIsCreating(true); try { const snap = await createSnapshot(label, 'manual'); await loadData(); setSelectedId(snap.id); } catch (e) { alert(t('snapshot.createFailed') + e.message); } finally { setIsCreating(false); } }; const handleRestore = async () => { if (!selectedId) return; const snap = snapshots.find(s => s.id === selectedId); if (!snap) return; const confirmMsg = t('snapshot.confirmRestore') .replace('{label}', snap.label) .replace('{date}', new Date(snap.timestamp).toLocaleString()); if (!confirm(confirmMsg)) { return; } setIsRestoring(true); try { await restoreSnapshot(snap.id); alert(t('snapshot.restoreSuccess')); if (onRestored) onRestored(); else window.location.reload(); } catch (e) { alert(t('snapshot.restoreFailed') + e.message); setIsRestoring(false); } }; const handleDelete = async (id, e) => { e.stopPropagation(); if (!confirm(t('snapshot.confirmDelete'))) return; try { const remaining = await deleteSnapshot(id); setSnapshots(remaining); if (selectedId === id) setSelectedId(remaining[0]?.id || null); } catch (err) { alert(t('snapshot.deleteFailed')); } }; const selectedSnap = snapshots.find(s => s.id === selectedId); const formatDate = (ts) => { const d = new Date(ts); return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }; return (
e.stopPropagation()} style={{ width: 800, maxWidth: '90vw', height: '80vh' }}>

{t('snapshot.title')} — {t('snapshot.subtitle')}

{/* 左侧列表 */}
{loading ? (
{t('snapshot.loading')}
) : snapshots.length === 0 ? (
{t('snapshot.empty')}
) : ( snapshots.map(s => (
setSelectedId(s.id)} style={{ padding: '12px 14px', marginBottom: 8, borderRadius: 'var(--radius-md)', border: s.id === selectedId ? '2px solid var(--accent)' : '1px solid var(--border-light)', background: s.id === selectedId ? 'var(--accent-light)' : 'var(--bg-secondary)', cursor: 'pointer', position: 'relative', }} >
{s.type === 'manual' ? '⭐ ' : ''}{s.label} {formatDate(s.timestamp)}
{t('snapshot.countChapters').replace('{count}', s.stats?.chapterCount || 0)} {t('snapshot.countWords').replace('{count}', Math.round((s.stats?.totalWords || 0) / 1000))} {t('snapshot.countSettings').replace('{count}', s.stats?.settingCount || 0)}
{/* 删除按钮 */}
)) )}
{/* 右侧详情 */}
{selectedSnap ? ( <>

{selectedSnap.type === 'manual' ? '⭐ ' : ''}{selectedSnap.label}

{t('snapshot.createdAt')} {new Date(selectedSnap.timestamp).toLocaleString()} {selectedSnap.type === 'auto' && ` ${t('snapshot.autoLabel')}`}

{selectedSnap.stats?.chapterCount || 0}
{t('snapshot.chapterCount')}
{(selectedSnap.stats?.totalWords || 0).toLocaleString()}
{t('snapshot.totalWords')}
{selectedSnap.stats?.settingCount || 0}
{t('snapshot.settingCount')}

{t('snapshot.includedChapters')}

{(selectedSnap.data?.chapters || []).slice(0, 10).map(ch => ( {ch.title} ))} {(selectedSnap.data?.chapters || []).length > 10 && ( {t('snapshot.andMore')} )}

{t('snapshot.restoreWarning')}

) : (
{t('snapshot.selectHint')}
)}
); }