import { useCallback, useEffect, useState } from "react" import { createFileRoute, Link, useNavigate } from "@tanstack/react-router" import type { Archive } from "@/db/schema" import { Plus, Video, Image, FileText, Lock, Globe } from "lucide-react" export const Route = createFileRoute("/archive")({ ssr: false, component: ArchivePage, }) type ArchiveType = "video" | "image" | "text" function ArchivePage() { const [archives, setArchives] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [creating, setCreating] = useState(false) const [showCreateModal, setShowCreateModal] = useState(false) const [hasAccess, setHasAccess] = useState(true) const navigate = useNavigate() const loadArchives = useCallback(async () => { setLoading(true) setError(null) try { const response = await fetch("/api/archives") const data = await response.json() if (!response.ok) { if (response.status === 403) { setHasAccess(false) return } throw new Error(data.error || "Failed to load archives") } setArchives(data.archives || []) setHasAccess(true) } catch (err) { console.error("[archive] failed to load archives", err) setError("Failed to load archives") } finally { setLoading(false) } }, []) useEffect(() => { void loadArchives() }, [loadArchives]) const handleCreateArchive = async ( title: string, type: ArchiveType, description?: string ) => { setCreating(true) setError(null) try { const response = await fetch("/api/archives", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ title, type, description }), }) const data = await response.json() if (!response.ok) { throw new Error(data.error || "Failed to create archive") } setArchives((prev) => [data.archive, ...prev]) setShowCreateModal(false) } catch (err) { console.error("[archive] failed to create archive", err) setError(err instanceof Error ? err.message : "Failed to create archive") } finally { setCreating(false) } } if (!hasAccess) { return } return (

Archive

My Archives

Store videos, images, and text privately. Share what you want.

{error && (
{error}
)} {loading && archives.length === 0 ? (
{Array.from({ length: 6 }).map((_, index) => (
))}
) : archives.length > 0 ? ( ) : ( !loading && (

No archives yet

Create your first archive to start storing content.

) )}
{showCreateModal && ( setShowCreateModal(false)} onCreate={handleCreateArchive} creating={creating} /> )}
) } function ArchiveGrid({ archives }: { archives: Archive[] }) { return (
{archives.map((archive) => ( ))}
) } function ArchiveCard({ archive }: { archive: Archive }) { const TypeIcon = { video: Video, image: Image, text: FileText, }[archive.type] || FileText const createdAt = new Date(archive.created_at).toLocaleDateString(undefined, { month: "short", day: "numeric", }) return (
{archive.is_public ? ( ) : ( )}

{archive.title}

{archive.description && (

{archive.description}

)}
{archive.type} {createdAt}
) } function CreateArchiveModal({ onClose, onCreate, creating, }: { onClose: () => void onCreate: (title: string, type: ArchiveType, description?: string) => void creating: boolean }) { const [title, setTitle] = useState("") const [type, setType] = useState("video") const [description, setDescription] = useState("") const handleSubmit = (e: React.FormEvent) => { e.preventDefault() if (!title.trim()) return onCreate(title.trim(), type, description.trim() || undefined) } return (

Create Archive

setTitle(e.target.value)} className="w-full rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-white placeholder-white/40 focus:border-white/30 focus:outline-none" placeholder="My Archive" required />
{(["video", "image", "text"] as ArchiveType[]).map((t) => { const Icon = { video: Video, image: Image, text: FileText }[t] return ( ) })}