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
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
183 lines
6.1 KiB
React
183 lines
6.1 KiB
React
"use client";
|
|
|
|
import { ArrowUpRight, Award, Check, CircleHelp } from "lucide-react";
|
|
import { usePathname } from "next/navigation";
|
|
|
|
const HEADER_MAP_EN = {
|
|
"Nome": "Name",
|
|
"Descrição": "Description",
|
|
"Série": "Series",
|
|
"Loja Oficial": "Official Store",
|
|
"Fabricante": "Manufacturer",
|
|
"Processador": "Processor",
|
|
"Memória Flash": "Flash Memory",
|
|
"PSRAM": "PSRAM",
|
|
"Conector USB": "USB Connector",
|
|
"Interface USB": "USB Interface",
|
|
"Antena": "Antenna",
|
|
"Bateria": "Battery",
|
|
"Display": "Display",
|
|
"Sensores": "Sensors",
|
|
"Botões": "Buttons",
|
|
"LEDs": "LEDs",
|
|
};
|
|
|
|
const HEADER_MAP_ES = {
|
|
"Nome": "Nombre",
|
|
"Descrição": "Descripción",
|
|
"Série": "Serie",
|
|
"Loja Oficial": "Tienda oficial",
|
|
"Fabricante": "Fabricante",
|
|
"Processador": "Procesador",
|
|
"Memória Flash": "Memoria flash",
|
|
"PSRAM": "PSRAM",
|
|
"Conector USB": "Conector USB",
|
|
"Interface USB": "Interfaz USB",
|
|
"Antena": "Antena",
|
|
"Bateria": "Batería",
|
|
"Display": "Pantalla",
|
|
"Sensores": "Sensores",
|
|
"Botões": "Botones",
|
|
"LEDs": "LEDs",
|
|
};
|
|
|
|
const HEADER_MAP_FR = {
|
|
"Nome": "Nom",
|
|
"Descrição": "Description",
|
|
"Série": "Série",
|
|
"Loja Oficial": "Boutique officielle",
|
|
"Fabricante": "Fabricant",
|
|
"Processador": "Processeur",
|
|
"Memória Flash": "Mémoire flash",
|
|
"PSRAM": "PSRAM",
|
|
"Conector USB": "Connecteur USB",
|
|
"Interface USB": "Interface USB",
|
|
"Antena": "Antenne",
|
|
"Bateria": "Batterie",
|
|
"Display": "Écran",
|
|
"Sensores": "Capteurs",
|
|
"Botões": "Boutons",
|
|
"LEDs": "LEDs",
|
|
};
|
|
|
|
const HEADER_MAP_DE = {
|
|
"Nome": "Name",
|
|
"Descrição": "Beschreibung",
|
|
"Série": "Serie",
|
|
"Loja Oficial": "Offizieller Shop",
|
|
"Fabricante": "Hersteller",
|
|
"Processador": "Prozessor",
|
|
"Memória Flash": "Flash-Speicher",
|
|
"PSRAM": "PSRAM",
|
|
"Conector USB": "USB-Anschluss",
|
|
"Interface USB": "USB-Schnittstelle",
|
|
"Antena": "Antenne",
|
|
"Bateria": "Batterie",
|
|
"Display": "Display",
|
|
"Sensores": "Sensoren",
|
|
"Botões": "Taster",
|
|
"LEDs": "LEDs",
|
|
};
|
|
const HEADER_MAP_ZH = {
|
|
"Nome": "名称",
|
|
"Descrição": "描述",
|
|
"Série": "系列",
|
|
"Loja Oficial": "官方商店",
|
|
"Fabricante": "制造商",
|
|
"Processador": "处理器",
|
|
"Memória Flash": "闪存",
|
|
"PSRAM": "PSRAM",
|
|
"Conector USB": "USB 接口",
|
|
"Interface USB": "USB 接口类型",
|
|
"Antena": "天线",
|
|
"Bateria": "电池",
|
|
"Display": "显示屏",
|
|
"Sensores": "传感器",
|
|
"Botões": "按键",
|
|
"LEDs": "LED",
|
|
};
|
|
|
|
export default function BoardCard({ board }) {
|
|
const pathname = usePathname() || "";
|
|
const isEn = pathname === "/en" || pathname.startsWith("/en/");
|
|
const isEs = pathname === "/es" || pathname.startsWith("/es/");
|
|
const isFr = pathname === "/fr" || pathname.startsWith("/fr/");
|
|
const isDe = pathname === "/de" || pathname.startsWith("/de/");
|
|
const isZh = pathname === "/zh-CN" || pathname.startsWith("/zh-CN/");
|
|
|
|
const mainFields = ["Nome", "Link", "Imagem", "Loja Oficial"];
|
|
|
|
const technicalFields = Object.keys(board).filter((key) => !mainFields.includes(key) && board[key]);
|
|
|
|
const valor = (campo) => board[campo]?.toString().toLowerCase().trim();
|
|
const recursos = technicalFields.filter((campo) => ["sim", "opcional"].includes(valor(campo)));
|
|
const lojaOficial = valor("Loja Oficial") === "sim";
|
|
|
|
return (
|
|
<article className="card card-interactive flex h-full flex-col overflow-hidden">
|
|
{board.Imagem && (
|
|
<div
|
|
className="flex shrink-0 justify-center border-b border-line bg-surface-2 p-4 [&_img]:h-44 [&_img]:w-auto [&_img]:max-w-full [&_img]:object-contain"
|
|
dangerouslySetInnerHTML={{ __html: board.Imagem }}
|
|
/>
|
|
)}
|
|
|
|
<div className="flex grow flex-col p-5">
|
|
{lojaOficial && (
|
|
<span className="chip chip-accent mb-3 w-fit">
|
|
<Award className="h-3.5 w-3.5" aria-hidden="true" />
|
|
{isEn ? "Official store" : isEs ? "Tienda oficial" : isFr ? "Boutique officielle" : isZh ? "官方商店" : isDe ? "Offizieller Shop" : "Loja oficial"}
|
|
</span>
|
|
)}
|
|
|
|
<h3 className="line-clamp-2 font-display text-lg font-semibold leading-snug tracking-[-0.02em] text-ink">
|
|
{board.Nome || (isEn ? "Generic board" : isEs ? "Placa genérica" : isFr ? "Carte générique" : isZh ? "通用开发板" : isDe ? "Generisches Board" : "Placa genérica")}
|
|
</h3>
|
|
|
|
{recursos.length > 0 && (
|
|
<div className="mt-4">
|
|
<p className="text-xs font-medium text-muted">
|
|
{isEn ? "On-board features" : isEs ? "Recursos integrados" : isFr ? "Fonctionnalités intégrées" : isZh ? "板载资源" : isDe ? "Integrierte Funktionen" : "Recursos embarcados"}
|
|
</p>
|
|
<ul className="mt-2 flex flex-wrap gap-1.5">
|
|
{recursos.map((campo) => {
|
|
const opcional = valor(campo) === "opcional";
|
|
const label = isEn
|
|
? (HEADER_MAP_EN[campo] || campo)
|
|
: isEs
|
|
? (HEADER_MAP_ES[campo] || campo)
|
|
: isFr
|
|
? (HEADER_MAP_FR[campo] || campo)
|
|
: isZh ? (HEADER_MAP_ZH[campo] || campo) : isDe
|
|
? (HEADER_MAP_DE[campo] || campo)
|
|
: campo;
|
|
return (
|
|
<li key={campo} className={`chip ${opcional ? "text-gold" : "text-ink-soft"}`}>
|
|
{opcional ? (
|
|
<CircleHelp className="h-3 w-3 text-gold" aria-hidden="true" />
|
|
) : (
|
|
<Check className="h-3 w-3 text-ok" aria-hidden="true" />
|
|
)}
|
|
{label}
|
|
{opcional && <span className="sr-only">{isEn ? " (optional)" : isEs ? " (opcional)" : isFr ? " (optionnel)" : isZh ? "(可选)" : isDe ? " (optional)" : " (opcional)"}</span>}
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
|
|
{board.Link && (
|
|
<a href={board.Link} target="_blank" rel="noopener noreferrer" className="btn btn-primary mt-6 w-full">
|
|
{isEn ? "View on AliExpress" : isEs ? "Ver en AliExpress" : isFr ? "Voir sur AliExpress" : isZh ? "在 AliExpress 查看" : isDe ? "Auf AliExpress ansehen" : "Ver no AliExpress"}
|
|
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
|
<span className="sr-only">
|
|
{isEn ? " (opens in new tab)" : isEs ? " (abre en una pestaña nueva)" : isFr ? " (ouvre un nouvel onglet)" : isZh ? "(在新标签页打开)" : isDe ? " (öffnet in neuem Tab)" : " (abre em nova aba)"}
|
|
</span>
|
|
</a>
|
|
)}
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|