Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FullStack Challenge - Franklin Martins #5

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/node_modules
6 changes: 6 additions & 0 deletions backend/.sequelizerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const path = require('path')

module.exports = {
config: path.resolve(__dirname, "src", "config", "database.js"),
'migrations-path': path.resolve(__dirname, "src", "database", "migrations")
};
244 changes: 244 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
# Maxxidata FullsTack Challenge

# Tecnologias utilizadas

- **PostgreSQL**: Banco de dados SQL;
- **Node.js**: v14.15.4
- **Sequelize**: ORM para construção, modelagem e manipulação do banco de dados;
- **Express**:Framework para aplicações web super flexível e robusto;

## Requisitos e comandos para funcionar na sua máquina

É necessário ter um banco postgres rodando no localhost, de preferência na porta 5432

- Node.js v12+

```bash
$ yarn
```

```bash
$ yarn sequelize db:migrate
```

```bash
$ yarn dev:server
```

# API

## Rotas

### Tipos de Profissionais

:large_blue_circle: `GET /types-of-professionals`

Retorno: HTTP 200

```json
[
{
"id": "ec6c1f19-ca13-494b-b6fb-237276de69dc",
"description": "DESENVOLVEDOR FULL STACK",
"createdAt": "2021-03-10T18:32:05.616Z",
"updatedAt": "2021-03-11T17:38:16.685Z",
"type": [
{
"id": "c770b7a4-0db0-4a5b-9efd-c6039af4684f",
"name": "Franklin",
"phone": "92 1122-3344"
}
]
}
]
```

:large_blue_circle: `GET /types-of-professionals/:id`

Retorno: HTTP 200

```json
{
"id": "ec6c1f19-ca13-494b-b6fb-237276de69dc",
"description": "DESENVOLVEDOR FULL STACK",
"createdAt": "2021-03-10T18:32:05.616Z",
"updatedAt": "2021-03-11T17:38:16.685Z",
"type": [
{
"id": "c770b7a4-0db0-4a5b-9efd-c6039af4684f",
"name": "Franklin"
}
]
}
```

:large_blue_circle: `POST /types-of-professionals`

Corpo da requisição:

```json
{
"type_of_professional": "..."
}
```

Retorno: HTTP 201

```json
{
"id": "b7d3f658-4f70-4b0e-93b0-c31610fbf5de",
"description": "ENGENHEIRO DE TESTES",
"updatedAt": "2021-03-13T14:16:48.002Z",
"createdAt": "2021-03-13T14:16:48.002Z"
}
```

:large_blue_circle: `PUT /types-of-professionals/:id`

Corpo da requisição:

```json
{
"type_of_professional": "..."
}
```

Retorno: HTTP 200

```json
{
"id": "b7d3f658-4f70-4b0e-93b0-c31610fbf5de",
"description": "ENGENHEIRO DE TESTES",
"updatedAt": "2021-03-13T14:16:48.002Z",
"createdAt": "2021-03-13T14:16:48.002Z"
}
```

:large_blue_circle: `DELETE /types-of-professionals/:id`

Retorno: HTTP 204 (Sem conteúdo)

### Profissionais

:large_blue_circle: `GET /professionals`

Retorno: HTTP 200

```json
[
{
"id": "c770b7a4-0db0-4a5b-9efd-c6039af4684f",
"name": "Franklin",
"email": "[email protected]",
"phone": "92 1122-3344",
"situation": true,
"createdAt": "2021-03-10T19:19:39.802Z",
"updatedAt": "2021-03-10T20:17:33.992Z",
"type_of_professional": "ec6c1f19-ca13-494b-b6fb-237276de69dc",
"type": {
"description": "DESENVOLVEDOR FULL STACK"
}
},
{
"id": "1be5fb78-33d5-4e70-94a9-ad57820e634e",
"name": "Geovana",
"email": "[email protected]",
"phone": "55 45952 8855",
"situation": true,
"createdAt": "2021-03-13T16:26:23.365Z",
"updatedAt": "2021-03-13T16:26:23.365Z",
"type_of_professional": "5943b984-b8cd-4191-ba76-108f8cc04a13",
"type": {
"description": "DESENVOLVEDOR MOBILE"
}
}
]
```

:large_blue_circle: ​`GET /professionals/:id`

Retorno: HTTP 200

```json
{
"id": "c770b7a4-0db0-4a5b-9efd-c6039af4684f",
"name": "Franklin",
"email": "[email protected]",
"phone": "92 1122-3344",
"situation": true,
"createdAt": "2021-03-10T19:19:39.802Z",
"updatedAt": "2021-03-10T20:17:33.992Z",
"type_of_professional": "ec6c1f19-ca13-494b-b6fb-237276de69dc",
"type": {
"description": "DESENVOLVEDOR FULL STACK"
}
}
```

