Layout mit Inline-Skript, das data-theme setzt, bevor der erste Pixel gemalt wird — sonst blitzt beim Laden das falsche Farbschema auf. Logo als React-Komponente statt als Bilddatei: nimmt Theme-Farben an, spart einen Netzwerkabruf und die Verläufe liegen einmalig im Root-Layout. Im hellen Modus greifen eigene Tokens für Verlaufstext und Wortmarke; der vollfarbige Signaturverlauf fällt auf warmem Weiß sonst unter WCAG AA.
84 lines
3.2 KiB
TypeScript
84 lines
3.2 KiB
TypeScript
import Link from "next/link";
|
|
import { requireUser } from "@/lib/auth";
|
|
import { getSettings } from "@/lib/settings";
|
|
import { env } from "@/lib/env";
|
|
import { AppShell } from "@/components/AppShell";
|
|
import { FlimmerMark } from "@/components/brand/FlimmerLogo";
|
|
|
|
/**
|
|
* Übersichtsseite.
|
|
*
|
|
* In dieser Etappe steht hier die Begrüßung und der Hinweis auf die nächsten
|
|
* Schritte; ab Etappe 5 ziehen „Weiterschauen", Kalender und Neuzugänge ein.
|
|
*/
|
|
export default async function DashboardPage() {
|
|
const user = await requireUser();
|
|
const settings = await getSettings();
|
|
|
|
return (
|
|
<AppShell user={user} instanceName={settings.instanceName}>
|
|
<section className="fl-card relative overflow-hidden p-6 sm:p-10">
|
|
<div
|
|
aria-hidden
|
|
className="pointer-events-none absolute -right-24 -top-32 h-72 w-72 rounded-full opacity-30 blur-3xl"
|
|
style={{ backgroundImage: "var(--fl-gradient)" }}
|
|
/>
|
|
<div className="relative">
|
|
<FlimmerMark className="h-12 w-12" />
|
|
<h1 className="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">
|
|
Hallo {user.name.split(" ")[0]}.
|
|
</h1>
|
|
<p className="mt-2 max-w-xl text-[var(--fl-muted)]">
|
|
Schön, dass du da bist. Sobald du deinen ersten Titel hinzufügst, findest du hier
|
|
deine laufenden Serien, die nächsten Episoden und was auf deiner Watchlist gerade
|
|
verfügbar geworden ist.
|
|
</p>
|
|
|
|
<div className="mt-6 flex flex-wrap gap-3">
|
|
<Link href="/suche" className="fl-btn fl-btn-primary">
|
|
Titel suchen und hinzufügen
|
|
</Link>
|
|
<Link href="/bibliothek" className="fl-btn fl-btn-ghost">
|
|
Zur Bibliothek
|
|
</Link>
|
|
</div>
|
|
|
|
{!env.tmdb.isConfigured && (
|
|
<p className="mt-6 max-w-xl rounded-xl border border-[color-mix(in_oklab,var(--fl-warning)_40%,transparent)] bg-[color-mix(in_oklab,var(--fl-warning)_10%,transparent)] px-3 py-2 text-sm text-[var(--fl-warning)]">
|
|
Es ist noch kein TMDB-Schlüssel hinterlegt. Ohne ihn findet die Suche keine
|
|
Metadaten — trage <code>TMDB_API_KEY</code> in der <code>.env</code> ein und starte
|
|
die Instanz neu.
|
|
</p>
|
|
)}
|
|
</div>
|
|
</section>
|
|
|
|
<div className="mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
<PlaceholderCard
|
|
title="Weiterschauen"
|
|
text="Deine laufenden Serien mit der jeweils nächsten Episode."
|
|
/>
|
|
<PlaceholderCard
|
|
title="Demnächst"
|
|
text="Kalender der Episoden, die in den nächsten Wochen ausgestrahlt werden."
|
|
/>
|
|
<PlaceholderCard
|
|
title="Neu verfügbar"
|
|
text="Watchlist-Titel, die auf einem deiner Dienste aufgetaucht sind."
|
|
/>
|
|
</div>
|
|
</AppShell>
|
|
);
|
|
}
|
|
|
|
function PlaceholderCard({ title, text }: { title: string; text: string }) {
|
|
return (
|
|
<div className="fl-card p-5">
|
|
<h2 className="text-sm font-semibold tracking-wide text-[var(--fl-muted)] uppercase">
|
|
{title}
|
|
</h2>
|
|
<p className="mt-2 text-sm text-[var(--fl-faint)]">{text}</p>
|
|
</div>
|
|
);
|
|
}
|