"use client";
import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import type { TischLabels, TischObject } from "./types";
interface ObjectFaceProps {
obj: TischObject;
labels: TischLabels;
flipped?: boolean;
}
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, flipped = false }: ObjectFaceProps) {
switch (obj.kind) {
case "project":
return (
({pad(obj.index + 1)})
{obj.year}
{obj.title}
{obj.tags.slice(0, 3).join(" · ")}
{labels.flip} ↻
{obj.title}
{obj.year}
{obj.description}
e.stopPropagation()}
>
{labels.details}
→
);
case "ticket":
return (
{labels.ticketTitle}
{obj.daysLeft}
{labels.ticketDays}
{labels.ticketJob}
{labels.ticketStub}
);
case "server":
return (
{labels.serverTitle}
{labels.servers.map((s) => (
{s.name}
{s.detail}
))}
{labels.serverNote}
);
case "book":
return ;
case "photo":
return (
);
case "sticker":
return (
{labels.sticker}
);
}
}
interface CurrentBook {
title: string;
authors: string[];
image: string | null;
progress: number;
}
// Tisch und Stapel zeigen das Buch beide; so wird es nur einmal geladen
let bookRequest: Promise | null = null;
function loadCurrentBook(): Promise {
if (!bookRequest) {
bookRequest = fetch("/api/n8n/hardcover/currently-reading")
.then((res) => (res.ok ? res.json() : null))
.then((data) => {
const list = data?.currentlyReading;
const first = Array.isArray(list) ? list[0] : list;
return first ?? null;
})
.catch(() => null);
}
return bookRequest;
}
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 ? (
) : book ? (
{book.title}
{book.authors.join(", ")}
) : (
{labels.bookFallback}
)}
{book ? `${progress} %` : " "}
);
}