CPF vizualização e erro 404
This commit is contained in:
parent
3993097c10
commit
fbf15e1cbc
56
et --hard 63659b6
Normal file
56
et --hard 63659b6
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
[33m3993097[m[33m ([m[1;36mHEAD[m[33m -> [m[1;32mmain[m[33m)[m Merge branch 'main' of https://git.popcode.com.br/RiseUP/riseup-squad23
|
||||||
|
[33m63659b6[m Verificação do cpf e colocar o erro 404
|
||||||
|
[33mecae83c[m[33m ([m[1;31mriseup/main[m[33m, [m[1;31mriseup/HEAD[m[33m, [m[1;31morigin/main[m[33m, [m[1;31morigin/HEAD[m[33m)[m Merge pull request 'Conectando-o-resto-das-API' (#2) from Conectando-o-resto-das-API into main
|
||||||
|
[33m908d545[m[33m ([m[1;31mriseup/Conectando-o-resto-das-API[m[33m, [m[1;31morigin/Conectando-o-resto-das-API[m[33m)[m feat: adicionar upload e delete de anexos do paciente
|
||||||
|
[33m4b404c0[m Merge branch 'main' of https://git.popcode.com.br/RiseUP/riseup-squad23
|
||||||
|
[33mbd20c2d[m Merge remote-tracking branch 'origin/main'
|
||||||
|
[33m8aeabd1[m[33m ([m[1;31mriseup/Fix-dos-erros-do-projeto[m[33m, [m[1;31morigin/Fix-dos-erros-do-projeto[m[33m)[m FIx: todos os erros que aparecia no console foram resolvidos
|
||||||
|
[33m0e29e7d[m melhorias na organização de pastas
|
||||||
|
[33m98f076a[m Mergin com TableMelhorias
|
||||||
|
[33m589d590[m Mergin com novas alterações de laudo
|
||||||
|
[33m7b28e2a[m Details melhorias
|
||||||
|
[33m9480edc[m[33m ([m[1;31mriseup/PaginaDetalhes[m[33m, [m[1;31morigin/PaginaDetalhes[m[33m)[m Pàgina detalhes
|
||||||
|
[33me4515cf[m Adição das cores nos cards de consulta
|
||||||
|
[33md3dd2fd[m[33m ([m[1;31mriseup/TableMelhorias[m[33m, [m[1;31morigin/TableMelhorias[m[33m)[m Detalhe nas tabelas
|
||||||
|
[33ma54b119[m Delete Anexos apos pacientes forem excluidos
|
||||||
|
[33m6e93cb5[m atualizar paciente
|
||||||
|
[33mb9a35be[m começo do concerto do editar
|
||||||
|
[33m82469bc[m Details funcional
|
||||||
|
[33mcdfe4ea[m Validação de CPF
|
||||||
|
[33m57c8f67[m[33m ([m[1;31mriseup/DetalhesMedico[m[33m, [m[1;31morigin/DetalhesMedico[m[33m)[m Detalhes do medico
|
||||||
|
[33mb021444[m Mudanças formularios e detalhes
|
||||||
|
[33md5d03b0[m[33m ([m[1;31mriseup/mudanças-de-laudo[m[33m, [m[1;31morigin/mudanças-de-laudo[m[33m)[m atualização do laudo
|
||||||
|
[33ma502bbd[m agendamentos no incio
|
||||||
|
[33m8e1fcd9[m Merge branch 'feature/novo-cadastro-paciente'
|
||||||
|
[33mbea9076[m Merge remote-tracking branch 'origin/PaginaDetalhes'
|
||||||
|
[33me35f217[m mergin branch inicio com main
|
||||||
|
[33m1af8268[m Atualizacão do laudo
|
||||||
|
[33m725d60d[m feat: ajeitei o nome
|
||||||
|
[33mbab85ff[m[33m ([m[1;31mriseup/AgendamentoSidebar[m[33m, [m[1;31morigin/AgendamentoSidebar[m[33m)[m Concertar Agendamento
|
||||||
|
[33mb2707e3[m Refatora o estilo do formulário do paciente para uma aparência de cartão com tipografia maior
|
||||||
|
[33m37e8959[m Refatora o estilo do formulário do paciente para uma aparência de cartão com tipografia maior
|
||||||
|
[33m0930385[m feat: uma piquena mudança
|
||||||
|
[33mf6a19c4[m feat: Adiciona formulário de cadastro de paciente
|
||||||
|
[33md91b5cf[m form de agendar consulta melhorado
|
||||||
|
[33m0a60dd7[m Tabela semana e mes
|
||||||
|
[33m7f07950[m[33m ([m[1;31mriseup/feature-Melhoria-no-Dashboard[m[33m, [m[1;31morigin/feature-Melhoria-no-Dashboard[m[33m)[m feat: Criação da página início e melhoria na navegação
|
||||||
|
[33m39e25ad[m Pagina de detalhes atualizada
|
||||||
|
[33m4f84791[m pequenas mudanaças na tabela de semana e mes
|
||||||
|
[33m6737955[m form para nova consulta e tabelas de horario
|
||||||
|
[33m26ded17[m Nova pagina de detalhes
|
||||||
|
[33m874de84[m Inicio do agendamento
|
||||||
|
[33mf3e7470[m[33m ([m[1;31mriseup/gerenciamento-de-laudo[m[33m, [m[1;31morigin/gerenciamento-de-laudo[m[33m)[m Laudo do Paciente
|
||||||
|
[33m709cd4e[m Merge finalizado
|
||||||
|
[33md6b3e86[m Merge detalhes-do-pacientes para main
|
||||||
|
[33m08ffa55[m Merge remote-tracking branch 'origin/CrudMedico'
|
||||||
|
[33m70c4d5f[m Termino da organização
|
||||||
|
[33medd567d[m Inicio da organização
|
||||||
|
[33m9c09113[m Mudanças pos feedback de davi
|
||||||
|
[33maa3a5fa[m Criação da página dos detalhes dos pacientes
|
||||||
|
[33m5534568[m Inicio de detalhes e atualização do paciente
|
||||||
|
[33m06ff7d5[m Funcionalidade de delete e botão de opções
|
||||||
|
[33m5b63fa2[m Mascara telefones
|
||||||
|
[33mfb9d783[m adição da mascara do CPF
|
||||||
|
[33ma489d84[m metodo GET e POST
|
||||||
|
[33m4eaabbd[m first commit
|
||||||
|
[33ma244691[m Initial commit
|
||||||
54
package-lock.json
generated
54
package-lock.json
generated
@ -33,6 +33,7 @@
|
|||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-input-mask": "^2.0.4",
|
"react-input-mask": "^2.0.4",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill": "^2.0.0",
|
||||||
|
"react-router-dom": "^7.9.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"recharts": "^3.1.2",
|
"recharts": "^3.1.2",
|
||||||
"sweetalert2": "^11.22.4",
|
"sweetalert2": "^11.22.4",
|
||||||
@ -30711,6 +30712,53 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-router": {
|
||||||
|
"version": "7.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.2.tgz",
|
||||||
|
"integrity": "sha512-i2TPp4dgaqrOqiRGLZmqh2WXmbdFknUyiCRmSKs0hf6fWXkTKg5h56b+9F22NbGRAMxjYfqQnpi63egzD2SuZA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "^1.0.1",
|
||||||
|
"set-cookie-parser": "^2.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router-dom": {
|
||||||
|
"version": "7.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.2.tgz",
|
||||||
|
"integrity": "sha512-pagqpVJnjZOfb+vIM23eTp7Sp/AAJjOgaowhP1f1TWOdk5/W8Uk8d/M/0wfleqx7SgjitjNPPsKeCZE1hTSp3w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"react-router": "7.9.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router/node_modules/cookie": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-scripts": {
|
"node_modules/react-scripts": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||||
@ -31978,6 +32026,12 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/set-cookie-parser": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/set-function-length": {
|
"node_modules/set-function-length": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-input-mask": "^2.0.4",
|
"react-input-mask": "^2.0.4",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill": "^2.0.0",
|
||||||
|
"react-router-dom": "^7.9.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"recharts": "^3.1.2",
|
"recharts": "^3.1.2",
|
||||||
"sweetalert2": "^11.22.4",
|
"sweetalert2": "^11.22.4",
|
||||||
|
|||||||
@ -1,98 +1,20 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
// componente de Modal para CPF duplicado
|
|
||||||
const DuplicatePatientModal = ({ show, onClose, onGoToDetails, patient }) => {
|
|
||||||
if (!show || !patient) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const patientName = patient.nome || patient.nome_completo || 'Paciente sem nome';
|
|
||||||
const patientCpf = patient.cpf || 'Não informado';
|
|
||||||
const patientId = patient.id || 'Não informado';
|
|
||||||
const patientDob = patient.data_nascimento || 'Não informada';
|
|
||||||
const patientPhone = patient.contato?.telefone1 || 'Não informado';
|
|
||||||
const patientPhoto = patient.foto || null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="modal show d-block" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
|
||||||
<div className="modal-dialog modal-dialog-centered">
|
|
||||||
<div className="modal-content">
|
|
||||||
<div className="modal-header bg-danger text-white">
|
|
||||||
<h5 className="modal-title">CPF já Cadastrado</h5>
|
|
||||||
<button type="button" className="btn-close" onClick={onClose} style={{ filter: 'invert(1)' }}></button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
<div className="d-flex align-items-center mb-3">
|
|
||||||
{patientPhoto ? (
|
|
||||||
<img src={patientPhoto} alt="Foto do Paciente" className="rounded-circle me-3" style={{ width: '80px', height: '80px', objectFit: 'cover' }} />
|
|
||||||
) : (
|
|
||||||
<div className="rounded-circle me-3 d-flex align-items-center justify-content-center" style={{ width: '80px', height: '80px', backgroundColor: '#e9ecef', fontSize: '2rem' }}>
|
|
||||||
👤
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div>
|
|
||||||
<p className="mb-1"><strong>Nome:</strong> {patientName}</p>
|
|
||||||
<p className="mb-1"><strong>CPF:</strong> {patientCpf}</p>
|
|
||||||
<p className="mb-1"><strong>ID:</strong> {patientId}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className="mb-1"><strong>Data de Nascimento:</strong> {patientDob}</p>
|
|
||||||
<p className="mb-1"><strong>Telefone:</strong> {patientPhone}</p>
|
|
||||||
</div>
|
|
||||||
<div className="modal-footer">
|
|
||||||
<button type="button" className="btn btn-primary" onClick={onClose}>
|
|
||||||
Continuar Cadastro
|
|
||||||
</button>
|
|
||||||
<button type="button" className="btn btn-primary" onClick={() => onGoToDetails(patientId)}>
|
|
||||||
Visualizar Paciente
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
// Modal para Erro 404
|
|
||||||
const Error404Modal = ({ show, onClose }) => {
|
|
||||||
if (!show) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="modal show d-block" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
|
||||||
<div className="modal-dialog modal-dialog-centered">
|
|
||||||
<div className="modal-content">
|
|
||||||
<div className="modal-header bg-danger text-white">
|
|
||||||
<h5 className="modal-title">Erro de Validação</h5>
|
|
||||||
<button type="button" className="btn-close" onClick={onClose} style={{ filter: 'invert(1)' }}></button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
<p className="text-danger" style={{ fontSize: '1.4rem' }}>(Erro 404). Por favor, tente novamente mais tarde.</p>
|
|
||||||
</div>
|
|
||||||
<div className="modal-footer">
|
|
||||||
<button type="button" className="btn btn-primary" onClick={onClose}>
|
|
||||||
Fechar
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
||||||
const [showDuplicateModal, setShowDuplicateModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [duplicatePatientData, setDuplicatePatientData] = useState(null);
|
const [showModal404, setShowModal404] = useState(false);
|
||||||
|
const [pacienteExistente, setPacienteExistente] = useState(null);
|
||||||
const [show404Modal, setShow404Modal] = useState(false);
|
|
||||||
|
|
||||||
const FormatTelefones = (valor) => {
|
const FormatTelefones = (valor) => {
|
||||||
const digits = String(valor).replace(/\D/g, '').slice(0, 11);
|
const digits = String(valor).replace(/\D/g, '').slice(0, 11);
|
||||||
return digits
|
return digits
|
||||||
.replace(/(\d)/, '($1')
|
.replace(/(\d)/, '($1')
|
||||||
.replace(/(\d{2})(\d)/, '$1) $2')
|
.replace(/(\d{2})(\d)/, '$1) $2' )
|
||||||
.replace(/(\d)(\d{4})/, '$1 $2')
|
.replace(/(\d)(\d{4})/, '$1 $2')
|
||||||
.replace(/(\d{4})(\d{4})/, '$1-$2');
|
.replace(/(\d{4})(\d{4})/, '$1-$2')
|
||||||
};
|
}
|
||||||
const ReceberRespostaAPIdoCPF = async (cpf) => {
|
|
||||||
|
const ReceberRespostaAPIdoCPF = async (cpf) =>{
|
||||||
var myHeaders = new Headers();
|
var myHeaders = new Headers();
|
||||||
myHeaders.append("Authorization", "Bearer <token>");
|
myHeaders.append("Authorization", "Bearer <token>");
|
||||||
myHeaders.append("Content-Type", "application/json");
|
myHeaders.append("Content-Type", "application/json");
|
||||||
@ -108,19 +30,19 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
redirect: 'follow'
|
redirect: 'follow'
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes/validar-cpf", requestOptions);
|
const response = await fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes/validar-cpf", requestOptions)
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
if (response.status === 404) {
|
throw new Error('Erro na API de validação de CPF. Status: ' + response.status);
|
||||||
|
|
||||||
throw new Error("404 Not Found");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json()
|
||||||
return result.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPatientById = async (id) => {
|
return result.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BuscarPacientePorId = async (id) => {
|
||||||
var myHeaders = new Headers();
|
var myHeaders = new Headers();
|
||||||
myHeaders.append("Authorization", "Bearer <token>");
|
myHeaders.append("Authorization", "Bearer <token>");
|
||||||
|
|
||||||
@ -141,42 +63,48 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ValidarCPF = async (cpf) => {
|
const ValidarCPF = async (cpf) => {
|
||||||
let aviso = '';
|
let aviso
|
||||||
let Erro = false;
|
let Erro = false
|
||||||
let patientData = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resultadoAPI = await ReceberRespostaAPIdoCPF(cpf);
|
const resultadoAPI = await ReceberRespostaAPIdoCPF(cpf)
|
||||||
const { valido, existe, id } = resultadoAPI;
|
const valido = resultadoAPI.valido
|
||||||
|
const ExisteNoBancoDeDados = resultadoAPI.existe
|
||||||
|
const idPaciente = resultadoAPI.id_paciente
|
||||||
|
|
||||||
if (!valido) {
|
if(valido === false){
|
||||||
aviso = 'CPF inválido';
|
aviso = 'CPF inválido'
|
||||||
Erro = true;
|
Erro = true
|
||||||
} else if (existe) {
|
|
||||||
aviso = 'O CPF informado já está presente no sistema.';
|
|
||||||
Erro = true;
|
|
||||||
patientData = await fetchPatientById(id);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
else if(ExisteNoBancoDeDados === true){
|
||||||
if (e.message === "404 Not Found") {
|
const paciente = await BuscarPacientePorId(idPaciente);
|
||||||
setShow404Modal(true);
|
if (paciente) {
|
||||||
Erro = true;
|
setPacienteExistente(paciente);
|
||||||
} else {
|
setShowModal(true);
|
||||||
aviso = 'Erro ao validar o CPF. Tente novamente.';
|
}
|
||||||
|
Erro = true
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro na validação do CPF:", error);
|
||||||
|
setShowModal404(true);
|
||||||
Erro = true;
|
Erro = true;
|
||||||
}
|
}
|
||||||
|
return [Erro,aviso]
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Erro, aviso, patientData };
|
|
||||||
};
|
|
||||||
const FormatCPF = (valor) => {
|
const FormatCPF = (valor) => {
|
||||||
const digits = String(valor).replace(/\D/g, '').slice(0, 11);
|
const digits = String(valor).replace(/\D/g, '').slice(0, 11);
|
||||||
return digits
|
return digits
|
||||||
.replace(/(\d{3})(\d)/, '$1.$2')
|
.replace(/(\d{3})(\d)/, '$1.$2')
|
||||||
.replace(/(\d{3})(\d)/, '$1.$2')
|
.replace(/(\d{3})(\d)/, '$1.$2')
|
||||||
.replace(/(\d{3})(\d{1,2})$/, '$1-$2');
|
.replace(/(\d{3})(\d{1,2})$/, '$1-$2');
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Estado para armazenar a URL da foto do avatar
|
||||||
const [avatarUrl, setAvatarUrl] = useState(null);
|
const [avatarUrl, setAvatarUrl] = useState(null);
|
||||||
|
|
||||||
|
// Estado para controlar quais seções estão colapsadas
|
||||||
const [collapsedSections, setCollapsedSections] = useState({
|
const [collapsedSections, setCollapsedSections] = useState({
|
||||||
dadosPessoais: true,
|
dadosPessoais: true,
|
||||||
infoMedicas: false,
|
infoMedicas: false,
|
||||||
@ -185,6 +113,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
contato: false,
|
contato: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Função para alternar o estado de colapso de uma seção
|
||||||
const handleToggleCollapse = (section) => {
|
const handleToggleCollapse = (section) => {
|
||||||
setCollapsedSections(prevState => ({
|
setCollapsedSections(prevState => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
@ -202,20 +131,28 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
} else {
|
} else {
|
||||||
setFormData(prev => ({ ...prev, imc: '' }));
|
setFormData(prev => ({ ...prev, imc: '' }));
|
||||||
}
|
}
|
||||||
}, [formData.peso, formData.altura, setFormData]);
|
}, [formData.peso, formData.altura]);
|
||||||
|
|
||||||
const [enderecoData, setEnderecoData] = useState({});
|
|
||||||
useEffect(() => { setEnderecoData(formData.endereco || {}); }, [formData.endereco]);
|
|
||||||
|
|
||||||
const [contato, setContato] = useState({});
|
const [enderecoData, setEnderecoData] = useState({})
|
||||||
useEffect(() => { setContato(formData.contato || {}); }, [formData.contato]);
|
useEffect(() => {setEnderecoData(formData.endereco || {}); console.log(enderecoData)}, [formData.endereco])
|
||||||
|
|
||||||
|
const [contato, setContato] = useState({})
|
||||||
|
|
||||||
|
useEffect(() => {setContato(formData.contato || {})}, [formData.contato])
|
||||||
|
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const { name, value, type, checked, files } = e.target;
|
const { name, value, type, checked, files } = e.target;
|
||||||
|
|
||||||
|
console.log(formData, name)
|
||||||
|
|
||||||
if (type === 'checkbox') {
|
if (type === 'checkbox') {
|
||||||
setFormData({ ...formData, [name]: checked });
|
setFormData({ ...formData, [name]: checked });
|
||||||
} else if (type === 'file') {
|
} else if (type === 'file') {
|
||||||
setFormData({ ...formData, [name]: files[0] });
|
setFormData({ ...formData, [name]: files[0] });
|
||||||
|
|
||||||
|
// Lógica para pré-visualizar a imagem no avatar
|
||||||
if (name === 'foto' && files[0]) {
|
if (name === 'foto' && files[0]) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onloadend = () => {
|
reader.onloadend = () => {
|
||||||
@ -223,22 +160,24 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
};
|
};
|
||||||
reader.readAsDataURL(files[0]);
|
reader.readAsDataURL(files[0]);
|
||||||
} else if (name === 'foto' && !files[0]) {
|
} else if (name === 'foto' && !files[0]) {
|
||||||
setAvatarUrl(null);
|
setAvatarUrl(null); // Limpa o avatar se nenhum arquivo for selecionado
|
||||||
}
|
}}
|
||||||
}
|
|
||||||
|
|
||||||
if (name.includes('cpf')) {
|
if (name.includes('cpf')) {
|
||||||
setFormData({ ...formData, cpf: FormatCPF(value) });
|
setFormData({...formData, cpf:FormatCPF(value) });
|
||||||
} else if (name.includes('telefone')) {
|
} else if (name.includes('telefone')) {
|
||||||
let telefoneFormatado = FormatTelefones(value);
|
let telefoneFormatado = FormatTelefones(value);
|
||||||
setContato(prev => ({ ...prev, [name]: telefoneFormatado }));
|
setContato(prev => ({ ...prev, [name]: telefoneFormatado }));
|
||||||
} else if (name === 'email') {
|
}else if (name === 'email') {
|
||||||
setContato(prev => ({ ...prev, email: value }));
|
setContato(prev => ({ ...prev, email: value }));
|
||||||
} else if (name.includes('endereco')) {
|
}else if(name.includes('endereco')) {
|
||||||
setEnderecoData(prev => ({ ...prev, [name.split('.')[1]]: value }));
|
setEnderecoData(prev => ({ ...prev, [name.split('.')[1]]: value }));
|
||||||
} else {
|
}else{
|
||||||
setFormData({ ...formData, [name]: value });
|
setFormData({ ...formData, [name]: value });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCepBlur = async () => {
|
const handleCepBlur = async () => {
|
||||||
const cep = formData.cep.replace(/\D/g, '');
|
const cep = formData.cep.replace(/\D/g, '');
|
||||||
if (cep.length === 8) {
|
if (cep.length === 8) {
|
||||||
@ -261,35 +200,19 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
<<<<<<< HEAD
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
if (!formData.nome || !formData.cpf || !formData.sexo || !formData.data_nascimento) {
|
|
||||||
alert('Por favor, preencha Nome, CPF, Gênero e data de nascimento.');
|
|
||||||
=======
|
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async () => {
|
||||||
e.preventDefault();
|
|
||||||
if (!formData.nome || !formData.cpf || !formData.sexo || !formData.data_nascimento){
|
if (!formData.nome || !formData.cpf || !formData.sexo || !formData.data_nascimento){
|
||||||
alert('Por favor, preencha Nome ,CPF, Gênero e data de nascimento.');
|
alert('Por favor, preencha Nome ,CPF, Gênero e data de nascimento.');
|
||||||
>>>>>>> ecae83cf4cc5cac2487d7fbd9cb61a8d706b01a3
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { Erro, aviso, patientData } = await ValidarCPF(formData.cpf);
|
const [CPFinvalido] = await ValidarCPF(formData.cpf);
|
||||||
|
if(CPFinvalido === true){
|
||||||
if (Erro) {
|
|
||||||
if (patientData) {
|
|
||||||
setDuplicatePatientData(patientData);
|
|
||||||
setShowDuplicateModal(true);
|
|
||||||
} else {
|
|
||||||
if (aviso) {
|
|
||||||
alert(aviso);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pacienteSalvo = await onSave({
|
onSave({
|
||||||
...formData,
|
...formData,
|
||||||
endereco: {
|
endereco: {
|
||||||
cep: enderecoData.cep,
|
cep: enderecoData.cep,
|
||||||
@ -322,55 +245,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
pacienteVip: formData.pacienteVip,
|
pacienteVip: formData.pacienteVip,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
<<<<<<< HEAD
|
|
||||||
};
|
};
|
||||||
=======
|
|
||||||
|
|
||||||
const pacienteId = pacienteSalvo.id;
|
|
||||||
|
|
||||||
try{
|
|
||||||
if (formData.foto) await uploadFotoPaciente(pacienteId, formData.foto);
|
|
||||||
if (formData.anexos) await uploadAnexoPaciente(pacienteId, formData.anexos);
|
|
||||||
alert("Paciente salvo com sucesso!");
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
alert("Erro ao salvar paciente ou enviar arquivos.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const uploadFotoPaciente = async (pacienteId, foto) => {
|
|
||||||
const formDataUpload = new FormData();
|
|
||||||
formDataUpload.append('foto', foto);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await fetch(`https://suaapi.com/pacientes/${pacienteId}/foto`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Authorization': 'Bearer <token>' },
|
|
||||||
body: formDataUpload
|
|
||||||
});
|
|
||||||
if (!res.ok) throw new Error('Erro ao enviar foto');
|
|
||||||
alert('Foto enviada com sucesso!');
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
alert('Falha ao enviar foto');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const uploadAnexoPaciente = async (pacienteId, anexo) => {
|
|
||||||
const formDataUpload = new FormData();
|
|
||||||
formDataUpload.append('anexo', anexo);
|
|
||||||
try {
|
|
||||||
const res = await fetch(`https://suaapi.com/pacientes/${pacienteId}/anexos`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Authorization': 'Bearer <token>' },
|
|
||||||
body: formDataUpload
|
|
||||||
});
|
|
||||||
if (!res.ok) throw new Error('Erro ao enviar anexo');
|
|
||||||
alert('Anexo enviado com sucesso!');
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
alert('Falha ao enviar anexo');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
>>>>>>> ecae83cf4cc5cac2487d7fbd9cb61a8d706b01a3
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card p-3">
|
<div className="card p-3">
|
||||||
@ -386,9 +261,9 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</h4>
|
</h4>
|
||||||
<div className={`collapse${collapsedSections.dadosPessoais ? ' show' : ''}`}>
|
<div className={`collapse${collapsedSections.dadosPessoais ? ' show' : ''}`}>
|
||||||
<div className="row mt-3">
|
<div className="row mt-3">
|
||||||
|
{/* AVATAR E INPUT DE FOTO */}
|
||||||
<div className="col-md-6 mb-3 d-flex align-items-center">
|
<div className="col-md-6 mb-3 d-flex align-items-center">
|
||||||
<div className="me-3">
|
<div className="me-3">
|
||||||
{/* AVATAR E INPUT DE FOTO */}
|
|
||||||
{avatarUrl ? (
|
{avatarUrl ? (
|
||||||
<img
|
<img
|
||||||
src={avatarUrl}
|
src={avatarUrl}
|
||||||
@ -450,7 +325,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label style={{ fontSize: '1.1rem' }}>CPF: *</label>
|
<label style={{ fontSize: '1.1rem' }}>CPF: *</label>
|
||||||
<input type="text" className="form-control" name="cpf" value={formData.cpf} onChange={handleChange} style={{ fontSize: '1.1rem' }} />
|
<input type="text" className="form-control" name="cpf" value={formData.cpf} onChange={ handleChange} style={{ fontSize: '1.1rem' }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label style={{ fontSize: '1.1rem' }}>RG:</label>
|
<label style={{ fontSize: '1.1rem' }}>RG:</label>
|
||||||
@ -542,6 +417,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CAMPOS MOVIDOS */}
|
{/* CAMPOS MOVIDOS */}
|
||||||
<div className="col-md-12 mb-3 mt-3">
|
<div className="col-md-12 mb-3 mt-3">
|
||||||
<label style={{ fontSize: '1.1rem' }}>Observações:</label>
|
<label style={{ fontSize: '1.1rem' }}>Observações:</label>
|
||||||
@ -555,9 +431,11 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
<span className="ms-2" style={{ fontSize: '1.1rem' }}>{formData.anexos ? formData.anexos.name : 'Nenhum arquivo escolhido'}</span>
|
<span className="ms-2" style={{ fontSize: '1.1rem' }}>{formData.anexos ? formData.anexos.name : 'Nenhum arquivo escolhido'}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* INFORMAÇÕES MÉDICAS */}
|
{/* INFORMAÇÕES MÉDICAS */}
|
||||||
<div className="mb-5 p-4 border rounded shadow-sm">
|
<div className="mb-5 p-4 border rounded shadow-sm">
|
||||||
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('infoMedicas')} style={{ fontSize: '1.8rem' }}>
|
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('infoMedicas')} style={{ fontSize: '1.8rem' }}>
|
||||||
@ -601,6 +479,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* INFORMAÇÕES DE CONVÊNIO */}
|
{/* INFORMAÇÕES DE CONVÊNIO */}
|
||||||
<div className="mb-5 p-4 border rounded shadow-sm">
|
<div className="mb-5 p-4 border rounded shadow-sm">
|
||||||
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('infoConvenio')} style={{ fontSize: '1.8rem' }}>
|
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('infoConvenio')} style={{ fontSize: '1.8rem' }}>
|
||||||
@ -653,6 +532,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ENDEREÇO */}
|
{/* ENDEREÇO */}
|
||||||
<div className="mb-5 p-4 border rounded shadow-sm">
|
<div className="mb-5 p-4 border rounded shadow-sm">
|
||||||
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('endereco')} style={{ fontSize: '1.8rem' }}>
|
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('endereco')} style={{ fontSize: '1.8rem' }}>
|
||||||
@ -694,6 +574,7 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CONTATO */}
|
{/* CONTATO */}
|
||||||
<div className="mb-5 p-4 border rounded shadow-sm">
|
<div className="mb-5 p-4 border rounded shadow-sm">
|
||||||
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('contato')} style={{ fontSize: '1.8rem' }}>
|
<h4 className="mb-4 cursor-pointer d-flex justify-content-between align-items-center" onClick={() => handleToggleCollapse('contato')} style={{ fontSize: '1.8rem' }}>
|
||||||
@ -724,23 +605,6 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Modal para CPF duplicado */}
|
|
||||||
<DuplicatePatientModal
|
|
||||||
show={showDuplicateModal}
|
|
||||||
onClose={() => setShowDuplicateModal(false)}
|
|
||||||
onGoToDetails={(id) => {
|
|
||||||
console.log(`Navegando para a página de detalhes do paciente com ID: ${id}`);
|
|
||||||
setShowDuplicateModal(false);
|
|
||||||
}}
|
|
||||||
patient={duplicatePatientData}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/*404 Error Modal */}
|
|
||||||
<Error404Modal
|
|
||||||
show={show404Modal}
|
|
||||||
onClose={() => setShow404Modal(false)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Botões */}
|
{/* Botões */}
|
||||||
<div className="mt-3 text-center">
|
<div className="mt-3 text-center">
|
||||||
<button className="btn btn-success me-3" onClick={handleSubmit} style={{ fontSize: '1.2rem', padding: '0.75rem 1.5rem' }}>
|
<button className="btn btn-success me-3" onClick={handleSubmit} style={{ fontSize: '1.2rem', padding: '0.75rem 1.5rem' }}>
|
||||||
@ -750,6 +614,77 @@ function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
|||||||
Cancelar
|
Cancelar
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Modal para paciente existente */}
|
||||||
|
{showModal && pacienteExistente && (
|
||||||
|
<div className="modal" style={{ display: 'block', backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<h5 className="modal-title">Ops! Este CPF já está cadastrado</h5>
|
||||||
|
<button type="button" className="btn-close" onClick={() => setShowModal(false)}></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="text-center mb-3">
|
||||||
|
<img
|
||||||
|
src={pacienteExistente.foto || 'https://via.placeholder.com/100'}
|
||||||
|
alt="Foto do Paciente"
|
||||||
|
className="rounded-circle"
|
||||||
|
style={{ width: '100px', height: '100px', objectFit: 'cover' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p><strong>ID do Paciente:</strong> {pacienteExistente.id}</p>
|
||||||
|
<p><strong>Nome Completo:</strong> {pacienteExistente.nome}</p>
|
||||||
|
<p><strong>CPF:</strong> {pacienteExistente.cpf}</p>
|
||||||
|
<p><strong>Data de Nascimento:</strong> {pacienteExistente.data_nascimento}</p>
|
||||||
|
<p><strong>Telefone:</strong> {pacienteExistente.contato.telefone1}</p>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => setShowModal(false)}
|
||||||
|
>
|
||||||
|
Fechar e Continuar no Cadastro
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
|
||||||
|
alert(`Navegando para os detalhes do paciente ID: ${pacienteExistente.id}`);
|
||||||
|
setShowModal(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Visualizar Paciente Existente
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Erro 404 */}
|
||||||
|
{showModal404 && (
|
||||||
|
<div className="modal" style={{ display: 'block', backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-header bg-danger text-white">
|
||||||
|
<h5 className="modal-title">Erro de Validação</h5>
|
||||||
|
<button type="button" className="btn-close btn-close-white" onClick={() => setShowModal404(false)}></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<p style={{ fontSize: '1.4rem' }}>(Erro 404).Por favor,tente novamente mais tarde.</p>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-primary" onClick={() => setShowModal404(false)}>
|
||||||
|
Fechar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user