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

[US11]: Configurar disponibilidade de Visita #104

Merged
merged 33 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8c7017b
feat: adicionando rota do sac
DanielRogs Dec 3, 2024
8caf08b
feat: adicionando rotas get pra puxar todos os sacs e sacs por assunto
arthur-suares Dec 5, 2024
cfd5a31
feat: configurando funcao delete
arthur-suares Dec 6, 2024
6d641ab
feat: primeira versão do sac
manuvaladares Dec 6, 2024
baeb16f
Merge branch 'feature/sac' of https://github.com/mdsreq-fga-unb/2024.…
manuvaladares Dec 6, 2024
2f45061
Merge branch 'feature/disponibilidade_de_visita' of https://github.co…
manuvaladares Dec 6, 2024
f54ed99
fix: corrigindo a pasta do componente sac
manuvaladares Dec 6, 2024
3c321d3
feat: adiciona o campo de assunto e anexar arquivo
manuvaladares Dec 6, 2024
b5a416c
feat: envio de emails!
arthur-suares Dec 7, 2024
4e82fa8
feat: consumindo a api de sac
arthur-suares Dec 7, 2024
33b13f2
fix: corrigindo dependencias no json
arthur-suares Dec 7, 2024
65b0cc7
feat: envio de emails pelo forms do front - v1
arthur-suares Dec 7, 2024
b6ffe70
fix: correcao de dependencias
arthur-suares Dec 7, 2024
7a793cd
fix: envio de emails com ou sem arquivo anexado
arthur-suares Dec 8, 2024
e00090f
feat: estilizacao do campo de endereco no sacsection
arthur-suares Dec 8, 2024
2e514db
feat: ajuste de fonte e bordas no sac
manuvaladares Dec 9, 2024
a510454
feat: adicinando novos campos ao model visita
DanielRogs Dec 9, 2024
589b8f7
feat: amostragem dos dias de visitas disponibilizados
JoaoODragonborn Dec 10, 2024
6d78aa4
feat: puxando vetor de sacs do banco e mostrando na tela
arthur-suares Dec 11, 2024
0798216
feat: campo select para filtrar sacs
arthur-suares Dec 12, 2024
bcde1a0
Merge branch 'develop' of https://github.com/mdsreq-fga-unb/2024.2-T0…
arthur-suares Dec 12, 2024
c8a8669
fix: correcao de dependencia
arthur-suares Dec 12, 2024
3b15ec4
feat: pagina de visualizacao de sacs no frontadmin
arthur-suares Dec 12, 2024
77c9812
feat: botao para inserir arquivo estilizado
manuvaladares Dec 12, 2024
29e8af6
Merge branch 'develop' of https://github.com/mdsreq-fga-unb/2024.2-T0…
DanielRogs Dec 13, 2024
b89a9d6
feat: adicionando bigpost
DanielRogs Dec 13, 2024
379fda7
feat: inserindo responsividade melhorada
DanielRogs Dec 13, 2024
936ddc6
fix: ajustando responsividade de páginas
DanielRogs Dec 14, 2024
cce6c60
Merge branch 'feature/sac' of https://github.com/mdsreq-fga-unb/2024.…
DanielRogs Dec 14, 2024
4388bfd
Merge branch 'feature/blog' of https://github.com/mdsreq-fga-unb/2024…
DanielRogs Dec 14, 2024
b2106d1
feat: adicionando novas páginas
DanielRogs Dec 14, 2024
8dfa3e1
feat: finalizando feat das visitas técnicas
DanielRogs Dec 16, 2024
6a8bab4
fix: corrigindo botões
DanielRogs Dec 16, 2024
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
4 changes: 3 additions & 1 deletion apps/backend/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ MONGODB_URI_DEV =
MONGODB_URI_PROD =
NODE_ENV =
SECRET_JWT =
SALT_BCRYPT =
SALT_BCRYPT =
MAIL_USER =
MAIL_PASS =
129 changes: 129 additions & 0 deletions apps/backend/src/controllers/sac.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import sacService from "../services/sac.service.js";
import nodemailerService from "../services/nodemailer.service.js";

import mongoose from "mongoose";

const createSac = async (req, res) => {
try {
const { nomeSobrenome, email, telefone, assunto, mensagem } = req.body;
if (!nomeSobrenome || !email || !telefone || !assunto || !mensagem) {
return res.status(400).send({ message: "Preencha todos os campos!" });
}

const sac = await sacService.createService(req.body);

if (!sac) {
return res.status(400).send({ message: 'Dados não salvo!' });
};

res.status(200).send({ message: 'Dados salvos com sucesso!', sac: sac });

} catch (err) {
res.status(500).send({ message: err.message })
}
}

