No TypeScript, não podemos simplesmente jogar dados soltos. Precisamos criar uma "Ficha Cadastral" (chamada de Interface). Isso ensina ao código quais informações um produto obrigatoriamente deve ter.

  1. Dentro da pasta src, crie uma pasta chamada types.
  2. Dentro de types, crie o arquivo types.ts.
  3. Cole o código abaixo:
// A palavra 'export' permite que outros arquivos do projeto usem este molde.
// A palavra 'interface' é o comando do TypeScript para criar uma estrutura de dados.
// 'TipoProduto' é o nome que escolhemos para o nosso molde (sempre com letra maiúscula).
export interface TipoProduto {
  
  // 'id' vai guardar a identificação única. 'number' significa que só aceita números.
  id: number;
  
  // 'nome' vai guardar o título do produto. 'string' significa que só aceita textos.
  nome: string;
  
  // 'preco' vai guardar o valor. Também é 'number' (usaremos números com ponto, ex: 299.90).
  preco: number;
  
  // 'descricao' é um texto explicativo sobre o produto.
  descricao: string;
  
  // 'avatar' vai receber o link de uma imagem da internet (por isso é um texto/string).
  avatar: string;
}

Como ainda não conectamos nosso site a um banco de dados real, vamos criar uma lista de "mentirinha" (Mock) para testar o visual da tela.

  1. Dentro de src, crie uma pasta chamada data.
  2. Dentro de data, crie o arquivo listaProdutos.ts.
  3. Cole o código abaixo. Leia os comentários para entender a sintaxe!
// Primeiro, importamos o molde que criamos no Passo 1.
import { TipoProduto } from '../types/types';

// 'export const' cria uma constante (variável que não muda de nome) e a libera para uso.
// 'listaProdutos' é o nome do nosso estoque.
// ': TipoProduto[]' é a regra! O colchete [] avisa: "Isso não é um produto só, é uma LISTA de produtos".
// O sinal de igual '=' vai atribuir a lista.
// Os colchetes abertos '[' e fechados ']' no final guardam todos os itens dentro.
export const listaProdutos: TipoProduto[] = [
  { // As chaves {} representam UM produto individual.
    id: 1,
    nome: "Headset Gamer Sem Fio",
    preco: 299.90,
    descricao: "Áudio espacial 7.1, espumas confortáveis e microfone retrátil.",
    avatar: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 2,
    nome: "Teclado Mecânico RGB",
    preco: 249.00,
    descricao: "Switches rápidos e iluminação colorida ajustável.",
    avatar: "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 3,
    nome: "Smartwatch Fitness",
    preco: 189.50,
    descricao: "Mede batimentos cardíacos, conta passos e exibe notificações.",
    avatar: "https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 4,
    nome: "Câmera Instantânea",
    preco: 420.00,
    descricao: "Tira fotos analógicas e imprime na hora.",
    avatar: "https://images.unsplash.com/photo-1526170375885-4d8ecf77b99f?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 5,
    nome: "Mouse Pad Gigante",
    preco: 89.90,
    descricao: "Superfície speed para movimentos rápidos.",
    avatar: "https://images.unsplash.com/photo-1616423640778-28d1b53229bd?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 6,
    nome: "Microfone Condensador USB",
    preco: 350.00,
    descricao: "Captação de voz cristalina, ideal para streams.",
    avatar: "https://images.unsplash.com/photo-1590602847861-f357a9332bbc?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 7,
    nome: "Monitor Ultrawide 29",
    preco: 1250.00,
    descricao: "Tela imersiva com painel IPS de alta fidelidade.",
    avatar: "https://images.unsplash.com/photo-1527443224154-c4a3942d3acf?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 8,
    nome: "Cadeira Ergonômica",
    preco: 850.00,
    descricao: "Apoio lombar e ajuste de inclinação de 180 graus.",
    avatar: "https://images.unsplash.com/photo-1598550476439-6847785fcea6?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 9,
    nome: "Webcam Full HD",
    preco: 199.00,
    descricao: "Resolução 1080p, foco automático e tampa de privacidade.",
    avatar: "https://images.unsplash.com/photo-1621259182978-fbf93132d53d?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 10,
    nome: "Fita LED Inteligente",
    preco: 120.00,
    descricao: "5 metros, controle por aplicativo e comando de voz.",
    avatar: "https://images.unsplash.com/photo-1550751827-4bd374c3f58b?w=120&auto=format&fit=crop&q=80"
  }
];

Agora vamos juntar tudo na tela de Produtos.

Abra o arquivo src/routes/Produtos/index.tsx e substitua TUDO pelo código abaixo. Leia cada comentário atentamente, pois eles explicam linha a linha o que os Hooks e as tags da tabela estão fazendo.

