Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4b2910c
chore: initialize project environment and boilerplate code
FilipeDiasTarkuss Aug 12, 2025
431dd4b
chore: initialize jest settings, react libray for test
FilipeDiasTarkuss Aug 12, 2025
ab539e5
chore(assets): add images to project
FilipeDiasTarkuss Aug 12, 2025
0a33731
test(atoms): add unit tests for atomic components
FilipeDiasTarkuss Aug 12, 2025
6659ca9
docs(readme): update Readme with current project instructions and imp…
FilipeDiasTarkuss Aug 12, 2025
4b35dc4
style (global): create global styles and light/dark theme
FilipeDiasTarkuss Aug 12, 2025
dad2dc0
feat: atomic components created and updates to components of the shad…
FilipeDiasTarkuss Aug 12, 2025
4aeaf53
feat: combining atomic components to increase hierarchy and create mo…
FilipeDiasTarkuss Aug 12, 2025
e054f9f
feat: Footer component created separately
FilipeDiasTarkuss Aug 12, 2025
b5061f1
feat: Hero section component created separately. Component that will …
FilipeDiasTarkuss Aug 12, 2025
a984feb
feat: Header component created separately with toggle theme button
FilipeDiasTarkuss Aug 12, 2025
60d2bd4
feat: loading component for fetching repository state
FilipeDiasTarkuss Aug 12, 2025
269943d
feat: component that will be render the repository content
FilipeDiasTarkuss Aug 12, 2025
b00ca36
feat: error component for Error repository state
FilipeDiasTarkuss Aug 12, 2025
4b62179
feat: header repository component, located on the repository card
FilipeDiasTarkuss Aug 12, 2025
4c09a5c
feat: component that will display the content of the API call, loadin…
FilipeDiasTarkuss Aug 12, 2025
acfce98
feat: custom hook to storage and update username params from URL
FilipeDiasTarkuss Aug 12, 2025
bfc887f
feat: component to call app context
FilipeDiasTarkuss Aug 12, 2025
1a1a3e7
feat: using react context api to create a custom context
FilipeDiasTarkuss Aug 12, 2025
6e2342c
feat: isolation of client-side providers so as not to interfere with …
FilipeDiasTarkuss Aug 12, 2025
6f8f6ec
feat: react query provider created
FilipeDiasTarkuss Aug 12, 2025
85a4ca3
feat: format to error messages
FilipeDiasTarkuss Aug 12, 2025
4a1e068
feat: format do date input
FilipeDiasTarkuss Aug 12, 2025
590949d
improv: function to render differents colors for repository languages
FilipeDiasTarkuss Aug 12, 2025
0f096b7
feat: add TypeScript interfaces for user and repository models
FilipeDiasTarkuss Aug 12, 2025
1676c2c
feat: add GitHub repository queries
FilipeDiasTarkuss Aug 12, 2025
2d9761b
chore: tailwind code merge function
FilipeDiasTarkuss Aug 12, 2025
0460df9
feat: initialize axios
FilipeDiasTarkuss Aug 12, 2025
e73904d
feat: main layout application
FilipeDiasTarkuss Aug 12, 2025
8198dea
feat: home page with suspense to prevent params unavailbles in build …
FilipeDiasTarkuss Aug 12, 2025
a1eab05
feat: user repository details page
FilipeDiasTarkuss Aug 12, 2025
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
41 changes: 41 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
193 changes: 89 additions & 104 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Teste Prático - Desenvolvedor Frontend React/Next.js

## Gitview - consulta de usuários e repositórios Github

## 🎯 Objetivo

Este teste prático tem como objetivo avaliar suas habilidades técnicas em desenvolvimento frontend, especificamente:
Expand All @@ -13,6 +15,7 @@ Este teste prático tem como objetivo avaliar suas habilidades técnicas em dese
## 📋 Especificações do Projeto

### Tecnologias Obrigatórias

- **Framework**: Next.js (versão 13+ recomendada)
- **Linguagem**: TypeScript
- **API**: GitHub Public API (`https://api.github.com`)
Expand All @@ -22,6 +25,7 @@ Este teste prático tem como objetivo avaliar suas habilidades técnicas em dese
### Funcionalidades Requeridas

#### 1. Página de Listagem de Repositórios

- **Endpoint**: `https://api.github.com/users/{username}/repos`
- **Funcionalidades**:
- Input para inserir username do GitHub
Expand All @@ -31,6 +35,7 @@ Este teste prático tem como objetivo avaliar suas habilidades técnicas em dese
- Estados de loading, erro e dados vazios

#### 2. Página de Detalhes do Repositório

