"use client"; import { useState, useEffect } from "react"; import { usePathname } from "next/navigation"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import PageHero from "@/components/PageHero"; import BoardCard from "@/components/BoardCard"; import { AlertTriangle, RefreshCw, Search, ShoppingCart, SlidersHorizontal } from "lucide-react"; 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 VALUE_MAP_EN = { "Sim": "Yes", "Não": "No", "Opcional": "Optional", }; 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 VALUE_MAP_ES = { "Sim": "Sí", "Não": "No", "Opcional": "Opcional", }; 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 VALUE_MAP_FR = { "Sim": "Oui", "Não": "Non", "Opcional": "Optionnel", }; const HEADER_MAP_DE = { "Nome": "Name", "Descrição": "Beschreibung", "Série": "Serie", "Loja Oficial": "Offizieller Store", "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": "Tasten", "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": "LEDs", }; const VALUE_MAP_DE = { "Sim": "Ja", "Não": "Nein", "Opcional": "Optional", }; const VALUE_MAP_ZH = { "Sim": "是", "Não": "否", "Opcional": "可选", }; export default function PlacasPage() { 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 [boards, setBoards] = useState([]); const [filteredBoards, setFilteredBoards] = useState([]); const [headers, setHeaders] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(""); const [activeFilters, setActiveFilters] = useState({}); const [filterOptions, setFilterOptions] = useState({}); const [filtrosAbertos, setFiltrosAbertos] = useState(false); const excludedColumns = ["Nome", "Descrição", "Link", "Imagem", "Loja Oficial"]; useEffect(() => { fetchBoards(); setFiltrosAbertos(window.matchMedia("(min-width: 1024px)").matches); }, []); useEffect(() => { applyFilters(); }, [boards, searchTerm, activeFilters]); const fetchBoards = async () => { try { setLoading(true); const response = await fetch("/api/placas"); if (!response.ok) { throw new Error(isEn ? "Failed to load board data" : isEs ? "Error al cargar los datos de las placas" : isFr ? "Erreur lors du chargement des données des cartes" : isZh ? "加载开发板数据出错" : isDe ? "Fehler beim Laden der Board-Daten" : "Erro ao carregar dados das placas"); } const result = await response.json(); setBoards(result.data); setHeaders(result.headers); setFilteredBoards(result.data); generateFilterOptions(result.data, result.headers); } catch (err) { setError(err.message); } finally { setLoading(false); } }; const generateFilterOptions = (data, headers) => { const options = {}; const filterableColumns = headers.filter((h) => !excludedColumns.includes(h)); filterableColumns.forEach((column) => { const uniqueValues = new Set(); data.forEach((item) => { const value = item[column]; if (value && value.toString().trim()) { uniqueValues.add(value.toString().trim()); } }); const values = Array.from(uniqueValues).sort(); const binaryValues = ["Sim", "Não", "Opcional"]; const isBinaryFilter = values.every((v) => binaryValues.includes(v)); options[column] = { values: values, isBinary: isBinaryFilter, }; }); setFilterOptions(options); }; const applyFilters = () => { let filtered = [...boards]; if (searchTerm) { filtered = filtered.filter((board) => { const searchLower = searchTerm.toLowerCase(); return ( board.Nome?.toLowerCase().includes(searchLower) || board.Descrição?.toLowerCase().includes(searchLower) ); }); } Object.keys(activeFilters).forEach((column) => { if (activeFilters[column] && activeFilters[column].length > 0) { filtered = filtered.filter((board) => { const boardValue = board[column]?.toString().trim(); if (activeFilters[column].includes("binary-enabled")) { return boardValue === "Sim" || boardValue === "Opcional"; } return activeFilters[column].includes(boardValue); }); } }); setFilteredBoards(filtered); }; const handleFilterToggle = (column, value) => { setActiveFilters((prev) => { const newFilters = { ...prev }; if (!newFilters[column]) { newFilters[column] = [value]; } else { const index = newFilters[column].indexOf(value); if (index > -1) { newFilters[column] = newFilters[column].filter((v) => v !== value); if (newFilters[column].length === 0) { delete newFilters[column]; } } else { newFilters[column] = [...newFilters[column], value]; } } return newFilters; }); }; const clearFilters = () => { setActiveFilters({}); setSearchTerm(""); }; const activeFilterCount = Object.keys(activeFilters).length + (searchTerm ? 1 : 0); const filterableColumns = headers.filter((h) => !excludedColumns.includes(h)); const hero = ( ); if (loading) { return (
{hero}
{Array.from({ length: 6 }).map((_, i) => (
))}

{isEn ? "Querying boards database…" : isEs ? "Consultando la base de datos de placas…" : isFr ? "Consultation de la base de cartes…" : isZh ? "正在查询开发板数据库…" : isDe ? "Board-Datenbank wird abgefragt…" : "Consultando o banco de placas…"}

); } if (error) { return (
{hero}
); } const filtros = (
{filterableColumns.map((column) => { const filterData = filterOptions[column]; if (!filterData) return null; const colLabel = isEn ? (HEADER_MAP_EN[column] || column) : isEs ? (HEADER_MAP_ES[column] || column) : isFr ? (HEADER_MAP_FR[column] || column) : isZh ? (HEADER_MAP_ZH[column] || column) : isDe ? (HEADER_MAP_DE[column] || column) : column; if (filterData.isBinary) { return ( ); } return (
{colLabel} {activeFilters[column]?.length > 0 && {activeFilters[column].length}}
{filterData.values.map((option) => { const optLabel = isEn ? (VALUE_MAP_EN[option] || option) : isEs ? (VALUE_MAP_ES[option] || option) : isFr ? (VALUE_MAP_FR[option] || option) : isZh ? (VALUE_MAP_ZH[option] || option) : isDe ? (VALUE_MAP_DE[option] || option) : option; return ( ); })}
); })}
); return (
{hero}

{filteredBoards.length}{" "} {isEn ? filteredBoards.length === 1 ? "board found" : "boards found" : isEs ? filteredBoards.length === 1 ? "placa encontrada" : "placas encontradas" : isFr ? filteredBoards.length === 1 ? "carte trouvée" : "cartes trouvées" : isZh ? "款开发板" : isDe ? filteredBoards.length === 1 ? "Board gefunden" : "Boards gefunden" : filteredBoards.length === 1 ? "placa encontrada" : "placas encontradas"}

{filteredBoards.length === 0 ? (
) : (
{filteredBoards.map((board, index) => ( ))}
)}
); }