feat: plakat redesign phase 4 (chat window, contact, footer, cleanup)

- AI chat moves into a window/sheet, opened from a new speech-bubble card on
  the desk; it now respects the chatbot consent and asks before sending
  anything to n8n (previously it ignored the consent)
- Contact as red poster section with big mail address and the form on a paper
  card; validation errors are finally shown inline (aria-invalid, role=alert)
- Footer as ink strip with dk0 wordmark, legal links and a button to reopen
  the privacy settings
- "About me" in the header opens the about window on the home page
- Remove the old About section and its parts (BentoChat, ActivityFeed,
  CurrentlyReading, ReadBooks), the unused ChatWidget, Projects and BentoGrid,
  their tests, wrappers, loaders, types and texts
- scripts/directus-cleanup-redesign.mjs: dry run by default, --apply archives
  hobbies, tech stack categories and old content pages and deletes four
  unused message overrides after a full JSON backup; run only after the
  redesign is live on production

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
denshooter
2026-10-15 19:05:24 +02:00
parent 08e856120b
commit 4f5089ce38
33 changed files with 534 additions and 2572 deletions
+7 -1
View File
@@ -4,6 +4,7 @@ import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { loadCurrentBook, type CurrentBook } from "../tisch/currentBook";
import ChatBody from "./ChatBody";
import type { WindowLabels, WindowRequest } from "./types";
const EMAIL = "contact@dk0.dev";
@@ -28,13 +29,15 @@ export function windowTitle(req: WindowRequest, labels: WindowLabels): string {
return labels.about.title;
case "contact":
return labels.contact.title;
case "chat":
return labels.chat.title;
}
}
/** Farbe des Punkts in der Ablage-Leiste */
export function windowAccent(req: WindowRequest): string {
if (req.kind === "project") return req.project.color;
return { now: "rgb(var(--plakat-red))", server: "rgb(var(--plakat-ok))", read: "#7a5240", about: "#2f5bea", contact: "rgb(var(--plakat-red))" }[req.kind];
return { now: "rgb(var(--plakat-red))", server: "rgb(var(--plakat-ok))", read: "#7a5240", about: "#2f5bea", contact: "rgb(var(--plakat-red))", chat: "#1d1b3d" }[req.kind];
}
interface WindowContentProps {
@@ -128,6 +131,9 @@ export default function WindowContent({ req, labels, onClose }: WindowContentPro
case "contact":
return <ContactBody labels={labels} onClose={onClose} />;
case "chat":
return <ChatBody labels={labels} />;
}
}