diff --git a/riso_backend/src/controllers/unit.controller.js b/riso_backend/src/controllers/unit.controller.js index 77519150..8a466d5a 100644 --- a/riso_backend/src/controllers/unit.controller.js +++ b/riso_backend/src/controllers/unit.controller.js @@ -120,7 +120,7 @@ const updateUnit = async (req, res) => { }catch (err){ return res.status(500).send({message: err.message}); } -} +}; const deleteUnit = async (req,res) => { try{ diff --git a/riso_backend/src/controllers/unitUser.controller.js b/riso_backend/src/controllers/unitUser.controller.js index f8cae9d5..5f0a081b 100644 --- a/riso_backend/src/controllers/unitUser.controller.js +++ b/riso_backend/src/controllers/unitUser.controller.js @@ -3,6 +3,47 @@ import unitService from "../services/unit.service.js"; import jwt from 'jsonwebtoken'; // Biblioteca para manipular o JWT +// Controller para exibir todas as unidades associadas a um usuário pelo código do usuário +const getUnitsByUserCode = async (req, res) => { + try { + // Extração do código do usuário do token JWT + const token = req.headers.authorization?.split(' ')[1]; + if (!token) { + return res.status(401).send({ message: 'Token not provided', substatus: 1 }); + } + + let userId; + try { + const decoded = jwt.verify(token, process.env.SECRET_JWT); // Decodifica o token + userId = decoded._id; // Pega o ID do usuário decodificado do token + } catch (err) { + return res.status(401).send({ message: 'Invalid token', substatus: 2 }); + } + + // Busca todas as associações UnitUser para o ID do usuário + const unitUsers = await unitUserService.findByUserIdService(userId); + if (!unitUsers || unitUsers.length === 0) { + return res.status(404).send({ message: 'No units found for this user', substatus: 3 }); + } + + // Extrai os IDs das unidades das associações + const unitIds = unitUsers.map((unitUser) => unitUser.unit); + + // Busca as unidades correspondentes aos IDs + const units = await unitService.findByIds(unitIds); + if (!units || units.length === 0) { + return res.status(404).send({ message: 'Units not found', substatus: 4 }); + } + + return res.status(200).send({ + message: 'Units retrieved successfully', + units, + }); + } catch (err) { + return res.status(500).send({ message: err.message }); + } +}; + const findAllUnitUser = async (req, res) => { try{ const unitUser = await unitUserService.findAllService(); @@ -66,7 +107,7 @@ const createRelationByUnitCode = async (req, res) => { } // Busca a unidade pelo código fornecido - const unit = await unitService.findByCode({ code }); + const unit = await unitService.findByCode(code); if (!unit) { return res.status(404).send({ message: 'Unit not found', substatus: 4 }); } @@ -152,7 +193,7 @@ const updateUnitUser = async (req, res) => { }catch(err) { return res.status(500).send({ message: err.message }); } -} +}; const deleteUnitUser = async (req,res) => { try{ @@ -172,9 +213,10 @@ const deleteUnitUser = async (req,res) => { }catch(err){ return res.status(500).send({ message: err.message }); } -} +}; export default { + getUnitsByUserCode, findAllUnitUser, createUnitUser, findByUserIdUnitUser, diff --git a/riso_backend/src/routes/unitUser.route.js b/riso_backend/src/routes/unitUser.route.js index 8f341b4c..96b37a8d 100644 --- a/riso_backend/src/routes/unitUser.route.js +++ b/riso_backend/src/routes/unitUser.route.js @@ -5,9 +5,10 @@ const unitUserRouter = express.Router() unitUserRouter.get('/findAllUnitUser', unitUserController.findAllUnitUser); unitUserRouter.post('/createUnitUser',unitUserController.createUnitUser); +unitUserRouter.post('/createRelationByUnitCode', unitUserController.createRelationByUnitCode); unitUserRouter.get('/findByUserId/:UserId', unitUserController.findByUserIdUnitUser); unitUserRouter.get('/findAllUsersByUnitId/:UnitId', unitUserController.findAllUsersByUnitIdUserUnit); -unitUserRouter.patch('/updateUnitUser/:id', ) +unitUserRouter.patch('/updateUnitUser/:id', unitUserController.updateUnitUser); unitUserRouter.delete('/deleteUnitUser/:id',unitUserController.deleteUnitUser); export default unitUserRouter; \ No newline at end of file diff --git a/riso_backend/src/services/unit.service.js b/riso_backend/src/services/unit.service.js index 8896cc82..482505a9 100644 --- a/riso_backend/src/services/unit.service.js +++ b/riso_backend/src/services/unit.service.js @@ -1,12 +1,28 @@ import Unit from "../models/Unit.js"; +/** + * Encontra todas as associações UnitUser para um ID de usuário específico. + * @param {string} userId - O ID do usuário. + * @returns {Promise} - Uma promessa que resolve para uma lista de associações UnitUser. + */ + const findAllService = () => Unit.find(); const findByCode = (code) => Unit.findOne({ code }); const createService = (body) => Unit.create(body); const updateService = (params, body) => Unit.updateOne(params, body, {new: true}); const deleteService = (params) => Unit.deleteOne(params); +const findByIds = async (ids) => { + try { + // Encontra todas as unidades cujos IDs estão na lista fornecida + const units = await Unit.find({ _id: { $in: ids } }); + return units; + } catch (err) { + throw new Error('Error finding units by IDs: ' + err.message); + } + }; export default { + findByIds, findAllService, findByCode, createService, diff --git a/riso_backend/src/services/unitUser.service.js b/riso_backend/src/services/unitUser.service.js index 5147b471..f64e8c2a 100644 --- a/riso_backend/src/services/unitUser.service.js +++ b/riso_backend/src/services/unitUser.service.js @@ -1,13 +1,28 @@ import UnitUser from "../models/UnitUser.js"; +/** + * Encontra todas as associações UnitUser para um ID de usuário específico. + * @param {string} userId - O ID do usuário. + * @returns {Promise} - Uma promessa que resolve para uma lista de associações UnitUser. + */ const findAllService = () => UnitUser.find(); const createService = (params, body) => UnitUser.create(params, body); const findByUserIdService = (userID) => UnitUser.find({ user: userID }); const findAllUsersByUnitIdService = (unitID) => UnitUser.find({ unit: unitID }); const updateService = (params, body) => UnitUser.updateOne(params, body, {new: true}); const deleteService = (params) => UnitUser.deleteOne(params); +const findByUserId = async (userId) => { + try { + // Encontra todas as associações UnitUser para o ID do usuário + const unitUsers = await UnitUser.find({ user: userId }).populate('unit'); + return unitUsers; + } catch (err) { + throw new Error('Error finding UnitUser associations: ' + err.message); + } + }; export default { + findByUserId, findAllService, createService, findByUserIdService, diff --git a/riso_frontend/public/script.js b/riso_frontend/public/script.js index 29f8d803..89fd8a3d 100644 --- a/riso_frontend/public/script.js +++ b/riso_frontend/public/script.js @@ -1,52 +1,99 @@ -const video = document.getElementById('video'); -let happinessCounter = 0; // Inicializa o contador de felicidade -const smiledFaces = new Map(); // Mapa para rastrear rostos que já sorriram - -Promise.all([ - faceapi.nets.tinyFaceDetector.loadFromUri('./models'), - faceapi.nets.faceLandmark68Net.loadFromUri('./models'), - faceapi.nets.faceRecognitionNet.loadFromUri('./models'), - faceapi.nets.faceExpressionNet.loadFromUri('./models') -]).then(startVideo); - -function startVideo() { - navigator.getUserMedia( - { video: {} }, - stream => video.srcObject = stream, - err => console.error(err) - ); -} +function initializeVideoScript() { + const video = document.getElementById('video'); + let happinessCounter = 0; // Inicializa o contador de felicidade + const smiledFaces = new Map(); // Mapa para rastrear rostos que já sorriram + + // Função para carregar os modelos necessários + async function loadModels() { + try { + // Carrega os modelos necessários para o face-api.js + await faceapi.nets.tinyFaceDetector.loadFromUri('./models'); + await faceapi.nets.faceLandmark68Net.loadFromUri('./models'); + await faceapi.nets.faceRecognitionNet.loadFromUri('./models'); + await faceapi.nets.faceExpressionNet.loadFromUri('./models'); + + console.log("Todos os modelos foram carregados com sucesso."); + startVideo(); // Inicia o vídeo após os modelos serem carregados + } catch (error) { + console.error("Erro ao carregar os modelos:", error); + } + } + + // Função para iniciar o vídeo + function startVideo() { + navigator.mediaDevices.getUserMedia({ video: {} }) + .then(stream => { + video.srcObject = stream; + }) + .catch(err => console.error("Erro ao acessar a câmera:", err)); + } + + // Função para verificar se todos os modelos foram carregados + function areModelsLoaded() { + return ( + faceapi.nets.tinyFaceDetector.isLoaded && + faceapi.nets.faceLandmark68Net.isLoaded && + faceapi.nets.faceRecognitionNet.isLoaded && + faceapi.nets.faceExpressionNet.isLoaded + ); + } + + // Adiciona um ouvinte de evento 'play' para quando o vídeo começar + video.addEventListener('play', async () => { + // Verifica se os modelos estão carregados antes de prosseguir + if (!areModelsLoaded()) { + console.error("Modelos não carregados corretamente."); + return; + } + + const canvas = faceapi.createCanvasFromMedia(video); + document.body.append(canvas); + const displaySize = { width: video.width, height: video.height }; + faceapi.matchDimensions(canvas, displaySize); + + setInterval(async () => { + try { + // Verifica novamente se os modelos estão carregados antes da inferência + if (!areModelsLoaded()) { + console.error("Modelos ainda não carregados. Tentando novamente..."); + return; + } -video.addEventListener('play', () => { - const canvas = faceapi.createCanvasFromMedia(video); - document.body.append(canvas); - const displaySize = { width: video.width, height: video.height }; - faceapi.matchDimensions(canvas, displaySize); - setInterval(async () => { - const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()) - .withFaceLandmarks() - .withFaceExpressions(); - - const resizedDetections = faceapi.resizeResults(detections, displaySize); - canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); - faceapi.draw.drawDetections(canvas, resizedDetections); - faceapi.draw.drawFaceLandmarks(canvas, resizedDetections); - faceapi.draw.drawFaceExpressions(canvas, resizedDetections); - - resizedDetections.forEach(detection => { - const faceId = detection.detection.box.x.toFixed(2) + detection.detection.box.y.toFixed(2); - const isSmiling = detection.expressions.happy > 0.9; - - if (isSmiling && !smiledFaces.has(faceId)) { - happinessCounter++; - smiledFaces.set(faceId, true); // Marca que esse rosto já teve o sorriso contado - console.log(`A pessoa ficou feliz ${happinessCounter} vezes`); - - // Remove o rosto do mapa após um curto período - setTimeout(() => { - smiledFaces.delete(faceId); - }, 5000); // Ajuste o tempo conforme necessário (5 segundos neste exemplo) + // Realiza a detecção de rostos + const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()) + .withFaceLandmarks() + .withFaceExpressions(); + + const resizedDetections = faceapi.resizeResults(detections, displaySize); + canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); + faceapi.draw.drawDetections(canvas, resizedDetections); + faceapi.draw.drawFaceLandmarks(canvas, resizedDetections); + faceapi.draw.drawFaceExpressions(canvas, resizedDetections); + + resizedDetections.forEach(detection => { + const faceId = detection.detection.box.x.toFixed(2) + detection.detection.box.y.toFixed(2); + const isSmiling = detection.expressions.happy > 0.9; + + if (isSmiling && !smiledFaces.has(faceId)) { + happinessCounter++; + smiledFaces.set(faceId, true); // Marca que esse rosto já teve o sorriso contado + console.log(`A pessoa ficou feliz ${happinessCounter} vezes`); + + // Remove o rosto do mapa após um curto período + setTimeout(() => { + smiledFaces.delete(faceId); + }, 5000); // Ajuste o tempo conforme necessário (5 segundos neste exemplo) + } + }); + } catch (error) { + console.error("Erro durante a detecção de rostos:", error); } - }); - }, 100); -}); + }, 100); + }); + + // Chama a função para carregar os modelos ao iniciar o script + loadModels(); +} + +// Chama a função para inicializar o script +initializeVideoScript(); diff --git a/riso_frontend/src/components/CodeModal/index.jsx b/riso_frontend/src/components/CodeModal/index.jsx index f9dde091..0c65a0bd 100644 --- a/riso_frontend/src/components/CodeModal/index.jsx +++ b/riso_frontend/src/components/CodeModal/index.jsx @@ -20,7 +20,7 @@ function CodeModal({
- Salvar + Buscar ); } diff --git a/riso_frontend/src/pages/DashBoardPage/GraficoBarras.html b/riso_frontend/src/pages/DashBoardPage/GraficoBarras.html new file mode 100644 index 00000000..4eff9ba2 --- /dev/null +++ b/riso_frontend/src/pages/DashBoardPage/GraficoBarras.html @@ -0,0 +1,162 @@ + + + + + + Gráfico de Barra com Chart.js + + + +

