diff --git a/package-lock.json b/package-lock.json index 9926bf5..068a8fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "bootstrap-icons": "^1.13.1", "dayjs": "^1.11.18", "flatpickr": "^4.6.13", + "html2pdf.js": "^0.12.1", "lucide-react": "^0.543.0", "perfect-scrollbar": "^1.5.6", "powershell": "^2.3.3", @@ -18118,6 +18119,12 @@ "@types/node": "*" } }, + "node_modules/@types/pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", + "license": "MIT" + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -18163,6 +18170,13 @@ "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==", "license": "BSD-3-Clause" }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", @@ -19593,6 +19607,15 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -19965,6 +19988,26 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvg": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", + "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -21088,6 +21131,15 @@ "postcss": "^8.4" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -22014,6 +22066,16 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -23229,6 +23291,17 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, + "node_modules/fast-png": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz", + "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==", + "license": "MIT", + "dependencies": { + "@types/pako": "^2.0.3", + "iobuffer": "^5.3.2", + "pako": "^2.1.0" + } + }, "node_modules/fast-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", @@ -23275,6 +23348,12 @@ "bser": "2.1.1" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -24525,6 +24604,29 @@ } } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/html2pdf.js": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/html2pdf.js/-/html2pdf.js-0.12.1.tgz", + "integrity": "sha512-3rBWQ96H5oOU9jtoz3MnE/epGi27ig9h8aonBk4JTpvUERM3lMRxhIRckhJZEi4wE0YfRINoYOIDY0hLY0CHgQ==", + "license": "MIT", + "dependencies": { + "html2canvas": "^1.0.0", + "jspdf": "^3.0.0" + } + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -24849,6 +24951,12 @@ "loose-envify": "^1.0.0" } }, + "node_modules/iobuffer": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz", + "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==", + "license": "MIT" + }, "node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -26609,6 +26717,23 @@ "node": ">=0.10.0" } }, + "node_modules/jspdf": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.3.tgz", + "integrity": "sha512-eURjAyz5iX1H8BOYAfzvdPfIKK53V7mCpBTe7Kb16PaM8JSXEcUQNBQaiWMI8wY5RvNOPj4GccMjTlfwRBd+oQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.9", + "fast-png": "^6.2.0", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.11", + "core-js": "^3.6.0", + "dompurify": "^3.2.4", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -28473,6 +28598,12 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -31496,6 +31627,16 @@ "node": ">=0.10.0" } }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -32375,6 +32516,16 @@ "node": ">=8" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -32934,6 +33085,16 @@ "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", "license": "MIT" }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -33255,6 +33416,15 @@ "node": ">=8" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -33965,6 +34135,15 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", diff --git a/package.json b/package.json index 450cc45..8f30168 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "bootstrap-icons": "^1.13.1", "dayjs": "^1.11.18", "flatpickr": "^4.6.13", + "html2pdf.js": "^0.12.1", "lucide-react": "^0.543.0", "perfect-scrollbar": "^1.5.6", "powershell": "^2.3.3", diff --git a/src/PagesMedico/DoctorRelatorioManager.jsx b/src/PagesMedico/DoctorRelatorioManager.jsx new file mode 100644 index 0000000..ce24602 --- /dev/null +++ b/src/PagesMedico/DoctorRelatorioManager.jsx @@ -0,0 +1,256 @@ +import API_KEY from '../components/utils/apiKeys'; +import { Link } from 'react-router-dom'; +import {useState, useEffect} from 'react' +import { useAuth } from '../components/utils/AuthProvider'; +import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient'; +import { useNavigate } from 'react-router-dom'; +import html2pdf from 'html2pdf.js'; +const DoctorRelatorioManager = () => { + const navigate = useNavigate() + const {getAuthorizationHeader} = useAuth(); + let authHeader = getAuthorizationHeader() + const [RelatoriosFiltrados, setRelatorios] = useState([]) + const [PacientesComRelatorios, setPacientesComRelatorios] = useState([]) + const [showModal, setShowModal] = useState(false) + const [index, setIndex] = useState() + + useEffect( () => { + let pacientesDosRelatorios = [] + + const ListarPacientes = async () => { + for (let i = 0; i < RelatoriosFiltrados.length; i++) { + let relatorio = RelatoriosFiltrados[i]; + let paciente_id = relatorio.patient_id; + const paciente = await GetPatientByID(paciente_id, authHeader); + console.log(paciente) + if (paciente.length > 0) { + pacientesDosRelatorios.push(paciente[0]); + } + + } + setPacientesComRelatorios(pacientesDosRelatorios); + + } + + ListarPacientes() + console.log(PacientesComRelatorios, 'aqui') + + }, [RelatoriosFiltrados]); + + useEffect(() => { + var myHeaders = new Headers(); +myHeaders.append("apikey", API_KEY); +myHeaders.append("Authorization", authHeader); + +var requestOptions = { + method: 'GET', + headers: myHeaders, + redirect: 'follow' +}; + +fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?patient_id&status", requestOptions) + .then(response => response.json()) + .then(data => { setRelatorios(data); console.log(data) }) + .catch(error => console.log('error', error)); + }, []) + + const BaixarPDFdoRelatorio = (nome_paciente) => { + const elemento = document.getElementById("folhaA4"); // tua div do relatório + const opt = { + margin: 0, + filename: `relatorio_${nome_paciente || "paciente"}.pdf`, + html2canvas: { scale: 2 }, + jsPDF: { unit: "mm", format: "a4", orientation: "portrait" }, + }; + + html2pdf().set(opt).from(elemento).save(); + } + + return ( +
+ {showModal && ( +
+
+
+
+
Relatório de {PacientesComRelatorios[index]?.full_name}
+ +
+
+
+ +
+

Clinica Rise up

+

Dr - CRM/SP 123456

+

Avenida - (79) 9 4444-4444

+
+ +
+

Paciente: {PacientesComRelatorios[index]?.full_name}

+

Data de nascimento: {PacientesComRelatorios[index]?.birth_date}

+ +

Data do exame: {}

+ +

Exame: {RelatoriosFiltrados[index]?.exam}

+ +

Diagnostico: {RelatoriosFiltrados[index]?.diagnosis}

+

Conclusão: {RelatoriosFiltrados[index]?.conclusion}

+
+ +
+

Dr {RelatoriosFiltrados[index]?.required_by}

+

Emitido em: 0

+
+ +
+
+
+ + + + +
+
+
+
+ )} + + +
+

