'use client'; import type { GuildBackupDashboard } from '@nexumi/shared'; import { Download, Info, Plus, RotateCcw, Trash2 } from 'lucide-react'; import { useState } from 'react'; import { toast } from 'sonner'; import { FieldAnchor } from '@/components/layout/field-anchor'; import { useTranslations } from '@/components/locale-provider'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; function formatDate(iso: string): string { return new Date(iso).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }); } interface GuildBackupManagerProps { guildId: string; initialBackups: GuildBackupDashboard[]; isOwner: boolean; } export function GuildBackupManager({ guildId, initialBackups, isOwner }: GuildBackupManagerProps) { const t = useTranslations(); const [backups, setBackups] = useState(initialBackups); const [name, setName] = useState(''); const [creating, setCreating] = useState(false); const [pendingId, setPendingId] = useState(null); const [infoId, setInfoId] = useState(null); const [infoText, setInfoText] = useState(null); async function handleCreate() { if (!name.trim()) { toast.error(t('modulePages.guildbackup.nameRequired')); return; } setCreating(true); try { const response = await fetch(`/api/guilds/${guildId}/guildbackup`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: name.trim() }) }); const body = (await response.json().catch(() => null)) as (GuildBackupDashboard & { error?: string }) | null; if (!response.ok || !body) { toast.error(body?.error ?? t('common.saveError')); return; } setBackups((prev) => [body, ...prev]); setName(''); toast.success(t('modulePages.guildbackup.created')); } catch { toast.error(t('common.saveError')); } finally { setCreating(false); } } async function handleInfo(backup: GuildBackupDashboard) { if (infoId === backup.id) { setInfoId(null); setInfoText(null); return; } setInfoId(backup.id); try { const response = await fetch(`/api/guilds/${guildId}/guildbackup/${backup.id}`); const body = (await response.json().catch(() => null)) as { payload?: { guildName: string; roles: unknown[]; channels: unknown[] } | null; error?: string; } | null; if (!response.ok || !body?.payload) { setInfoText(t('modulePages.guildbackup.infoUnavailable')); return; } setInfoText( `${t('modulePages.guildbackup.infoGuildName')}: ${body.payload.guildName} · ${t('modulePages.guildbackup.infoRoles')}: ${body.payload.roles.length} · ${t('modulePages.guildbackup.infoChannels')}: ${body.payload.channels.length}` ); } catch { setInfoText(t('modulePages.guildbackup.infoUnavailable')); } } function handleDownload(backup: GuildBackupDashboard) { window.open(`/api/guilds/${guildId}/guildbackup/${backup.id}/download`, '_blank'); } async function handleDelete(backup: GuildBackupDashboard) { if (!window.confirm(t('modulePages.guildbackup.confirmDelete'))) { return; } setPendingId(backup.id); try { const response = await fetch(`/api/guilds/${guildId}/guildbackup/${backup.id}`, { method: 'DELETE' }); if (!response.ok) { toast.error(t('common.saveError')); return; } setBackups((prev) => prev.filter((entry) => entry.id !== backup.id)); toast.success(t('common.saveSuccess')); } catch { toast.error(t('common.saveError')); } finally { setPendingId(null); } } async function handleRestore(backup: GuildBackupDashboard) { if (!window.confirm(t('modulePages.guildbackup.confirmRestoreStep1'))) { return; } if (!window.confirm(t('modulePages.guildbackup.confirmRestoreStep2'))) { return; } setPendingId(backup.id); try { const response = await fetch(`/api/guilds/${guildId}/guildbackup/${backup.id}/restore`, { method: 'POST' }); const body = (await response.json().catch(() => null)) as { error?: string } | null; if (!response.ok) { toast.error(body?.error ?? t('common.saveError')); return; } toast.success(t('modulePages.guildbackup.restoreQueued')); } catch { toast.error(t('common.saveError')); } finally { setPendingId(null); } } return (
{t('modulePages.guildbackup.createTitle')} {t('modulePages.guildbackup.createDescription')}
setName(event.target.value)} placeholder={t('modulePages.guildbackup.namePlaceholder')} />
{t('modulePages.guildbackup.listTitle')} {t('modulePages.guildbackup.listDescription')} {backups.length === 0 && (

{t('modulePages.guildbackup.empty')}

)} {backups.map((backup) => (

{backup.name}

{formatDate(backup.createdAt)} · {t('modulePages.guildbackup.infoRoles')}: {backup.roleCount} ·{' '} {t('modulePages.guildbackup.infoChannels')}: {backup.channelCount}

{!isOwner && ( {t('modulePages.guildbackup.ownerOnlyBadge')} )}
{infoId === backup.id && infoText && (

{infoText}

)}
{isOwner && ( )}
))}
); }