Compare commits
4 Commits
54625235d5
...
04ed9b46b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 04ed9b46b2 | |||
| fbf15e1cbc | |||
| 3993097c10 | |||
| 63659b69cc |
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-input-mask": "^2.0.4",
|
||||
"react-quill": "^2.0.0",
|
||||
"react-router-dom": "^7.9.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"recharts": "^3.1.2",
|
||||
"sweetalert2": "^11.22.4",
|
||||
@ -30711,6 +30712,53 @@
|
||||
"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": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||
@ -31978,6 +32026,12 @@
|
||||
"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": {
|
||||
"version": "1.2.2",
|
||||
"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-input-mask": "^2.0.4",
|
||||
"react-quill": "^2.0.0",
|
||||
"react-router-dom": "^7.9.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"recharts": "^3.1.2",
|
||||
"sweetalert2": "^11.22.4",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import InputMask from "react-input-mask";
|
||||
|
||||
|
||||
function DoctorForm({ onSave, onCancel, PatientDict }) {
|
||||
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
|
||||
|
||||
function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage }) {
|
||||
|
||||
// Estado para controlar modal de feedback
|
||||
const [showMessage, setShowMessage] = useState(false);
|
||||
const [message, setMessage] = useState('');
|
||||
const [messageType, setMessageType] = useState('success'); // 'success' ou 'danger'
|
||||
|
||||
function PatientForm({ onSave, onCancel, formData, setFormData }) {
|
||||
// Estado para controlar a exibição do modal e os dados do paciente existente
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [showModal404, setShowModal404] = useState(false);
|
||||
const [pacienteExistente, setPacienteExistente] = useState(null);
|
||||
|
||||
const FormatTelefones = (valor) => {
|
||||
const digits = String(valor).replace(/\D/g, '').slice(0, 11);
|
||||
@ -36,28 +32,63 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
};
|
||||
|
||||
const response = await fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes/validar-cpf", requestOptions)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Erro na API de validação de CPF. Status: ' + response.status);
|
||||
}
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
return result.data
|
||||
|
||||
}
|
||||
|
||||
// Função para buscar os dados completos do paciente pelo ID
|
||||
const BuscarPacientePorId = async (id) => {
|
||||
var myHeaders = new Headers();
|
||||
myHeaders.append("Authorization", "Bearer <token>");
|
||||
|
||||
var requestOptions = {
|
||||
method: 'GET',
|
||||
headers: myHeaders,
|
||||
redirect: 'follow'
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${id}`, requestOptions);
|
||||
const result = await response.json();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Erro ao buscar paciente por ID:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const ValidarCPF = async (cpf) => {
|
||||
let aviso
|
||||
let Erro = false
|
||||
|
||||
const resultadoAPI = await ReceberRespostaAPIdoCPF(cpf)
|
||||
try {
|
||||
const resultadoAPI = await ReceberRespostaAPIdoCPF(cpf)
|
||||
const valido = resultadoAPI.valido
|
||||
const ExisteNoBancoDeDados = resultadoAPI.existe
|
||||
const idPaciente = resultadoAPI.id_paciente
|
||||
|
||||
const valido = resultadoAPI.valido
|
||||
const ExisteNoBancoDeDados = resultadoAPI.existe
|
||||
|
||||
if(valido === false){
|
||||
aviso = 'CPF inválido'
|
||||
Erro = true
|
||||
}
|
||||
else if(ExisteNoBancoDeDados === true){
|
||||
aviso = 'O CPF informado já está presente no sistema'
|
||||
Erro = true
|
||||
if(valido === false){
|
||||
aviso = 'CPF inválido'
|
||||
Erro = true
|
||||
}
|
||||
else if(ExisteNoBancoDeDados === true){
|
||||
const paciente = await BuscarPacientePorId(idPaciente);
|
||||
if (paciente) {
|
||||
setPacienteExistente(paciente);
|
||||
setShowModal(true);
|
||||
}
|
||||
Erro = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Erro na validação do CPF:", error);
|
||||
setShowModal404(true);
|
||||
Erro = true;
|
||||
}
|
||||
return [Erro,aviso]
|
||||
}
|
||||
@ -115,6 +146,8 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
const handleChange = (e) => {
|
||||
const { name, value, type, checked, files } = e.target;
|
||||
|
||||
console.log(formData, name)
|
||||
|
||||
if (type === 'checkbox') {
|
||||
setFormData({ ...formData, [name]: checked });
|
||||
} else if (type === 'file') {
|
||||
@ -129,24 +162,21 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
reader.readAsDataURL(files[0]);
|
||||
} else if (name === 'foto' && !files[0]) {
|
||||
setAvatarUrl(null); // Limpa o avatar se nenhum arquivo for selecionado
|
||||
}}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
if (name.includes('cpf')) {
|
||||
|
||||
setFormData({...formData, cpf:FormatCPF(value) });
|
||||
|
||||
}else if (name.includes('telefone')) {
|
||||
} else if (name.includes('telefone')) {
|
||||
let telefoneFormatado = FormatTelefones(value);
|
||||
setContato(prev => ({ ...prev, [name]: telefoneFormatado }));
|
||||
}else if (name === 'email') {
|
||||
setContato(prev => ({ ...prev, email: value }));
|
||||
setContato(prev => ({ ...prev, email: value }));
|
||||
}else if(name.includes('endereco')) {
|
||||
setEnderecoData(prev => ({ ...prev, [name.split('.')[1]]: value }));
|
||||
}else{
|
||||
console.log(formData, value)
|
||||
setFormData({ ...formData, [name]: value });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleCepBlur = async () => {
|
||||
@ -172,27 +202,19 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const handleSubmit = async () => {
|
||||
if (!formData.nome || !formData.cpf || !formData.sexo || !formData.data_nascimento){
|
||||
console.log(formData)
|
||||
setMessage('Por favor, preencha: Nome, CPF, Gênero, Data de Nascimento .');
|
||||
setMessageType('danger');
|
||||
setShowMessage(true);
|
||||
alert('Por favor, preencha Nome ,CPF, Gênero e data de nascimento.');
|
||||
return;
|
||||
}
|
||||
|
||||
const CPFinvalido = await ValidarCPF(formData.cpf);
|
||||
if(CPFinvalido[0] === true){
|
||||
setMessage(CPFinvalido[1]);
|
||||
setMessageType('danger');
|
||||
setShowMessage(true); return
|
||||
const [CPFinvalido] = await ValidarCPF(formData.cpf);
|
||||
if(CPFinvalido === true){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const pacienteSalvo = await onSave({
|
||||
onSave({
|
||||
...formData,
|
||||
id: 2,
|
||||
endereco: {
|
||||
cep: enderecoData.cep,
|
||||
cidade: enderecoData.cidade,
|
||||
@ -223,87 +245,11 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
validadeIndeterminada: formData.validadeIndeterminada,
|
||||
pacienteVip: formData.pacienteVip,
|
||||
},
|
||||
|
||||
});
|
||||
setMessage('Paciente salvo com sucesso!');
|
||||
setMessageType('success');
|
||||
setShowMessage(true);
|
||||
|
||||
|
||||
const pacienteId = pacienteSalvo.id;
|
||||
|
||||
try{
|
||||
if (formData.foto) await uploadFotoPaciente(pacienteId, formData.foto);
|
||||
if (formData.anexos) await uploadAnexoPaciente(pacienteId, formData.anexos);
|
||||
|
||||
} 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, 'deu erro');
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="card p-3" style={{ position: 'relative' }}>
|
||||
{/* Modal de feedback */}
|
||||
{showMessage && (
|
||||
<div className="modal-backdrop" style={{ position: 'fixed', top: 0, left: 0, width: '100vw', height: '100vh', background: 'rgba(0,0,0,0.15)', zIndex: 1050 }}></div>
|
||||
)}
|
||||
{showMessage && (
|
||||
<div className="modal d-block" tabIndex="-1" role="dialog" style={{ zIndex: 1100 }}>
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content" style={{ borderRadius: '12px', boxShadow: '0 4px 24px rgba(0,0,0,0.10)' }}>
|
||||
<div className="modal-header" style={{ borderBottom: '2px solid #23336f1a' }}>
|
||||
<h5 className="modal-title" style={{ fontWeight: 700, color: '#23336f' }}>
|
||||
{messageType === 'danger' ? 'Atenção' : 'Sucesso'}
|
||||
</h5>
|
||||
<button type="button" className="btn-close" aria-label="Close" onClick={() => setShowMessage(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body" style={{ fontSize: '1.3rem', color: '#23336f' }}>
|
||||
{message}
|
||||
</div>
|
||||
<div className="modal-footer" style={{ borderTop: '2px solid #23336f1a', justifyContent: 'flex-end' }}>
|
||||
<button type="button" className="btn btn-primary" style={{ minWidth: 100 }} onClick={setCurrentPage('table')}>
|
||||
Fechar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="card p-3">
|
||||
<h3 className="mb-4 text-center" style={{ fontSize: '2.5rem' }}>MediConnect</h3>
|
||||
|
||||
{/* DADOS PESSOAIS */}
|
||||
@ -367,7 +313,7 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
</div>
|
||||
<div className="col-md-6 mb-3">
|
||||
<label style={{ fontSize: '1.1rem' }}>Data de nascimento: *</label>
|
||||
<input type="date" className="form-control" name="data_nascimento" value={formData.data_nascimento} onChange={handleChange} style={{ fontSize: '1.1rem' }} min="1900-01-01" max="2025-09-24"s/>
|
||||
<input type="date" className="form-control" name="data_nascimento" value={formData.data_nascimento} onChange={handleChange} style={{ fontSize: '1.1rem' }} />
|
||||
</div>
|
||||
<div className="col-md-6 mb-3">
|
||||
<label style={{ fontSize: '1.1rem' }}>Gênero: *</label>
|
||||
@ -669,6 +615,77 @@ function PatientForm({ onSave, onCancel,formData, setFormData,setCurrentPage })
|
||||
Cancelar
|
||||
</button>
|
||||
</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-secondary" onClick={() => setShowModal404(false)}>
|
||||
Fechar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
347
src/pages/Table.jsx
Normal file
347
src/pages/Table.jsx
Normal file
@ -0,0 +1,347 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
function TablePaciente({ setCurrentPage, setPatientID }) {
|
||||
const [pacientes, setPacientes] = useState([]);
|
||||
const [search, setSearch] = useState("");
|
||||
const [filtroConvenio, setFiltroConvenio] = useState("Todos");
|
||||
const [filtroVIP, setFiltroVIP] = useState(false);
|
||||
const [filtroAniversariante, setFiltroAniversariante] = useState(false);
|
||||
|
||||
// Estado para controlar a exibição do erro 404
|
||||
const [showError404, setShowError404] = useState(false);
|
||||
|
||||
const GetAnexos = async (id) => {
|
||||
var myHeaders = new Headers();
|
||||
myHeaders.append("Authorization", "Bearer <token>");
|
||||
|
||||
var requestOptions = {
|
||||
method: 'GET',
|
||||
headers: myHeaders,
|
||||
redirect: 'follow'
|
||||
};
|
||||
try {
|
||||
const response = await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${id}/anexos`, requestOptions);
|
||||
if (!response.ok) {
|
||||
setShowError404(true);
|
||||
setTimeout(() => setShowError404(false), 5000); // Esconde a mensagem após 5 segundos
|
||||
throw new Error('Erro 404');
|
||||
}
|
||||
const result = await response.json();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.log('error', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
const DeleteAnexo = async (patientID) => {
|
||||
const RespostaGetAnexos = await GetAnexos(patientID);
|
||||
for (let i = 0; i < RespostaGetAnexos.length; i++) {
|
||||
const idAnexo = RespostaGetAnexos[i].id;
|
||||
|
||||
var myHeaders = new Headers();
|
||||
myHeaders.append("Authorization", "Bearer <token>");
|
||||
|
||||
var requestOptions = {
|
||||
method: 'DELETE',
|
||||
headers: myHeaders,
|
||||
redirect: 'follow'
|
||||
};
|
||||
|
||||
fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos/${idAnexo}`, requestOptions)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
setShowError404(true);
|
||||
setTimeout(() => setShowError404(false), 5000); // Esconde a mensagem após 5 segundos
|
||||
throw new Error('Erro 404');
|
||||
}
|
||||
return response.text();
|
||||
})
|
||||
.then(result => console.log('anexo excluido com sucesso', result))
|
||||
.catch(error => console.log('error', error));
|
||||
}
|
||||
}
|
||||
|
||||
const deletePatient = async (id) => {
|
||||
DeleteAnexo(id);
|
||||
const requestOptionsDelete = { method: "DELETE", redirect: "follow" };
|
||||
if (!window.confirm("Tem certeza que deseja excluir este paciente?")) return;
|
||||
await fetch(
|
||||
`https://mock.apidog.com/m1/1053378-0-default/pacientes/${id}`,
|
||||
requestOptionsDelete
|
||||
)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
setShowError404(true);
|
||||
setTimeout(() => setShowError404(false), 5000); // Esconde a mensagem após 5 segundos
|
||||
throw new Error('Erro 404');
|
||||
}
|
||||
return response.text();
|
||||
})
|
||||
.then((mensage) => console.log(mensage))
|
||||
.catch((error) => console.log("Deu problema", error));
|
||||
};
|
||||
|
||||
const toggleVIP = async (id, atual) => {
|
||||
const novoStatus = atual === true ? false : true;
|
||||
await fetch(
|
||||
`https://mock.apidog.com/m1/1053378-0-default/pacientes/${id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ vip: novoStatus }),
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
setShowError404(true);
|
||||
setTimeout(() => setShowError404(false), 5000);
|
||||
throw new Error('Erro 404');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(() => {
|
||||
setPacientes((prev) =>
|
||||
prev.map((p) => (p.id === id ? { ...p, vip: novoStatus } : p))
|
||||
);
|
||||
})
|
||||
.catch((error) => console.log("Erro ao atualizar VIP:", error));
|
||||
};
|
||||
|
||||
const updateConvenio = async (id, convenio) => {
|
||||
await fetch(
|
||||
`https://mock.apidog.com/m1/1053378-0-default/pacientes/${id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ convenio }),
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
setShowError404(true);
|
||||
setTimeout(() => setShowError404(false), 5000);
|
||||
throw new Error('Erro 404');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(() => {
|
||||
setPacientes((prev) =>
|
||||
prev.map((p) => (p.id === id ? { ...p, convenio } : p))
|
||||
);
|
||||
})
|
||||
.catch((error) => console.log("Erro ao atualizar convênio:", error));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes")
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
setShowError404(true);
|
||||
setTimeout(() => setShowError404(false), 5000);
|
||||
throw new Error('Erro 404');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((result) => setPacientes(result["data"]))
|
||||
.catch((error) =>
|
||||
console.log("Erro para encontrar pacientes no banco de dados", error)
|
||||
);
|
||||
}, []);
|
||||
|
||||
const ehAniversariante = (dataNascimento) => {
|
||||
if (!dataNascimento) return false;
|
||||
const hoje = new Date();
|
||||
const nascimento = new Date(dataNascimento);
|
||||
return (
|
||||
hoje.getDate() === nascimento.getDate() &&
|
||||
hoje.getMonth() === nascimento.getMonth()
|
||||
);
|
||||
};
|
||||
|
||||
const pacientesFiltrados = pacientes.filter((paciente) => {
|
||||
const texto = `${paciente.nome}`.toLowerCase();
|
||||
const passaBusca = texto.includes(search.toLowerCase());
|
||||
const passaVIP = filtroVIP ? paciente.vip === true : true;
|
||||
const passaConvenio =
|
||||
filtroConvenio === "Todos" || paciente.convenio === filtroConvenio;
|
||||
const passaAniversario = filtroAniversariante
|
||||
? ehAniversariante(paciente.data_nascimento)
|
||||
: true;
|
||||
return passaBusca && passaVIP && passaConvenio && passaAniversario;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="page-heading">
|
||||
<h3>Lista de Pacientes</h3>
|
||||
</div>
|
||||
<div className="page-content">
|
||||
<section className="row">
|
||||
<div className="col-12">
|
||||
<div className="card">
|
||||
<div className="card-header d-flex justify-content-between align-items-center">
|
||||
<h4 className="card-title mb-0">Pacientes Cadastrados</h4>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => setCurrentPage("form-layout")}
|
||||
>
|
||||
<i className="bi bi-plus-circle"></i> Adicionar Paciente
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="card-body">
|
||||
{showError404 && (
|
||||
<div className="alert alert-danger" role="alert">
|
||||
(Erro 404). Por favor, tente novamente mais tarde.
|
||||
</div>
|
||||
)}
|
||||
<div className="card p-3 mb-3">
|
||||
<h5 className="mb-3">
|
||||
<i className="bi bi-funnel-fill me-2 text-primary"></i> Filtros
|
||||
</h5>
|
||||
<div
|
||||
className="d-flex flex-nowrap align-items-center gap-2"
|
||||
style={{ overflowX: "auto", paddingBottom: "6px" }}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="Buscar por nome..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
style={{
|
||||
minWidth: 250,
|
||||
maxWidth: 300,
|
||||
width: 260,
|
||||
flex: "0 0 auto",
|
||||
}}
|
||||
/>
|
||||
<select
|
||||
className="form-select"
|
||||
value={filtroConvenio}
|
||||
onChange={(e) => setFiltroConvenio(e.target.value)}
|
||||
style={{
|
||||
minWidth: 200,
|
||||
width: 180,
|
||||
flex: "0 0 auto",
|
||||
}}
|
||||
>
|
||||
<option>Todos os Convênios</option>
|
||||
<option>Bradesco Saúde</option>
|
||||
<option>Hapvida</option>
|
||||
<option>Unimed</option>
|
||||
</select>
|
||||
<button
|
||||
className={`btn ${filtroVIP ? "btn-primary" : "btn-outline-primary"}`}
|
||||
onClick={() => setFiltroVIP(!filtroVIP)}
|
||||
style={{ flex: "0 0 auto", whiteSpace: "nowrap" }}
|
||||
>
|
||||
<i className="bi bi-award me-1"></i> VIP
|
||||
</button>
|
||||
<button
|
||||
className={`btn ${filtroAniversariante
|
||||
? "btn-primary"
|
||||
: "btn-outline-primary"
|
||||
}`}
|
||||
onClick={() =>
|
||||
setFiltroAniversariante(!filtroAniversariante)
|
||||
}
|
||||
style={{ flex: "0 0 auto", whiteSpace: "nowrap" }}
|
||||
>
|
||||
<i className="bi bi-calendar me-1"></i> Aniversariantes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="table-responsive">
|
||||
<table className="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nome</th>
|
||||
<th>CPF</th>
|
||||
<th>Email</th>
|
||||
<th>Telefone</th>
|
||||
<th>Status</th>
|
||||
<th>Ações</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{pacientesFiltrados.length > 0 ? (
|
||||
pacientesFiltrados.map((paciente) => (
|
||||
<tr key={paciente.id}>
|
||||
<td>{paciente.nome}</td>
|
||||
<td>{paciente.cpf}</td>
|
||||
<td>{paciente.email}</td>
|
||||
<td>{paciente.telefone}</td>
|
||||
<td>
|
||||
<span
|
||||
className={`badge ${paciente.ativo === "ativo"
|
||||
? "bg-success"
|
||||
: "bg-danger"
|
||||
}`}
|
||||
>
|
||||
{paciente.ativo}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-flex gap-2">
|
||||
<button
|
||||
className="btn btn-sm"
|
||||
style={{
|
||||
backgroundColor: "#E6F2FF",
|
||||
color: "#004085",
|
||||
}}
|
||||
onClick={() => {
|
||||
setCurrentPage("details-page-paciente");
|
||||
setPatientID(paciente.id);
|
||||
}}
|
||||
>
|
||||
<i className="bi bi-eye me-1"></i> Ver Detalhes
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm"
|
||||
style={{
|
||||
backgroundColor: "#FFF3CD",
|
||||
color: "#856404",
|
||||
}}
|
||||
onClick={() => {
|
||||
setCurrentPage("edit-page-paciente");
|
||||
setPatientID(paciente.id);
|
||||
}}
|
||||
>
|
||||
<i className="bi bi-pencil me-1"></i> Editar
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm"
|
||||
style={{
|
||||
backgroundColor: "#F8D7DA",
|
||||
color: "#721C24",
|
||||
}}
|
||||
onClick={() => deletePatient(paciente.id)}
|
||||
>
|
||||
<i className="bi bi-trash me-1"></i> Excluir
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan="6" className="text-center">
|
||||
Nenhum paciente encontrado.
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default TablePaciente;
|
||||
Loading…
x
Reference in New Issue
Block a user