'use client' import { useCallback, useEffect, useState } from 'react' import { Download, FileText, Layers, Link2, RotateCcw, Trash2 } from 'lucide-react' import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { notifyPagesChanged } from '@/lib/pages' type TrashEntry = { id: string; type: 'bookmark' | 'page' | 'collection'; originalId: string; title: string; deletedAt: string } const TYPE_ICON = { bookmark: Link2, page: FileText, collection: Layers } as const export function TrashClient() { const [entries, setEntries] = useState([]) const [busy, setBusy] = useState(null) const [exporting, setExporting] = useState(false) const load = useCallback(async () => { try { const res = await fetch('/api/trash', { cache: 'no-store' }) if (!res.ok) { toast.error('Could not load the trash'); return } setEntries(await res.json()) } catch { toast.error('Could not load the trash') } }, []) useEffect(() => { const timer = setTimeout(() => { void load() }, 0) return () => clearTimeout(timer) }, [load]) const restore = async (entry: TrashEntry) => { setBusy(entry.id) try { const res = await fetch(`/api/trash/${entry.id}/restore`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' }) if (!res.ok) { toast.error((await res.json().catch(() => null))?.error ?? 'Could not restore'); return } toast.success(`Restored “${entry.title}”`) if (entry.type === 'page') notifyPagesChanged() await load() } catch { toast.error('Could not restore') } finally { setBusy(null) } } const purge = async (entry: TrashEntry) => { if (!confirm(`Delete “${entry.title}” permanently? This cannot be undone.`)) return setBusy(entry.id) try { const res = await fetch(`/api/trash/${entry.id}`, { method: 'DELETE' }) if (!res.ok) { toast.error('Could not delete permanently'); return } toast.success('Deleted permanently') await load() } catch { toast.error('Could not delete permanently') } finally { setBusy(null) } } const exportData = async () => { setExporting(true) try { const res = await fetch('/api/export') if (!res.ok) { toast.error('Could not export your data'); return } const blob = await res.blob() const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `computer-export-${new Date().toISOString().slice(0, 10)}.json` document.body.appendChild(a); a.click(); a.remove() URL.revokeObjectURL(url) toast.success('Export downloaded') } catch { toast.error('Could not export your data') } finally { setExporting(false) } } return (

Trash

Deleted bookmarks, pages and collections stay recoverable here. Restoring brings back content and owner-scoped links, but never a share or public link that was revoked in the meantime.

{entries.length === 0 ? (

The trash is empty.

) : (
{entries.map((entry) => { const Icon = TYPE_ICON[entry.type] return (

{entry.title}

{new Date(entry.deletedAt).toLocaleString('en-US', { timeZone: 'UTC' })}

{entry.type}
) })}
)}
) }