348 lines
11 KiB
TypeScript
348 lines
11 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import Link from "next/link";
|
|
import { JetBrains_Mono } from "next/font/google";
|
|
import { Dictionary } from "@/lib/IDict";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const jetbrainsMono = JetBrains_Mono({
|
|
subsets: ["latin", "cyrillic"],
|
|
});
|
|
|
|
// Иконки SVG скрыты для экономии места (оставь как были)
|
|
const Icons = {
|
|
Telegram: () => (
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className="size-6"
|
|
>
|
|
<path d="m22 2-7 20-4-9-9-4Z" />
|
|
<path d="M22 2 11 13" />
|
|
</svg>
|
|
),
|
|
Youtube: () => (
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className="size-6"
|
|
>
|
|
<path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.42a2.78 2.78 0 0 0-1.94 2C1 8.11 1 12 1 12s0 3.89.46 5.58a2.78 2.78 0 0 0 1.94 2c1.72.42 8.6.42 8.6.42s6.88 0 8.6-.42a2.78 2.78 0 0 0 1.94-2C23 15.89 23 12 23 12s0-3.89-.46-5.58z" />
|
|
<polygon
|
|
points="9.75 15.02 15.5 12 9.75 8.98 9.75 15.02"
|
|
fill="currentColor"
|
|
/>
|
|
</svg>
|
|
),
|
|
Discord: () => (
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className="size-6"
|
|
>
|
|
<path d="M19.73 5.42a19.06 19.06 0 0 0-4.73-1.45 14.1 14.1 0 0 0-.6 1.2A17.65 17.65 0 0 0 9.6 5.17a14.1 14.1 0 0 0-.6-1.2 19.06 19.06 0 0 0-4.73 1.45 19.64 19.64 0 0 0-3.37 13.5 19.34 19.34 0 0 0 5.86 3 13.9 13.9 0 0 0 1.26-2.03 13.2 13.2 0 0 1-2-.95c.16-.12.3-.25.45-.38a13.3 13.3 0 0 0 11.08 0c.15.13.3.26.45.38a13.2 13.2 0 0 1-2 .95 13.9 13.9 0 0 0 1.26 2.03 19.34 19.34 0 0 0 5.86-3 19.64 19.64 0 0 0-3.37-13.5ZM8.5 15.2c-1.07 0-1.95-1-1.95-2.22s.87-2.22 1.95-2.22c1.08 0 1.96 1 1.95 2.22 0 1.21-.88 2.22-1.95 2.22Zm7 0c-1.07 0-1.95-1-1.95-2.22s.87-2.22 1.95-2.22c1.08 0 1.96 1 1.95 2.22 0 1.21-.88 2.22-1.95 2.22Z" />
|
|
</svg>
|
|
),
|
|
X: () => (
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className="size-6"
|
|
>
|
|
<path d="M4 4l11.733 16H20L8.267 4z" />
|
|
<path d="M4 20l6.768-6.768m2.464-2.464L20 4" />
|
|
</svg>
|
|
),
|
|
Instagram: () => (
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className="size-6"
|
|
>
|
|
<rect width="20" height="20" x="2" y="2" rx="5" ry="5" />
|
|
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
|
|
<line x1="17.5" x2="17.51" y1="6.5" y2="6.5" />
|
|
</svg>
|
|
),
|
|
Habr: () => (
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2.5"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className="size-6"
|
|
>
|
|
<path d="M5 5v14M19 5v14M5 12h14" />
|
|
</svg>
|
|
),
|
|
};
|
|
|
|
const FlickeringSocialIcon = ({ social }: { social: any }) => {
|
|
const [opacity, setOpacity] = useState(1);
|
|
|
|
useEffect(() => {
|
|
let timeoutId: NodeJS.Timeout;
|
|
const flicker = () => {
|
|
if (Math.random() > 0.6) {
|
|
setOpacity(Math.random() * 0.5 + 0.1);
|
|
setTimeout(() => setOpacity(1), Math.random() * 120 + 30);
|
|
}
|
|
timeoutId = setTimeout(flicker, Math.random() * 6000 + 1000);
|
|
};
|
|
timeoutId = setTimeout(flicker, Math.random() * 3000);
|
|
return () => clearTimeout(timeoutId);
|
|
}, []);
|
|
|
|
return (
|
|
<Link
|
|
href={social.href}
|
|
title={social.name}
|
|
className={cn(
|
|
"p-2 rounded-lg transition-all duration-300 relative",
|
|
"dark:bg-transparent dark:border-none",
|
|
"bg-muted/50 border border-transparent hover:border-border hover:shadow-inner",
|
|
social.color,
|
|
social.glow,
|
|
"hover:!opacity-100 hover:scale-110 active:scale-95",
|
|
)}
|
|
style={{ opacity, transition: "opacity 0.05s ease-in-out" }}
|
|
>
|
|
<div
|
|
className={`absolute inset-0 blur-[6px] opacity-20 hidden dark:block ${social.bgGlow}`}
|
|
/>
|
|
<social.icon />
|
|
</Link>
|
|
);
|
|
};
|
|
|
|
export function Footer({
|
|
dict,
|
|
lang,
|
|
}: {
|
|
dict: Dictionary["footer"];
|
|
lang: string;
|
|
}) {
|
|
const sitemap = [
|
|
{
|
|
title: dict.sections.product,
|
|
links: [
|
|
{ name: dict.links.features, href: `/${lang}#features` },
|
|
{ name: dict.links.pricing, href: `/${lang}#pricing` },
|
|
{ name: dict.links.protocol, href: `/${lang}/docs` },
|
|
{ name: dict.links.profile, href: `/${lang}/auth` },
|
|
],
|
|
},
|
|
{
|
|
title: dict.sections.resources,
|
|
links: [
|
|
{ name: dict.links.faq, href: `/${lang}#faq` },
|
|
{ name: dict.links.comms, href: `/${lang}/blog` },
|
|
],
|
|
},
|
|
{
|
|
title: dict.sections.legal,
|
|
links: [
|
|
{ name: dict.links.privacy, href: `/${lang}/docs` },
|
|
{ name: dict.links.terms, href: `/${lang}/docs` },
|
|
],
|
|
},
|
|
];
|
|
|
|
const socialLinks = [
|
|
{
|
|
name: "Telegram",
|
|
href: "#",
|
|
icon: Icons.Telegram,
|
|
color: "text-[#0088cc]",
|
|
glow: "dark:drop-shadow-[0_0_8px_rgba(0,136,204,0.8)]",
|
|
bgGlow: "bg-[#0088cc]",
|
|
},
|
|
{
|
|
name: "YouTube",
|
|
href: "#",
|
|
icon: Icons.Youtube,
|
|
color: "text-[#ff0000]",
|
|
glow: "dark:drop-shadow-[0_0_8px_rgba(255,0,0,0.8)]",
|
|
bgGlow: "bg-[#ff0000]",
|
|
},
|
|
{
|
|
name: "Discord",
|
|
href: "#",
|
|
icon: Icons.Discord,
|
|
color: "text-[#5865F2]",
|
|
glow: "dark:drop-shadow-[0_0_8px_rgba(88,101,242,0.8)]",
|
|
bgGlow: "bg-[#5865F2]",
|
|
},
|
|
{
|
|
name: "X",
|
|
href: "#",
|
|
icon: Icons.X,
|
|
color: "text-foreground",
|
|
glow: "dark:drop-shadow-[0_0_8px_rgba(255,255,255,0.5)]",
|
|
bgGlow: "bg-white",
|
|
},
|
|
{
|
|
name: "Instagram",
|
|
href: "#",
|
|
icon: Icons.Instagram,
|
|
color: "text-[#E1306C]",
|
|
glow: "dark:drop-shadow-[0_0_8px_rgba(225,48,108,0.8)]",
|
|
bgGlow: "bg-[#E1306C]",
|
|
},
|
|
{
|
|
name: "Habr",
|
|
href: "#",
|
|
icon: Icons.Habr,
|
|
color: "text-[#65A3BE]",
|
|
glow: "dark:drop-shadow-[0_0_8px_rgba(101,163,190,0.8)]",
|
|
bgGlow: "bg-[#65A3BE]",
|
|
},
|
|
];
|
|
|
|
return (
|
|
<footer
|
|
className={`mt-20 border-t border-border/20 bg-background pt-16 pb-12 ${jetbrainsMono.className}`}
|
|
>
|
|
<div className="container mx-auto px-6 max-w-6xl">
|
|
<div className="flex flex-col lg:flex-row justify-between items-start gap-16 lg:gap-8">
|
|
<div className="flex flex-col gap-3 max-w-xs">
|
|
<Link
|
|
href={`/${lang}`}
|
|
className="flex items-center gap-3 group hover:scale-105 transition-transform duration-300 w-fit mt-1"
|
|
>
|
|
<div className="text-2xl sm:text-3xl tracking-widest flex items-center select-none font-bold">
|
|
<span
|
|
className="text-transparent animate-neon-flicker transition-all duration-300"
|
|
style={{
|
|
WebkitTextStroke: "1px #00E5F2",
|
|
filter: "drop-shadow(0 0 5px rgba(0,229,242,0.6))",
|
|
}}
|
|
>
|
|
Net
|
|
</span>
|
|
<span
|
|
className="text-transparent transition-all duration-300"
|
|
style={{
|
|
WebkitTextStroke: "1px #00E5F2",
|
|
filter: "drop-shadow(0 0 5px rgba(0,229,242,0.6))",
|
|
}}
|
|
>
|
|
runner
|
|
</span>
|
|
<span
|
|
className="ml-2 text-transparent opacity-90 group-hover:opacity-100 transition-all duration-300"
|
|
style={{
|
|
WebkitTextStroke: "1px #8B3DFF",
|
|
filter: "drop-shadow(0 0 5px rgba(139,61,255,0.6))",
|
|
}}
|
|
>
|
|
VPN
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
|
|
<div className="text-xs font-bold text-primary/80 tracking-widest uppercase mt-1 drop-shadow-[0_0_5px_rgba(139,61,255,0.5)]">
|
|
{dict.protocolStatus}
|
|
</div>
|
|
|
|
<p className="text-muted-foreground text-sm leading-relaxed mt-2 max-w-50">
|
|
{dict.tagline}
|
|
</p>
|
|
|
|
<div className="flex flex-wrap gap-5 mt-4 items-center">
|
|
{socialLinks.map((social) => (
|
|
<FlickeringSocialIcon key={social.name} social={social} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-wrap md:flex-nowrap gap-12 lg:gap-16">
|
|
{sitemap.map((section, idx) => (
|
|
<div key={idx} className="flex flex-col gap-5">
|
|
<h4 className="text-foreground font-black text-[13px] uppercase tracking-widest">
|
|
{section.title}
|
|
</h4>
|
|
<ul className="flex flex-col gap-3">
|
|
{section.links.map((link, linkIdx) => (
|
|
<li key={linkIdx}>
|
|
<Link
|
|
href={link.href}
|
|
className="text-muted-foreground hover:text-primary text-sm transition-colors duration-200"
|
|
>
|
|
{link.name}
|
|
</Link>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-20 border border-border/30 bg-card/20 rounded-xl p-6 md:px-10 md:py-8 flex flex-col md:flex-row justify-between items-start md:items-center gap-8 shadow-2xl relative overflow-hidden">
|
|
<div className="absolute top-0 left-1/4 w-1/2 h-full bg-primary/10 blur-3xl -z-10 pointer-events-none" />
|
|
|
|
<div className="flex flex-col gap-1">
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-1.5 h-1.5 rounded-full bg-primary shadow-[0_0_8px_rgba(139,61,255,0.8)] animate-pulse" />
|
|
<span className="text-[10px] text-muted-foreground/60 uppercase tracking-widest font-bold">
|
|
{dict.uplinkStatus}
|
|
</span>
|
|
</div>
|
|
<div className="text-2xl font-black text-foreground tracking-tight mt-1">
|
|
464.6 MBPS
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-1">
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-1.5 h-1.5 rounded-full bg-primary shadow-[0_0_8px_rgba(139,61,255,0.8)]" />
|
|
<span className="text-[10px] text-muted-foreground/60 uppercase tracking-widest font-bold">
|
|
{dict.activeNode}
|
|
</span>
|
|
</div>
|
|
<div className="text-2xl font-black text-foreground tracking-tight mt-1">
|
|
TYO-SEC-05
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-1">
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-1.5 h-1.5 rounded-full bg-green-500 shadow-[0_0_8px_rgba(34,197,94,0.8)]" />
|
|
<span className="text-[10px] text-muted-foreground/60 uppercase tracking-widest font-bold">
|
|
{dict.latency}
|
|
</span>
|
|
</div>
|
|
<div className="text-2xl font-black text-foreground tracking-tight mt-1">
|
|
16 MS
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|