import { useCallback, useEffect, useMemo, useState } from "react" import { createFileRoute, Link, useNavigate } from "@tanstack/react-router" import { createCanvasProject, fetchCanvasList, } from "@/lib/canvas/client" import type { SerializedCanvas, SerializedCanvasSummary, } from "@/lib/canvas/types" export const Route = createFileRoute("/canvas/")({ ssr: false, component: CanvasProjectsPage, }) function summarize(snapshot: SerializedCanvas): SerializedCanvasSummary { return { canvas: snapshot.canvas, previewImage: snapshot.images[0] ?? null, imageCount: snapshot.images.length, } } function CanvasProjectsPage() { const [projects, setProjects] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [creating, setCreating] = useState(false) const navigate = useNavigate() const loadProjects = useCallback(async () => { setLoading(true) setError(null) try { const data = await fetchCanvasList() setProjects(data) } catch (err) { console.error("[canvas] failed to load projects", err) setError("Failed to load projects") } finally { setLoading(false) } }, []) useEffect(() => { void loadProjects() }, [loadProjects]) const handleCreateProject = useCallback(async () => { if (creating) { return } setCreating(true) setError(null) try { const snapshot = await createCanvasProject() const summary = summarize(snapshot) setProjects((prev) => [summary, ...prev]) navigate({ to: "/canvas/$canvasId", params: { canvasId: snapshot.canvas.id } }) } catch (err) { console.error("[canvas] failed to create project", err) setError("Unable to create a new project") } finally { setCreating(false) } }, [creating, navigate]) const showSkeletonGrid = loading && projects.length === 0 return (

Canvas

My Projects

Choose a canvas to continue exploring ideas. Each project preserves its own layout, prompts, and styles.

{loading ? ( Loading… ) : null}
{error ? (
{error}
) : null} {showSkeletonGrid ? (
{Array.from({ length: 6 }).map((_, index) => (
))}
) : ( )} {!projects.length && !loading ? (

You don't have any projects yet.

Start a new canvas to begin planning, brainstorming, or designing.

) : null}
) } function ProjectsGrid({ projects, }: { projects: SerializedCanvasSummary[] }) { if (!projects.length) { return null } return (
{projects.map((project) => ( ))}
) } function CanvasProjectCard({ project, }: { project: SerializedCanvasSummary }) { const previewUrl = useMemo(() => { const preview = project.previewImage if (!preview) { return null } if (preview.imageUrl) { return preview.imageUrl } if (preview.imageData) { const mime = preview.metadata && typeof preview.metadata.mimeType === "string" ? (preview.metadata.mimeType as string) : "image/png" return `data:${mime};base64,${preview.imageData}` } return null }, [project.previewImage]) const imageCountLabel = project.imageCount === 1 ? "image" : "images" const updatedAt = useMemo(() => { const date = new Date(project.canvas.updatedAt) return date.toLocaleDateString(undefined, { month: "short", day: "numeric", }) }, [project.canvas.updatedAt]) return (
{previewUrl ? (
) : (
No preview yet
)}
{updatedAt} {project.imageCount} {imageCountLabel}

{project.canvas.name}

Tap to open canvas

) }