Simulador da Copa do Mundo com React + IA: minha experiência em um desafio de estágio
Recentemente participei de um desafio técnico para uma vaga de estágio em desenvolvimento de software, e resolvi compartilhar como foi o processo de construção do projeto — não só o resultado final, mas principalmente como pensei, organizei e resolvi os problemas ao longo do caminho.
O desafio consistia em desenvolver uma aplicação capaz de simular uma Copa do Mundo completa, desde o sorteio dos grupos até a definição do campeão.
Sobre o desafio
A proposta era construir uma aplicação que:
- Consumisse uma API com 32 seleções
- Distribuísse essas seleções em 8 grupos (A–H) de forma aleatória
- Simulasse todos os jogos da fase de grupos
- Calculasse a classificação com base em regras reais (pontos e saldo de gols)
- Definisse os classificados para o mata-mata
- Simulasse todas as fases eliminatórias (oitavas, quartas, semifinais e final)
- Em caso de empate, resolvesse com disputa de pênaltis
- Enviasse o resultado final para uma API
Ou seja, não era apenas um projeto visual — envolvia lógica de negócio completa, fluxo de dados bem definido e organização de código.
Stack escolhida
Para o desenvolvimento, optei por:
- React (com Vite) → para construção da interface
- JavaScript puro (ES6+) → sem uso de TypeScript, focando na base
- CSS puro → com abordagem mobile-first e organização por componente
- Arquitetura baseada em separação de responsabilidades
Organizei o projeto em:
components/→ camada de interfaceutils/→ regras de negócio (simulação, classificação, etc.)services/→ comunicação com API
Essa separação foi essencial para manter o código limpo e escalável.
Regras de negócio e lógica
A parte mais interessante (e desafiadora) foi implementar a lógica da Copa:
- Sorteio aleatório dos grupos (utilizando algoritmo de embaralhamento)
- Geração de jogos “todos contra todos” dentro de cada grupo
- Cálculo de pontuação:
- Vitória: 3 pontos
- Empate: 1 ponto
- Critérios de desempate:
- Pontos
- Saldo de gols
- Sorteio (aleatório)
- Geração do chaveamento das oitavas (ex: 1º do grupo A x 2º do grupo B)
- Simulação das fases eliminatórias com:
- Placar aleatório
- Pênaltis em caso de empate
Toda essa lógica foi isolada em funções puras dentro da pasta utils, o que facilitou muito o controle e a manutenção.
Uso de IA no desenvolvimento (Antigravity)
Um dos pontos mais interessantes desse projeto foi a forma como utilizei IA (no caso, o Antigravity).
Ao invés de pedir soluções prontas, utilizei uma abordagem mais estratégica:
👉 Prompt por etapa (step by step)
Cada alteração era guiada por um prompt específico, extremamente claro e sem margem para erro, como:
- “Extraia esse trecho em um componente sem alterar a lógica existente”
- “Mova apenas os estilos relacionados a esse componente para um arquivo CSS próprio”
- “Não altere nomes de variáveis nem a estrutura de dados existente”
Essa forma de trabalhar foi essencial para evitar que a IA “quebrasse” o projeto. Em vez de delegar tudo, eu passei a controlar o processo, usando a IA como apoio e não como substituição do raciocínio.
Na prática, foi quase como um pair programming, onde cada passo precisava ser validado antes de seguir para o próximo. Isso me ajudou a manter consistência no código e evitar regressões.
Componentização e organização
Inicialmente, toda a aplicação estava concentrada no App.jsx, o que rapidamente se tornou difícil de manter.
A partir disso, iniciei uma refatoração focada em componentização:
GroupCard→ responsável por renderizar os grupos, partidas e tabelaMatchItem→ representação de uma partida individualKnockoutPhase→ componente reutilizável para todas as fases do mata-mataChampionBanner→ exibição do campeãoQualifiedList→ lista dos classificados
Além disso, cada componente passou a ter seu próprio arquivo de CSS, reduzindo o acoplamento e facilitando a manutenção.
Esse processo deixou o App.jsx muito mais limpo, atuando apenas como orquestrador da aplicação.
Um dos principais desafios: React Strict Mode
Durante o desenvolvimento, me deparei com um comportamento que eu não conhecia bem.
Ao enviar o resultado final para a API, percebi que a requisição estava sendo disparada duas vezes. Isso ficou evidente ao analisar o console com o DevTools.
Investigando, entendi que o React Strict Mode, em ambiente de desenvolvimento, executa alguns ciclos (como o useEffect) duas vezes de forma intencional, justamente para identificar efeitos colaterais.
Para resolver isso, utilizei o useRef como uma flag de controle, garantindo que o envio do resultado acontecesse apenas uma vez.
Esse foi um ponto importante porque, além de resolver o problema, me fez entender melhor o ciclo de vida do React e o papel do Strict Mode.
Aprendizados principais
Esse projeto acabou indo muito além do escopo inicial. Alguns dos principais aprendizados foram:
- Importância da separação entre lógica e interface
- Como estruturar um projeto pensando em escalabilidade
- Uso consciente de IA no desenvolvimento
- Entendimento mais profundo de hooks do React (
useEffect,useRef) - Organização de CSS por componente
- Controle de efeitos colaterais
Conclusão
Apesar de ser um desafio de estágio, encarei o projeto como algo mais próximo de um cenário real de desenvolvimento.
A aplicação não apenas atende aos requisitos propostos, como também foi estruturada com foco em organização, clareza e manutenção.
Mais do que entregar o resultado, o objetivo foi ter controle total sobre o que estava sendo construído, entendendo cada decisão tomada ao longo do processo.
- Esse tipo de experiência reforça que escrever código não é só fazer funcionar, mas sim construir soluções de forma consciente e evolutiva.