- **Endpoint**: `https://api.github.com/repos/{owner}/{repo}`
- **Informações obrigatórias**:
- Nome do repositório
Expand All @@ -44,10 +49,10 @@ Este teste prático tem como objetivo avaliar suas habilidades técnicas em dese

## 🏗️ Estrutura do Projeto (Design Atômico)

Organize seu projeto seguindo rigorosamente a metodologia de Design Atômico:

```
src/
├── app/
│ └── repository/ # Página de detalhes do repositório selecionado
├── components/
│ ├── atoms/ # Elementos básicos (Button, Input, Text, Icon)
│ ├── molecules/ # Combinações de átomos (SearchBox, RepoCard)
Expand All @@ -64,144 +69,123 @@ src/
## ⚡ Requisitos Técnicos

### 1. Design Atômico
- [ ] Separação clara entre átomos, moléculas, organismos, templates e páginas
- [ ] Componentes reutilizáveis e bem documentados
- [ ] Props tipadas com TypeScript
- [ ] Storybook é um diferencial (opcional)

- [x] Separação clara entre átomos, moléculas, organismos, templates e páginas
- [x] Componentes reutilizáveis e bem documentados
- [x] Props tipadas com TypeScript
- [x] Storybook é um diferencial (opcional)

### 2. Boas Práticas React/Next.js
- [ ] Uso de Server Components quando apropriado
- [ ] Implementação de Error Boundaries
- [ ] Otimizações de performance (useMemo, useCallback quando necessário)
- [ ] SEO básico (meta tags, títulos dinâmicos)
- [ ] Responsividade mobile-first

- [x] Uso de Server Components quando apropriado
- [x] Implementação de Error Boundaries
- [x] Otimizações de performance (useMemo, useCallback quando necessário)
- [x] SEO básico (meta tags, títulos dinâmicos)
- [x] Responsividade mobile-first

### 3. Hooks do React
- [ ] **useState**: Gerenciamento de estado local
- [ ] **useEffect**: Efeitos colaterais e lifecycle
- [ ] **useContext**: Compartilhamento de estado global (se necessário)
- [ ] **Custom Hooks**: Criação de pelo menos 1 hook personalizado
- [ ] **useMemo/useCallback**: Otimizações quando apropriado

### 4. Implementação de Cache
Escolha uma das opções e implemente corretamente:
- [x] **useState**: Gerenciamento de estado local
- [x] **useEffect**: Efeitos colaterais e lifecycle
- [x] **useContext**: Compartilhamento de estado global (se necessário)
- [x] **Custom Hooks**: Criação de pelo menos 1 hook personalizado
- [x] **useMemo/useCallback**: Otimizações quando apropriado

#### Opção A: SWR
```typescript
import useSWR from 'swr'

const { data, error, isLoading } = useSWR(
`/api/users/${username}/repos`,
fetcher,
{
revalidateOnFocus: false,
dedupingInterval: 300000, // 5 minutos
}
)
```
### 4. Implementação de Cache

#### Opção B: React Query (TanStack Query)
```typescript
import { useQuery } from '@tanstack/react-query'
Escolha uma das opções e implemente corretamente:

const { data, isLoading, error } = useQuery({
queryKey: ['repos', username],
queryFn: () => fetchUserRepos(username),
staleTime: 300000, // 5 minutos
})
```
#### React Query (TanStack Query)

#### Opção C: Next.js Fetch Cache
```typescript
const repos = await fetch(`https://api.github.com/users/${username}/repos`, {
next: { revalidate: 300 } // 5 minutos
})
import { useQuery } from "@tanstack/react-query";

const {
data: user,
error: userError,
isFetching: userLoading,
} = useQuery({
queryKey: ["user", username],
queryFn: () => getGithubUser(username),
enabled: false,
});