Gráfico de Barras

+ + + + + + + + + + + + + diff --git a/riso_frontend/src/pages/DashBoardPage/GraficoDiario.html b/riso_frontend/src/pages/DashBoardPage/GraficoDiario.html deleted file mode 100644 index aee43073..00000000 --- a/riso_frontend/src/pages/DashBoardPage/GraficoDiario.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - Gráfico de Linhas com Chart.js - - - -

Gráfico de Linhas

- - - - - \ No newline at end of file diff --git a/riso_frontend/src/pages/DashBoardPage/GraficoLinhas.html b/riso_frontend/src/pages/DashBoardPage/GraficoLinhas.html new file mode 100644 index 00000000..781be10a --- /dev/null +++ b/riso_frontend/src/pages/DashBoardPage/GraficoLinhas.html @@ -0,0 +1,115 @@ + + + + + + Gráfico de Linhas com Chart.js + + + +

Gráfico de Linhas

+ + + + + + + + + + + + + diff --git a/riso_frontend/src/pages/DashBoardPage/graficoMensal.html b/riso_frontend/src/pages/DashBoardPage/graficoMensal.html deleted file mode 100644 index 482be776..00000000 --- a/riso_frontend/src/pages/DashBoardPage/graficoMensal.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - Gráfico de Barra com Chart.js - - - -

