Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c66f352
Initial commit
allbertuu Feb 11, 2026
7d32c7d
Merge branch 'master' of https://github.com/allbertuu/pokedex
allbertuu Feb 11, 2026
e9f67ab
chore: delete `logo.png`
allbertuu Feb 11, 2026
4dd853f
feat: Pokémon listing feature (ML2)
allbertuu Feb 11, 2026
3709815
chore: delete `package-lock.json`
allbertuu Feb 11, 2026
7812c14
test: Pokémon listing feature (ML2)
allbertuu Feb 11, 2026
341e49f
Merge branch 'master' of https://github.com/allbertuu/pokedex
allbertuu Feb 11, 2026
16adafa
test(PokémonList): refactor tests to use mock data
allbertuu Feb 11, 2026
cbc74cf
refactor: move `Pokemon` type definition to a separate file
allbertuu Feb 11, 2026
bd86fce
feat(PokemonsList): add loading icon indicator
allbertuu Feb 11, 2026
d03baa2
feat(PokemonsList): add `tabIndex` for keyboard navigation accessibility
allbertuu Feb 12, 2026
476ff57
fix(styles): change bg color to css style
allbertuu Feb 12, 2026
868fb0b
test(PokemonsList): enhance tests for `Pokémon` information display a…
allbertuu Feb 12, 2026
1db024a
fix(pokedex): use `getPokemonByName` from `pokenode-ts`
allbertuu Feb 12, 2026
ea0a025
feat(home): add search and filtering functionality for `PokémonsList`
allbertuu Feb 12, 2026
9f6c8ec
feat(home): add search and filtering functionality for `PokémonsList`…
allbertuu Feb 12, 2026
8ea6be4
Merge branch 'master' of https://github.com/allbertuu/pokedex
allbertuu Feb 12, 2026
5dbe074
docs(readme): add README for onboarding and project overview
allbertuu Feb 13, 2026
19052ef
docs(readme): update README with images
allbertuu Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .cta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"projectName": "pokedex",
"mode": "file-router",
"typescript": true,
"packageManager": "npm",
"tailwind": true,
"addOnOptions": {},
"git": true,
"version": 1,
"framework": "react-cra",
"chosenAddOns": [
"biome"
]
}
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
count.txt
.env
.nitro
.tanstack
.wrangler
*-lock.json
35 changes: 35 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"files.watcherExclude": {
"**/routeTree.gen.ts": true
},
"search.exclude": {
"**/routeTree.gen.ts": true
},
"files.readonlyInclude": {
"**/routeTree.gen.ts": true
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[css]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit"
}
}
195 changes: 143 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,143 @@
### Would you like to work with us? Apply [here](https://looqbox.gupy.io/)!

