4f5089ce38
- 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>
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import Link from "next/link";
|
|
import { useLocale, useTranslations } from "next-intl";
|
|
import { useConsent } from "./ConsentProvider";
|
|
|
|
const pill =
|
|
"inline-flex items-center rounded-full px-4 py-2 text-sm font-medium shadow-[inset_0_0_0_1.5px_rgb(var(--plakat-paper)/0.5)] transition-[background-color,color,transform] duration-150 ease-out hover:bg-paper hover:text-ink active:scale-[0.97]";
|
|
|
|
const Footer = () => {
|
|
const locale = useLocale();
|
|
const t = useTranslations("footer");
|
|
const { resetConsent } = useConsent();
|
|
const year = new Date().getFullYear();
|
|
|
|
return (
|
|
<footer className="bg-ink px-4 pb-10 pt-12 text-paper sm:px-6 lg:px-10">
|
|
<div className="flex flex-wrap items-end justify-between gap-6">
|
|
<Link
|
|
href={`/${locale}`}
|
|
className="font-display text-[clamp(4rem,14vw,9rem)] font-extrabold leading-[0.8] tracking-[-0.05em]"
|
|
aria-label="dk0"
|
|
>
|
|
dk<span className="text-signal">0</span>
|
|
</Link>
|
|
<a href="#top" className={pill}>
|
|
{t("backToTop")} <span aria-hidden="true" className="ml-1.5">↑</span>
|
|
</a>
|
|
</div>
|
|
|
|
<nav className="mt-8 flex flex-wrap gap-2 border-t-2 border-paper/20 pt-6" aria-label={t("legalNotice")}>
|
|
<Link href={`/${locale}/legal-notice`} className={pill}>
|
|
{t("legalNotice")}
|
|
</Link>
|
|
<Link href={`/${locale}/privacy-policy`} className={pill}>
|
|
{t("privacyPolicy")}
|
|
</Link>
|
|
<button type="button" onClick={resetConsent} className={pill} title={t("privacySettingsTitle")}>
|
|
{t("privacySettings")}
|
|
</button>
|
|
<a href="https://github.com/Denshooter" target="_blank" rel="noopener noreferrer" className={pill}>
|
|
GitHub
|
|
</a>
|
|
<a href="https://linkedin.com/in/dkonkol" target="_blank" rel="noopener noreferrer" className={pill}>
|
|
LinkedIn
|
|
</a>
|
|
</nav>
|
|
|
|
<div className="mt-8 grid gap-1.5 font-mono text-xs text-paper/70">
|
|
<p>
|
|
© {year} Dennis Konkol · {t("role")} · {t("madeIn")}
|
|
</p>
|
|
<p>{t("builtWith")}</p>
|
|
<p>{t("aiDisclaimer")}</p>
|
|
</div>
|
|
</footer>
|
|
);
|
|
};
|
|
|
|
export default Footer;
|