"use client"; import { useEffect, useState } from "react"; import Image from "next/image"; import Link from "next/link"; import type { TischLabels, TischObject } from "./types"; import { loadCurrentBook, type CurrentBook } from "./currentBook"; interface ObjectFaceProps { obj: TischObject; labels: TischLabels; } const pad = (n: number) => String(n).padStart(2, "0"); // Rand und Rundung, die alle Objekte teilen const edge = "h-full w-full overflow-hidden rounded-2xl border-2 border-ink"; /** Zeichnet ein Objekt. Größe und Position bestimmt der Container (Tisch oder Stapel). */ export default function ObjectFace({ obj, labels }: ObjectFaceProps) { switch (obj.kind) { case "project": return (
({pad(obj.index + 1)}) {obj.year}

{obj.title}

{obj.tags.slice(0, 3).join(" · ")}
{labels.flip} ↗
); case "ticket": return (
{labels.ticketTitle}
{obj.daysLeft}
{labels.ticketDays}
{labels.ticketJob}
{labels.ticketStub}
); case "server": return (

{labels.serverTitle}

{labels.servers.map((s) => (
))}

{labels.serverNote}

); case "book": return ; case "photo": return (
Dennis Konkol
{labels.photoCaption}
); case "sticker": return (
{labels.sticker}
); } } function BookFace({ href, labels }: { href: string; labels: TischLabels }) { const [book, setBook] = useState(undefined); useEffect(() => { let alive = true; loadCurrentBook().then((b) => { if (alive) setBook(b); }); return () => { alive = false; }; }, []); const progress = book && Number.isFinite(book.progress) ? Math.max(0, Math.min(100, book.progress)) : 0; return (
{book?.image && ( )}
{labels.bookLabel} {book === undefined ? (