Refactor: padroniza schema de conexões e atualiza UI do diagrama + melhorias na página de série

- Padroniza JSON de conexões (vários chips): normaliza "numero", unifica categorias, substitui "restricoes" por "avisos" (array), adiciona "alimentacao" e revisa campos de tipo/funcões/avisos.
- Atualiza large conjunto de arquivos em public/conexoes (ESP32, ESP32-S2/S3/C3/C5/C6/H2/P4) para o novo formato e dados mais completos.
- Adapta ConnectionsDiagram.jsx ao novo schema:
  - atualiza FILTER_CATEGORIES e type_colors;
  - usa cores por tipo (type_colors) para background/bordas/indicadores;
  - renomeia/exibe avisos, altera labels (ex: "Conexão" → "Pino"), melhora renderização de badges e contadores;
  - refina modal (overlay, classes, exibição de categorias, seção de alimentação e lista de avisos).
- Altera page de série (app/series/[key]/page.jsx):
  - adiciona bloco "Sobre a Matriz de Conexões Flexível";
  - adiciona links rápidos: Datasheet, Guia de Programação e (condicional) Manual Técnico;
  - ajusta estilos de botões/grades e espaçamento (md:mx-8);
  - simplifica previous/next (retorna null em vez de placeholders vazios).
- Atualiza public/series.json com links de manual/guia, correções de specs (GPIO, temperaturas, descrições) e outras metadatas.

Resultados: dados de conexões padronizados, componente de diagrama consistente com o novo schema, melhor UX na página de série e acesso direto a documentação.
This commit is contained in:
Lucas Rayan committed 2025-10-27 10:56:03 -03:00
1 parent 941dd266a0
commit e169e29d0d
11 files changed
+5139 -3433

No files matched your search

