import Link from "next/link"; import type { Metadata } from "next"; import { requireUser } from "@/lib/auth"; import { getSettings } from "@/lib/settings"; import { getUpcomingEpisodes } from "@/lib/stats"; import { AppShell } from "@/components/AppShell"; import { CalendarMonth } from "@/components/CalendarMonth"; import { episodeCode, formatDateLong } from "@/lib/labels"; export const metadata: Metadata = { title: "Kalender" }; /** Monatsangabe aus der URL („2026-09") oder der laufende Monat. */ function parseMonth(value: string | undefined): Date { const match = value?.match(/^(\d{4})-(\d{2})$/); if (match) { const year = Number(match[1]); const month = Number(match[2]) - 1; if (year >= 1900 && year <= 2200 && month >= 0 && month <= 11) { return new Date(year, month, 1); } } const now = new Date(); return new Date(now.getFullYear(), now.getMonth(), 1); } function monthParam(date: Date): string { return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`; } export default async function CalendarPage({ searchParams, }: { searchParams: Promise<{ monat?: string }>; }) { const user = await requireUser("/kalender"); const settings = await getSettings(); const params = await searchParams; const month = parseMonth(params.monat); const from = new Date(month.getFullYear(), month.getMonth(), 1); // Das Raster reicht in den Vor- und Folgemonat hinein — die Termine auch. const gridFrom = new Date(from.getTime() - 7 * 86_400_000); const gridTo = new Date(from.getFullYear(), from.getMonth() + 1, 7); const episodes = await getUpcomingEpisodes(user.id, gridFrom, gridTo); const inMonth = episodes.filter((episode) => episode.airDate.getMonth() === month.getMonth()); const previous = new Date(month.getFullYear(), month.getMonth() - 1, 1); const next = new Date(month.getFullYear(), month.getMonth() + 1, 1); return (

Kalender

Ausstrahlungstermine der Serien in deiner Bibliothek.

Termine im {month.toLocaleDateString("de-DE", { month: "long" })}

{inMonth.length === 0 ? (
In diesem Monat läuft nichts aus deiner Bibliothek.
) : (
    {inMonth.map((episode) => (
  1. {formatDateLong(episode.airDate)} {episode.title} {episodeCode(episode.seasonNumber, episode.episodeNumber)} {episode.name} {episode.runtime && ( {episode.runtime} min )}
  2. ))}
)}
); }