Lista de Relatórios

+
+
+
+
+
+
+

Relatórios Cadastrados

+ + + +
+ +
+
+
+ {" "} + Filtros +
+ +
+ +
+
+ +
+ + + + + + + + + + + + + + {RelatoriosFiltrados.length > 0 ? ( + RelatoriosFiltrados.map((relatorio, index) => ( + + + + + + + + + + + )) + ) : ( + + + + )} + +
PacienteCPFExame
{PacientesComRelatorios[index]?.full_name}{PacientesComRelatorios[index]?.cpf}{relatorio.exam} +
+ + + + + + + +
+ +
+ Nenhum paciente encontrado. +
+
+
+
+
+
+
+ +
+ + ) +} + +export default DoctorRelatorioManager \ No newline at end of file diff --git a/src/PagesMedico/EditPageRelatorio.jsx b/src/PagesMedico/EditPageRelatorio.jsx new file mode 100644 index 0000000..831d8ad --- /dev/null +++ b/src/PagesMedico/EditPageRelatorio.jsx @@ -0,0 +1,65 @@ +import React, { useEffect, useState } from 'react' +import FormRelatorio from '../components/FormRelatorio' +import { useParams } from 'react-router-dom' +import API_KEY from '../components/utils/apiKeys' +import { useAuth } from '../components/utils/AuthProvider' +const EditPageRelatorio = () => { + const params = useParams() + const {getAuthorizationHeader} = useAuth() + let authHeader = getAuthorizationHeader() + const [DictInfo, setDictInfo] = useState({}) + + let RelatorioID = params.id + + const handleSave = (RelatorioInfos) => { + var myHeaders = new Headers(); + myHeaders.append("apikey", API_KEY); + myHeaders.append("Authorization", authHeader); + myHeaders.append("Content-Type", "application/json"); + + const raw = JSON.stringify({...RelatorioInfos, order_number:'REL-2025-4386'}) + + console.log(RelatorioInfos) + + var requestOptions = { + method: 'PATCH', + headers: myHeaders, + body: raw, + redirect: 'follow' + +}; + + fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?id=eq.${RelatorioID}`, requestOptions) + .then(response => response.text()) + .then(result => console.log(result)) + .catch(error => console.log('error', error)); + + } + + useEffect(() => { + var myHeaders = new Headers(); + myHeaders.append("apikey", API_KEY); + myHeaders.append("Authorization", authHeader); + + var requestOptions = { + method: 'GET', + headers: myHeaders, + redirect: 'follow' + }; + + fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?id=eq.${RelatorioID}`, requestOptions) + .then(response => response.json()) + .then(result => setDictInfo(result[0])) + .catch(error => console.log('error', error)); + }, []) + + console.log(RelatorioID) + + return ( +
+ +
+ ) +} + +export default EditPageRelatorio \ No newline at end of file diff --git a/src/PagesMedico/FormNovoRelatorio.jsx b/src/PagesMedico/FormNovoRelatorio.jsx new file mode 100644 index 0000000..3691793 --- /dev/null +++ b/src/PagesMedico/FormNovoRelatorio.jsx @@ -0,0 +1,44 @@ + +import '../PagesMedico/styleMedico/FormNovoRelatorio.css' +import API_KEY from '../components/utils/apiKeys' +import FormRelatorio from '../components/FormRelatorio' +import { useState } from 'react' +import { useAuth } from '../components/utils/AuthProvider' +const FormNovoRelatorio = () => { + const [DictInfo, setDictInfo] = useState({}) + + const {getAuthorizationHeader} = useAuth() + let authHeader = getAuthorizationHeader() + + const handleSave = (data) => { + console.log("Relatório salvo:", data); + + var myHeaders = new Headers(); +myHeaders.append("apikey", API_KEY); +myHeaders.append("Authorization", authHeader); +myHeaders.append("Content-Type", "application/json"); + +var raw = JSON.stringify({...data}); + +var requestOptions = { + method: 'POST', + headers: myHeaders, + body: raw, + redirect: 'follow' +}; + +fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports", requestOptions) + .then(response => response.text()) + .then(result => console.log(result)) + .catch(error => console.log('error', error)); + } + + return ( +
+

Criar Novo Relatorio

+ +
+ ) +} + +export default FormNovoRelatorio \ No newline at end of file diff --git a/src/PagesMedico/styleMedico/FormNovoRelatorio.css b/src/PagesMedico/styleMedico/FormNovoRelatorio.css new file mode 100644 index 0000000..a8fafa3 --- /dev/null +++ b/src/PagesMedico/styleMedico/FormNovoRelatorio.css @@ -0,0 +1,55 @@ +#folhaA4 { + width: 210mm; + min-height: 207mm; + padding: 20mm; + margin: 10mm auto; + border: 1px solid #ccc; + background: white; + +} + +#primeiraLinha{ + display: flex; + flex-direction: row; + gap: 20px; + margin-bottom: 20px; +} + +input,textarea,label{ + font-size: 1.1rem; +} + +textarea{ + width: 100%; + height: 100px; + +} + +.submitButton{ + display: flex; + margin-left: auto; + height:50% ; + padding: 8px 20px; + + font-size: medium; +} + +.bi-download{ + font-size: 1.2rem; + margin-right: 5px; + font-weight: bold; +} + +#infoPaciente{ + margin-top: 50px; + margin-bottom: 40px; +} + +#header-relatorio{ + text-align: center; + margin-bottom: 30px; +} + +.info-paciente{ + font-weight: bold; +} diff --git a/src/PagesMedico/styleMedico/geral.css b/src/PagesMedico/styleMedico/geral.css index 2e86a44..2d46acb 100644 --- a/src/PagesMedico/styleMedico/geral.css +++ b/src/PagesMedico/styleMedico/geral.css @@ -268,4 +268,25 @@ html[data-bs-theme="dark"] tbody tr:hover { html[data-bs-theme="dark"] td { border-bottom: 1px solid var(--cor-borda); color: var(--cor-texto); -} \ No newline at end of file +} +.modal-tabela-relatorio{ + width: 70rem; +} + +.modal-dialog.modal-tabela-relatorio { + max-width: 900px; /* largura máxima da modal */ + width: 100%; /* ocupa até o limite */ + margin: 1.75rem auto; /* centraliza vertical e horizontalmente */ +} + +.modal-content { + height: auto; /* altura variável conforme o conteúdo */ + max-height: none; /* remove limite interno */ +} + +.modal-body { + max-height: 70vh; /* limite vertical — 80% da altura da tela */ + overflow-y: auto; /* ativa rolagem vertical */ + overflow-x: hidden; /* impede rolagem horizontal */ + padding: 20px; /* espaço interno mais agradável */ +} diff --git a/src/components/FormRelatorio.jsx b/src/components/FormRelatorio.jsx new file mode 100644 index 0000000..7c04a49 --- /dev/null +++ b/src/components/FormRelatorio.jsx @@ -0,0 +1,201 @@ +import React from 'react' +import '../PagesMedico/styleMedico/FormNovoRelatorio.css' +import { useState } from 'react' +import { useNavigate } from 'react-router-dom' +import { useAuth } from '../components/utils/AuthProvider' +import { GetPatientByCPF } from '../components/utils/Functions-Endpoints/Patient' +import { FormatCPF } from '../components/utils/Formatar/Format' +import html2pdf from 'html2pdf.js' + +const FormRelatorio = ({onSave, DictInfo, setDictInfo }) => { + const {getAuthorizationHeader} = useAuth() + let authHeader = getAuthorizationHeader() + const navigate= useNavigate() + + const [showModal, setShowModal] = useState(false) + + const BaixarPDFdoRelatorio = () => { + const elemento = document.getElementById("folhaA4"); // tua div do relatório + const opt = { + margin: 0, + filename: `relatorio_${DictInfo?.paciente_nome || "paciente"}.pdf`, + html2canvas: { scale: 2 }, + jsPDF: { unit: "mm", format: "a4", orientation: "portrait" }, + }; + + html2pdf().set(opt).from(elemento).save(); + } + + const handleChange = (e) => { + const { name, value } = e.target; + console.log(name, value) + if(name === 'paciente_cpf') { + const formattedCPF = FormatCPF(value); + setDictInfo((prev) => ({ ...prev, [name]: formattedCPF })); + + const fetchPatient = async () => { + const patientData = await GetPatientByCPF(formattedCPF, authHeader); + if (patientData) { + setDictInfo((prev) => ({ + ...prev, + paciente_cpf:value, + paciente_nome: patientData.full_name, + paciente_id: patientData.id + })); + } + + }; + if(formattedCPF.length === 14){ + fetchPatient(); + } + }else{ + setDictInfo((prev) => ({ ...prev, [name]: value })); + } + } + + const handleSubmit = (e) => { + e.preventDefault(); + console.log(DictInfo) + setShowModal(true) + + +onSave({ + "patient_id": DictInfo.paciente_id, + + "exam": DictInfo.exam, + "diagnosis": DictInfo.diagnosis, + "conclusion": DictInfo.conclusao, + "status": "draft", + "requested_by": DictInfo.requested_by, + + "hide_date": false, + "hide_signature": false, +}); + + } + + return ( +
+ {showModal &&( +
+
+
+
+
Relatório criado com sucesso
+ +
+
+

Você também pode baixa-lo agora em pdf

+
+
+ + + +
+
+
+
+ )} + + +
+ +
+
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+ +
+
+ + +
+ +
+ + +
+
+ + + +
+
+ +

