O TFC
é um site informativo sobre partidas e classificações de futebol! ⚽️
No time de desenvolvimento do TFC
, utilizei TDD para como boa prática de desenvolvimento.
Nesse projeto, utilizei um back-end dockerizado utilizando modelagem de dados através do Sequelize.
Para adicionar uma partida é necessário ter um token, portanto a pessoa deverá estar logada para fazer as alterações.
🔰 Iniciando o projeto
- Clone o repositório
*
git clone git@github.com:tryber/sd-017-trybe-futebol-clube.git
.
-
Entre na pasta do repositório que você acabou de clonar:
cd sd-017-trybe-futebol-clube
-
Em seguida, entre na pasta app:
cd app
-
Em seguida, entre na pasta backend:
cd backend
- Instale as dependências [Caso existam]
*
npm install
Na sua máquina você deve ter:
- Sistema Operacional Distribuição Unix
- Node versão 16
- Docker
- Docker-compose versão >=1.29.2
➡️ O node
deve ter versão igual ou superior à 16.15.0 LTS
:
- Para instalar o nvm, acesse esse link;
- Rode os comandos abaixo para instalar a versão correta de node
e usá-la:
- nvm install 16 --lts
- nvm use 16
- nvm alias default 16
➡️ Odocker-compose
deve ter versão igual ou superior àˆ1.29.2
:
* Use esse link de referência para realizar a instalação corretamente no ubuntu;
* Acesse o [link da documentação oficial com passos para desinstalar] (https://docs.docker.com/compose/install/#uninstallation) caso necessário.
⚠️ Inicialização do compose e verificação dos logs das aplicações
- Para isso, garanta que as aplicações, tanto do back, quanto do front-end, possuem arquivos
Dockerfile
válidos; - Utilize os scripts de apoio
npm run compose:up
/npm run compose:down
, para facilitar a execução do seu compose.
⚙️ Variáveis de ambiente
No diretório app/backend/
renomeie o arquivo .env.example
para .env
e configure os valores de acordo com o cenário do seu ambiente (credenciais de banco de dados, secrets desejadas e etc). Isso vai permitir que você inicialize a aplicação fora do container e ela se conecte com seu banco local caso deseje.
./app/backend/.env.example
JWT_SECRET=jwt_secret
APP_PORT=3001
DB_USER=seu_user
DB_PASS=sua_senha
DB_HOST=localhost
DB_PORT=3306
TRYBE_FUTEBOL_CLUBE
.
Rotas
Esse projeto é composto de 4 seções principais:
- User e Login
- Times
- Partidas
- Placar
-
A rota utilizada deve ser (
/login
); -
A rota deve receber os campos
email
epassword
e esses campos devem ser validados no banco de dados:- O campo
email
deve receber um email válido; - O Campo
password
deve ter mais de 6 caracteres.
- O campo
-
O body da requisição deve conter o seguinte formato:
{ "email": "string", "password": "string" }
⚠️ Todos os campos abaixo devem estar preenchidos e de forma adequado, caso contrário será retornado um erro descrevendo o problema.
-
O avaliador verificará se é possível fazer o login com dados corretos e que, após o acesso, será redirecionado para a tela de jogos.
-
Se o login foi feito com sucesso, o resultado retornado deverá ser similar ao exibido abaixo, com um status http
200
:{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjU0NTI3MTg5fQ.XS_9AA82iNoiVaASi0NtJpqOQ_gHSHhxrpIdigiT-fc" // Aqui deve ser o token gerado pelo backend. }
-
Essat rota deve receber um
header
com parâmetroauthorization
, onde ficará armazenado o token gerado no login, vc pode conseguir esse token na rota/login
; -
O avaliador verificará se ao tentar bater na rota com um token válido, o mesmo retornará o tipo de usuário.
A resposta deve ser de status 200
com um objeto
contendo a role
do user:
{ "role": "admin" }
- Resposta com status
200
e com umjson
contendo o retorno no seguinte modelo:
[
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
{
"id": 2,
"teamName": "Bahia"
},
{
"id": 3,
"teamName": "Botafogo"
},
...
]
- Resposta com status
200
e com umjson
contendo o retorno no seguinte modelo:
{
"id": 5,
"teamName": "Cruzeiro"
}
Exemplo de retorno:
```json
[
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 1,
"awayTeam": 8,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Grêmio"
}
},
...
{
"id": 41,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 9,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Internacional"
}
}
]
```
- Essa requisição deverá usar
query string
para definir o parâmetro: ex:matches?inProgress=true
Exemplo de retorno da requisição:
[
{
"id": 41,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 9,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Internacional"
}
},
{
"id": 42,
"homeTeam": 6,
"homeTeamGoals": 1,
"awayTeam": 1,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "Ferroviária"
},
"teamAway": {
"teamName": "Avaí/Kindermann"
}
}
]
- Essa requisição deverá usar
query string
para definir o parâmetro. ex:matches?inProgress=false
Exemplo de retorno da requisição:
[
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 1,
"awayTeam": 8,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Grêmio"
}
},
{
"id": 2,
"homeTeam": 9,
"homeTeamGoals": 1,
"awayTeam": 14,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "Internacional"
},
"teamAway": {
"teamName": "Santos"
}
}
]
8 - O endpoint /matches
com método POST
salva uma partida com o status de inProgress como true no banco de dados
-
Retornar a partida inserida no banco de dados;
-
O corpo da requisição terá o seguinte formato:
{
"homeTeam": 16,
"awayTeam": 8,
"homeTeamGoals": 2,
"awayTeamGoals": 2
}
- Caso a partida seja inserida com sucesso, deve-se retornar os dados da partida, com status
201
:
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 8,
"awayTeamGoals": 2,
"inProgress": true,
}
9 - O endpoint /matches/:id/finish
com método PATCH
altera o status de inProgress para false no banco de dados
-
Será recebido o
id
pelo parâmetro da URL; -
Deve-se retornar, com um status
200
, a seguinte mensagem:
{ "message": "Finished" }
-
O endpoint deve ser do tipo
PATCH
; -
Será recebido o
id
pelo parâmetro da URL; -
O corpo da requisição terá o seguinte formato:
{
"homeTeamGoals": 3,
"awayTeamGoals": 1
}
Retorno esperado:
[
{
name: 'Santos',
totalPoints: '9',
totalGames: '3',
totalVictories: '3',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '9',
goalsOwn: '3',
goalsBalance: '6',
efficiency: '100'
},
{
name: 'Palmeiras',
totalPoints: '7',
totalGames: '3',
totalVictories: '2',
totalDraws: '1',
totalLosses: '0',
goalsFavor: '10',
goalsOwn: '5',
goalsBalance: '5',
efficiency: '77.78'
},
{
name: 'Corinthians',
totalPoints: '6',
totalGames: '2',
totalVictories: '2',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '6',
goalsOwn: '1',
goalsBalance: '5',
efficiency: '100'
},
{
name: 'Grêmio',
totalPoints: '6',
totalGames: '2',
totalVictories: '2',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '4',
goalsOwn: '1',
goalsBalance: '3',
efficiency: '100'
},
{
name: 'Real Brasília',
totalPoints: '6',
totalGames: '2',
totalVictories: '2',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '2',
goalsOwn: '0',
goalsBalance: '2',
efficiency: '100'
},
{
name: 'São Paulo',
totalPoints: '4',
totalGames: '2',
totalVictories: '1',
totalDraws: '1',
totalLosses: '0',
goalsFavor: '4',
goalsOwn: '1',
goalsBalance: '3',
efficiency: '66.67'
},
{
name: 'Internacional',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '4',
goalsOwn: '6',
goalsBalance: '-2',
efficiency: '44.44'
},
{
name: 'Botafogo',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '2',
goalsOwn: '4',
goalsBalance: '-2',
efficiency: '44.44'
},
{
name: 'Ferroviária',
totalPoints: '3',
totalGames: '2',
totalVictories: '1',
totalDraws: '0',
totalLosses: '1',
goalsFavor: '3',
goalsOwn: '2',
goalsBalance: '1',
efficiency: '50'
},
{
name: 'Napoli-SC',
totalPoints: '2',
totalGames: '2',
totalVictories: '0',
totalDraws: '2',
totalLosses: '0',
goalsFavor: '2',
goalsOwn: '2',
goalsBalance: '0',
efficiency: '33.33'
},
{
name: 'Cruzeiro',
totalPoints: '1',
totalGames: '2',
totalVictories: '0',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '2',
goalsOwn: '3',
goalsBalance: '-1',
efficiency: '16.67'
},
{
name: 'Flamengo',
totalPoints: '1',
totalGames: '2',
totalVictories: '0',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '1',
goalsOwn: '2',
goalsBalance: '-1',
efficiency: '16.67'
},
{
name: 'Minas Brasília',
totalPoints: '1',
totalGames: '3',
totalVictories: '0',
totalDraws: '1',
totalLosses: '2',
goalsFavor: '3',
goalsOwn: '6',
goalsBalance: '-3',
efficiency: '11.11'
},
{
name: 'Avaí/Kindermann',
totalPoints: '1',
totalGames: '3',
totalVictories: '0',
totalDraws: '1',
totalLosses: '2',
goalsFavor: '3',
goalsOwn: '7',
goalsBalance: '-4',
efficiency: '11.11'
},
{
name: 'São José-SP',
totalPoints: '0',
totalGames: '3',
totalVictories: '0',
totalDraws: '0',
totalLosses: '3',
goalsFavor: '2',
goalsOwn: '5',
goalsBalance: '-3',
efficiency: '0'
},
{
name: 'Bahia',
totalPoints: '0',
totalGames: '3',
totalVictories: '0',
totalDraws: '0',
totalLosses: '3',
goalsFavor: '0',
goalsOwn: '4',
goalsBalance: '-4',
efficiency: '0'
}
]
Retorno esperado:
[
{
name: 'Palmeiras',
totalPoints: '6',
totalGames: '2',
totalVictories: '2',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '7',
goalsOwn: '0',
goalsBalance: '7',
efficiency: '100'
},
{
name: 'Corinthians',
totalPoints: '6',
totalGames: '3',
totalVictories: '2',
totalDraws: '0',
totalLosses: '1',
goalsFavor: '6',
goalsOwn: '2',
goalsBalance: '4',
efficiency: '66.67'
},
{
name: 'Internacional',
totalPoints: '6',
totalGames: '2',
totalVictories: '2',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '3',
goalsOwn: '0',
goalsBalance: '3',
efficiency: '100'
},
{
name: 'São José-SP',
totalPoints: '6',
totalGames: '2',
totalVictories: '2',
totalDraws: '0',
totalLosses: '0',
goalsFavor: '3',
goalsOwn: '1',
goalsBalance: '2',
efficiency: '100'
},
{
name: 'São Paulo',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '5',
goalsOwn: '5',
goalsBalance: '0',
efficiency: '44.44'
},
{
name: 'Ferroviária',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '4',
goalsOwn: '5',
goalsBalance: '-1',
efficiency: '44.44'
},
{
name: 'Real Brasília',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '3',
goalsOwn: '4',
goalsBalance: '-1',
efficiency: '44.44'
},
{
name: 'Grêmio',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '5',
goalsOwn: '7',
goalsBalance: '-2',
efficiency: '44.44'
},
{
name: 'Flamengo',
totalPoints: '4',
totalGames: '3',
totalVictories: '1',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '1',
goalsOwn: '3',
goalsBalance: '-2',
efficiency: '44.44'
},
{
name: 'Avaí/Kindermann',
totalPoints: '3',
totalGames: '2',
totalVictories: '1',
totalDraws: '0',
totalLosses: '1',
goalsFavor: '1',
goalsOwn: '1',
goalsBalance: '0',
efficiency: '50'
},
{
name: 'Cruzeiro',
totalPoints: '3',
totalGames: '3',
totalVictories: '1',
totalDraws: '0',
totalLosses: '2',
goalsFavor: '6',
goalsOwn: '7',
goalsBalance: '-1',
efficiency: '33.33'
},
{
name: 'Santos',
totalPoints: '2',
totalGames: '2',
totalVictories: '0',
totalDraws: '2',
totalLosses: '0',
goalsFavor: '3',
goalsOwn: '3',
goalsBalance: '0',
efficiency: '33.33'
},
{
name: 'Bahia',
totalPoints: '2',
totalGames: '2',
totalVictories: '0',
totalDraws: '2',
totalLosses: '0',
goalsFavor: '2',
goalsOwn: '2',
goalsBalance: '0',
efficiency: '33.33'
},
{
name: 'Minas Brasília',
totalPoints: '1',
totalGames: '2',
totalVictories: '0',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '1',
goalsOwn: '3',
goalsBalance: '-2',
efficiency: '16.67'
},
{
name: 'Botafogo',
totalPoints: '0',
totalGames: '2',
totalVictories: '0',
totalDraws: '0',
totalLosses: '2',
goalsFavor: '1',
goalsOwn: '4',
goalsBalance: '-3',
efficiency: '0'
},
{
name: 'Napoli-SC',
totalPoints: '0',
totalGames: '3',
totalVictories: '0',
totalDraws: '0',
totalLosses: '3',
goalsFavor: '1',
goalsOwn: '10',
goalsBalance: '-9',
efficiency: '0'
}
]
Retorno esperado:
[
{
name: 'Palmeiras',
totalPoints: '13',
totalGames: '5',
totalVictories: '4',
totalDraws: '1',
totalLosses: '0',
goalsFavor: '17',
goalsOwn: '5',
goalsBalance: '12',
efficiency: '86.67',
},
{
name: 'Corinthians',
totalPoints: '12',
totalGames: '5',
totalVictories: '4',
totalDraws: '0',
totalLosses: '1',
goalsFavor: '12',
goalsOwn: '3',
goalsBalance: '9',
efficiency: '80',
},
{
name: 'Santos',
totalPoints: '11',
totalGames: '5',
totalVictories: '3',
totalDraws: '2',
totalLosses: '0',
goalsFavor: '12',
goalsOwn: '6',
goalsBalance: '6',
efficiency: '73.33',
},
{
name: 'Grêmio',
totalPoints: '10',
totalGames: '5',
totalVictories: '3',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '9',
goalsOwn: '8',
goalsBalance: '1',
efficiency: '66.67',
},
{
name: 'Internacional',
totalPoints: '10',
totalGames: '5',
totalVictories: '3',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '7',
goalsOwn: '6',
goalsBalance: '1',
efficiency: '66.67',
},
{
name: 'Real Brasília',
totalPoints: '10',
totalGames: '5',
totalVictories: '3',
totalDraws: '1',
totalLosses: '1',
goalsFavor: '5',
goalsOwn: '4',
goalsBalance: '1',
efficiency: '66.67',
},
{
name: 'São Paulo',
totalPoints: '8',
totalGames: '5',
totalVictories: '2',
totalDraws: '2',
totalLosses: '1',
goalsFavor: '9',
goalsOwn: '6',
goalsBalance: '3',
efficiency: '53.33',
},
{
name: 'Ferroviária',
totalPoints: '7',
totalGames: '5',
totalVictories: '2',
totalDraws: '1',
totalLosses: '2',
goalsFavor: '7',
goalsOwn: '7',
goalsBalance: '0',
efficiency: '46.67',
},
{
name: 'São José-SP',
totalPoints: '6',
totalGames: '5',
totalVictories: '2',
totalDraws: '0',
totalLosses: '3',
goalsFavor: '5',
goalsOwn: '6',
goalsBalance: '-1',
efficiency: '40',
},
{
name: 'Flamengo',
totalPoints: '5',
totalGames: '5',
totalVictories: '1',
totalDraws: '2',
totalLosses: '2',
goalsFavor: '2',
goalsOwn: '5',
goalsBalance: '-3',
efficiency: '33.33',
},
{
name: 'Cruzeiro',
totalPoints: '4',
totalGames: '5',
totalVictories: '1',
totalDraws: '1',
totalLosses: '3',
goalsFavor: '8',
goalsOwn: '10',
goalsBalance: '-2',
efficiency: '26.67',
},
{
name: 'Avaí/Kindermann',
totalPoints: '4',
totalGames: '5',
totalVictories: '1',
totalDraws: '1',
totalLosses: '3',
goalsFavor: '4',
goalsOwn: '8',
goalsBalance: '-4',
efficiency: '26.67',
},
{
name: 'Botafogo',
totalPoints: '4',
totalGames: '5',
totalVictories: '1',
totalDraws: '1',
totalLosses: '3',
goalsFavor: '3',
goalsOwn: '8',
goalsBalance: '-5',
efficiency: '26.67',
},
{
name: 'Bahia',
totalPoints: '2',
totalGames: '5',
totalVictories: '0',
totalDraws: '2',
totalLosses: '3',
goalsFavor: '2',
goalsOwn: '6',
goalsBalance: '-4',
efficiency: '13.33',
},
{
name: 'Minas Brasília',
totalPoints: '2',
totalGames: '5',
totalVictories: '0',
totalDraws: '2',
totalLosses: '3',
goalsFavor: '4',
goalsOwn: '9',
goalsBalance: '-5',
efficiency: '13.33',
},
{
name: 'Napoli-SC',
totalPoints: '2',
totalGames: '5',
totalVictories: '0',
totalDraws: '2',
totalLosses: '3',
goalsFavor: '3',
goalsOwn: '12',
goalsBalance: '-9',
efficiency: '13.33',
},
];