Usuário pode se cadastrar na aplicação, escolher os pedidos e verificar o carrinho de compras.
Aplicação com intenção de simular um sistema de compras em um estabelecimento alimentício. O usuário pode se cadastrar e logar com seus dados de e-mail e senha. Depois de logado e com o token autenticado, a página inicial com os produtos da loja fica visível para escolher variedades de hambúrgueres e complementos. Por fim, pode clicar no carrinho.Além de um painel administrativo onde o representante do estabelecimento consegue ver todos os pedidos e seus status atualizados.
- VS Code
- Insomnia
- Yarn
- Node.JS
- Express.JS
- Docker
- PostgreSQL
- Postbird
- Sequelize (ORM)
- UUID (v4)
- Yup
- Bcrypt
- Multer
- JWT (JSON Web Token)
- Mongoose
- MongoDB Compass
Na aplicação foi utilizado o Node.JS na versão 18.14.0 em LTS.
~
O Yarn na versão 1.22.19
🔸 npm install -g yarn
ou sudo npm install -g yarn
~
O Docker na configuração para computador 4.21.1 e versão 24.0.2
~
O Postbird na versão instalada em Postbird.Setup.0.8.4.exe
~
O Sequelize na versão 6.32.1
🔸 yarn add sequelize
~
Foi usado o programa Insomnia para testar as requisições das rotas simulando o Front-end.
~
O MongoDB Compass (GUI) na configuração do computador versão 1.40.4 (Estável).
~
Framework Express na versão 4.18.2
🔸 yarn add express
~
Biblioteca UUID do tipo v.4 e na versão 9.0.0
🔸 yarn add uuid
~
Biblioteca Yup na versão 1.2.0
🔸 yarn add yup
~
Biblioteca Bcrypt na versão 5.1.0
🔸 yarn add bcrypt
~
Biblioteca Multer na versão 1.4.5-1ts.1
🔸 yarn add multer
~
Biblioteca JWT na versão 9.0.2
🔸 yarn add jsonwebtoken
~
Biblioteca Mongoose na versão 7.6.1
🔸 yarn add mongoose
~
O Nodemon na versão 3.0.1
🔸 yarn add nodemon -D
Criado um script no package.json
para o nodemon: "dev".
~
O Sucrase na versão 3.33.0
🔸 yarn add sucrase -D
~
O Eslint na versão 8.0.1
🔸 yarn add eslint -D
~
O Prettier nas versões 8.8.0 e 5.0.0
🔸 yarn add prettier eslint-config-prettier eslint-plugin-prettier -D
~
O Sequelize-cli na versão 6.6.1
🔸 yarn add sequelize-cli -D
~
-
Para rodar o repositório é necessário clonar o mesmo.
-
Pra inicar escreva no terminal:
npm init -y
- Após instaladas as dependências, dê o comando seguinte para rodar a aplicação do servidor:
yarn dev
-
Parar de rodar o servidor: no terminal clicar nas teclas de "Ctrl" e "C".
-
Para debugar:
yarn debug
- Para usar o Sequelize com o PostgreSQL, precisa instalar:
yarn add pg pg-hstore
- Para rodar a Migration:
yarn sequelize db:migrate
- Para desfazer todas as Migrations:
yarn sequelize db:migrate:undo:all
- Para rodar o banco de dados relacional PostgreSQL:
docker start codeburguer-postgres
- Para derrubar o banco de dados relacional PostgreSQL:
docker stop codeburguer-postgres
-
Utilizei o Insomnia para realizar as requisições desejadas.
-
Para rodar o banco de dados não relacional MongoDB:
docker start mongo
- Para derrubar o banco de dados não relacional MongoDB:
docker stop mongo
~
Caminho da URL: http://localhost:3000
Método | URL | Descrição |
---|---|---|
POST | /users | Cria um usuário usando as informações enviadas dentro do arquivo request.body . |
POST | /sessions | Verifica se o e-mail e senha correspondem com as informações do usuário cadastrado no banco de dados. |
POST | /products | Cria um produto usando as informações enviadas dentro do arquivo request.body . E faz o upload do arquivo recebido do Insomnia. |
GET | /products | Procura todos os produtos no banco de dados da tabela products . E retorna um JSON da lista com todos os dados dos produtos. |
POST | /categories | Cria uma categoria usando a informação enviada dentro do arquivo request.body com token. E faz o upload do arquivo recebido do Insomnia. |
GET | /categories | Procura todas as categorias no banco de dados da tabela categories . E retorna um JSON da lista com todos os dados das categorias. |
POST | /orders | Cria um pedido usando as informações enviadas dentro do arquivo request.body com token atualizado. |
GET | /orders | Procura todos os pedidos no banco de dados. Sem o body e com token atualizado. E retorna um JSON da lista com informações de user, products e status . |
PUT | /orders/:id | Atualiza o status específico do pedido, a partir do id, usando o arquivo request.body . E responde com uma mensagem de sucesso. |
PUT | /products/:id | Atualiza algum dado específico do pedido, a partir do id, usando o arquivo request.body . Faz o upload do arquivo recebido do Insomnia (quando tiver). E responde com uma mensagem de sucesso. |
PUT | /categories/:id | Atualiza algum dado específico da categoria, a partir do id, usando o arquivo request.body . Faz o upload do arquivo recebido do Insomnia (quando tiver). E responde com uma mensagem de sucesso. |
Serve como interceptador.
Assim que o usuário tentar acessar a rota, faz uma validação da informação se está correta ou se está incorreta.
middlewares() {
this.app.use(express.json())
this.app.use('/product-file', express.static(resolve(__dirname, '..', 'uploads')))
this.app.use('/category-file', express.static(resolve(__dirname, '..', 'uploads')))
}
~
routes() {
this.app.use(routes)
}
~
export default(request, response, next) => {
const authToken = request.headers.authorization
-
Se o usuário não mandar um token:
- Responde status HTTP com o código
401
(Unauthorized) - Retorna o seguinte JSON:
{ error: 'Token não fornecido' }
- Responde status HTTP com o código
-
Se o usuário mandar um token errado:
- Responde status HTTP com o código
401
(Unauthorized) - Retorna o seguinte JSON:
{ error: 'Token inválido' }
- Responde status HTTP com o código
-
Se o usuário mandar um token válido:
- Retorna o JSON com todas as informações dos produtos da tabela do banco de dados. Acesso autorizado para a rota.
~
Serve para criações de tabelas para o banco de dados. E para modificá-las.
Precisa estar, primeiramente, com o Docker rodando. E em seguida, precisa rodar a Migration.
- Criação da Tabela de Usuários:
- id
- name
- password_hash
- admin
- created_at
- updated_at
~
- Criação da Tabela de Produtos:
- id
- name
- price
- category
- path
- created_at
- updated_at
~
- Criação da Tabela de Categorias:
- id
- name
- path
- created_at
- updated_at
~
- Deletar campo na tabela:
- Remover coluna category que está na Tabela de Produtos
~
- Criar campo na tabela:
- Adicionar coluna category_id na Tabela de Produtos
~
- Acrescentar campo na tabela:
- Adicionar coluna offer na Tabela de Produtos
~
- Acrescentar campo na tabela:
- Adicionar coluna path na Tabela de Categorias
~
Padrão do objeto que espero receber no Insomnia.
name: Yup.string().required(),
email: Yup.string().email().required(),
password: Yup.string().required().min(6),
admin: Yup.boolean(),
-
Se encontrar algum dado inválido:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o(s) motivo(s) do(s) erro(s) no formato JSON:
{ error: err.errors }
- Responde status HTTP com o código
-
Se encontrar um email já existente:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o seguinte JSON:
{ error: 'E-mail já cadastrado' }
- Responde status HTTP com o código
-
Criando com sucesso um usuário:
- Responde status HTTP com o código
201
(Created) - Retorna o seguinte JSON:
{ id: user.id, name, email, admin }
- Responde status HTTP com o código
~
email: Yup.string().email().required(),
password: Yup.string().required(),
-
Se não encontrar o email ou senha do usuário:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o seguinte JSON:
{ error: 'Email ou senha incorreto' }
- Responde status HTTP com o código
-
Encontrando com sucesso email e senha do usuário:
- Responde status HTTP com o código
200
(OK) - Retorna o seguinte JSON:
{id: user.id, email, name: user.name, admin: user.admin, token: jwt.sign }
- Responde status HTTP com o código
~
name: Yup.string().required(),
price: Yup.number().required(),
category_id: Yup.number().required(),
offer: Yup.boolean(),
-
Se encontrar algum dado inválido:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o(s) motivo(s) do(s) erro(s) no formato JSON:
{ error: err.errors }
- Responde status HTTP com o código
-
Criando com sucesso um produto:
- Responde status HTTP com o código
200
(OK) - Retorna o seguinte JSON:
{ id, name, price, category_id, path, updated_at, created_at, offer }
- Responde status HTTP com o código
-
Encontrando todos os produtos cadastrados:
- Responde status HTTP com o código
200
(OK) - Retorna o seguinte JSON:
{ url, id, name, price, path, updated_at, created_at, category_id: category: { id, name }, offer }
- Responde status HTTP com o código
-
Se encontrar um usuário que não seja admin:
- Responde status HTTP com o código
401
(Unauthorized)
- Responde status HTTP com o código
~
name: Yup.string().required(),
-
Se encontrar algum dado inválido:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o(s) motivo(s) do(s) erro(s) no formato JSON:
{ error: err.errors }
- Responde status HTTP com o código
-
Se encontrar alguma categoria repetida:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o erro no formato JSON:
{ error: 'Categoria já existe' }
- Responde status HTTP com o código
-
Criando com sucesso uma categoria:
- Responde status HTTP com o código
200
(OK) - Retorna o seguinte JSON:
{ name, id }
- Responde status HTTP com o código
-
Se encontrar um usuário que não seja admin:
- Responde status HTTP com o código
401
(Unauthorized)
- Responde status HTTP com o código
~
products: Yup.array().required().of(
Yup.object().shape({
id: Yup.number().required(),
quantity: Yup.number().required(),
})
)
-
Se encontrar algum dado inválido:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o(s) motivo(s) do(s) erro(s) no formato JSON:
{ error: err.errors }
- Responde status HTTP com o código
-
Criando com sucesso um pedido:
- Responde status HTTP com o código
201
(Created) - Retorna o seguinte JSON:
{ id: product.id, name: product.name, price: product.price, category: product.category.name, url: product.url, quantity: request.body.products[productIndex].quantity }
- Responde status HTTP com o código
-
Se encontrar um usuário que não seja admin:
- Responde status HTTP com o código
401
(Unauthorized)
- Responde status HTTP com o código
~
name: Yup.string(),
price: Yup.number(),
category_id: Yup.number(),
offer: Yup.boolean(),
-
Se encontrar algum dado inválido:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o(s) motivo(s) do(s) erro(s) no formato JSON:
{ error: err.errors }
- Responde status HTTP com o código
-
Alterando com sucesso um produto:
- Responde status HTTP com o código
200
(OK)
- Responde status HTTP com o código
-
Se encontrar um usuário que não seja admin:
- Responde status HTTP com o código
401
(Unauthorized)
- Responde status HTTP com o código
-
Se não encontrar algum produto pelo ID:
- Responde status HTTP com o código
401
(Unauthorized) - Retorna o seguinte JSON:
{ error: 'Verifique se o ID do seu produto está correto' }
- Responde status HTTP com o código
~
name: Yup.string(),
-
Se encontrar algum dado inválido:
- Responde status HTTP com o código
400
(Bad Request) - Retorna o(s) motivo(s) do(s) erro(s) no formato JSON:
{ error: err.errors }
- Responde status HTTP com o código
-
Se não encontrar alguma categoria pelo ID:
- Responde status HTTP com o código
401
(Unauthorized) - Retorna o erro no formato JSON:
{ error: 'Verifique se o ID da sua categoria está correto' }
- Responde status HTTP com o código
-
Alterando com sucesso uma categoria:
- Responde status HTTP com o código
200
(OK)
- Responde status HTTP com o código
-
Se encontrar um usuário que não seja admin:
- Responde status HTTP com o código
401
(Unauthorized)
- Responde status HTTP com o código
~
Responsável pela leitura e escrita de dados. Auxiliar na interface da aplicação com o banco de dados.
super.init({
name: Sequelize.STRING,
email: Sequelize.STRING,
password: Sequelize.VIRTUAL,
password_hash: Sequelize.STRING,
admin: Sequelize.BOOLEAN,
},
{
sequelize,
})
~
super.init(
{
name: Sequelize.STRING,
price: Sequelize.INTEGER,
path: Sequelize.STRING,
offer: Sequelize.BOOLEAN,
url: {
type: Sequelize.VIRTUAL,
get() {
return `http://localhost:3000/product-file/${this.path}`
},
},
},
{
sequelize,
})
~
super.init(
{
name: Sequelize.STRING,
path: Sequelize.STRING,
url: {
type: Sequelize.VIRTUAL,
get() {
return `http://localhost:3000/category-file/${this.path}`
},
},
},
{
sequelize,
})
~
static associate(models){
this.belongsTo(models.Category, {
foreignKey: 'category_id',
as: 'category',
})
}
~
✔️ Aplicação back-end finalizada.