const sendMail = async (req, res) => {
try {
const data = JSON.parse(req.body.data);
const { nomeSobrenome, email, telefone, assunto, mensagem } = data;

let emailSetor;

switch (assunto) {
case 'Sugestao':
emailSetor = '[email protected]';
break;
case 'Elogio':
emailSetor = '[email protected]';
break;
case 'Duvida':
emailSetor = '[email protected]';
break;
case 'Reclamacao':
emailSetor = '[email protected]';
break;
case 'Parceria/Patrocinio':
emailSetor = '[email protected]';
break;
default:
return res.status(400).send({ message: 'Houve algum erro no campo assunto' });
}

// Configura o corpo do e-mail
const emailBody = `
Nome: ${nomeSobrenome}
Email: ${email}
Telefone: ${telefone}
Assunto: ${assunto}
Mensagem: ${mensagem}
`;

// Configura os anexos se houver
const attachments = req.file
? [{ path: req.file.path }]
: [];

// Envia o e-mail
await nodemailerService.send(emailSetor, assunto, emailBody, attachments);

res.status(200).send({ message: 'E-mail enviado com sucesso!' });
} catch (err) {
console.error('Erro ao enviar e-mail:', err);
res.status(500).send({ message: 'Erro ao enviar e-mail.' });
}
};


const findAllSac = async (req, res) => {
const sacs = await sacService.findAllService();

if (sacs.length === 0) {
return res.status(400).send({ message: 'Não há nenhum sac no momento' });
}

res.send(sacs);
}

const findAssuntoSac = async (req, res) => {
const assunto = req.params.assunto;

const sacs = await sacService.findByAssunto(assunto);

if (sacs.length === 0) {
return res.status(400).send({ message: 'Não há nenhum sac deste tipo no momento' });
}

res.send(sacs);
}


const deleteSacById = async (req, res) => {
const id = req.params.id;

if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).send({ message: "Id invalido!" });
}

try {
const result = await sacService.deleteById(id);

if (result.deletedCount > 0) {
return res.send({message: 'SAC deletado com sucesso.'});
} else {
return res.send({message: 'Nenhum SAC encontrado para o id fornecido.'});
}

} catch (error) {
console.error('Erro ao deletar SAC:', error);
return res.status(500).send({ message: "Erro interno ao tentar deletar o SAC." });
}
}

export default {
createSac,
findAllSac,
findAssuntoSac,
deleteSacById,
sendMail
};
53 changes: 48 additions & 5 deletions apps/backend/src/controllers/visita.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import VisitaService from"../services/visita.service.js";