+79 -51
View File
@@ -3,30 +3,43 @@
import { useState, useEffect, useMemo } from "react";
const FILTER_CATEGORIES = [
{ id: "All", name: "Todos", color: "#64748b" },
{ id: "Ground", name: "Terra (GND)", color: "#64748b" },
{ id: "All", name: "Todos", color: "#374151" },
{ id: "GND", name: "Terra (GND)", color: "#64748b" },
{ id: "Power", name: "Alimentação", color: "#ef4444" },
{ id: "RTC", name: "RTC", color: "#f59e0b" },
{ id: "GPIO", name: "GPIO", color: "#22c55e" },
{ id: "Low Power", name: "GPIO LP", color: "#f59e0b" },
{ id: "ADC", name: "ADC", color: "#ec4899" },
{ id: "DAC", name: "DAC", color: "#a855f7" },
{ id: "Touch", name: "Touch", color: "#06b6d4" },
{ id: "UART", name: "UART", color: "#3b82f6" },
{ id: "SPI", name: "SPI", color: "#ef4444" },
{ id: "I2C", name: "I2C", color: "#10b981" },
{ id: "PWM", name: "PWM", color: "#f97316" },
{ id: "USB", name: "USB", color: "#8b5cf6" },
{ id: "Clock", name: "Clock", color: "#eab308" },
{ id: "JTAG", name: "JTAG", color: "#8b5cf6" },
{ id: "Strapping", name: "Inicialização", color: "#dc2626" },
{ id: "DSI", name: "Display (DSI)", color: "#f97316" },
{ id: "CSI", name: "Câmera (CSI)", color: "#14b8a6" },
{ id: "Ethernet", name: "Ethernet", color: "#3b82f6" },
{ id: "SD", name: "Cartão SD", color: "#10b981" },
{ id: "I2C", name: "I2C", color: "#f59e0b" },
{ id: "Antena", name: "Antena", color: "#22d3ee" },
];
const type_colors = {
power: "#ef4444",
ground: "#64748b",
io: "#22c55e",
analog: "#ec4899",
dedicated: "#3b82f6",
nc: "#9ca3af",
};
export default function ConnectionsDiagram({ connections, color }) {
const [activeFilter, setActiveFilter] = useState("All");
const [selectedConnection, setSelectedConnection] = useState(null);
const [hoveredConnection, setHoveredConnection] = useState(null);
const [searchQuery, setSearchQuery] = useState("");
const [viewMode, setViewMode] = useState("grid"); // 'grid' or 'list'
const [viewMode, setViewMode] = useState("grid");
const [showTooltip, setShowTooltip] = useState(null);
const isConnectionVisible = (connection) => {
@@ -326,17 +339,17 @@ export default function ConnectionsDiagram({ connections, color }) {
onBlur={() => setHoveredConnection(null)}
aria-label={`Connection ${connection.nome}, number ${connection.numero}`}
aria-describedby={showTooltip === index ? `tooltip-${index}` : undefined}
className="relative w-full flex flex-col items-center justify-center p-3 rounded-2xl border-2 transition-all duration-300 opacity-100 hover:scale-110 hover:shadow-2xl hover:z-10 cursor-pointer active:scale-95 focus:outline-none focus:ring-4 focus:ring-offset-2"
className="relative w-full flex flex-col items-center justify-center p-3 rounded-2xl border-2 transition-all duration-300 opacity-100 hover:scale-110 hover:shadow-2xl hover:z-10 cursor-pointer active:scale-95 focus:outline-none focus:border-4"
style={{
backgroundColor: connection.cor + "15",
borderColor: isHovered ? connection.cor : connection.cor + "60",
backgroundColor: type_colors[connection.tipo] + (isHovered ? "20" : "10"),
borderColor: isHovered ? type_colors[connection.tipo] : type_colors[connection.tipo] + "60",
transform: isHovered ? "translateY(-2px)" : undefined,
focusRingColor: connection.cor,
focusRingColor: type_colors[connection.tipo],
}}
>
<div
className="w-14 h-14 rounded-full flex items-center justify-center text-white font-bold text-sm mb-3 shadow-lg ring-2 ring-white"
style={{ backgroundColor: connection.cor }}
className="w-14 h-14 rounded-full flex items-center justify-center text-white font-bold text-sm mb-3 shadow-lg"
style={{ backgroundColor: type_colors[connection.tipo] }}
>
{typeof connection.numero === "number"
? connection.numero
@@ -347,23 +360,23 @@ export default function ConnectionsDiagram({ connections, color }) {
{connection.nome}
</div>
<div className="flex flex-wrap gap-1 justify-center">
<div className="flex flex-wrap gap-1 justify-center leading-2">
{connection.categorias.slice(0, 5).map((cat) => (
<span
key={cat}
className="w-1.5 h-1.5 rounded-full"
className="w-1.5 h-1.5 my-auto rounded-full"
style={{ backgroundColor: getCategoryColor(cat) }}
title={cat}
/>
))}
{connection.categorias.length > 5 && (
<span className="text-[10px] text-gray-500 font-medium">
<span className="text-[10px] text-gray-500 font-medium leading-2">
+{connection.categorias.length - 5}
</span>
)}
</div>
{connection.restricoes && (
{connection.avisos && (
<div
className="absolute -top-2 -right-2 bg-red-500 rounded-full p-1.5 shadow-lg ring-2 ring-white"
aria-label="Has restrictions"
@@ -391,7 +404,7 @@ export default function ConnectionsDiagram({ connections, color }) {
style={{ minWidth: "200px" }}
>
<div className="font-bold mb-1">{connection.nome}</div>
<div className="text-gray-300 mb-2">{connection.numero}</div>
<div className="text-gray-300 mb-2">Pino {connection.numero}</div>
<div className="flex flex-wrap gap-1 mb-2">
{connection.categorias.map((cat) => (
<span
@@ -425,7 +438,7 @@ export default function ConnectionsDiagram({ connections, color }) {
<th className="px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider">Nome</th>
<th className="px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider">Categorias</th>
<th className="px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider">Funções</th>
<th className="px-6 py-4 text-center text-xs font-bold text-gray-700 uppercase tracking-wider">Status</th>
<th className="px-6 py-4 text-center text-xs font-bold text-gray-700 uppercase tracking-wider">Avisos</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
@@ -438,7 +451,7 @@ export default function ConnectionsDiagram({ connections, color }) {
<td className="px-6 py-4 whitespace-nowrap">
<div
className="w-10 h-10 rounded-full flex items-center justify-center text-white font-bold text-sm shadow-md"
style={{ backgroundColor: connection.cor }}
style={{ backgroundColor: type_colors[connection.tipo] }}
>
{typeof connection.numero === "number"
? connection.numero
@@ -469,19 +482,19 @@ export default function ConnectionsDiagram({ connections, color }) {
</div>
</td>
<td className="px-6 py-4 text-center">
{connection.restricoes ? (
{connection.avisos ? (
<span className="inline-flex items-center gap-1 px-2 py-1 rounded-full bg-red-100 text-red-700 text-xs font-medium">
<svg className="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
</svg>
Atenção
Sim
</span>
) : (
<span className="inline-flex items-center gap-1 px-2 py-1 rounded-full bg-green-100 text-green-700 text-xs font-medium">
<svg className="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
OK
Não
</span>
)}
</td>
@@ -493,7 +506,7 @@ export default function ConnectionsDiagram({ connections, color }) {
</div>
)}
{connections.some(c => c.restricoes) && (
{connections.some(c => c.avisos) && (
<div className="bg-linear-to-r from-amber-50 to-yellow-50 border-2 border-amber-200 rounded-2xl p-6 shadow-sm">
<div className="flex gap-4">
<div className="shrink-0">
@@ -537,7 +550,7 @@ export default function ConnectionsDiagram({ connections, color }) {
{selectedConnection && (
<div
className="fixed inset-0 bg-black bg-opacity-80 backdrop-blur-sm flex items-center justify-center p-4 z-50 animate-fadeIn"
className="fixed inset-0 bg-opacity-80 backdrop-blur-xs flex items-center justify-center p-4 z-50 animate-fadeIn"
onClick={() => setSelectedConnection(null)}
role="dialog"
aria-modal="true"
@@ -552,7 +565,7 @@ export default function ConnectionsDiagram({ connections, color }) {
<div className="flex items-center gap-5 flex-1">
<div
className="w-16 h-16 rounded-2xl flex items-center justify-center text-white font-bold text-xl shadow-xl ring-4 ring-white shrink-0"
style={{ backgroundColor: selectedConnection.cor }}
style={{ backgroundColor: type_colors[selectedConnection.tipo] }}
>
{typeof selectedConnection.numero === "number"
? selectedConnection.numero
@@ -563,7 +576,7 @@ export default function ConnectionsDiagram({ connections, color }) {
{selectedConnection.nome}
</h3>
<p className="text-base text-gray-600">
Conexão {selectedConnection.numero}
Pino {selectedConnection.numero}
</p>
</div>
</div>
@@ -589,7 +602,7 @@ export default function ConnectionsDiagram({ connections, color }) {
</div>
<div className="flex-1 overflow-y-auto p-8 space-y-8">
<div>
{selectedConnection.categorias.length > 0 && (<div>
<h4 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M7 3a1 1 0 000 2h6a1 1 0 100-2H7zM4 7a1 1 0 011-1h10a1 1 0 110 2H5a1 1 0 01-1-1zM2 11a2 2 0 012-2h12a2 2 0 012 2v4a2 2 0 01-2 2H4a2 2 0 01-2-2v-4z" />
@@ -601,19 +614,43 @@ export default function ConnectionsDiagram({ connections, color }) {
{selectedConnection.categorias.map((cat) => (
<span
key={cat}
className="px-4 py-2 rounded-xl text-sm font-bold text-white shadow-md ring-2 ring-white"
className="px-4 py-2 rounded-xl text-sm font-bold text-white shadow-md"
style={{ backgroundColor: getCategoryColor(cat) }}
>
{cat === "Strapping" ? "Inicialização" : cat}
</span>
))}
</div>
</div>
</div>)}
{selectedConnection.alimentacao && (
<div>
<h4 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clipRule="evenodd" />
</svg>
Alimentado por:
</h4>
<div className="bg-linear-to-br from-blue-50 to-indigo-50 rounded-2xl p-6 border border-blue-200">
<ul className="space-y-3">
{selectedConnection.alimentacao.map((source, index) => (
<li key={index} className="flex items-start gap-4 text-sm group">
<span
className="mt-1.5 shrink-0 w-2 h-2 rounded-full"
style={{ backgroundColor: type_colors["power"] }}
/>
<span className="text-gray-800 font-medium leading-relaxed">{source}</span>
</li>
))}
</ul>
</div>
</div>
)}
<div>
<h4 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clipRule="evenodd" />
<path d="M13 7H7v6h6V7zM5 3a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2V5a2 2 0 00-2-2H5z" />
</svg>
Funções da Conexão
</h4>
@@ -623,8 +660,8 @@ export default function ConnectionsDiagram({ connections, color }) {
{selectedConnection.funcoes.map((func, index) => (
<li key={index} className="flex items-start gap-4 text-sm group">
<span
className="mt-1 shrink-0 w-2 h-2 rounded-full group-hover:scale-125 transition-transform"
style={{ backgroundColor: color }}
className="mt-1.5 shrink-0 w-2 h-2 rounded-full"
style={{ backgroundColor: type_colors[selectedConnection.tipo] }}
/>
<span className="text-gray-800 font-medium leading-relaxed">{func}</span>
</li>
@@ -633,7 +670,7 @@ export default function ConnectionsDiagram({ connections, color }) {
</div>
</div>
{selectedConnection.restricoes && (
{selectedConnection.avisos && (
<div className="bg-linear-to-br from-red-50 to-rose-50 border-2 border-red-200 rounded-2xl p-6 shadow-sm">
<div className="flex gap-4">
<div className="shrink-0">
@@ -653,11 +690,16 @@ export default function ConnectionsDiagram({ connections, color }) {
</div>
<div className="flex-1">
<p className="text-lg font-bold text-red-900 mb-3">
Alertas Importantes
</p>
<p className="text-sm text-red-800 leading-relaxed">
{selectedConnection.restricoes}
Avisos Importantes
</p>
{selectedConnection.avisos.map((aviso, index) => (
<div key={index} className="flex items-start gap-3 mb-2">
<span className="text-red-600 font-bold">•</span>
<span className="text-sm text-red-800 leading-relaxed">
{aviso}
</span>
</div>
))}
</div>
</div>
</div>
@@ -678,20 +720,6 @@ export default function ConnectionsDiagram({ connections, color }) {
</div>
)}
<div className="bg-white rounded-2xl shadow-lg p-6 border-2 border-gray-100">
<h3 className="text-lg font-bold text-gray-800 mb-3 flex items-center gap-2">
<svg className="w-5 h-5 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" />
</svg>
Sobre a Matriz de Conexões Flexível
</h3>
<p className="text-gray-700 leading-relaxed">
O ESP32 possui uma matriz de conexões flexível que permite mapear diversas funções para múltiplos pinos.
Isso significa que muitas conexões podem ser configuradas para desempenhar diferentes papéis, dependendo das necessidades do seu projeto.
Consulte a documentação oficial para entender como aproveitar ao máximo essa flexibilidade.
</p>
</div>
<style jsx>{`
@keyframes fadeIn {
from {