since3-portal/modules/templates/ui/views/templates-view.tsx
2026-10-05 08:23:02 +02:00

125 lines
7 KiB
TypeScript

import Image from "next/image"
import Link from "next/link"
import { EyeIcon } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { buttonVariants } from "@/components/ui/button"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { getClients } from "@/modules/admin/queries/clients"
import { dateFormat, shareState, type ShareState } from "../../lib/preview"
import { getTemplate, templates } from "../../lib/registry"
import { getVariants } from "../../queries/variants"
import { CreateVariantButton } from "../components/create-variant-button"
const shareBadge: Record<ShareState, { label: string; variant: "success" | "warning" | "neutral" }> = {
shared: { label: "Geteilt", variant: "success" },
expired: { label: "Abgelaufen", variant: "warning" },
private: { label: "Privat", variant: "neutral" },
}
const TemplatesView = async () => {
const [variants, clients] = await Promise.all([getVariants(), getClients()])
const clientNames = new Map(clients.map((client) => [client.id, client.name]))
return (
<div className="flex w-full flex-col gap-10">
<div className="flex flex-col gap-2">
<h1 className="text-2xl font-semibold md:text-3xl">Vorlagen</h1>
<p className="max-w-2xl text-sm text-muted-foreground">
Demo-Webseiten für Pitches: Vorlage wählen, für den Kunden anpassen und als Link teilen.
</p>
</div>
<section className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
{templates.map((template) => (
<article key={template.key} className="group flex flex-col overflow-hidden rounded-xl border bg-card">
<div className="relative aspect-[4/3] overflow-hidden">
<Image
src={template.cover}
alt=""
fill
sizes="(min-width: 1280px) 25vw, (min-width: 640px) 50vw, 100vw"
className="object-cover transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/10 to-transparent" />
<span className="absolute top-3 left-3 rounded-full bg-black/50 px-2.5 py-1 text-xs text-white backdrop-blur">
{template.industry}
</span>
<div className="absolute bottom-3 left-3 flex gap-1.5">
{template.palettes.map((palette) => (
<span
key={palette.key}
title={palette.label}
className="size-4 rounded-full ring-2 ring-white/70"
style={{ background: `linear-gradient(135deg, ${palette.bg} 50%, ${palette.accent} 50%)` }}
/>
))}
</div>
</div>
<div className="flex flex-1 flex-col gap-2 p-4">
<h2 className="font-semibold">{template.name}</h2>
<p className="flex-1 text-sm text-muted-foreground">{template.description}</p>
<div className="mt-3 flex flex-wrap gap-2">
<a
href={`/preview/${template.key}`}
target="_blank"
rel="noreferrer"
className={buttonVariants({ variant: "outline", size: "sm" })}
>
<EyeIcon /> Ansehen
</a>
<CreateVariantButton templateKey={template.key} />
</div>
</div>
</article>
))}
</section>
<section className="flex flex-col gap-4">
<h2 className="text-lg font-semibold">Varianten</h2>
{variants.length === 0 ? (
<p className="rounded-xl border border-dashed p-8 text-center text-sm text-muted-foreground">
Noch keine Varianten. Wähle oben eine Vorlage und klicke auf „Anpassen“.
</p>
) : (
<div className="overflow-hidden rounded-xl border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Vorlage</TableHead>
<TableHead className="hidden md:table-cell">Client</TableHead>
<TableHead>Link</TableHead>
<TableHead className="hidden md:table-cell">Geändert</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{variants.map((variant) => {
const badge = shareBadge[shareState(variant.share_token, variant.share_expires_at)]
return (
<TableRow key={variant.id}>
<TableCell>
<Link href={`/admin/templates/${variant.id}`} className="font-medium hover:underline">
{variant.name}
</Link>
</TableCell>
<TableCell>{getTemplate(variant.template_key)?.name ?? variant.template_key}</TableCell>
<TableCell className="hidden md:table-cell">
{(variant.client_id && clientNames.get(variant.client_id)) ?? "—"}
</TableCell>
<TableCell><Badge variant={badge.variant}>{badge.label}</Badge></TableCell>
<TableCell className="hidden text-muted-foreground md:table-cell">
{dateFormat.format(new Date(variant.updated_at))}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</div>
)}
</section>
</div>
)
}
export default TemplatesView