"use client"; import Image from "next/image"; import { useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; import { useTheme } from "next-themes"; import { useMutation } from "convex/react"; import { useTranslations } from "next-intl"; import { ChevronDown, Coins, LayoutTemplate, Monitor, Moon, Search, Sun, } from "lucide-react"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { api } from "@/convex/_generated/api"; import type { Doc } from "@/convex/_generated/dataModel"; import { authClient } from "@/lib/auth-client"; import { CreditOverview } from "@/components/dashboard/credit-overview"; import { CreditsActivityChart } from "@/components/dashboard/credits-activity-chart"; import { RecentTransactions } from "@/components/dashboard/recent-transactions"; import CanvasCard from "@/components/dashboard/canvas-card"; import { useDashboardSnapshot } from "@/hooks/use-dashboard-snapshot"; import { toast } from "@/lib/toast"; function getInitials(nameOrEmail: string) { const normalized = nameOrEmail.trim(); if (!normalized) return "U"; const parts = normalized.split(/\s+/).filter(Boolean); if (parts.length >= 2) { return `${parts[0][0]}${parts[1][0]}`.toUpperCase(); } return normalized.slice(0, 2).toUpperCase(); } export function DashboardPageClient() { const t = useTranslations("toasts"); const router = useRouter(); const welcomeToastSentRef = useRef(false); const { theme = "system", setTheme } = useTheme(); const { data: session, isPending: isSessionPending } = authClient.useSession(); const { snapshot: dashboardSnapshot } = useDashboardSnapshot(session?.user?.id); const createCanvas = useMutation(api.canvases.create); const [isCreatingWorkspace, setIsCreatingWorkspace] = useState(false); const [hasClientMounted, setHasClientMounted] = useState(false); useEffect(() => { setHasClientMounted(true); }, []); const displayName = session?.user.name?.trim() || session?.user.email || "Nutzer"; const initials = getInitials(displayName); const canvases = dashboardSnapshot?.canvases; useEffect(() => { if (!session?.user || welcomeToastSentRef.current) return; const key = `ls-dashboard-welcome-${session.user.id}`; if (typeof window !== "undefined" && sessionStorage.getItem(key)) return; welcomeToastSentRef.current = true; sessionStorage.setItem(key, "1"); toast.success(t("auth.welcomeOnDashboard")); }, [t, session?.user]); const handleSignOut = async () => { toast.info(t("auth.signedOut")); await authClient.signOut(); router.replace("/auth/sign-in"); router.refresh(); }; const handleCreateWorkspace = async () => { if (isCreatingWorkspace) return; if (!session?.user) return; setIsCreatingWorkspace(true); try { const canvasId = await createCanvas({ name: "Neuer Workspace", description: "", }); router.push(`/canvas/${canvasId}`); } finally { setIsCreatingWorkspace(false); } }; return (
Account Theme setTheme(value)} > Light Dark System Einstellungen Abrechnung Abmelden

Guten Tag, {displayName}

Überblick über deine Credits und laufende Generierungen.

Credit-Übersicht
Arbeitsbereiche
{isSessionPending || canvases === undefined ? (
Arbeitsbereiche werden geladen...
) : canvases.length === 0 ? (
Noch kein Arbeitsbereich vorhanden. Mit „Neuer Arbeitsbereich“ legst du den ersten an.
) : (
{canvases.map((canvas: Doc<"canvases">) => ( router.push(`/canvas/${id}`)} /> ))}
)}
); }