O TFC
é um site informativo sobre partidas e classificações de futebol! ⚽️
Nesse projeto, existe um back-end usando TypeScript, Node.js, docker e também utilizando modelagem de dados através do Sequelize.respeitando as regras de negócio, e com a API sendo consumida por um front-end do projeto.
Para adicionar uma partida é necessário ter um token, portanto a pessoa deverá estar logada para fazer as alterações. O back-end implementa regras de negócio para popular adequadamente a tabela disponível no front-end que será exibida para o usuário do sistema.
Estrutura do projeto
O projeto é composto de 4 entidades importantes para sua estrutura:
1️⃣ Banco de dados:
- Será um container docker MySQL já configurado no docker-compose através de um serviço definido como
db
. - Tem o papel de fornecer dados para o serviço de backend.
- Você também pode conectar a um Cliente MySQL (Workbench, Beekeeper, DBeaver e etc), colocando as credenciais configuradas no docker-compose no serviço
db
.
2️⃣ Back-end:
- Deve rodar na porta
3001
, pois o front-end faz requisições para ele nessa porta por padrão; - A aplicação deve ser inicializada a partir do arquivo
app/backend/src/server.ts
;
3️⃣ Front-end:
- O front se comunica com serviço de back-end pela url
http://localhost:3001
através dos endpoints.
4️⃣ Docker:
- O
docker-compose
tem a responsabilidade de unir todos os serviços conteinerizados (backend, frontend e db) e subir o projeto completo com o comandonpm run compose:up
ounpm run compose:up:dev
;
Iniciando o projeto
- Clone o repositório
git clone git@github.com:MarcleyRosa/TFC.git
-
Entre na pasta do repositório que você acabou de clonar:
cd TFC
- Instale as dependências
*
npm install
Configurações mínimas para execução do projeto
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.14.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.14 --lts
nvm use 16.14
nvm alias default 16.14
➡️ 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 caso necessário.
Configuração Docker
⚠ O docker-compose precisa estar na versão 1.29 ou superior. ⚠ Veja aqui a documentação para atualizar o docker-compose.
-
O arquivo
docker-compose.yml
também pode ser utilizado para executar a aplicação na sua máquina local, para isso é necessário executar o comandonpm run compose:up
na raiz do projeto. -
Obs.: Se você quiser fazer o build da aplicação usando o
docker-compose.dev.yml
, você pode usar o comando:npm run compose:up:dev -- --build
.
Inicialização do compose e verificação dos logs das aplicações
- Considerando o uso do parâmetro
healthcheck
em cada container do seudocker-compose.yml
, a inicialização dos containers deve aguardar o comando de status de saúde (o que valida se aquele container está operacional ou não):- No container
db
, representado por um comandoping
no banco de dados; - No back-end, representado por um comando
lsof
, que vai procurar aplicações ativas na porta definida (por padrão, no caso3001
); - No front-end, representado por um comando
lsof
, que vai procurar aplicações ativas na porta definida (por padrão, no caso3000
).
- No container
sempre considerando as premissas anteriores.
- Nesse caso, a partir da pasta
./app
(onde está seu docker-compose), é possível rodar o comandodocker-compose logs
(Para ver todos os status) oudocker-compose logs <nome-do-seu-serviço>
(Para mostrar somente o de um escopo específico).- No nosso contexto, rodando o comando
docker-compose logs backend
:
- No nosso contexto, rodando o comando
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
Sequelize
package.json
do diretório app/backend
contém um script db:reset
que é responsável por "dropar" o banco, recriar e executar as migrations e seeders. Você pode executá-lo com o commando npm run db:reset
se por algum motivo precisar recriar a base de dados;
Testes de cobertura
Para rodar testes de cobertura no seu back-end, utilize o comando: npm run test:coverage
.
- Comece rodando o comando
npm run build
na pasta doback-end
para fazer o build da aplicação;
Introdução
-
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" }
Introdução
- O consumo da rota
/teams
retorna os nomes dos times associados à partida na renderização do front-end
Exemplos de Retorno
[
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
{
"id": 2,
"teamName": "Bahia"
},
{
"id": 3,
"teamName": "Botafogo"
},
...
]
{
"id": 5,
"teamName": "Cruzeiro"
}
Introdução
-
Será validado que, ao escolher a opção de partidas em andamento, serão filtradas todas as partidas em andamento;
-
Essa requisição deverá usar
query string
para definir o parâmetro: ex:matches?inProgress=true
Exemplos de Retorno
Exemplo de retorno da requisição:
[
{
"id": 41,
"homeTeamId": 16,
"homeTeamGoals": 2,
"awayTeamId": 9,
"awayTeamGoals": 0,
"inProgress": true,
"homeTeam": {
"teamName": "São Paulo"
},
"awayTeam": {
"teamName": "Internacional"
}
},
{
"id": 42,
"homeTeamId": 6,
"homeTeamGoals": 1,
"awayTeamId": 1,
"awayTeamGoals": 0,
"inProgress": true,
"homeTeam": {
"teamName": "Ferroviária"
},
"awayTeam": {
"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,
"homeTeamId": 16,
"homeTeamGoals": 1,
"awayTeamId": 8,
"awayTeamGoals": 1,
"inProgress": false,
"homeTeam": {
"teamName": "São Paulo"
},
"awayTeam": {
"teamName": "Grêmio"
}
},
{
"id": 2,
"homeTeamId": 9,
"homeTeamGoals": 1,
"awayTeamId": 14,
"awayTeamGoals": 1,
"inProgress": false,
"homeTeam": {
"teamName": "Internacional"
},
"awayTeam": {
"teamName": "Santos"
}
}
]
-
A partida só pode ser criada com token JWT validado;
-
O corpo da requisição terá o seguinte formato:
{
"homeTeamId": 16, // O valor deve ser o id do time
"awayTeamId": 8, // O valor deve ser o id do time
"homeTeamGoals": 2,
"awayTeamGoals": 2,
}
- Retorno caso a partida seja inserida com sucesso:
{
"id": 1,
"homeTeamId": 16,
"homeTeamGoals": 2,
"awayTeamId": 8,
"awayTeamGoals": 2,
"inProgress": true,
}
-
Será recebido o
id
pelo parâmetro da URL; -
O corpo da requisição terá o seguinte formato:
{
"homeTeamGoals": 3,
"awayTeamGoals": 1
}
Introdução
- `Classificação`: Posição na classificação;
- `Time`: Nome do time;
- `P`: Total de Pontos;
- `J`: Total de Jogos;
- `V`: Total de Vitórias;
- `E`: Total de Empates;
- `D`: Total de Derrotas;
- `GP`: Gols marcados a favor;
- `GC`: Gols sofridos;
- `SG`: Saldo total de gols;
- `%`: Aproveitamento do time.
Ordem para desempate
1º Total de Vitórias;
2º Saldo de gols;
3º Gols a favor;
4º Gols sofridos.
- Os endpoints dessa seção, irão alimentar uma tabela idêntica ao exemplo abaixo no front-end:
| Classificação | Time | P | J | V | E | D | GP | GC | SG | % |
| ------------- | ----------- | --- | --- | --- | --- | --- | --- | --- | --- | ---- |
| 1 | Ferroviária | 38 | 15 | 12 | 2 | 1 | 44 | 13 | 31 | 84.4 |
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
},
...
]