feat(admin): add minimal Drafts list to load existing drafts from /api/drafts

This commit is contained in:
Ender 2025-10-24 03:14:17 +02:00
parent 54fb0226bf
commit 45f7b3e8d5

View File

@ -6,6 +6,7 @@ import { useEffect, useState } from 'react';
export default function EditorShell({ onLogout }: { onLogout?: () => void }) { export default function EditorShell({ onLogout }: { onLogout?: () => void }) {
const [draft, setDraft] = useState<string>(''); const [draft, setDraft] = useState<string>('');
const [draftId, setDraftId] = useState<string | null>(null); const [draftId, setDraftId] = useState<string | null>(null);
const [drafts, setDrafts] = useState<string[]>([]);
useEffect(() => { useEffect(() => {
const savedId = localStorage.getItem('voxblog_draft_id'); const savedId = localStorage.getItem('voxblog_draft_id');
@ -23,6 +24,15 @@ export default function EditorShell({ onLogout }: { onLogout?: () => void }) {
} catch {} } catch {}
})(); })();
} }
(async () => {
try {
const res = await fetch('/api/drafts');
if (res.ok) {
const data = await res.json();
if (Array.isArray(data.items)) setDrafts(data.items);
}
} catch {}
})();
}, []); }, []);
const saveDraft = async () => { const saveDraft = async () => {
@ -44,6 +54,18 @@ export default function EditorShell({ onLogout }: { onLogout?: () => void }) {
} catch {} } catch {}
}; };
const loadDraft = async (id: string) => {
try {
const res = await fetch(`/api/drafts/${id}`);
if (!res.ok) return;
const data = await res.json();
setDraft(data.content || '');
setDraftId(data.id || id);
localStorage.setItem('voxblog_draft_id', data.id || id);
if (data.content) localStorage.setItem('voxblog_draft', data.content);
} catch {}
};
return ( return (
<AdminLayout title="VoxBlog Admin" onLogout={onLogout}> <AdminLayout title="VoxBlog Admin" onLogout={onLogout}>
<Typography variant="h4" sx={{ mb: 2 }}> <Typography variant="h4" sx={{ mb: 2 }}>
@ -51,6 +73,19 @@ export default function EditorShell({ onLogout }: { onLogout?: () => void }) {
</Typography> </Typography>
<Box sx={{ display: 'grid', gap: 3 }}> <Box sx={{ display: 'grid', gap: 3 }}>
<Recorder onTranscript={(t) => setDraft(t)} /> <Recorder onTranscript={(t) => setDraft(t)} />
<Box>
<Typography variant="subtitle1" sx={{ mb: 1 }}>Drafts</Typography>
<Stack direction="row" spacing={1} sx={{ flexWrap: 'wrap', mb: 1 }}>
{drafts.map(id => (
<Button key={id} size="small" variant={draftId === id ? 'contained' : 'outlined'} onClick={() => loadDraft(id)}>
{id.slice(0, 8)}
</Button>
))}
{drafts.length === 0 && (
<Typography variant="body2">No drafts yet.</Typography>
)}
</Stack>
</Box>
<Box> <Box>
<Typography variant="subtitle1" sx={{ mb: 1 }}>Draft</Typography> <Typography variant="subtitle1" sx={{ mb: 1 }}>Draft</Typography>
<TextField <TextField