diff --git a/src/PagesPaciente/CardConsultaPaciente.jsx b/src/PagesPaciente/CardConsultaPaciente.jsx new file mode 100644 index 00000000..c7dd660c --- /dev/null +++ b/src/PagesPaciente/CardConsultaPaciente.jsx @@ -0,0 +1,70 @@ +import React from 'react' +import { useEffect, useMemo,useState } from 'react' +import { GetDoctorByID } from '../components/utils/Functions-Endpoints/Doctor' +import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient' +import { useAuth } from '../components/utils/AuthProvider' + +const CardConsultaPaciente = ({consulta}) => { + + const [Paciente, setPaciente] = useState({}) + const [Medico, setMedico] = useState({}) + const {getAuthorizationHeader} = useAuth() + + const authHeader = getAuthorizationHeader() + + const ids = useMemo(() => { + return { + doctor_id: consulta?.doctor_id, + patient_id: consulta?.patient_id, + status: consulta?.status + }; + }, [consulta]); + + + useEffect(() => { + const BuscarMedicoEPaciente = async () => { + if (!ids.doctor_id || !ids.patient_id || ids.status === 'nada') return; + + try { + const [Doctor, Patient] = await Promise.all([ + GetDoctorByID(ids.doctor_id, authHeader), + GetPatientByID(ids.patient_id, authHeader) + ]); + + setMedico(Doctor?.[0] || null); + setPaciente(Patient?.[0] || null); + } catch (error) { + console.error('Erro ao buscar médico/paciente:', error); + } + }; + + BuscarMedicoEPaciente(); + }, [ids, authHeader]); + + + + console.log(consulta, "dento do card") + + let horario = consulta.scheduled_at.split("T")[1] + let Data = consulta.scheduled_at.split("T")[0] + + console.log(horario) + + return ( +
+
+ + + {`${Data?.split("-")[2]}/${Data?.split("-")[1]}`} + +
+
+ + Dr {Medico?.full_name} - {Medico?.specialty} + +
+
+ ) +} + +export default CardConsultaPaciente \ No newline at end of file diff --git a/src/PagesPaciente/ConsultaCadastroManager.jsx b/src/PagesPaciente/ConsultaCadastroManager.jsx new file mode 100644 index 00000000..e8eb64e9 --- /dev/null +++ b/src/PagesPaciente/ConsultaCadastroManager.jsx @@ -0,0 +1,81 @@ +import React from 'react' +import FormConsultaPaciente from './FormConsultaPaciente' +import { useState, useEffect } from 'react' +import { useNavigate } from 'react-router-dom' +import { useAuth } from '../components/utils/AuthProvider' +import API_KEY from '../components/utils/apiKeys' + +import dayjs from 'dayjs' +import { UserInfos } from '../components/utils/Functions-Endpoints/General' +const ConsultaCadastroManager = () => { + + const {getAuthorizationHeader} = useAuth() + const [Dict, setDict] = useState({}) + const navigate = useNavigate() + const [idUsuario, setIDusuario] = useState("") + + let authHeader = getAuthorizationHeader() + + + useEffect(() => { + const ColherInfoUsuario =async () => { + const result = await UserInfos(authHeader) + + setIDusuario(result?.profile?.id) + + } + ColherInfoUsuario() + + + }, []) + + const handleSave = (Dict) => { + let DataAtual = dayjs() + var myHeaders = new Headers(); + myHeaders.append("apikey", API_KEY); + myHeaders.append("Authorization", authHeader); + myHeaders.append("Content-Type", "application/json"); + + var raw = JSON.stringify({ + "patient_id": Dict.patient_id, + "doctor_id": Dict.doctor_id, + "scheduled_at": `${Dict.dataAtendimento}T${Dict.horarioInicio}:00.000Z`, + "duration_minutes": 30, + "appointment_type": Dict.tipo_consulta, + + "patient_notes": "Prefiro horário pela manhã", + "insurance_provider": Dict.convenio, + "status": Dict.status, + "created_by": idUsuario + }); + + var requestOptions = { + method: 'POST', + headers: myHeaders, + body: raw, + redirect: 'follow' + }; + + fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments", requestOptions) + .then(response => response.text()) + .then(result => console.log(result)) + .catch(error => console.log('error', error)); + + } + + + + + + + return ( + + + +
+ navigate("/paciente/agendamento/")}/> +
+ ) +} + +export default ConsultaCadastroManager \ No newline at end of file diff --git a/src/PagesPaciente/ConsultasPaciente.jsx b/src/PagesPaciente/ConsultasPaciente.jsx new file mode 100644 index 00000000..1a390711 --- /dev/null +++ b/src/PagesPaciente/ConsultasPaciente.jsx @@ -0,0 +1,96 @@ +import React from 'react' +import "./style.css" +import CardConsultaPaciente from './CardConsultaPaciente' +import { useNavigate } from 'react-router-dom' +import { useEffect, useState } from 'react' +import API_KEY from '../components/utils/apiKeys' +import { useAuth } from '../components/utils/AuthProvider' + +const ConsultasPaciente = () => { + const {getAuthorizationHeader} = useAuth() + + let authHeader = getAuthorizationHeader() + + const [consultas, setConsultas] = useState([]) + +const FiltrarAgendamentos = (agendamentos, id) => { + // Verifica se a lista de agendamentos é válida antes de tentar filtrar + if (!agendamentos || !Array.isArray(agendamentos)) { + console.error("A lista de agendamentos é inválida."); + setConsultas([]); // Garante que setConsultas receba uma lista vazia + return; + } + + // 1. Filtragem + // O método .filter() cria uma nova lista contendo apenas os itens que retornarem 'true' + const consultasFiltradas = agendamentos.filter(agendamento => { + // A condição: o patient_id do agendamento deve ser estritamente igual ao id fornecido + // Usamos toString() para garantir a comparação, pois um pode ser number e o outro string + return agendamento.patient_id && agendamento.patient_id.toString() === id.toString(); + }); + + // 2. Adicionar a lista no setConsultas + console.log(consultasFiltradas) + setConsultas(consultasFiltradas); +} + +// Exemplo de como você chamaria (assumindo que DadosAgendamento é sua lista original): +// FiltrarAgendamentos(DadosAgendamento, Paciente.id); + + useEffect(() => { + var myHeaders = new Headers(); + myHeaders.append("Authorization", authHeader); + myHeaders.append("apikey", API_KEY) + + var requestOptions = { + method: 'GET', + headers: myHeaders, + redirect: 'follow' + }; + + fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select&doctor_id&patient_id&status&scheduled_at&order&limit&offset", requestOptions) + .then(response => response.json()) + .then(result => {FiltrarAgendamentos(result, "6e7f8829-0574-42df-9290-8dbb70f75ada" )}) + .catch(error => console.log('error', error)); + + }, []) + + const navigate = useNavigate() +/* + const consultas = [ + { + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "doctor_id": "eaca4372-17bc-4905-9eff-7aeda46157b4", + "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7", + "scheduled_at": "2019-08-24T14:15:22Z", + "status": "string" + } +]*/ + + return ( +
+

Gerencie suas consultas

+ +
+ + + +

Seus proximos atendimentos

+ + {consultas.map((consulta) => ( + + + ))} + + +

Historico de consultas:

+ +
+
+ ) +} + +export default ConsultasPaciente \ No newline at end of file diff --git a/src/PagesPaciente/FormConsultaPaciente.jsx b/src/PagesPaciente/FormConsultaPaciente.jsx new file mode 100644 index 00000000..55678fdb --- /dev/null +++ b/src/PagesPaciente/FormConsultaPaciente.jsx @@ -0,0 +1,318 @@ +import InputMask from "react-input-mask"; + +import { useState, useEffect } from "react"; +import { GetPatientByCPF } from "../components/utils/Functions-Endpoints/Patient"; +import { GetDoctorByName, GetAllDoctors } from "../components/utils/Functions-Endpoints/Doctor"; +import { useAuth } from "../components/utils/AuthProvider"; +import API_KEY from "../components/utils/apiKeys"; + +const FormConsultaPaciente = ({ onCancel, onSave, setAgendamento, agendamento }) => { + const {getAuthorizationHeader} = useAuth() + + console.log(agendamento, 'aqui2') + + const [selectedFile, setSelectedFile] = useState(null); + const [anexos, setAnexos] = useState([]); + const [loadingAnexos, setLoadingAnexos] = useState(false); + const [acessibilidade, setAcessibilidade] = useState({cadeirante:false,idoso:false,gravida:false,bebe:false, autista:false }) + + +const [todosProfissionais, setTodosProfissionais] = useState([]) +const [profissionaisFiltrados, setProfissionaisFiltrados] = useState([]); +const [isDropdownOpen, setIsDropdownOpen] = useState(false); + + + const [horarioInicio, setHorarioInicio] = useState(''); + const [horarioTermino, setHorarioTermino] = useState(''); + + const [horariosDisponiveis, sethorariosDisponiveis] = useState([]) + + let authHeader = getAuthorizationHeader() + + const FormatCPF = (valor) => { + const digits = String(valor).replace(/\D/g, '').slice(0, 11); + return digits + .replace(/(\d{3})(\d)/, '$1.$2') + .replace(/(\d{3})(\d)/, '$1.$2') + .replace(/(\d{3})(\d{1,2})$/, '$1-$2'); + } + + + + const handleChange = (e) => { + const {value, name} = e.target; + console.log(value, name, agendamento) + + if(name === 'email'){ + setAgendamento({...agendamento, contato:{ + ...agendamento.contato, + email:value + }})} + else if(name === 'status'){ + if(agendamento.status==='requested'){ + setAgendamento((prev) => ({ + ...prev, + status:'confirmed', + })); + }else if(agendamento.status === 'confirmed'){ + console.log(value) + setAgendamento((prev) => ({ + ...prev, + status:'requested', + })); + }} + + else if(name === 'paciente_cpf'){ + + let cpfFormatted = FormatCPF(value) + const fetchPatient = async () => { + let patientData = await GetPatientByCPF(cpfFormatted, authHeader); + if (patientData) { + setAgendamento((prev) => ({ + ...prev, + paciente_nome: patientData.full_name, + patient_id: patientData.id + })); + }} + setAgendamento(prev => ({ ...prev, cpf: cpfFormatted })) + fetchPatient() + }else if(name==='convenio'){ + setAgendamento({...agendamento,insurance_provider:value}) + } + else{ + setAgendamento({...agendamento,[name]:value}) + } + } + + + + +useEffect(() => { + const ChamarMedicos = async () => { + const Medicos = await GetAllDoctors(authHeader) + setTodosProfissionais(Medicos) + } + ChamarMedicos(); + + var myHeaders = new Headers(); + myHeaders.append("Content-Type", "application/json"); + myHeaders.append("apikey", API_KEY) + myHeaders.append("Authorization", `Bearer ${authHeader.split(' ')[1]}`); + +var raw = JSON.stringify({ + "doctor_id": agendamento.doctor_id, + "start_date": agendamento.dataAtendimento, + "end_date": `${agendamento.dataAtendimento}T23:59:59.999Z`, + +}); + +var requestOptions = { + method: 'POST', + headers: myHeaders, + body: raw, + redirect: 'follow' +}; + +fetch("https://yuanqfswhberkoevtmfr.supabase.co/functions/v1/get-available-slots", requestOptions) + .then(response => response.json()) + .then(result => {console.log(result); sethorariosDisponiveis(result)}) + .catch(error => console.log('error', error)); + +}, [agendamento.dataAtendimento, agendamento.doctor_id]) + + +// FUNÇÃO DE BUSCA E FILTRAGEM +const handleSearchProfissional = (e) => { + const term = e.target.value; + handleChange(e); + // 2. Lógica de filtragem: + if (term.trim() === '') { + setProfissionaisFiltrados([]); + setIsDropdownOpen(false); + return; + } + // Adapte o nome da propriedade (ex: 'nome', 'full_name') + const filtered = todosProfissionais.filter(p => + p.full_name.toLowerCase().includes(term.toLowerCase()) + ); + + setProfissionaisFiltrados(filtered); + setIsDropdownOpen(filtered.length > 0); // Abre se houver resultados +}; + + +// FUNÇÃO PARA SELECIONAR UM ITEM DO DROPDOWN +const handleSelectProfissional = async (profissional) => { + setAgendamento(prev => ({ + ...prev, + doctor_id: profissional.id, + medico_nome: profissional.full_name + })); + // 2. Fecha o dropdown + setProfissionaisFiltrados([]); + setIsDropdownOpen(false); + }; + + +const formatarHora = (datetimeString) => { + return datetimeString.substring(11, 16); + }; + + const opcoesDeHorario = horariosDisponiveis?.slots?.map(item => ({ + + value: formatarHora(item.datetime), + label: formatarHora(item.datetime), + disabled: !item.available + })); + +const handleSubmit = (e) => { + e.preventDefault(); + alert("Agendamento salvo!"); + onSave({...agendamento, horarioInicio:horarioInicio}) + }; + + return ( +
+ + +
+ 1 + +

Informações do atendimento

+ + +
+ +
{/* NOVO CONTAINER PAI */} +
+ + +
+ + {/* DROPDOWN - RENDERIZAÇÃO CONDICIONAL */} + {isDropdownOpen && profissionaisFiltrados.length > 0 && ( +
+ {profissionaisFiltrados.map((profissional) => ( +
handleSelectProfissional(profissional)} + > + {profissional.full_name} +
+ ))} +
+ )} +
+ +
+ + +
+ + +
+ +
+
+ +
+ + +
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ + + + {/* Dropdown de Término */} +
+ + +
+
+ + + +
+ +
+ + +
+ + +
+
+
+ +
+ + +
+
+ +
+ ); +}; + +export default FormConsultaPaciente; \ No newline at end of file diff --git a/src/PagesPaciente/style.css b/src/PagesPaciente/style.css new file mode 100644 index 00000000..bbeba568 --- /dev/null +++ b/src/PagesPaciente/style.css @@ -0,0 +1,44 @@ + +/* Estilo geral do card para agrupar e dar um formato */ +.card-consulta { + background-color: #007bff; /* Um tom de azul padrão */ + display: flex; /* Para colocar horário e info lado a lado */ + border-radius: 10px; /* Cantos arredondados */ + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Sombra suave */ + overflow: hidden; /* Garante que o fundo azul não 'vaze' */ + width: 280px; /* Largura de exemplo */ + margin: 20px; + font-family: Arial, sans-serif; /* Fonte legível */ +} + +/* 1. Estilo para o Horário (Fundo Azul e Texto Branco/Grande) */ +.horario-container { + background-color: #007bff; /* Um tom de azul padrão */ + color: white; /* Texto branco */ + padding: 15px 20px; /* Espaçamento interno */ + display: flex; + align-items: center; /* Centraliza verticalmente */ + justify-content: center; /* Centraliza horizontalmente */ + flex-shrink: 0; /* Impede que o container do horário encolha */ + border-right: 1px solid #0056b3; /* Uma linha sutil de separação */ +} + +.horario { + font-size: 2.2em; /* Torna o horário grande */ + font-weight: bold; /* Deixa em negrito */ +} + +/* 2. Estilo para as Informações (Fundo Branco) */ +.info-container { + border-radius: 20px 0px 0px 20px; + background-color: white; /* Fundo branco, como solicitado */ + color: #333; /* Cor escura para o texto para bom contraste */ + padding: 15px; /* Espaçamento interno */ + display: flex; + align-items: center; + flex-grow: 1; /* Faz com que a div de informações preencha o espaço restante */ +} + +.informacao { + font-size: 1.1em; +} \ No newline at end of file diff --git a/src/components/AgendarConsulta/CardConsulta.jsx b/src/components/AgendarConsulta/CardConsulta.jsx index f760ae1c..8a4e3e4f 100644 --- a/src/components/AgendarConsulta/CardConsulta.jsx +++ b/src/components/AgendarConsulta/CardConsulta.jsx @@ -3,10 +3,12 @@ import { GetPatientByID } from '../utils/Functions-Endpoints/Patient'; import { useAuth } from '../utils/AuthProvider'; import { useNavigate } from 'react-router-dom'; import { useMemo } from 'react'; - +import "./style/card-consulta.css" const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, setDictInfo, setSelectedId} ) => { const navigate = useNavigate(); + console.log(DadosConsulta, "AQUIIII") + const {getAuthorizationHeader} = useAuth() const authHeader = getAuthorizationHeader() const [Paciente, setPaciente] = useState() @@ -48,7 +50,7 @@ const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, se console.log(DadosConsulta.status) return ( -
+
{DadosConsulta.id? @@ -65,23 +67,18 @@ const CardConsulta = ( {DadosConsulta, TabelaAgendamento, setShowDeleteModal, se
-
+
- - - +