spomeni/src/app/dashboard/page.tsx
2026-06-20 19:28:05 +02:00

119 lines
4.7 KiB
TypeScript

import Link from "next/link";
import { auth } from "@clerk/nextjs/server";
import { prisma } from "@/lib/prisma";
import { redirect } from "next/navigation";
import { UserButton } from "@clerk/nextjs";
import CopyButton from "@/components/CopyButton";
import DeleteMonumentButton from "@/components/DeleteMonumentButton";
import DeleteImageButton from "@/components/DeleteImageButton";
export default async function DashboardPage() {
const { userId } = await auth();
if (!userId) redirect("/sign-in");
const user = await prisma.user.findUnique({
where: { clerkId: userId },
include: { images: { orderBy: { order: "asc" } } },
});
if (!user) {
redirect("/onboarding");
}
const monumentUrl = `https://${user.subdomain}.${process.env.NEXT_PUBLIC_APP_DOMAIN}`;
return (
<div className="min-h-screen bg-stone-50">
<header className="border-b border-stone-200 bg-white">
<div className="mx-auto flex max-w-5xl items-center justify-between px-6 py-4">
<h1 className="text-xl font-semibold text-stone-900">SpomeniQR</h1>
<UserButton />
</div>
</header>
<main className="mx-auto max-w-5xl px-6 py-8">
<div className="rounded-lg border border-stone-200 bg-white p-6">
<h2 className="text-2xl font-semibold text-stone-900">{user.title || "Untitled Memorial"}</h2>
{(user.bornDate || user.passedDate) && (
<p className="mt-1 text-sm tracking-wider text-stone-400">
{user.bornDate}{user.bornDate && user.passedDate ? " — " : ""}{user.passedDate}
</p>
)}
<p className="mt-2 text-sm text-stone-500">
{user.published ? "Published" : "Draft"} &middot; Subdomain: <span className="font-mono">{user.subdomain}</span>
</p>
<div className="mt-6 flex flex-wrap gap-3">
<Link
href={monumentUrl}
target="_blank"
className="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-primary-light"
>
View Monument
</Link>
<Link
href="/dashboard/edit"
className="rounded-lg border border-stone-200 px-4 py-2 text-sm font-medium text-stone-700 transition-colors hover:bg-stone-50"
>
Edit
</Link>
</div>
</div>
{user.images.length > 0 && (
<div className="mt-6">
<h3 className="text-lg font-medium text-stone-900">Images</h3>
<div className="mt-3 grid grid-cols-3 gap-4">
{user.images.map((img) => (
<div key={img.id} className="group relative overflow-hidden rounded-lg border border-stone-200">
<img src={img.url} alt="" className="h-40 w-full object-cover" />
<DeleteImageButton imageId={img.id} />
</div>
))}
</div>
</div>
)}
<div className="mt-6">
<h3 className="text-lg font-medium text-stone-900">Monument QR Code</h3>
<p className="mt-1 text-sm text-stone-500">Download and display this QR code at your monument location.</p>
<div className="mt-4 rounded-lg border border-stone-200 bg-white p-4">
<img
src={`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(monumentUrl)}`}
alt="QR Code"
className="h-48 w-48"
/>
<a
href={`https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${encodeURIComponent(monumentUrl)}`}
download
className="mt-4 inline-block rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-primary-light"
>
Download QR
</a>
</div>
</div>
<div className="mt-6">
<h3 className="text-lg font-medium text-stone-900">Share Link</h3>
<div className="mt-2 flex items-center gap-2">
<input
type="text"
readOnly
value={monumentUrl}
className="flex-1 rounded-lg border border-stone-200 bg-stone-50 px-3 py-2 font-mono text-sm text-stone-700"
/>
<CopyButton text={monumentUrl} />
</div>
</div>
<div className="mt-10 border-t border-stone-200 pt-6">
<h3 className="text-sm font-medium text-red-600">Danger Zone</h3>
<p className="mt-1 text-xs text-stone-500">Permanently delete your monument and all associated images.</p>
<div className="mt-3">
<DeleteMonumentButton />
</div>
</div>
</main>
</div>
);
}