const {
data: repositories,
error: repositoriesError,
isFetching: reposLoading,
} = useQuery({
queryKey: ["repos", username],
queryFn: () => getGithubRepositories(username),
enabled: !!user,
});
```

### 5. Testes Unitários
- [ ] **Mínimo obrigatório**:

- [x] **Mínimo obrigatório**:
- 2 componentes atômicos testados
- 1 funcionalidade principal (busca de repositórios)
- 1 custom hook testado
- [ ] **Cobertura**: Testes de renderização, interação e estados
- [ ] **Mocks**: APIs mockadas adequadamente
- [ ] **Casos de teste**: Happy path, loading, error states

## 🚀 Instruções de Entrega

### 1. Configuração do Repositório
1. Faça um fork deste repositório
2. Clone o fork para sua máquina local
3. Crie uma branch com seu nome: `feature/nome-sobrenome`
4. Desenvolva o projeto na sua branch

### 2. Desenvolvimento
1. Inicie o projeto Next.js com TypeScript
2. Configure as dependências necessárias
3. Implemente as funcionalidades seguindo os requisitos
4. Escreva os testes unitários
5. Documente o código quando necessário

### 3. Commits
**⚠️ IMPORTANTE**: Seus commits serão avaliados! Siga as boas práticas:

- Use **Conventional Commits**: `feat:`, `fix:`, `test:`, `docs:`, etc.
- Commits atômicos e descritivos
- Mensagens em português ou inglês (seja consistente)
- Exemplos:
```
feat: add search component with atomic design structure
test: add unit tests for Button atom component
feat: implement SWR cache for GitHub API calls
fix: handle error states in repository details page
docs: update README with setup instructions
```

### 4. Pull Request
Quando finalizar o desenvolvimento:

1. Push da sua branch para o fork
2. Abra um Pull Request para a branch `main` do repositório original
3. **Título do PR**: `[TESTE] Nome Completo - Desenvolvedor Frontend`

#### Template do Pull Request:
```markdown
- [x] **Cobertura**: Testes de renderização, interação e estados
- [x] **Mocks**: APIs mockadas adequadamente
- [x] **Casos de teste**: Happy path, loading, error states

````markdown
## 📝 Descrição
Breve descrição do que foi implementado.

Foi implmentado todas as funcionalidades pedidas. O design do projeto segue em um tom moderno e dark com a opção de tema light.

Como funciona: No input inicial o usuário insere o username do perfil github e, se encontrado, será mostrado dois card, um de usuário e outro com a listagem dos repositórios.

Há cobertura para caso o usuário não tenha sido encontrado, caso não tenha repositórios e caso esteja com acesso negado pela api do github.

## ✅ Checklist de Requisitos
- [ ] Design Atômico implementado
- [ ] Hooks do React utilizados adequadamente
- [ ] Cache implementado (especificar qual: SWR/React Query/Next.js)
- [ ] Testes unitários incluídos
- [ ] TypeScript configurado
- [ ] Responsividade implementada

- [x] Design Atômico implementado
- [x] Hooks do React utilizados adequadamente
- [x] Cache implementado (especificar qual: SWR/React Query/Next.js)
- [x] Testes unitários incluídos
- [x] TypeScript configurado
- [x] Responsividade implementada

## 🧪 Testes
- Total de testes: X
- Componentes testados: [listar]
- Hooks testados: [listar]
- Cobertura estimada: X%

- Total de testes: 9
- Componentes testados: [button, input]
- Hooks testados: [userSearchFilter]
- Cobertura estimada: 100%

## 🚀 Como executar

```bash
# Comandos para instalar e executar
npm install
npm run dev
npm run test
```
````

## 📱 Screenshots
[Adicione capturas de tela da aplicação funcionando]

![Logo do projeto](./public/images/home.png)
![Logo do projeto](./public/images/userfound.png)
![Logo do projeto](./public/images/repo.png)

## 🔧 Decisões Técnicas

Explique brevemente suas principais decisões arquiteturais:
- Por que escolheu determinada biblioteca de cache
- Como organizou os componentes atômicos
- Desafios encontrados e soluções

- **Por que escolheu determinada biblioteca de cache**: Já utilizo as bibliotecas e extensões da Tanstack em muitos projetos com NextJs, então possuindo familiridade resolvi adota-la. O funcionado o gerenciamento de dados em cache e as atualizações sem alteração na arvore inteira ou ate mesmo em todo os dados de um objeto/array são um fator crucial.

- **Como organizou os componentes atômicos**: Eu utilizei a biblioteca ShadcnUI para ter os atoms, a base de componentes, com algumas adaptações particulares do meu projeto, como as estilizações e comportamento do input. Criei as molecules com a junção de atoms e/ou funcionalidades, usando o conceito de reusabilidade. Os organisms são os componentes mais completos e únicos que muitas vezes são client-side para não compromenter o carregamento server-side da página principal.

- **Desafios encontrados e soluções**: Encontrar uma forma de fazer que tenha uma chamada server-side nesse desafio, a única chamada server-side que foi implementada com utilidade foi a da página de detalhes do repositório. A estruturação em "componentes atômicos" também foi algo novo, até então não utilizei esse tipo de design patterns.

## ⏱️ Tempo Investido
Aproximadamente X horas

Aproximadamente 10 horas

```

## 📏 Critérios de Avaliação
Expand Down Expand Up @@ -254,3 +238,4 @@ Aproximadamente X horas
**Boa sorte! 🚀**

Estamos ansiosos para ver sua solução e conhecer seu estilo de desenvolvimento!
```
21 changes: 21 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/atoms",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
16 changes: 16 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
baseDirectory: __dirname,
});

const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
];

export default eslintConfig;
Loading