126 lines
5.2 KiB
TypeScript
126 lines
5.2 KiB
TypeScript
import Link from "next/link";
|
|
import { Mail } from "lucide-react";
|
|
import { FaLinkedin } from "react-icons/fa6";
|
|
import { SiGitea } from "react-icons/si";
|
|
import type { Locale, Dictionary } from "@/lib/dictionaries";
|
|
import { LogoMark } from "@/components/ui/Logo";
|
|
|
|
interface FooterProps {
|
|
locale: Locale;
|
|
dict: Dictionary;
|
|
}
|
|
|
|
export default function Footer({ locale, dict }: FooterProps) {
|
|
const footerLinks = {
|
|
[dict.footer.product]: [
|
|
{ label: dict.nav.features, href: `/${locale}/#features` },
|
|
{ label: dict.nav.services, href: `/${locale}/services` },
|
|
{ label: dict.nav.contact, href: `/${locale}/contact` },
|
|
],
|
|
[dict.footer.company]: [
|
|
{ label: dict.nav.about, href: `/${locale}/about` },
|
|
],
|
|
[dict.footer.connect]: [
|
|
{ label: "Source Code", href: "https://git.ksan.dev/ksan", external: true },
|
|
{ label: "Email", href: "mailto:contact@ksan.dev", external: true },
|
|
{ label: "LinkedIn", href: "https://linkedin.com", external: true },
|
|
],
|
|
};
|
|
|
|
const socials = [
|
|
{ icon: SiGitea, href: "https://git.ksan.dev/ksan", label: "Gitea" },
|
|
{ icon: Mail, href: "mailto:contact@ksan.dev", label: "Email" },
|
|
{ icon: FaLinkedin, href: "https://linkedin.com", label: "LinkedIn" },
|
|
];
|
|
|
|
return (
|
|
<footer className="relative z-10 mt-32 border-t border-border/40">
|
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-purple-400/40 to-transparent" />
|
|
|
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-64 overflow-hidden">
|
|
<div className="absolute left-1/2 top-0 h-64 w-[60rem] -translate-x-1/2 -translate-y-1/2 rounded-full bg-purple-500/15 blur-3xl" />
|
|
</div>
|
|
|
|
<div className="relative mx-auto max-w-7xl px-6 py-16 lg:px-8 lg:py-20">
|
|
<div className="grid grid-cols-2 gap-12 lg:grid-cols-5">
|
|
<div className="col-span-2 max-w-sm">
|
|
<Link href={`/${locale}`} className="inline-flex items-center gap-2.5">
|
|
<div className="flex h-8 w-8 items-center justify-center rounded-lg border border-purple-400/30 bg-purple-500/10 shadow-glow-sm">
|
|
<LogoMark className="w-[19px] text-white" />
|
|
</div>
|
|
<span className="font-display text-base font-medium text-text-primary">
|
|
ksan.dev
|
|
</span>
|
|
</Link>
|
|
|
|
<p className="mt-5 text-sm leading-relaxed text-text-secondary">
|
|
Full-stack engineering, end to end. Everything built and hosted by me.
|
|
</p>
|
|
|
|
<div className="mt-6 flex items-center gap-3">
|
|
{socials.map((social) => (
|
|
<a
|
|
key={social.label}
|
|
href={social.href}
|
|
target={social.href.startsWith("http") ? "_blank" : undefined}
|
|
rel={social.href.startsWith("http") ? "noopener noreferrer" : undefined}
|
|
className="flex h-9 w-9 items-center justify-center rounded-lg border border-border/50 text-text-secondary transition-all hover:border-purple-400/40 hover:bg-purple-500/10 hover:text-purple-300"
|
|
aria-label={social.label}
|
|
>
|
|
<social.icon className="h-4 w-4" />
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{Object.entries(footerLinks).map(([title, links]) => (
|
|
<div key={title}>
|
|
<h4 className="mb-4 font-mono text-xs uppercase tracking-widest text-text-secondary">
|
|
{title}
|
|
</h4>
|
|
<ul className="space-y-3">
|
|
{links.map((link) => (
|
|
<li key={link.label}>
|
|
{"external" in link && link.external ? (
|
|
<a
|
|
href={link.href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-sm text-text-secondary transition-colors hover:text-text-primary"
|
|
>
|
|
{link.label}
|
|
</a>
|
|
) : (
|
|
<Link
|
|
href={link.href}
|
|
className="text-sm text-text-secondary transition-colors hover:text-text-primary"
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
)}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="mt-16 flex flex-col items-start gap-4 border-t border-border/40 pt-8 sm:flex-row sm:items-center sm:justify-between">
|
|
<p className="font-mono text-xs text-text-secondary">
|
|
© {new Date().getFullYear()} ksan.dev · {dict.footer.rights}
|
|
</p>
|
|
<p className="font-mono text-xs text-text-secondary">
|
|
<span className="inline-flex items-center gap-2">
|
|
<span className="relative flex h-1.5 w-1.5">
|
|
<span className="absolute inset-0 animate-ping rounded-full bg-purple-400 opacity-75" />
|
|
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-purple-400" />
|
|
</span>
|
|
{dict.footer.status}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|