Gráfico de Barras

- - - - - \ No newline at end of file diff --git a/riso_frontend/src/pages/DashBoardPage/index.jsx b/riso_frontend/src/pages/DashBoardPage/index.jsx index 035d2ca9..a775b3d1 100644 --- a/riso_frontend/src/pages/DashBoardPage/index.jsx +++ b/riso_frontend/src/pages/DashBoardPage/index.jsx @@ -13,18 +13,26 @@ function DashBoardPage() { const faceApiScript = document.createElement("script"); faceApiScript.src = "/face-api.min.js"; // Ajuste o caminho conforme necessário faceApiScript.async = true; - faceApiScript.onload = () => { - // Adiciona script.js após face-api.min.js ser carregado + + // Função para adicionar o script.js após face-api.min.js ser carregado + const addScriptJs = () => { const script = document.createElement("script"); script.src = "/script.js"; // Ajuste o caminho conforme necessário script.async = true; document.body.appendChild(script); }; + + faceApiScript.onload = addScriptJs; document.body.appendChild(faceApiScript); - + // Cleanup: remove os scripts quando o componente é desmontado return () => { document.body.removeChild(faceApiScript); + // Remove script.js se necessário + const existingScript = document.querySelector('script[src="/script.js"]'); + if (existingScript) { + document.body.removeChild(existingScript); + } }; }, []); diff --git a/riso_frontend/src/pages/HomePage/index.jsx b/riso_frontend/src/pages/HomePage/index.jsx index 2d63b6c6..3cd4af9f 100644 --- a/riso_frontend/src/pages/HomePage/index.jsx +++ b/riso_frontend/src/pages/HomePage/index.jsx @@ -7,6 +7,7 @@ import { FillButton } from "../../components/Button/styled"; import AddUnitModal from "../../components/addUnitModal"; import CodeModal from "../../components/CodeModal"; import { createUnit, getAllUnits } from "../../services/unitServices"; +import { createRelationByUnitCode } from "../../services/userUnit"; function HomePage() { @@ -64,6 +65,17 @@ function HomePage() { } }; + const searchUnit = async (event) => { + event.preventDefault(); + try { + await createRelationByUnitCode(code); + fetchUnits(); + setIsVisibleCode(false); + } catch (err) { + console.log(err.response); + } + } + function logOut() { Cookies.remove("token"); navigate('/'); @@ -103,6 +115,7 @@ function HomePage() { diff --git a/riso_frontend/src/services/userUnit.js b/riso_frontend/src/services/userUnit.js new file mode 100644 index 00000000..a1ceba1f --- /dev/null +++ b/riso_frontend/src/services/userUnit.js @@ -0,0 +1,22 @@ +import axios from "axios"; +import Cookies from 'js-cookie'; + +const baseURL = 'http://localhost:3000'; + +export function createRelationByUnitCode(code){ + const body = { + code: code, + } + + const response = axios.post( + `${baseURL}/unitUser/createRelationByUnitCode`, + body, + { + headers: { + Authorization: `Bearer ${Cookies.get("token")}`, + }, + } + ); + + return response; +} \ No newline at end of file