Modelo do relatório

+
+ +
+

Clinica Rise up

+

Dr {DictInfo.requested_by} - CRM/SP 123456

+

Avenida - (79) 9 4444-4444

+
+ +
+

Paciente: {DictInfo?.paciente_nome}

+

Data de nascimento:

+ +

Data do exame: {DictInfo.data_exam}

+ +

Exame: {DictInfo.exam}

+ +

Diagnostico: {DictInfo.diagnostico}

+ +

Conclusão: {DictInfo.conclusao}

+ +
+ +
+

Dr {DictInfo.requested_by}

+

Emitido em: 0

+
+ +
+ +
+ ) +} + +export default FormRelatorio \ No newline at end of file diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index 35abe99..e05dbeb 100644 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -1,43 +1,97 @@ import React, { useState, useEffect } from "react"; -import { Link } from "react-router-dom"; -import menuItems from "../data/sidebar-items-medico.json"; // Use "sidebar-items-secretaria.json" para secretaria e "sidebar-items-adm.json" para ADM +import { Link, useNavigate } from "react-router-dom"; import TrocardePerfis from "./TrocardePerfis"; import MobileMenuToggle from "./MobileMenuToggle"; -// 1. Recebe 'menuItems' e 'onLogout' como props -function Sidebar({ menuItems, onLogout }) { +function Sidebar({ menuItems }) { const [isActive, setIsActive] = useState(true); const [openSubmenu, setOpenSubmenu] = useState(null); const [isMobile, setIsMobile] = useState(false); + const [showLogoutModal, setShowLogoutModal] = useState(false); + const navigate = useNavigate(); - // Detectar se é mobile/tablet + // Detecta se é mobile/tablet useEffect(() => { const checkScreenSize = () => { - setIsMobile(window.innerWidth < 992); - // Em mobile/tablet, sidebar começa fechada - if (window.innerWidth < 992) { - setIsActive(false); - } else { - setIsActive(true); - } + const mobile = window.innerWidth < 992; + setIsMobile(mobile); + setIsActive(!mobile); }; checkScreenSize(); window.addEventListener("resize", checkScreenSize); - return () => window.removeEventListener("resize", checkScreenSize); }, []); - const toggleSidebar = () => { - setIsActive(!isActive); + const toggleSidebar = () => setIsActive(!isActive); + const handleSubmenuClick = (submenuName) => + setOpenSubmenu(openSubmenu === submenuName ? null : submenuName); + + const handleLogoutClick = () => setShowLogoutModal(true); + + const handleLogoutConfirm = async () => { + try { + const token = + localStorage.getItem("token") || + localStorage.getItem("authToken") || + localStorage.getItem("userToken") || + localStorage.getItem("access_token") || + sessionStorage.getItem("token") || + sessionStorage.getItem("authToken"); + + if (token) { + const response = await fetch( + "https://mock.apidog.com/m1/1053378-0-default/auth/v1/logout", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + } + ); + + if (response.status === 204) console.log("Logout realizado com sucesso"); + else if (response.status === 401) console.log("Token inválido ou expirado"); + else { + try { + const errorData = await response.json(); + console.error("Erro no logout:", errorData); + } catch { + console.error("Erro no logout - status:", response.status); + } + } + } + + clearAuthData(); + navigate("/login"); + } catch (error) { + console.error("Erro durante logout:", error); + clearAuthData(); + navigate("/login"); + } finally { + setShowLogoutModal(false); + } }; - const handleSubmenuClick = (submenuName) => { - setOpenSubmenu(openSubmenu === submenuName ? null : submenuName); + const clearAuthData = () => { + ["token","authToken","userToken","access_token","user","auth","userData"].forEach(key => { + localStorage.removeItem(key); + sessionStorage.removeItem(key); + }); + + if (window.caches) { + caches.keys().then(names => { + names.forEach(name => { + if (name.includes("auth") || name.includes("api")) caches.delete(name); + }); + }); + } }; + const handleLogoutCancel = () => setShowLogoutModal(false); + const renderLink = (item) => { - // Links internos (rotas do React Router) if (item.url && item.url.startsWith("/")) { return ( @@ -46,15 +100,8 @@ function Sidebar({ menuItems, onLogout }) { ); } - - // Links externos return ( - + {item.icon && } {item.name} @@ -63,12 +110,8 @@ function Sidebar({ menuItems, onLogout }) { return ( <> - {/* Botão toggle para mobile */} - {isMobile && ( - - )} - - {/* Backdrop para mobile */} + {/* Toggle e backdrop para mobile */} + {isMobile && } {isMobile && isActive && (
)} + {/* Modal de Logout */} + {showLogoutModal && ( +
+
+

Confirmar Logout

+

Tem certeza que deseja encerrar a sessão?

+
+ + +
+
+
+ )} + + {/* Sidebar */}