Files
ESPDocs/components/Footer.jsx
T
Lucas RayanandClaude Sonnet 5.5 5a9fe676fc
CI / Lint e auditorias (push) Successful in 1m10s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Successful in 2m39s
Release / Plano (reaproveitar a imagem?) (push) Successful in 6s
Release / ci (push) Skipped
Release / Publica a imagem (linux/arm64) (push) Successful in 18s
Release / Cria a release no Gitea (push) Successful in 5s
feat(i18n): Simplified Chinese (zh-CN), search answers per locale, fr/de/es data fixes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 23:28:39 -03:00

435 lines
15 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import Logo from "@/components/Logo";
import GiteaMark from "@/components/GiteaMark";
import { ArrowUpRight } from "lucide-react";
import { SITE } from "@/lib/seo";
import { LOCALES, getLocalizedHref } from "@/i18n/links";
const COLUMNS_PT = [
{
title: "Explorar",
links: [
{ href: "/series", label: "Séries ESP32" },
{ href: "/comparacao", label: "Comparador" },
{ href: "/catalogo", label: "Catálogo de placas" },
{ href: "/livro", label: "O livro" },
],
},
{
title: "Ferramentas",
links: [
{ href: "/seletor", label: "Seletor inteligente" },
{ href: "/diagnostico", label: "Diagnóstico" },
{ href: "/componentes", label: "Component Registry" },
{ href: "/frameworks", label: "Frameworks e SDKs" },
],
},
{
title: "Projeto",
links: [
{ href: "/sobre", label: "Sobre o ESPDocs" },
{ href: "/glossario", label: "Glossário" },
{ href: SITE.repositorio, label: "Repositório", external: true },
{ href: `${SITE.repositorio}/issues`, label: "Reportar um problema", external: true },
],
},
];
const COLUMNS_EN = [
{
title: "Explore",
links: [
{ href: "/series", label: "ESP32 Series" },
{ href: "/comparacao", label: "Comparator" },
{ href: "/catalogo", label: "Board Catalog" },
],
},
{
title: "Tools",
links: [
{ href: "/seletor", label: "Smart Selector" },
{ href: "/diagnostico", label: "Diagnostics" },
{ href: "/componentes", label: "Component Registry" },
{ href: "/frameworks", label: "Frameworks & SDKs" },
],
},
{
title: "Project",
links: [
{ href: "/sobre", label: "About ESPDocs" },
{ href: "/glossario", label: "Glossary" },
{ href: SITE.repositorio, label: "Repository", external: true },
{ href: `${SITE.repositorio}/issues`, label: "Report an issue", external: true },
],
},
];
const COLUMNS_ES = [
{
title: "Explorar",
links: [
{ href: "/series", label: "Series ESP32" },
{ href: "/comparacao", label: "Comparador" },
{ href: "/catalogo", label: "Catálogo de placas" },
],
},
{
title: "Herramientas",
links: [
{ href: "/seletor", label: "Selector inteligente" },
{ href: "/diagnostico", label: "Diagnóstico" },
{ href: "/componentes", label: "Component Registry" },
{ href: "/frameworks", label: "Frameworks y SDKs" },
],
},
{
title: "Proyecto",
links: [
{ href: "/sobre", label: "Acerca de ESPDocs" },
{ href: "/glossario", label: "Glosario" },
{ href: SITE.repositorio, label: "Repositorio", external: true },
{ href: `${SITE.repositorio}/issues`, label: "Reportar un problema", external: true },
],
},
];
const COLUMNS_FR = [
{
title: "Explorer",
links: [
{ href: "/series", label: "Séries ESP32" },
{ href: "/comparacao", label: "Comparateur" },
{ href: "/catalogo", label: "Catalogue de cartes" },
],
},
{
title: "Outils",
links: [
{ href: "/seletor", label: "Sélecteur intelligent" },
{ href: "/diagnostico", label: "Diagnostic" },
{ href: "/componentes", label: "Component Registry" },
{ href: "/frameworks", label: "Frameworks et SDKs" },
],
},
{
title: "Projet",
links: [
{ href: "/sobre", label: "À propos d'ESPDocs" },
{ href: "/glossario", label: "Glossaire" },
{ href: SITE.repositorio, label: "Dépôt", external: true },
{ href: `${SITE.repositorio}/issues`, label: "Signaler un problème", external: true },
],
},
];
const COLUMNS_DE = [
{
title: "Erkunden",
links: [
{ href: "/series", label: "ESP32-Serien" },
{ href: "/comparacao", label: "Vergleich" },
{ href: "/catalogo", label: "Board-Katalog" },
],
},
{
title: "Werkzeuge",
links: [
{ href: "/seletor", label: "Intelligente Auswahl" },
{ href: "/diagnostico", label: "Diagnose" },
{ href: "/componentes", label: "Component Registry" },
{ href: "/frameworks", label: "Frameworks & SDKs" },
],
},
{
title: "Projekt",
links: [
{ href: "/sobre", label: "Über ESPDocs" },
{ href: "/glossario", label: "Glossar" },
{ href: SITE.repositorio, label: "Repository", external: true },
{ href: `${SITE.repositorio}/issues`, label: "Problem melden", external: true },
],
},
];
const COLUMNS_ZH = [
{
title: "探索",
links: [
{ href: "/series", label: "ESP32 系列" },
{ href: "/comparacao", label: "对比工具" },
{ href: "/catalogo", label: "开发板目录" },
],
},
{
title: "工具",
links: [
{ href: "/seletor", label: "智能选型" },
{ href: "/diagnostico", label: "故障诊断" },
{ href: "/componentes", label: "Component Registry" },
{ href: "/frameworks", label: "框架与 SDK" },
],
},
{
title: "项目",
links: [
{ href: "/sobre", label: "关于 ESPDocs" },
{ href: "/glossario", label: "术语表" },
{ href: SITE.repositorio, label: "代码仓库", external: true },
{ href: `${SITE.repositorio}/issues`, label: "反馈问题", external: true },
],
},
];
export default function Footer() {
const pathname = usePathname() || "";
const year = new Date().getFullYear();
const currentLocale =
LOCALES.find((l) => pathname === `/${l.code}` || pathname.startsWith(`/${l.code}/`))?.code || "pt";
const isPt = currentLocale === "pt";
const isEn = currentLocale === "en";
const isEs = currentLocale === "es";
const isFr = currentLocale === "fr";
const isDe = currentLocale === "de";
const isZh = currentLocale === "zh-CN";
const getLinkHref = (href) => getLocalizedHref(`/${currentLocale}${href}`, currentLocale);
const columns = isPt
? COLUMNS_PT.map((column) => ({
...column,
links: column.links.filter((link) => link.href !== "/livro" || isPt),
}))
: isEs
? COLUMNS_ES
: isFr
? COLUMNS_FR
: isZh ? COLUMNS_ZH : isDe
? COLUMNS_DE
: COLUMNS_EN;
return (
<footer
className="mt-20 border-t border-line md:mt-28"
aria-label={
isPt
? "Rodapé do ESPDocs"
: isEs
? "Pie de página de ESPDocs"
: isFr
? "Pied de page d'ESPDocs"
: isZh ? "ESPDocs 页脚" : isDe
? "ESPDocs-Fußzeile"
: "ESPDocs footer"
}
>
<div className="shell py-14 md:py-20">
<div className="grid gap-12 lg:grid-cols-[1.1fr_2fr]">
<div>
<Link
href={getLinkHref("/")}
className="inline-flex min-h-11 items-center gap-2.5"
aria-label={
isPt
? "ESPDocs, página inicial"
: isEs
? "ESPDocs, página de inicio"
: isFr
? "ESPDocs, page d'accueil"
: isZh ? "ESPDocs,首页" : isDe
? "ESPDocs, Startseite"
: "ESPDocs, homepage"
}
>
<Logo className="h-7 w-7" />
<span className="font-display text-2xl font-semibold tracking-[-0.045em] text-ink">ESPDocs</span>
</Link>
<p className="mt-5 max-w-sm text-sm leading-relaxed text-muted">
{isPt ? (
<>
Documentação independente do ecossistema ESP32, escrita em português brasileiro.
Dados públicos, curadoria editorial e links para as fontes oficiais.
</>
) : isEs ? (
<>
Documentación independiente del ecosistema ESP32.
Datos públicos, curaduría editorial y enlaces a las fuentes oficiales.
</>
) : isFr ? (
<>
Documentation indépendante de l&apos;écosystème ESP32.
Données publiques, sélection éditoriale et liens vers les sources officielles.
</>
) : isZh ? ( <>ESP32 生态的独立文档。公开数据、编辑整理,并链接到官方资料来源。</> ) : isDe ? (
<>
Unabhängige Dokumentation des ESP32-Ökosystems.
Öffentliche Daten, redaktionelle Betreuung und Links zu offiziellen Quellen.
</>
) : (
<>
Independent documentation of the ESP32 ecosystem.
Open data, editorial curation, and links to official sources.
</>
)}
</p>
{isPt && (
<>
<Link
href="/pt/livro"
className="group mt-7 grid grid-cols-[3rem_1fr_auto] items-center gap-3.5 rounded-2xl border border-line bg-surface p-3.5 transition-colors duration-300 hover:border-line-strong"
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={SITE.livroCapa}
alt=""
aria-hidden="true"
width={48}
height={72}
className="h-[72px] w-12 rounded-md object-cover shadow-md"
/>
<span className="min-w-0">
<span className="text-xs font-semibold text-accent">Livro novo</span>
<span className="mt-0.5 block font-display text-base font-semibold leading-tight text-ink">Microcontroladores ESP32</span>
<span className="mt-1 block text-xs text-muted">Conectividade, eficiência e desempenho</span>
</span>
<ArrowUpRight className="h-4 w-4 text-faint transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-accent" aria-hidden="true" />
</Link>
<div className="mt-4 flex flex-wrap gap-x-5 gap-y-2 text-sm">
<a href={SITE.livroAmazon} target="_blank" rel="noopener noreferrer" className="inline-flex min-h-11 items-center gap-1 text-muted transition-colors hover:text-accent">
Amazon
<ArrowUpRight className="h-3.5 w-3.5" aria-hidden="true" />
</a>
<a href={SITE.livroUiclap} target="_blank" rel="noopener noreferrer" className="inline-flex min-h-11 items-center gap-1 text-muted transition-colors hover:text-accent">
UICLAP
<ArrowUpRight className="h-3.5 w-3.5" aria-hidden="true" />
</a>
</div>
</>
)}
</div>
<div className="grid grid-cols-2 gap-8 sm:grid-cols-4">
{columns.map((column) => (
<nav key={column.title} aria-label={column.title}>
<h2 className="text-sm font-semibold text-ink">{column.title}</h2>
<ul className="mt-2 space-y-0">
{column.links.map((link) => (
<li key={link.href}>
{link.external ? (
<a
href={link.href}
target="_blank"
rel="noopener noreferrer"
className="inline-flex min-h-11 items-center gap-1 text-sm text-muted transition-colors hover:text-accent"
>
{link.label}
<ArrowUpRight className="h-3 w-3" aria-hidden="true" />
</a>
) : (
<Link href={getLinkHref(link.href)} className="inline-flex min-h-11 min-w-11 items-center text-sm text-muted transition-colors hover:text-accent">
{link.label}
</Link>
)}
</li>
))}
</ul>
</nav>
))}
<div>
<h2 className="text-sm font-semibold text-ink">{isPt ? "Autor" : isEs ? "Autor" : isFr ? "Auteur" : isZh ? "作者" : isDe ? "Autor" : "Author"}</h2>
<p className="mt-4 text-sm leading-relaxed text-muted">
Lucas Rayan Guerra
<br />
<span className="text-xs text-faint">Ciência Embarcada</span>
</p>
<div className="mt-4 flex items-center gap-2">
<a
href={SITE.repositorio}
target="_blank"
rel="noopener noreferrer"
aria-label={
isPt
? "Gitea do projeto (abre em nova aba)"
: isEs
? "Gitea del proyecto (abre en una pestaña nueva)"
: isFr
? "Gitea du projet (ouvre un nouvel onglet)"
: isZh ? "项目 Gitea(在新标签页打开)" : isDe
? "Projekt-Gitea (öffnet in neuem Tab)"
: "Project Gitea (opens in new tab)"
}
className="grid h-11 w-11 place-items-center rounded-full border border-line text-ink transition-colors hover:border-line-strong hover:bg-surface"
>
<GiteaMark className="h-4 w-4" />
</a>
<a
href={SITE.autorLinkedin}
target="_blank"
rel="noopener noreferrer"
aria-label={
isPt
? "LinkedIn do autor (abre em nova aba)"
: isEs
? "LinkedIn del autor (abre en una pestaña nueva)"
: isFr
? "LinkedIn de l'auteur (ouvre un nouvel onglet)"
: isZh ? "作者 LinkedIn(在新标签页打开)" : isDe
? "LinkedIn des Autors (öffnet in neuem Tab)"
: "Author LinkedIn (opens in new tab)"
}
className="grid h-11 w-11 place-items-center rounded-full border border-line text-ink transition-colors hover:border-line-strong hover:bg-surface"
>
<svg className="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M4.98 3.5a2.5 2.5 0 1 1 0 5.001 2.5 2.5 0 0 1 0-5zM3 8.98h4v12H3v-12zm6.5 0h3.8v1.6h.1c.5-.9 1.8-1.9 3.6-1.9 3.8 0 4.5 2.5 4.5 5.8v6.5h-4v-5.8c0-1.4-.1-3.2-2-3.2-2 0-2.3 1.6-2.3 3.1v5.9h-4v-12z" />
</svg>
</a>
</div>
</div>
</div>
</div>
<div className="mt-14 flex flex-col gap-4 border-t border-line pt-6 text-xs leading-relaxed text-faint md:flex-row md:items-center md:justify-between">
<p>
© {year}{" "}
{isPt
? "ESPDocs. Projeto independente, sem afiliação com a Espressif Systems."
: isEs
? "ESPDocs. Proyecto independiente, sin afiliación con Espressif Systems."
: isFr
? "ESPDocs. Projet indépendant, sans affiliation avec Espressif Systems."
: isZh ? "ESPDocs。独立项目,与乐鑫(Espressif Systems)无任何关联。" : isDe
? "ESPDocs. Unabhängiges Projekt, nicht verbunden mit Espressif Systems."
: "ESPDocs. Independent project, not affiliated with Espressif Systems."}
</p>
<p className="flex flex-wrap items-center gap-x-5 gap-y-2">
<a href={SITE.blog} target="_blank" rel="noopener noreferrer" className="inline-flex min-h-11 items-center gap-1 transition-colors hover:text-accent">
Ciência Embarcada
<ArrowUpRight className="h-3 w-3" aria-hidden="true" />
</a>
<a href={SITE.autorUrl} target="_blank" rel="noopener noreferrer" className="inline-flex min-h-11 items-center gap-1 transition-colors hover:text-accent">
lucasrguerra.dev.br
<ArrowUpRight className="h-3 w-3" aria-hidden="true" />
</a>
<span>
{isPt
? "Fontes oficiais: Espressif Systems."
: isEs
? "Fuentes oficiales: Espressif Systems."
: isFr
? "Sources officielles : Espressif Systems."
: isZh ? "官方资料来源:乐鑫(Espressif Systems)。" : isDe
? "Offizielle Quellen: Espressif Systems."
: "Official sources: Espressif Systems."}
</span>
</p>
</div>
</div>
</footer>
);
}