:large_blue_circle: ​`POST /professionals`

Corpo da requisição:

```json
{
"name": "Jefferson",
"email": "[email protected]",
"phone": "92 4545 4545",
"type_of_professional": "engenheiro de testes",
"situation": true
}
```

Retorno: HTTP 201

```json
{
"id": "6ef889bb-7b1b-45c8-b19f-da6126fefd05",
"name": "Jefferson",
"email": "[email protected]",
"phone": "92 4545 4545",
"situation": true,
"createdAt": "2021-03-13T17:45:22.767Z",
"updatedAt": "2021-03-13T17:45:22.767Z",
"type_of_professional": "b7d3f658-4f70-4b0e-93b0-c31610fbf5de",
"type": {
"description": "ENGENHEIRO DE TESTES"
}
}
```

:large_blue_circle: ​`PUT /professionals/:id`

Corpo da requisição:

```json
{
"name": "Franklin",
"email": "[email protected]",
"phone": "92 91122-3344",
"type_of_professional": "FullStack",
"situation": true
}
```

Retorno: HTTP 200

```json
{
"id": "6ef889bb-7b1b-45c8-b19f-da6126fefd05",
"name": "Franklin",
"email": "[email protected]",
"phone": "92 91122-3344",
"situation": true,
"createdAt": "2021-03-13T17:45:22.767Z",
"updatedAt": "2021-03-13T17:45:22.767Z",
"type_of_professional": "b7d3f658-4f70-4b0e-93b0-c31610fbf5de",
"type": {
"description": "FULLSTACK"
}
}
```

:large_blue_circle: ​`DELETE /professionals/:id`

Retorno: HTTP 204 (Sem conteúdo)
24 changes: 24 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "backend",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev:server": "nodemon src/server.js"
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"pg": "^8.5.1",
"pg-hstore": "^2.3.3",
"sequelize": "^6.5.0",
"swagger-jsdoc": "6.0.0",
"swagger-ui-express": "^4.1.6",
"uuid": "^8.3.2",
"uuidv4": "^6.2.6"
},
"devDependencies": {
"nodemon": "^2.0.7",
"sequelize-cli": "^6.2.0"
}
}
12 changes: 12 additions & 0 deletions backend/src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const express = require('express');
const routes = require('./routes/index.routes');
const cors = require('cors');
require('./database');

const app = express();

app.use(cors())
app.use(express.json());
app.use('/',routes);

module.exports = app
11 changes: 11 additions & 0 deletions backend/src/config/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
dialect: 'postgres',
host: 'localhost',
username: 'postgres',
password: 'docker',
database: 'maxxidata',
define: {
timestamps: true,
underscored: true
}
}
81 changes: 81 additions & 0 deletions backend/src/controllers/ProfessionalsController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const Professional = require('../models/Professional')
const TypeOfProfessional = require('../models/TypeOfProfessional')


class ProfessionalsController {
async index(request, response){
const { id } = request.params;

try {
const professional = await Professional.findByPk(id, {
include: { association: 'type', attributes: ['description'] }
});

return response.status(200).json(professional)
} catch (error) {
return response.status(404).json({message: 'Could not find Professional'});
}
}
async show(request, response){
const professionals = await Professional.findAll({
include: { association: 'type', attributes: ['description'] }
});

return response.status(200).json(professionals)
}
async create(request, response){
const { name, email, phone, situation, type_of_professional } = request.body

const description = type_of_professional.toUpperCase();
const [ typeOfProfessional ] = await TypeOfProfessional.findOrCreate({
where: { description }
})

const professional = await Professional.create({
name, email, phone, situation,
type_of_professional: typeOfProfessional.dataValues.id
})//save Professional on database

const professionalSaved = await Professional.findByPk(professional.id, {
include: {association: 'type', attributes: ['description']}
})//return professional with associations

return response.status(201).json(professionalSaved)
}
async update(request, response){
const { id } = request.params;
const { name, email, phone, situation, type_of_professional } = request.body;

try {
let professional = await Professional.findByPk(id);

const description = type_of_professional.toUpperCase();
const [ typeOfProfessional ] = await TypeOfProfessional.findOrCreate({
where: { description }
})

const updatedProfessional = await professional.update({
name, email, phone, situation, type_of_professional: typeOfProfessional.dataValues.id
})

return response.status(200).json(updatedProfessional);
} catch (error) {
return response.status(404).json({message: 'Professional not found'});
}
}
async destroy(request, response){
const { id } = request.params

try {
const professional = await Professional.findByPk(id);

await professional.destroy();

return response.status(204).json();
} catch (error) {
return response.status(404).json({message: 'Could not delete'});
}
}
}

module.exports = ProfessionalsController
Loading