# Looqbox FrontEnd Challenge
![Looqbox](https://github.com/looqbox/looqbox-frontend-challenge/blob/master/logo.png)

## Challenge
In this challenge you will need to build a **S**ingle **P**age **A**pplication using ReactJS and a provided api

We will not use anything from your project other than evaluate your skills and you are free to use it in your portfolio

## Stack
We use:
- ReactJS
- Redux
- TypeScript
- AntDesign

## Submitting
- Make a fork of this repository
- Create your branch
- ⚠️ Do a initial Commit when you start
- ⚠️ Do a final commit when you finish
- When you're done send us a pull request

# Guidelines
You need to create a Single Page Application (SPA) that displays a list of Pokémon and allows users to search for them, using the [Pokeapi](https://pokeapi.co/docs/v2). Your app must be dynamic, meaning you **must not** reload the page to show new content.

The PokeAPI was chosen for its simplicity in making requests. Since it is an open API, please **be mindful of how many requests** you make.

## Requirements:

- On the main page, include a search bar and a preloaded list of Pokémon.
- Clicking on any Pokémon should display a card, modal, or page with that Pokémon’s information.
- Typing in the search bar and pressing Enter should display the search result instead of the list.
- Your app must include at least two different routes (e.g., /home, /details — be creative!).
- Add a README file to document your project.

You may use any libraries or dependencies you like (e.g., Axios, Bootstrap, Material UI...).

## Bonus points!
- Pagination
- Error handling
- Documentation
- Linting
- Charts
- Unit Testing
- Ant Design

## Useful links
- [React docs](https://react.dev/)
- [PokeApi docs](https://pokeapi.co/docs/v2)
- [Redux](https://redux.js.org/)
# 🚀 Onboarding: Guia de Viagem pela Pokédex

> "O lixo de uns é o tesouro de outros."
> No desenvolvimento, o que muitos negligenciam (documentação, clareza e facilidade de revisão), eu trato como prioridade. Este projeto não é apenas um consumo de API; é um reflexo de como organizo meu pensamento e facilito a vida de quem trabalha comigo.

Bem-vindo(a)! Se você é dev, gestor ou até mesmo leigo (e vou me esforçar pra alcançar você), este guia foi feito para que você não perca tempo tentando entender tudo *o que* eu fiz, mas sim para que possamos discutir *por que* tomei cada decisão.

## 📌 Sumário

* [✨ Funcionalidades](#-funcionalidades)
* [🧠 Decisões Técnicas](#-decisões-técnicas-lógica-tecnologias-e-paradigmas)
* [🛠️ Tech Stack](#%EF%B8%8F-tech-stack)
* [🚀 Próximos Passos (Roadmap)](#-próximos-passos-roadmap)
* [🏁 Como rodar e revisar o projeto](#-como-rodar-e-revisar-o-projeto)
* [🍮 Pausa para o Café](#-pausa-para-o-café)

---

## ✨ Funcionalidades

Aqui está o resumo das funcionalidades implementadas.

* **🔍 Busca:** Barra de busca funcional na página principal. Ao pressionar **Enter**, a lista é filtrada dinamicamente, priorizando a intenção do usuário.
* **📜 Listagem:** Lista de Pokémons pré-carregada para evitar telas vazias no primeiro acesso.
* **📑 Detalhes (incompleto):** Página dedicada para cada Pokémon, exibindo informações, estatísticas e gráficos.
* **🛣️ Roteamento Avançado:** Navegação multipáginas utilizando um sistema de rotas baseado em arquivos (`/home` e `/details/$pokemonName`).
* **♿ Acessibilidade (A11y):** Navegação completa via teclado. Use `Tab` para percorrer e `Enter` para selecionar.
* **🖼️ Fallback de Imagem:** Tratativa para Pokémons sem foto oficial com a clássica imagem do *"Quem é esse Pokémon?"*.
<img width="263" height="324" alt="image" src="https://github.com/user-attachments/assets/09ff6571-5fcc-4d5b-9c82-078c0ad1475c" />

### 🏆 Bonus!

Os seguintes itens extras que garantem a robustez do projeto:

* [x] **Error Handling:** Sistema de captura de erros com feedback visual e contato direto com o dev.
* [x] **Documentation:** Este guia completo de onboarding.
* [x] **Linting:** Configuração rigorosa com Biome para código limpo.
* [ ] **Charts (incompleto):** Visualização de stats com Recharts.
* [x] **Unit Testing:** Lógica central testada com Vitest.

## 🧠 Decisões técnicas (lógica, tecnologias e paradigmas)

Minha maior decisão técnica foi separar as responsabilidades da `PokemonsList`. Segui uma arquitetura **inspirada no MVC (Model-View-Controller)** adaptada ao ecossistema React.

<img width="614" height="127" alt="image" src="https://github.com/user-attachments/assets/960d177f-fa00-46f6-bc90-00e6e18e1f8e" />

### 1. A Camada de Serviço (Service Layer)
Isolei toda a comunicação externa e as regras de negócio em `src/services/pokedex.ts`.

* **Por que?** Desacoplamento total. Se a PokéAPI mudar seu contrato ou se precisarmos trocar a biblioteca de fetch, a interface do usuário permanece intacta.

* **O Ganho**: O código de negócio - as leis que regem o mundo real - não "vaza" para os componentes. Isso facilita a criação de Mocks para testes e centraliza a fonte única da verdade.

### 2. Separação de Preocupações (Smart Hook + Context)

Deleguei o controle de fluxo de dados (loading, erro, filtragem e fetching) para um **Custom Hook integrado ao Context**.

* **O Ganho:** A `PokemonsList` foca 100% na "View". Ela não sabe como os dados chegam; ela apenas os renderiza da melhor forma visual. Isso reduz a carga cognitiva e torna o código altamente testável.

### 3. UX na busca por Pokémon

* **Tratativa de 404:** Em vez de exibir um erro sistêmico, trato o "Not Found" como um estado da interface, informando amigavelmente que nenhum Pokémon foi encontrado.
* **Feedback Proativo:** Implementei uma forma de contato direto comigo que envia o erro automaticamente.
<img width="519" alt="image" src="https://github.com/user-attachments/assets/596c1d1c-a4dd-4aa3-8390-b2c1a9ef4e6a" />


## 🛠️ Tech Stack

> **Disclaimer:** Toda decisão técnica serve apenas para este snapshot do projeto. Não tenho remorso em mudar de ideia caso os requisitos mudem. A melhor decisão é a que resolve o problema do negócio com a ferramenta certa.

| Tecnologia | Por que usei? |
| --- | --- |
| **Vite** | Aplicação simples, poucas rotas e sem necessidade de SEO pesado. Custo de deploy menor (Static) sem precisar de servidor Node.js para SSR. |
| **TanStack Router** | Roteamento robusto com **Type Safety** absoluto e excelente suporte para *search params* (rota `/details`). |
| **TailwindCSS** | Optei por não usar libs de componentes (como AntDesign) para manter o bundle leve e ter controle total do design (algo que valorizo muito) sem "sobrescrever" estilos pesados. Cuidei para que a interface tivessse boa acessibilidade, ainda que dessa forma mais "crua". |
| **Biome** | Toolchain *all-in-one* para lint e format. Mais rápido que Prettier e com quase zero configuração. |
| **Vitest** | Rapidez e ótima DX para garantir que o "coração" da lógica esteja seguro, com bons testes automatizados. |
| **pokenode-ts** | Recomendação oficial da PokéAPI. Tipagem *built-in* que facilita a integração e paginação, além de função de cache configurado com Axios. |

#### 💡 Destaque Técnico: Arquivos `.d.ts`

Utilizei arquivos de definição de tipos específicos para não "sujar" o código de produção com tipos que não geram código executável, mantendo a compilação limpa e eficiente. Além de um contrato único do formato dos dados para toda a aplicação se basear.

## 🚀 Próximos Passos (Roadmap)

Se eu tivesse mais tempo (ou para uma V2), meu foco seria:

* **GraphQL:** Implementar para evitar *over-fetching* na home, buscando e organizando apenas os dados estritamente necessários para a listagem inicial.
* **Paginação:** Dessa forma a página inicial pode mostrar mais Pokémons e o usuário navegar na vasta coleção que existe. O módulo `pokenode-ts` facilita esse processo ainda mais.
* **Busca por termo incompleto (fuzzy search):** Eu percebi que a PokéAPI não permite pesquisar dessa forma nativamente, como um _fuzzy search_. A aplicação hoje busca por termos exatos, mas seria muito legal implementar isso de alguma forma no futuro. As soluções que pensei eram desnecessariamente complexas...

## 🏁 Como rodar e revisar o projeto:

1. Clone o repositório:

```bash
git clone https://github.com/allbertuu/pokedex.git
```

2. Acesse o diretório do projeto:

```bash
cd pokedex
```

3. Instale as dependências:

```bash
npm install
```

4. Inicie o servidor de desenvolvimento:

```bash
npm run dev
```

5. Abra o navegador e acesse:

```bash
http://localhost:3000
```

## 🧪 Testes

Para executar os testes, utilize o comando:

```bash
npm test
```

**Recomendação de Revisão:** Comece pelo arquivo `src/services/pokedex.ts` (a base), passe pelo `src/contexts/PokemonContext.tsx` (a orquestração) e termine nos componentes da pasta `pages/`.

---

## 🍮 Pausa para o Café

Se este projeto fosse um doce, seria um **pudim**: clássico, mas que exige a técnica certa para não ficar cheio de furinhos (bugs). Sou um desenvolvedor apaixonado por cultura japonesa, corredor amador e alguém que acredita que código limpo é, acima de tudo, um gesto de respeito aos meus colegas de equipe.

---

Fim.
_Esse quam videri_
35 changes: 35 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"includes": [
"**/src/**/*",
"**/.vscode/**/*",
"**/index.html",
"**/vite.config.ts",
"!**/src/routeTree.gen.ts",
"!**/src/styles.css"
]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"assist": { "actions": { "source": { "organizeImports": "on" } } },
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}
21 changes: 21 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Pokédex, mas com a premissa de que clareza é uma funcionalidade."
/>
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>Pokédex</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Binary file removed logo.png
Binary file not shown.
50 changes: 50 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "pokedex",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 3000",
"build": "vite build && tsc",
"preview": "vite preview",
"test": "vitest run",
"test:watch": "vitest run --watch",
"test:ui": "vitest --ui",
"format": "biome format",
"lint": "biome lint",
"check": "biome check",
"check:write": "biome check --write"
},
"dependencies": {
"@tailwindcss/vite": "^4.0.6",
"@tanstack/react-devtools": "^0.7.0",
"@tanstack/react-router": "^1.132.0",
"@tanstack/react-router-devtools": "^1.132.0",
"@tanstack/router-plugin": "^1.132.0",
"axios": "^1.13.5",
"axios-cache-interceptor": "^1.11.4",
"lucide-react": "^0.545.0",
"motion": "^12.34.0",
"pokenode-ts": "^1.20.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"recharts": "^3.7.0",
"tailwindcss": "^4.0.6"
},
"devDependencies": {
"@biomejs/biome": "2.2.4",
"@tanstack/devtools-vite": "^0.3.11",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^22.10.2",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"@vitejs/plugin-react": "^5.0.4",
"jsdom": "^27.4.0",
"typescript": "^5.7.2",
"vite": "^7.1.7",
"vitest": "^3.2.4",
"web-vitals": "^5.1.0"
}
}
Binary file added public/favicon.ico
Binary file not shown.
Binary file added public/logo192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/logo512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"short_name": "TanStack App",
"name": "Create TanStack App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
3 changes: 3 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
Binary file added public/tanstack-circle-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading