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>
800 lines
35 KiB
React
800 lines
35 KiB
React
"use client";
|
||
|
||
import Header from "@/components/Header";
|
||
import Footer from "@/components/Footer";
|
||
import PageHero from "@/components/PageHero";
|
||
import { useEffect, useState, useMemo, Fragment } from "react";
|
||
import { usePathname } from "next/navigation";
|
||
import Link from "next/link";
|
||
import seriesDataPt from "@/public/series.json";
|
||
import seriesDataEn from "@/data/en/series.json";
|
||
import seriesDataEs from "@/data/es/series.json";
|
||
import seriesDataFr from "@/data/fr/series.json";
|
||
import seriesDataDe from "@/data/de/series.json";
|
||
import seriesDataZh from "@/data/zh-CN/series.json";
|
||
import { getLocalizedHref } from "@/i18n/links";
|
||
import { ArrowRight, ArrowUpRight, Check, ChevronDown, Scale } from "lucide-react";
|
||
|
||
const MIN_SERIES = 2;
|
||
const MAX_SERIES = 4;
|
||
|
||
/* Lê "seguranca.ecc" além de chaves simples. */
|
||
function valorDe(objeto, caminho) {
|
||
return caminho.split(".").reduce((atual, parte) => atual?.[parte], objeto);
|
||
}
|
||
|
||
const COMPARE_FIELDS_PT = [
|
||
{ category: "Geral", fields: [
|
||
{ key: "nome_completo", label: "Nome Completo" },
|
||
{ key: "descricao", label: "Descrição" },
|
||
]},
|
||
{ category: "Disponibilidade e Ferramentas", fields: [
|
||
{ key: "esp_idf_minimo", label: "ESP-IDF mínimo" },
|
||
{ key: "arduino_core", label: "Core Arduino" },
|
||
{ key: "depuracao", label: "Depuração / JTAG" },
|
||
{ key: "encapsulamento", label: "Encapsulamento" },
|
||
{ key: "modulos", label: "Módulos disponíveis" },
|
||
]},
|
||
{ category: "Processador", fields: [
|
||
{ key: "arquitetura", label: "Arquitetura" },
|
||
{ key: "nucleos", label: "Núcleos" },
|
||
{ key: "frequencia", label: "Frequência" },
|
||
{ key: "coprocessador_ulp", label: "Coprocessador ULP" },
|
||
{ key: "aceleradores_ia", label: "Aceleradores de IA" },
|
||
]},
|
||
{ category: "Conectividade", fields: [
|
||
{ key: "wifi", label: "Wi-Fi" },
|
||
{ key: "bluetooth", label: "Bluetooth" },
|
||
{ key: "zigbee_thread", label: "Zigbee/Thread" },
|
||
{ key: "matter", label: "Matter" },
|
||
{ key: "ethernet", label: "Ethernet" },
|
||
]},
|
||
{ category: "Memória", fields: [
|
||
{ key: "memoria_sram", label: "SRAM" },
|
||
{ key: "memoria_sram_rtc", label: "SRAM RTC" },
|
||
{ key: "memoria_rom", label: "ROM" },
|
||
{ key: "flash_externa", label: "Flash Externa" },
|
||
{ key: "psram_externa", label: "PSRAM Externa" },
|
||
]},
|
||
{ category: "Periféricos Digitais", fields: [
|
||
{ key: "gpio", label: "GPIO" },
|
||
{ key: "uart", label: "UART" },
|
||
{ key: "spi", label: "SPI" },
|
||
{ key: "i2c", label: "I²C" },
|
||
{ key: "i2s", label: "I²S" },
|
||
{ key: "pwm", label: "PWM" },
|
||
{ key: "can", label: "CAN" },
|
||
{ key: "usb", label: "USB" },
|
||
{ key: "depuracao", label: "Depuração / JTAG" },
|
||
{ key: "sdio", label: "SDIO" },
|
||
]},
|
||
{ category: "Periféricos Analógicos", fields: [
|
||
{ key: "adc", label: "ADC" },
|
||
{ key: "dac", label: "DAC" },
|
||
{ key: "touch", label: "Touch Capacitivo" },
|
||
{ key: "sensor_hall", label: "Sensor Hall" },
|
||
{ key: "sensor_temperatura", label: "Sensor de Temperatura" },
|
||
]},
|
||
{ category: "Segurança", fields: [
|
||
{ key: "seguranca.aes", label: "AES" },
|
||
{ key: "seguranca.sha", label: "SHA" },
|
||
{ key: "seguranca.rsa", label: "RSA / MPI" },
|
||
{ key: "seguranca.ecc", label: "ECC (curvas elípticas)" },
|
||
{ key: "seguranca.ecdsa", label: "ECDSA em hardware" },
|
||
{ key: "seguranca.hmac", label: "HMAC" },
|
||
{ key: "seguranca.assinatura_digital", label: "Assinatura Digital (DS)" },
|
||
{ key: "seguranca.key_manager", label: "Key Manager" },
|
||
{ key: "seguranca.rng", label: "Gerador aleatório (RNG)" },
|
||
{ key: "seguranca.criptografia_flash", label: "Criptografia de flash" },
|
||
{ key: "seguranca.secure_boot", label: "Secure Boot" },
|
||
{ key: "seguranca.protecao_dpa", label: "Proteção contra DPA" },
|
||
]},
|
||
{ category: "Interfaces Especiais", fields: [
|
||
{ key: "lcd", label: "LCD" },
|
||
{ key: "camera", label: "Câmera" },
|
||
{ key: "mipi_csi", label: "MIPI CSI" },
|
||
{ key: "mipi_dsi", label: "MIPI DSI" },
|
||
{ key: "ethernet_mac", label: "Ethernet MAC" },
|
||
]},
|
||
{ category: "Especificações Ambientais", fields: [
|
||
{ key: "temperatura_operacao", label: "Temp. Operação" },
|
||
{ key: "temperatura_armazenamento", label: "Temp. Armazenamento" },
|
||
]},
|
||
];
|
||
|
||
const COMPARE_FIELDS_EN = [
|
||
{ category: "General", fields: [
|
||
{ key: "nome_completo", label: "Full Name" },
|
||
{ key: "descricao", label: "Description" },
|
||
]},
|
||
{ category: "Availability and Tools", fields: [
|
||
{ key: "esp_idf_minimo", label: "Minimum ESP-IDF" },
|
||
{ key: "arduino_core", label: "Arduino Core" },
|
||
{ key: "depuracao", label: "Debugging / JTAG" },
|
||
{ key: "encapsulamento", label: "Package" },
|
||
{ key: "modulos", label: "Available Modules" },
|
||
]},
|
||
{ category: "Processor", fields: [
|
||
{ key: "arquitetura", label: "Architecture" },
|
||
{ key: "nucleos", label: "Cores" },
|
||
{ key: "frequencia", label: "Frequency" },
|
||
{ key: "coprocessador_ulp", label: "ULP Coprocessor" },
|
||
{ key: "aceleradores_ia", label: "AI Accelerators" },
|
||
]},
|
||
{ category: "Connectivity", fields: [
|
||
{ key: "wifi", label: "Wi-Fi" },
|
||
{ key: "bluetooth", label: "Bluetooth" },
|
||
{ key: "zigbee_thread", label: "Zigbee/Thread" },
|
||
{ key: "matter", label: "Matter" },
|
||
{ key: "ethernet", label: "Ethernet" },
|
||
]},
|
||
{ category: "Memory", fields: [
|
||
{ key: "memoria_sram", label: "SRAM" },
|
||
{ key: "memoria_sram_rtc", label: "RTC SRAM" },
|
||
{ key: "memoria_rom", label: "ROM" },
|
||
{ key: "flash_externa", label: "External Flash" },
|
||
{ key: "psram_externa", label: "External PSRAM" },
|
||
]},
|
||
{ category: "Digital Peripherals", fields: [
|
||
{ key: "gpio", label: "GPIO" },
|
||
{ key: "uart", label: "UART" },
|
||
{ key: "spi", label: "SPI" },
|
||
{ key: "i2c", label: "I²C" },
|
||
{ key: "i2s", label: "I²S" },
|
||
{ key: "pwm", label: "PWM" },
|
||
{ key: "can", label: "CAN" },
|
||
{ key: "usb", label: "USB" },
|
||
{ key: "depuracao", label: "Debugging / JTAG" },
|
||
{ key: "sdio", label: "SDIO" },
|
||
]},
|
||
{ category: "Analog Peripherals", fields: [
|
||
{ key: "adc", label: "ADC" },
|
||
{ key: "dac", label: "DAC" },
|
||
{ key: "touch", label: "Capacitive Touch" },
|
||
{ key: "sensor_hall", label: "Hall Sensor" },
|
||
{ key: "sensor_temperatura", label: "Temperature Sensor" },
|
||
]},
|
||
{ category: "Security", fields: [
|
||
{ key: "seguranca.aes", label: "AES" },
|
||
{ key: "seguranca.sha", label: "SHA" },
|
||
{ key: "seguranca.rsa", label: "RSA / MPI" },
|
||
{ key: "seguranca.ecc", label: "ECC (elliptic curves)" },
|
||
{ key: "seguranca.ecdsa", label: "Hardware ECDSA" },
|
||
{ key: "seguranca.hmac", label: "HMAC" },
|
||
{ key: "seguranca.assinatura_digital", label: "Digital Signature (DS)" },
|
||
{ key: "seguranca.key_manager", label: "Key Manager" },
|
||
{ key: "seguranca.rng", label: "Random Generator (TRNG)" },
|
||
{ key: "seguranca.criptografia_flash", label: "Flash Encryption" },
|
||
{ key: "seguranca.secure_boot", label: "Secure Boot" },
|
||
{ key: "seguranca.protecao_dpa", label: "DPA Protection" },
|
||
]},
|
||
{ category: "Special Interfaces", fields: [
|
||
{ key: "lcd", label: "LCD" },
|
||
{ key: "camera", label: "Camera" },
|
||
{ key: "mipi_csi", label: "MIPI CSI" },
|
||
{ key: "mipi_dsi", label: "MIPI DSI" },
|
||
{ key: "ethernet_mac", label: "Ethernet MAC" },
|
||
]},
|
||
{ category: "Environmental Specifications", fields: [
|
||
{ key: "temperatura_operacao", label: "Operating Temp." },
|
||
{ key: "temperatura_armazenamento", label: "Storage Temp." },
|
||
]},
|
||
];
|
||
|
||
const COMPARE_FIELDS_ES = [
|
||
{ category: "General", fields: [
|
||
{ key: "nome_completo", label: "Nombre completo" },
|
||
{ key: "descricao", label: "Descripción" },
|
||
]},
|
||
{ category: "Disponibilidad y herramientas", fields: [
|
||
{ key: "esp_idf_minimo", label: "ESP-IDF mínimo" },
|
||
{ key: "arduino_core", label: "Core Arduino" },
|
||
{ key: "depuracao", label: "Depuración / JTAG" },
|
||
{ key: "encapsulamento", label: "Encapsulado" },
|
||
{ key: "modulos", label: "Módulos disponibles" },
|
||
]},
|
||
{ category: "Procesador", fields: [
|
||
{ key: "arquitetura", label: "Arquitectura" },
|
||
{ key: "nucleos", label: "Núcleos" },
|
||
{ key: "frequencia", label: "Frecuencia" },
|
||
{ key: "coprocessador_ulp", label: "Coprocesador ULP" },
|
||
{ key: "aceleradores_ia", label: "Aceleradores de IA" },
|
||
]},
|
||
{ category: "Conectividad", fields: [
|
||
{ key: "wifi", label: "Wi-Fi" },
|
||
{ key: "bluetooth", label: "Bluetooth" },
|
||
{ key: "zigbee_thread", label: "Zigbee/Thread" },
|
||
{ key: "matter", label: "Matter" },
|
||
{ key: "ethernet", label: "Ethernet" },
|
||
]},
|
||
{ category: "Memoria", fields: [
|
||
{ key: "memoria_sram", label: "SRAM" },
|
||
{ key: "memoria_sram_rtc", label: "SRAM RTC" },
|
||
{ key: "memoria_rom", label: "ROM" },
|
||
{ key: "flash_externa", label: "Flash externa" },
|
||
{ key: "psram_externa", label: "PSRAM externa" },
|
||
]},
|
||
{ category: "Periféricos digitales", fields: [
|
||
{ key: "gpio", label: "GPIO" },
|
||
{ key: "uart", label: "UART" },
|
||
{ key: "spi", label: "SPI" },
|
||
{ key: "i2c", label: "I²C" },
|
||
{ key: "i2s", label: "I²S" },
|
||
{ key: "pwm", label: "PWM" },
|
||
{ key: "can", label: "CAN" },
|
||
{ key: "usb", label: "USB" },
|
||
{ key: "depuracao", label: "Depuración / JTAG" },
|
||
{ key: "sdio", label: "SDIO" },
|
||
]},
|
||
{ category: "Periféricos analógicos", fields: [
|
||
{ key: "adc", label: "ADC" },
|
||
{ key: "dac", label: "DAC" },
|
||
{ key: "touch", label: "Touch capacitivo" },
|
||
{ key: "sensor_hall", label: "Sensor Hall" },
|
||
{ key: "sensor_temperatura", label: "Sensor de temperatura" },
|
||
]},
|
||
{ category: "Seguridad", fields: [
|
||
{ key: "seguranca.aes", label: "AES" },
|
||
{ key: "seguranca.sha", label: "SHA" },
|
||
{ key: "seguranca.rsa", label: "RSA / MPI" },
|
||
{ key: "seguranca.ecc", label: "ECC (curvas elípticas)" },
|
||
{ key: "seguranca.ecdsa", label: "ECDSA en hardware" },
|
||
{ key: "seguranca.hmac", label: "HMAC" },
|
||
{ key: "seguranca.assinatura_digital", label: "Firma digital (DS)" },
|
||
{ key: "seguranca.key_manager", label: "Key Manager" },
|
||
{ key: "seguranca.rng", label: "Generador aleatorio (TRNG)" },
|
||
{ key: "seguranca.criptografia_flash", label: "Cifrado de flash" },
|
||
{ key: "seguranca.secure_boot", label: "Secure Boot" },
|
||
{ key: "seguranca.protecao_dpa", label: "Protección contra DPA" },
|
||
]},
|
||
{ category: "Interfaces especiales", fields: [
|
||
{ key: "lcd", label: "LCD" },
|
||
{ key: "camera", label: "Cámara" },
|
||
{ key: "mipi_csi", label: "MIPI CSI" },
|
||
{ key: "mipi_dsi", label: "MIPI DSI" },
|
||
{ key: "ethernet_mac", label: "Ethernet MAC" },
|
||
]},
|
||
{ category: "Especificaciones ambientales", fields: [
|
||
{ key: "temperatura_operacao", label: "Temp. operación" },
|
||
{ key: "temperatura_armazenamento", label: "Temp. almacenamiento" },
|
||
]},
|
||
];
|
||
|
||
const COMPARE_FIELDS_FR = [
|
||
{ category: "Général", fields: [
|
||
{ key: "nome_completo", label: "Nom complet" },
|
||
{ key: "descricao", label: "Description" },
|
||
]},
|
||
{ category: "Disponibilité et outils", fields: [
|
||
{ key: "esp_idf_minimo", label: "ESP-IDF minimum" },
|
||
{ key: "arduino_core", label: "Core Arduino" },
|
||
{ key: "depuracao", label: "Débogage / JTAG" },
|
||
{ key: "encapsulamento", label: "Boîtier" },
|
||
{ key: "modulos", label: "Modules disponibles" },
|
||
]},
|
||
{ category: "Processeur", fields: [
|
||
{ key: "arquitetura", label: "Architecture" },
|
||
{ key: "nucleos", label: "Cœurs" },
|
||
{ key: "frequencia", label: "Fréquence" },
|
||
{ key: "coprocessador_ulp", label: "Coprocesseur ULP" },
|
||
{ key: "aceleradores_ia", label: "Accélérateurs IA" },
|
||
]},
|
||
{ category: "Connectivité", fields: [
|
||
{ key: "wifi", label: "Wi-Fi" },
|
||
{ key: "bluetooth", label: "Bluetooth" },
|
||
{ key: "zigbee_thread", label: "Zigbee/Thread" },
|
||
{ key: "matter", label: "Matter" },
|
||
{ key: "ethernet", label: "Ethernet" },
|
||
]},
|
||
{ category: "Mémoire", fields: [
|
||
{ key: "memoria_sram", label: "SRAM" },
|
||
{ key: "memoria_sram_rtc", label: "SRAM RTC" },
|
||
{ key: "memoria_rom", label: "ROM" },
|
||
{ key: "flash_externa", label: "Flash externe" },
|
||
{ key: "psram_externa", label: "PSRAM externe" },
|
||
]},
|
||
{ category: "Périphériques numériques", fields: [
|
||
{ key: "gpio", label: "GPIO" },
|
||
{ key: "uart", label: "UART" },
|
||
{ key: "spi", label: "SPI" },
|
||
{ key: "i2c", label: "I²C" },
|
||
{ key: "i2s", label: "I²S" },
|
||
{ key: "pwm", label: "PWM" },
|
||
{ key: "can", label: "CAN" },
|
||
{ key: "usb", label: "USB" },
|
||
{ key: "depuracao", label: "Débogage / JTAG" },
|
||
{ key: "sdio", label: "SDIO" },
|
||
]},
|
||
{ category: "Périphériques analogiques", fields: [
|
||
{ key: "adc", label: "ADC" },
|
||
{ key: "dac", label: "DAC" },
|
||
{ key: "touch", label: "Touch capacitif" },
|
||
{ key: "sensor_hall", label: "Capteur Hall" },
|
||
{ key: "sensor_temperatura", label: "Capteur de température" },
|
||
]},
|
||
{ category: "Sécurité", fields: [
|
||
{ key: "seguranca.aes", label: "AES" },
|
||
{ key: "seguranca.sha", label: "SHA" },
|
||
{ key: "seguranca.rsa", label: "RSA / MPI" },
|
||
{ key: "seguranca.ecc", label: "ECC (courbes elliptiques)" },
|
||
{ key: "seguranca.ecdsa", label: "ECDSA matériel" },
|
||
{ key: "seguranca.hmac", label: "HMAC" },
|
||
{ key: "seguranca.assinatura_digital", label: "Signature numérique (DS)" },
|
||
{ key: "seguranca.key_manager", label: "Key Manager" },
|
||
{ key: "seguranca.rng", label: "Générateur aléatoire (TRNG)" },
|
||
{ key: "seguranca.criptografia_flash", label: "Chiffrement de flash" },
|
||
{ key: "seguranca.secure_boot", label: "Secure Boot" },
|
||
{ key: "seguranca.protecao_dpa", label: "Protection contre DPA" },
|
||
]},
|
||
{ category: "Interfaces spéciales", fields: [
|
||
{ key: "lcd", label: "LCD" },
|
||
{ key: "camera", label: "Caméra" },
|
||
{ key: "mipi_csi", label: "MIPI CSI" },
|
||
{ key: "mipi_dsi", label: "MIPI DSI" },
|
||
{ key: "ethernet_mac", label: "Ethernet MAC" },
|
||
]},
|
||
{ category: "Spécifications environnementales", fields: [
|
||
{ key: "temperatura_operacao", label: "Temp. de fonctionnement" },
|
||
{ key: "temperatura_armazenamento", label: "Temp. de stockage" },
|
||
]},
|
||
];
|
||
|
||
const COMPARE_FIELDS_DE = [
|
||
{ category: "Allgemein", fields: [
|
||
{ key: "nome_completo", label: "Vollständiger Name" },
|
||
{ key: "descricao", label: "Beschreibung" },
|
||
]},
|
||
{ category: "Verfügbarkeit und Werkzeuge", fields: [
|
||
{ key: "esp_idf_minimo", label: "Mindest-ESP-IDF" },
|
||
{ key: "arduino_core", label: "Arduino-Core" },
|
||
{ key: "depuracao", label: "Debugging / JTAG" },
|
||
{ key: "encapsulamento", label: "Gehäuse" },
|
||
{ key: "modulos", label: "Verfügbare Module" },
|
||
]},
|
||
{ category: "Prozessor", fields: [
|
||
{ key: "arquitetura", label: "Architektur" },
|
||
{ key: "nucleos", label: "Kerne" },
|
||
{ key: "frequencia", label: "Taktfrequenz" },
|
||
{ key: "coprocessador_ulp", label: "ULP-Coprozessor" },
|
||
{ key: "aceleradores_ia", label: "KI-Beschleuniger" },
|
||
]},
|
||
{ category: "Konnektivität", fields: [
|
||
{ key: "wifi", label: "Wi-Fi" },
|
||
{ key: "bluetooth", label: "Bluetooth" },
|
||
{ key: "zigbee_thread", label: "Zigbee/Thread" },
|
||
{ key: "matter", label: "Matter" },
|
||
{ key: "ethernet", label: "Ethernet" },
|
||
]},
|
||
{ category: "Speicher", fields: [
|
||
{ key: "memoria_sram", label: "SRAM" },
|
||
{ key: "memoria_sram_rtc", label: "RTC-SRAM" },
|
||
{ key: "memoria_rom", label: "ROM" },
|
||
{ key: "flash_externa", label: "Externer Flash" },
|
||
{ key: "psram_externa", label: "Externer PSRAM" },
|
||
]},
|
||
{ category: "Digitale Peripherie", fields: [
|
||
{ key: "gpio", label: "GPIO" },
|
||
{ key: "uart", label: "UART" },
|
||
{ key: "spi", label: "SPI" },
|
||
{ key: "i2c", label: "I²C" },
|
||
{ key: "i2s", label: "I²S" },
|
||
{ key: "pwm", label: "PWM" },
|
||
{ key: "can", label: "CAN" },
|
||
{ key: "usb", label: "USB" },
|
||
{ key: "depuracao", label: "Debugging / JTAG" },
|
||
{ key: "sdio", label: "SDIO" },
|
||
]},
|
||
{ category: "Analoge Peripherie", fields: [
|
||
{ key: "adc", label: "ADC" },
|
||
{ key: "dac", label: "DAC" },
|
||
{ key: "touch", label: "Kapazitiver Touch" },
|
||
{ key: "sensor_hall", label: "Hall-Sensor" },
|
||
{ key: "sensor_temperatura", label: "Temperatursensor" },
|
||
]},
|
||
{ category: "Sicherheit", fields: [
|
||
{ key: "seguranca.aes", label: "AES" },
|
||
{ key: "seguranca.sha", label: "SHA" },
|
||
{ key: "seguranca.rsa", label: "RSA / MPI" },
|
||
{ key: "seguranca.ecc", label: "ECC (Elliptische Kurven)" },
|
||
{ key: "seguranca.ecdsa", label: "Hardware-ECDSA" },
|
||
{ key: "seguranca.hmac", label: "HMAC" },
|
||
{ key: "seguranca.assinatura_digital", label: "Digitale Signatur (DS)" },
|
||
{ key: "seguranca.key_manager", label: "Key Manager" },
|
||
{ key: "seguranca.rng", label: "Zufallsgenerator (TRNG)" },
|
||
{ key: "seguranca.criptografia_flash", label: "Flash-Verschlüsselung" },
|
||
{ key: "seguranca.secure_boot", label: "Secure Boot" },
|
||
{ key: "seguranca.protecao_dpa", label: "DPA-Schutz" },
|
||
]},
|
||
{ category: "Spezielle Schnittstellen", fields: [
|
||
{ key: "lcd", label: "LCD" },
|
||
{ key: "camera", label: "Kamera" },
|
||
{ key: "mipi_csi", label: "MIPI CSI" },
|
||
{ key: "mipi_dsi", label: "MIPI DSI" },
|
||
{ key: "ethernet_mac", label: "Ethernet MAC" },
|
||
]},
|
||
{ category: "Umgebungsbedingungen", fields: [
|
||
{ key: "temperatura_operacao", label: "Betriebstemp." },
|
||
{ key: "temperatura_armazenamento", label: "Lagertemp." },
|
||
]},
|
||
];
|
||
const COMPARE_FIELDS_ZH = [
|
||
{ category: "概览", fields: [
|
||
{ key: "nome_completo", label: "完整名称" },
|
||
{ key: "descricao", label: "描述" },
|
||
]},
|
||
{ category: "可用性与工具", fields: [
|
||
{ key: "esp_idf_minimo", label: "最低 ESP-IDF 版本" },
|
||
{ key: "arduino_core", label: "Arduino 核心" },
|
||
{ key: "depuracao", label: "调试 / JTAG" },
|
||
{ key: "encapsulamento", label: "封装" },
|
||
{ key: "modulos", label: "可用模组" },
|
||
]},
|
||
{ category: "处理器", fields: [
|
||
{ key: "arquitetura", label: "架构" },
|
||
{ key: "nucleos", label: "内核" },
|
||
{ key: "frequencia", label: "频率" },
|
||
{ key: "coprocessador_ulp", label: "ULP 协处理器" },
|
||
{ key: "aceleradores_ia", label: "AI 加速器" },
|
||
]},
|
||
{ category: "无线连接", fields: [
|
||
{ key: "wifi", label: "Wi-Fi" },
|
||
{ key: "bluetooth", label: "蓝牙" },
|
||
{ key: "zigbee_thread", label: "Zigbee/Thread" },
|
||
{ key: "matter", label: "Matter" },
|
||
{ key: "ethernet", label: "以太网" },
|
||
]},
|
||
{ category: "内存", fields: [
|
||
{ key: "memoria_sram", label: "SRAM" },
|
||
{ key: "memoria_sram_rtc", label: "RTC SRAM" },
|
||
{ key: "memoria_rom", label: "ROM" },
|
||
{ key: "flash_externa", label: "外部闪存" },
|
||
{ key: "psram_externa", label: "外部 PSRAM" },
|
||
]},
|
||
{ category: "数字外设", fields: [
|
||
{ key: "gpio", label: "GPIO" },
|
||
{ key: "uart", label: "UART" },
|
||
{ key: "spi", label: "SPI" },
|
||
{ key: "i2c", label: "I²C" },
|
||
{ key: "i2s", label: "I²S" },
|
||
{ key: "pwm", label: "PWM" },
|
||
{ key: "can", label: "CAN" },
|
||
{ key: "usb", label: "USB" },
|
||
{ key: "depuracao", label: "调试 / JTAG" },
|
||
{ key: "sdio", label: "SDIO" },
|
||
]},
|
||
{ category: "模拟外设", fields: [
|
||
{ key: "adc", label: "ADC" },
|
||
{ key: "dac", label: "DAC" },
|
||
{ key: "touch", label: "电容触摸" },
|
||
{ key: "sensor_hall", label: "霍尔传感器" },
|
||
{ key: "sensor_temperatura", label: "温度传感器" },
|
||
]},
|
||
{ category: "安全", fields: [
|
||
{ key: "seguranca.aes", label: "AES" },
|
||
{ key: "seguranca.sha", label: "SHA" },
|
||
{ key: "seguranca.rsa", label: "RSA / MPI" },
|
||
{ key: "seguranca.ecc", label: "ECC(椭圆曲线)" },
|
||
{ key: "seguranca.ecdsa", label: "硬件 ECDSA" },
|
||
{ key: "seguranca.hmac", label: "HMAC" },
|
||
{ key: "seguranca.assinatura_digital", label: "数字签名(DS)" },
|
||
{ key: "seguranca.key_manager", label: "密钥管理器" },
|
||
{ key: "seguranca.rng", label: "随机数发生器(TRNG)" },
|
||
{ key: "seguranca.criptografia_flash", label: "闪存加密" },
|
||
{ key: "seguranca.secure_boot", label: "安全启动" },
|
||
{ key: "seguranca.protecao_dpa", label: "DPA 防护" },
|
||
]},
|
||
{ category: "特殊接口", fields: [
|
||
{ key: "lcd", label: "LCD" },
|
||
{ key: "camera", label: "摄像头" },
|
||
{ key: "mipi_csi", label: "MIPI CSI" },
|
||
{ key: "mipi_dsi", label: "MIPI DSI" },
|
||
{ key: "ethernet_mac", label: "以太网 MAC" },
|
||
]},
|
||
{ category: "环境规格", fields: [
|
||
{ key: "temperatura_operacao", label: "工作温度" },
|
||
{ key: "temperatura_armazenamento", label: "存储温度" },
|
||
]},
|
||
];
|
||
|
||
export default function Comparacao() {
|
||
const pathname = usePathname();
|
||
const isEn = pathname?.startsWith("/en");
|
||
const isEs = pathname?.startsWith("/es");
|
||
const isFr = pathname?.startsWith("/fr");
|
||
const isDe = pathname?.startsWith("/de");
|
||
const isZh = pathname?.startsWith("/zh-CN");
|
||
const currentLocale = isEs ? "es" : isEn ? "en" : isFr ? "fr" : isZh ? "zh-CN" : isDe ? "de" : "pt";
|
||
const seriesData = isEs ? seriesDataEs : isEn ? seriesDataEn : isFr ? seriesDataFr : isZh ? seriesDataZh : isDe ? seriesDataDe : seriesDataPt;
|
||
const compareFields = isEs ? COMPARE_FIELDS_ES : isEn ? COMPARE_FIELDS_EN : isFr ? COMPARE_FIELDS_FR : isZh ? COMPARE_FIELDS_ZH : isDe ? COMPARE_FIELDS_DE : COMPARE_FIELDS_PT;
|
||
|
||
const [selectedSeries, setSelectedSeries] = useState(["ESP32", "ESP32-S3"]);
|
||
const [soDiferencas, setSoDiferencas] = useState(false);
|
||
const [collapsedCategories, setCollapsedCategories] = useState(() => ({
|
||
[isEs ? "Interfaces especiales" : isEn ? "Special Interfaces" : isFr ? "Interfaces spéciales" : isZh ? "特殊接口" : isDe ? "Spezielle Schnittstellen" : "Interfaces Especiais"]: true,
|
||
[isEs ? "Especificaciones ambientales" : isEn ? "Environmental Specifications" : isFr ? "Spécifications environnementales" : isZh ? "环境规格" : isDe ? "Umgebungsbedingungen" : "Especificações Ambientais"]: true,
|
||
}));
|
||
|
||
const series = Object.entries(seriesData);
|
||
|
||
// O seletor envia as séries finalistas em ?chips=ESP32-S3,ESP32-C6.
|
||
useEffect(() => {
|
||
const chips = new URLSearchParams(window.location.search).get("chips");
|
||
if (!chips) return;
|
||
const validas = [...new Set(chips.split(","))].filter((k) => seriesData[k]).slice(0, MAX_SERIES);
|
||
if (validas.length >= MIN_SERIES) setSelectedSeries(validas);
|
||
}, [seriesData]);
|
||
|
||
const toggleSeries = (seriesKey) => {
|
||
if (selectedSeries.includes(seriesKey)) {
|
||
if (selectedSeries.length > MIN_SERIES) setSelectedSeries(selectedSeries.filter((s) => s !== seriesKey));
|
||
} else if (selectedSeries.length < MAX_SERIES) {
|
||
setSelectedSeries([...selectedSeries, seriesKey]);
|
||
}
|
||
};
|
||
|
||
const toggleCategory = (category) => {
|
||
setCollapsedCategories({ ...collapsedCategories, [category]: !collapsedCategories[category] });
|
||
};
|
||
|
||
const renderValue = (value) => {
|
||
if (!value || value === "Não" || value === "No" || value === "Non" || (value === "Nein" || value === "否")) return <span className="text-muted">{isEs || isEn ? "No" : isFr ? "Non" : isZh ? "否" : isDe ? "Nein" : "Não"}</span>;
|
||
if (value === "Sim" || value === "Yes" || value === "Sí" || value === "Oui" || (value === "Ja" || value === "是")) {
|
||
return (
|
||
<span className="inline-flex items-center gap-1.5 font-medium text-ok">
|
||
<Check className="h-4 w-4" aria-hidden="true" />
|
||
{isEs ? "Sí" : isEn ? "Yes" : isFr ? "Oui" : isZh ? "是" : isDe ? "Ja" : "Sim"}
|
||
</span>
|
||
);
|
||
}
|
||
return <span className="font-medium text-ink">{value}</span>;
|
||
};
|
||
|
||
const valores = (key) => selectedSeries.map((k) => String(valorDe(seriesData[k], key) ?? (isEs || isEn ? "No" : isFr ? "Non" : isZh ? "否" : isDe ? "Nein" : "Não")));
|
||
const diferem = (key) => new Set(valores(key)).size > 1;
|
||
|
||
return (
|
||
<div className="site-canvas min-h-screen">
|
||
<Header />
|
||
|
||
<main id="conteudo">
|
||
<PageHero
|
||
isEn={isEn}
|
||
isEs={isEs}
|
||
isFr={isFr}
|
||
isDe={isDe} isZh={isZh}
|
||
trail={[{ label: isEs ? "Comparador" : isEn ? "Comparator" : isFr ? "Comparateur" : isZh ? "对比工具" : isDe ? "Vergleich" : "Comparador" }]}
|
||
icon={Scale}
|
||
label={isEs ? "Hasta cuatro series lado a lado" : isEn ? "Up to four series side by side" : isFr ? "Jusqu'à quatre séries côte à côte" : isZh ? "最多四个系列并排对比" : isDe ? "Bis zu vier Serien im Vergleich" : "Até quatro séries lado a lado"}
|
||
title={isEs ? "Comparador de series ESP32" : isEn ? "ESP32 Series Comparator" : isFr ? "Comparateur de séries ESP32" : isZh ? "系列对比工具" : isDe ? "ESP32-Serien-Vergleich" : "Comparador de séries"}
|
||
lede={
|
||
isEs
|
||
? "Ponga núcleos, radio, memoria, periféricos y seguridad en la misma tabla y vea lo que realmente cambia de un chip a otro."
|
||
: isEn
|
||
? "Put cores, radio, memory, peripherals, and security in the same table and see what really changes from chip to chip."
|
||
: isFr
|
||
? "Placez les cœurs, la radio, la mémoire, les périphériques et la sécurité dans le même tableau et voyez ce qui change réellement d'une puce à l'autre."
|
||
: isZh ? "把内核、无线、内存、外设和安全放进同一张表,看看芯片之间到底有什么不同。" : isDe
|
||
? "Stellen Sie Kerne, Funk, Speicher, Peripherie und Sicherheit in derselben Tabelle gegenüber und sehen Sie, was sich wirklich von Chip zu Chip ändert."
|
||
: "Coloque núcleos, rádio, memória, periféricos e segurança na mesma tabela e veja o que realmente muda de um chip para outro."
|
||
}
|
||
/>
|
||
|
||
<section className="shell pt-10 sm:pt-12" aria-labelledby="escolha-titulo">
|
||
<div className="panel p-5 sm:p-7">
|
||
<div className="flex flex-wrap items-end justify-between gap-3">
|
||
<div>
|
||
<h2 id="escolha-titulo" className="text-base font-semibold text-ink">
|
||
{isEs ? (
|
||
<>Elija de {MIN_SERIES} a {MAX_SERIES} series</>
|
||
) : isEn ? (
|
||
<>Choose {MIN_SERIES} to {MAX_SERIES} series</>
|
||
) : isFr ? (
|
||
<>Choisissez de {MIN_SERIES} à {MAX_SERIES} séries</>
|
||
) : isZh ? ( <>请选择 {MIN_SERIES} 到 {MAX_SERIES} 个系列</> ) : isDe ? (
|
||
<>Wählen Sie {MIN_SERIES} bis {MAX_SERIES} Serien</>
|
||
) : (
|
||
<>Escolha de {MIN_SERIES} a {MAX_SERIES} séries</>
|
||
)}
|
||
</h2>
|
||
<p role="status" aria-live="polite" className="mt-1 text-sm text-muted">
|
||
{isEs ? (
|
||
<>
|
||
{selectedSeries.length} de {MAX_SERIES} seleccionadas
|
||
{selectedSeries.length === MAX_SERIES && ". Elimine una para cambiar."}
|
||
</>
|
||
) : isEn ? (
|
||
<>
|
||
{selectedSeries.length} of {MAX_SERIES} selected
|
||
{selectedSeries.length === MAX_SERIES && ". Remove one to switch."}
|
||
</>
|
||
) : isFr ? (
|
||
<>
|
||
{selectedSeries.length} sur {MAX_SERIES} sélectionnées
|
||
{selectedSeries.length === MAX_SERIES && ". Supprimez-en une pour en changer."}
|
||
</>
|
||
) : isZh ? ( <>
|
||
已选 {selectedSeries.length} / {MAX_SERIES} 个{selectedSeries.length === MAX_SERIES && "。请先移除一个再更换。"}
|
||
</> ) : isDe ? (
|
||
<>
|
||
{selectedSeries.length} von {MAX_SERIES} ausgewählt
|
||
{selectedSeries.length === MAX_SERIES && ". Entfernen Sie eine zum Wechseln."}
|
||
</>
|
||
) : (
|
||
<>
|
||
{selectedSeries.length} de {MAX_SERIES} selecionadas
|
||
{selectedSeries.length === MAX_SERIES && ". Remova uma para trocar."}
|
||
</>
|
||
)}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div className="mt-4 flex flex-wrap gap-2">
|
||
{series.map(([key]) => {
|
||
const marcada = selectedSeries.includes(key);
|
||
const bloqueada = !marcada && selectedSeries.length >= MAX_SERIES;
|
||
return (
|
||
<button
|
||
key={key}
|
||
type="button"
|
||
onClick={() => toggleSeries(key)}
|
||
aria-pressed={marcada}
|
||
aria-disabled={bloqueada}
|
||
className={`chip-btn ${bloqueada ? "opacity-50" : ""}`}
|
||
>
|
||
{marcada && <Check className="h-4 w-4" aria-hidden="true" />}
|
||
{key}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="shell mt-8" aria-labelledby="tabela-titulo">
|
||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||
<h2 id="tabela-titulo" className="text-base font-semibold text-ink">
|
||
{isEs ? "Especificaciones" : isEn ? "Specifications" : isFr ? "Spécifications" : isZh ? "规格" : isDe ? "Spezifikationen" : "Especificações"}
|
||
</h2>
|
||
<label className="flex min-h-11 cursor-pointer items-center gap-2.5 text-sm font-medium text-ink-soft">
|
||
<input
|
||
type="checkbox"
|
||
checked={soDiferencas}
|
||
onChange={(e) => setSoDiferencas(e.target.checked)}
|
||
className="h-5 w-5 cursor-pointer accent-[var(--accent)]"
|
||
/>
|
||
{isEs ? "Mostrar solo diferencias" : isEn ? "Show differences only" : isFr ? "Afficher uniquement les différences" : isZh ? "仅显示差异" : isDe ? "Nur Unterschiede anzeigen" : "Mostrar só as diferenças"}
|
||
</label>
|
||
</div>
|
||
|
||
<div className="panel mt-3 overflow-hidden">
|
||
<div className="overflow-x-auto">
|
||
<table className="w-full min-w-[30rem] border-collapse text-sm">
|
||
<caption className="sr-only">
|
||
{isEs ? (
|
||
<>Comparación de las series {selectedSeries.join(", ")}</>
|
||
) : isEn ? (
|
||
<>Comparison of series {selectedSeries.join(", ")}</>
|
||
) : isFr ? (
|
||
<>Comparaison des séries {selectedSeries.join(", ")}</>
|
||
) : isZh ? ( <>系列对比:{selectedSeries.join(", ")}</> ) : isDe ? (
|
||
<>Vergleich der Serien {selectedSeries.join(", ")}</>
|
||
) : (
|
||
<>Comparação das séries {selectedSeries.join(", ")}</>
|
||
)}
|
||
</caption>
|
||
<thead>
|
||
<tr className="border-b border-line bg-surface-2">
|
||
<th scope="col" className="sticky left-0 z-20 w-28 bg-surface-2 px-4 py-4 text-left font-semibold text-muted sm:w-52 sm:px-6">
|
||
{isEs ? "Especificación" : isEn ? "Specification" : isFr ? "Spécification" : isZh ? "规格项" : isDe ? "Spezifikation" : "Especificação"}
|
||
</th>
|
||
{selectedSeries.map((seriesKey) => (
|
||
<th key={seriesKey} scope="col" className="min-w-40 px-4 py-4 text-left sm:px-6">
|
||
<Link href={getLocalizedHref(`/series/${seriesKey}`, currentLocale)} className="inline-flex min-h-11 items-center gap-1 font-display text-lg font-semibold tracking-[-0.03em] text-ink hover:text-accent">
|
||
{seriesKey}
|
||
<ArrowUpRight className="h-4 w-4 text-muted" aria-hidden="true" />
|
||
</Link>
|
||
</th>
|
||
))}
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{compareFields.map(({ category, fields }) => {
|
||
const visiveis = soDiferencas ? fields.filter(({ key }) => diferem(key)) : fields;
|
||
if (soDiferencas && visiveis.length === 0) return null;
|
||
const isCollapsed = collapsedCategories[category] && !soDiferencas;
|
||
return (
|
||
<Fragment key={category}>
|
||
<tr className="border-y border-line bg-surface-2/60">
|
||
<th scope="rowgroup" colSpan={selectedSeries.length + 1} className="p-0 text-left">
|
||
<button
|
||
type="button"
|
||
onClick={() => toggleCategory(category)}
|
||
aria-expanded={!isCollapsed}
|
||
className="flex min-h-12 w-full cursor-pointer items-center justify-between gap-3 px-4 py-3 text-left font-semibold text-ink sm:px-6"
|
||
>
|
||
<span className="sticky left-4 sm:left-6">{category}</span>
|
||
<ChevronDown className={`h-4 w-4 shrink-0 text-muted transition-transform ${isCollapsed ? "" : "rotate-180"}`} aria-hidden="true" />
|
||
</button>
|
||
</th>
|
||
</tr>
|
||
|
||
{!isCollapsed &&
|
||
visiveis.map(({ key, label }) => (
|
||
<tr key={key} className="border-b border-line last:border-b-0 hover:bg-surface-2/50">
|
||
<th scope="row" className="sticky left-0 z-10 bg-surface px-4 py-3.5 text-left align-top font-medium text-muted sm:px-6">
|
||
{label}
|
||
</th>
|
||
{selectedSeries.map((seriesKey) => (
|
||
<td key={seriesKey} className="px-4 py-3.5 align-top sm:px-6">
|
||
{renderValue(valorDe(seriesData[seriesKey], key))}
|
||
</td>
|
||
))}
|
||
</tr>
|
||
))}
|
||
</Fragment>
|
||
);
|
||
})}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="shell section" aria-labelledby="docs-titulo">
|
||
<h2 id="docs-titulo" className="section-title">
|
||
{isEs ? "Documentación oficial" : isEn ? "Official documentation" : isFr ? "Documentation officielle" : isZh ? "官方文档" : isDe ? "Offizielle Dokumentation" : "Documentação oficial"}
|
||
</h2>
|
||
<div className="mt-6 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||
{selectedSeries.map((seriesKey) => {
|
||
const seriesItem = seriesData[seriesKey];
|
||
return (
|
||
<div key={seriesKey} className="card flex flex-col justify-between gap-5 p-5">
|
||
<Link href={getLocalizedHref(`/series/${seriesKey}`, currentLocale)} className="inline-flex min-h-11 items-center font-display text-lg font-semibold tracking-[-0.03em] text-ink hover:text-accent">
|
||
{seriesKey}
|
||
</Link>
|
||
{seriesItem.datasheet ? (
|
||
<a href={seriesItem.datasheet} target="_blank" rel="noopener noreferrer" className="btn btn-ghost btn-sm">
|
||
{isEs ? "Datasheet oficial" : isEn ? "Official datasheet" : isFr ? "Fiche technique officielle" : isZh ? "官方数据手册" : isDe ? "Offizielles Datenblatt" : "Datasheet oficial"}
|
||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||
<span className="sr-only"> {isEs ? "(abre en una nueva pestaña)" : isEn ? "(opens in a new tab)" : isFr ? "(ouvre un nouvel onglet)" : isZh ? "(在新标签页打开)" : isDe ? "(öffnet in neuem Tab)" : "(abre em nova aba)"}</span>
|
||
</a>
|
||
) : (
|
||
<span className="text-sm text-muted">
|
||
{isEs ? "Datasheet aún no publicado" : isEn ? "Datasheet not yet published" : isFr ? "Fiche technique pas encore publiée" : isZh ? "数据手册尚未发布" : isDe ? "Datenblatt noch nicht veröffentlicht" : "Datasheet ainda não publicado"}
|
||
</span>
|
||
)}
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
<div className="panel mt-10 flex flex-col items-start justify-between gap-6 p-7 sm:p-10 md:flex-row md:items-center">
|
||
<div className="max-w-2xl">
|
||
<h2 className="section-title">
|
||
{isEs ? "¿Desea probar en banco?" : isEn ? "Want to test on the bench?" : isFr ? "Envie de tester sur l'établi ?" : isZh ? "想在工作台上试试?" : isDe ? "Möchten Sie es auf dem Prüfplatz testen ?" : "Quer testar na bancada?"}
|
||
</h2>
|
||
<p className="mt-3 text-base text-muted">
|
||
{isEs
|
||
? "Vea las placas de desarrollo con patillaje, periféricos y enlace a la tienda oficial."
|
||
: isEn
|
||
? "Explore development boards with pinouts, peripherals, and official store links."
|
||
: isFr
|
||
? "Découvrez les cartes de développement avec brochage, périphériques et lien vers la boutique officielle."
|
||
: isZh ? "查看带引脚、外设和商店链接的开发板。" : isDe
|
||
? "Entdecken Sie die Entwicklungsboards mit Pinbelegung, Peripherie und Link zum offiziellen Store."
|
||
: "Veja as placas de desenvolvimento com pinagem, periféricos e link para a loja."}
|
||
</p>
|
||
</div>
|
||
<Link href={getLocalizedHref("/catalogo", currentLocale)} className="btn btn-primary shrink-0">
|
||
{isEs ? "Ver catálogo de placas" : isEn ? "View boards catalog" : isFr ? "Voir le catalogue de cartes" : isZh ? "查看开发板目录" : isDe ? "Board-Katalog ansehen" : "Ver catálogo de placas"}
|
||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||
</Link>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|