Project Trybe Soccer Club
In this repository there is a Full Stack application, from back-end to front-end, and the front-end was developed by Trybe. I was responsible for the development of the API (using TDD), database and application integration through docker-compose.
The API was developed using TypeScript following the principles of SOLID and POO, Sequelize for data modeling, sinon and chai for creation and test stubs.
Demonstration
Functionalities
- Login
- View a table with all teams and their rankings
- Filter sorting by home or visitor
- View matches in progress or finished
- Filters matches that are in progress or finished
Running locally
Clone the project
git clone git@github.com:lucas-da-silva/project-trybe-soccer-club.git
Enter the project directory
cd project-trybe-soccer-club
Upload the containers e install the dependencies (required docker-compose)
npm run compose:up
The frontend is configured for port: 3000
Stop the containers
npm run compose:down
Running the tests
Enter the backend container with the following command
docker exec -it app_backend sh
Running the tests
npm test
API documentation
Returns a login token
POST /login
Request body
{
"email": "user@user.com", // Be valid and in the database
"password": "secret_user", // Size greater than 6 and match the email
}
Response body
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjU0NTI3MTg5fQ.XS_9AA82iNoiVaASi0NtJpqOQ_gHSHhxrpIdigiT-fc" // Token generated.
}
Returns role
GET /login/validate
In the header
Authorization | token (created in the previous route) |
---|
Response body
{ "role": "admin" }
Returns all teams
GET /teams
Response body
[
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
...
]
Returns a team
GET /teams/${id}
Parameter | Type | Description |
---|---|---|
id |
number |
Required. The ID to time you want |
Response body
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
Returns all matches including team name
GET /matches
This route can use query string as a parameter
Parameter | Type | Description |
---|---|---|
inProgress |
boolean |
Optional. Used to filter ongoing (true ) or finished (false ) matches |
Response body
[
{
"id": 1,
"homeTeamId": 16,
"homeTeamGoals": 1,
"awayTeamId": 8,
"awayTeamGoals": 1,
"inProgress": false,
"homeTeam": {
"teamName": "São Paulo"
},
"awayTeam": {
"teamName": "Grêmio"
}
},
...
]
Create a new match
POST /matches
In the header
Authorization | token (created in POST /login ) |
---|
Request body
{
"homeTeamId": 16, // The value must be the team id
"awayTeamId": 8, // The value must be the team id
"homeTeamGoals": 2,
"awayTeamGoals": 2
}
Response body
{
"id": 1,
"homeTeamId": 16,
"homeTeamGoals": 2,
"awayTeamId": 8,
"awayTeamGoals": 2,
"inProgress": true
}
Update matches in progress
PATCH /matches/${id}
Parameter | Type | Description |
---|---|---|
id |
number |
Required. The match ID you want to update |
Request boby
{
"homeTeamGoals": 3,
"awayTeamGoals": 1
}
Response body
{ "message": "Updated" }
Finish a match
PATCH /matches/${id}/finished
Parameter | Type | Description |
---|---|---|
id |
number |
Required. The ID of the match you want to end |
Response body
{ "message": "Finished" }
Team ranking
GET /leaderboard
Response body
[
{
"name": "Palmeiras",
"totalPoints": 13,
"totalGames": 5,
"totalVictories": 4,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 17,
"goalsOwn": 5,
"goalsBalance": 12,
"efficiency": "86.67"
},
...
]
Ranking of teams with home games
GET /leaderboard/home
Response body
[
{
"name": "Santos",
"totalPoints": 9,
"totalGames": 3,
"totalVictories": 3,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 9,
"goalsOwn": 3,
"goalsBalance": 6,
"efficiency": "100.00"
},
...
]
Ranking of teams with away games
GET /leaderboard/away
Response body
[
{
"name": "Palmeiras",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 7,
"goalsOwn": 0,
"goalsBalance": 7,
"efficiency": "100.00"
},
...
]
Stack used
Full-stack: Docker
Back-end: Typescript, Express, Sequelize, Sinon.JS, Chai, JWT, bcrypt
Database: MySQL