// --- ÁREA DE IMPORTAÇÕES ---

// Importamos o 'useState' (para criar a memória da tela) e o 'useEffect' (para executar ações ao carregar a tela)
import { useState, useEffect } from 'react';

// Importamos o molde para garantir que não vamos errar os campos do produto
import { TipoProduto } from '../../types/types';

// Importamos a nossa lista de mentirinha com os 10 produtos
import { listaProdutos } from '../../data/listaProdutos';

// --- INÍCIO DO COMPONENTE ---
export default function Produtos() {

  // 1. CRIANDO A MEMÓRIA DA TELA (useState)
  // Lemos assim:
  // - 'produtos': é a caixa onde os dados vão ficar guardados.
  // - 'setProdutos': é o controle remoto. Só ele tem permissão para colocar ou tirar dados da caixa.
  // - 'useState<TipoProduto[]>': Avisa ao React que essa memória só aceita uma lista de produtos.
  // - '([])': É o valor inicial. A tela começa com a lista VAZIA antes de carregar.
  const [produtos, setProdutos] = useState<TipoProduto[]>([]);

  // 2. AÇÃO AO ABRIR A PÁGINA (useEffect)
  // O useEffect observa o ciclo de vida do componente.
  useEffect(() => {
    // Usamos o controle remoto para pegar a 'listaProdutos' do arquivo e colocar dentro da memória 'produtos'
    setProdutos(listaProdutos);
    
    // ATENÇÃO: Esse array vazio [] no final é crucial.
    // Ele diz ao React: "Faça essa ação APENAS UMA VEZ, no exato momento em que a página abrir".
  }, []);

  // 3. DESENHANDO A TELA (return JSX)
  return (
    // A tag <main> é o contêiner principal. Adicionamos um estilo Cyberpunk Neon diretamente nela.
    <main style={{ padding: '20px', backgroundColor: '#0d0d0d', color: '#39ff14', minHeight: '100vh' }}>
      <h1>Painel de Produtos</h1>
      
      {/* --- INÍCIO DA TABELA --- */}
      {/* <table> cria a estrutura. As bordas foram pintadas de verde neon (#39ff14) */}
      <table border={1} cellPadding={10} style={{ width: '100%', borderCollapse: 'collapse', borderColor: '#39ff14' }}>
        
        {/* <thead> representa o CABEÇALHO da tabela (os títulos das colunas) */}
        <thead>
          {/* <tr> significa Table Row (Linha da tabela). Pintamos o fundo de cinza escuro. */}
          <tr style={{ backgroundColor: '#1a1a1a', color: '#ff00ff' }}>
            {/* <th> significa Table Heading (Célula de título) */}
            <th>Foto</th>
            <th>ID</th>
            <th>Nome</th>
            <th>Preço</th>
            <th>Descrição</th>
          </tr>
        </thead>

        {/* <tbody> representa o CORPO da tabela (onde os dados vão ficar) */}
        <tbody>
          
          {/* 
            A MÁGICA DO MAP:
            O '.map()' pega a nossa memória 'produtos' e funciona como uma impressora.
            Para cada produto na lista, ele roda o código abaixo uma vez, apelidando o produto atual de 'item'.
          */}
          {produtos.map((item) => (
            
            // Para cada item, criamos uma linha nova <tr>
            // O React EXIGE que toda linha gerada por um '.map()' tenha uma 'key' única.
            // Passamos o 'item.id' para o React não se perder ao atualizar a tela.
            <tr key={item.id} style={{ borderBottom: '1px solid #39ff14' }}>
              
              {/* <td> significa Table Data (Célula de dado comum) */}
              
              {/* Coluna 1: A Imagem */}
              <td>
                <img 
                  src={item.avatar} // Puxa o link da internet guardado no mock
                  alt={item.nome}   // Texto alternativo caso a imagem quebre
                  width={60} 
                  height={60} 
                  style={{ objectFit: 'cover', borderRadius: '4px', border: '1px solid #ff00ff' }} 
                />
              </td>
              
              {/* Coluna 2: O ID */}
              {/* Usamos chaves {} no JSX sempre que queremos escrever uma variável do JavaScript no meio do HTML */}
              <td>{item.id}</td>
              
              {/* Coluna 3: O Nome (em negrito) */}
              <td><strong>{item.nome}</strong></td>
              
              {/* Coluna 4: O Preço */}
              {/* .toFixed(2) obriga o número a sempre mostrar 2 casas decimais (Ex: 299.9 vira 299.90) */}
              <td>R$ {item.preco.toFixed(2)}</td>
              
              {/* Coluna 5: A Descrição */}
              <td>{item.descricao}</td>
              
            </tr>
          ))}
        </tbody>
      </table>
    </main>
  );
}