const createVisita = async (req, res) => {
try {
const { startDateTime, endDateTime } = req.body;
const { startDateTime, endDateTime, status } = req.body;

if(!startDateTime || !endDateTime)
return res.status(400).json({ message: "Preencha todos os campos para criar a disponibilidade!"});
if(!startDateTime || !endDateTime || !status)
return res.status(400).send({ message: "Preencha todos os campos para criar a disponibilidade!"});

const visita = await VisitaService.createService(req.body);

Expand All @@ -21,16 +21,59 @@ const createVisita = async (req, res) => {
const findAllVisita = async (req, res) => {
try {
const visita = await VisitaService.findAllService();

return res.send(200).send({ message: "Visitas encontradas!", visita });

return res.status(200).send({ message: "Visitas encontradas!", visita });

} catch (err) {
return res.send(500).send({ message: err.message });
}
};

const deleteVisita = async (req, res) => {
try {
const { id } = req.params;

if(!id)
return res.status(400).send({ message: "ID não identificado!"});

const visita = await VisitaService.deleteService({_id: id});

if (!visita)
return res.status(404).send({ message: "Visita não encontrada!" });

return res.status(200).send({ message: "Visita deletada!", visita });
} catch (err) {
return res.status(500).send({ message: err.message });
}
};

const patchVisita = async (req, res) => {
try {
const { id } = req.params;
const updateData = req.body;

if (!id)
return res.status(400).send({ message: "ID não informado!" });

if (!Object.keys(updateData).length)
return res.status(400).send({ message: "Nenhuma informação para atualizar!" });

const updatedVisita = await VisitaService.patchService({ _id: id }, updateData);

if (!updatedVisita)
return res.status(404).send({ message: "Visita não encontrada!" });

return res.status(200).send({ message: "Visita atualizada com sucesso!", updatedVisita });
} catch (err) {
return res.status(500).send({ message: err.message });
}
}

export default {
createVisita,
findAllVisita,
deleteVisita,
patchVisita,
};


39 changes: 20 additions & 19 deletions apps/backend/src/middlewares/auth.middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,33 @@ dotenv.config();
export const authMiddleware = (req, res, next) => {
try {
const { authorization } = req.headers;

if (!authorization)
return res.status(401).send({message: 'User Unauthorized'});

if (!authorization)
return res.status(401).send({message: 'User Unauthorized'});
const parts = authorization.split(" ");

const parts = authorization.split(" ");
if (parts.length !== 2)
return res.status(401).send({message: 'User Unauthorized'});

if (parts.length !== 2)
return res.status(401).send({message: 'User Unauthorized'});

const [schema, token] = parts;

if (schema !== "Bearer")
return res.status(401).send({message: 'User Unauthorized'});
const [schema, token] = parts;
if (schema !== "Bearer")
return res.status(401).send({message: 'User Unauthorized'});

jwt.verify(token, process.env.SECRET_JWT, async (error, decoded) => {
if(error) return res.status(401).send({message: 'Token Invalid'});

const user = await userService.findByIdService({ _id: decoded._id});
jwt.verify(token, process.env.SECRET_JWT, async (error, decoded) => {
if(error) {
return res.status(401).send({message: 'Token Invalid'});
}

const user = await userService.findByIdService({ _id: decoded.sub});

if (!user || !user.id)
return res.status(401).send({message: "Invalid User!"});
if (!user || !user.id)
return res.status(401).send({message: "Invalid User!"});

req.userID = decoded._id;
req.userID = decoded._id;

return next();
});
return next();
});
} catch(err) {
return res.status(500).send({ message: err.message });
}
Expand Down
10 changes: 10 additions & 0 deletions apps/backend/src/middlewares/sac.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import multer from "multer";

const upload = multer({
dest: "uploads/",
limits: {
fileSize: 15 * 1024 * 1024 // 15MB em bytes
}
});

export default upload;
27 changes: 27 additions & 0 deletions apps/backend/src/models/Sac.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import mongoose from "mongoose";

const SacSchema = new mongoose.Schema({
nomeSobrenome: {
type: String,
require: true,
},
email: {
type: String,
require: true,
},
telefone: {
type: String,
require: true,
},
assunto: {
type: String,
require: true,
},
mensagem: {
type: String,
require: true,
}
});

const Sac = mongoose.model('Sac', SacSchema);
export default Sac;
6 changes: 5 additions & 1 deletion apps/backend/src/models/Visita.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const VisitaSchema = new mongoose.Schema({
type: Date,
require: true,
},
status: {
type: String,
require: true,
},
nameVisitor: {
type: String,
require: false,
Expand All @@ -21,7 +25,7 @@ const VisitaSchema = new mongoose.Schema({
type: String,
require: false,
},
Institution: {
institution: {
type: String,
require: false,
}
Expand Down
4 changes: 3 additions & 1 deletion apps/backend/src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { Router } from "express";
import cors from 'cors';
import visitaRouter from "./visita.route.js";
import userRouter from "./user.route.js";
import sacRouter from "./sac.route.js";
import { authMiddleware } from "../middlewares/auth.middleware.js";

const router = Router();

router.use('/visita', cors(), visitaRouter);
router.use('/visita', cors(), authMiddleware, visitaRouter);
router.use('/user', cors(), userRouter);
router.use('/sac', cors(), sacRouter);

export default router;
32 changes: 32 additions & 0 deletions apps/backend/src/routes/sac.route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import express from 'express';
import upload from "../middlewares/sac.middleware.js"
const sacRouter = express.Router();

import sacController from '../controllers/sac.controller.js';

sacRouter.post('/createSac', sacController.createSac);
sacRouter.post(
'/sendMail',
upload.single("arquivo"),
(req, res, next) => {
try {
if (req.file && req.file.size > 15 * 1024 * 1024) {
return res.status(400).send({ message: "O arquivo é muito grande. O limite é de 15MB." });
}
next(); // Prossegue para o controlador, mesmo sem arquivo
} catch (err) {
if (err.code === "LIMIT_FILE_SIZE") {
return res.status(400).send({ message: "O arquivo é muito grande. O limite é de 15MB." });
}
next(err);
}
},
sacController.sendMail
);


sacRouter.get('/', sacController.findAllSac);
sacRouter.get('/:assunto', sacController.findAssuntoSac);
sacRouter.delete('/:id', sacController.deleteSacById);

export default sacRouter;
2 changes: 2 additions & 0 deletions apps/backend/src/routes/visita.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ const visitaRouter = express.Router();

visitaRouter.post('/createVisita', visitaController.createVisita);
visitaRouter.get('/findAllVisita', visitaController.findAllVisita);
visitaRouter.delete('/deleteVisita/:id', visitaController.deleteVisita);
visitaRouter.patch('/patchVisita/:id', visitaController.patchVisita);

export default visitaRouter;
Loading