From b9f8efb039639aec9b9a1795b0a0c2a305ba5ace Mon Sep 17 00:00:00 2001 From: GagoDuBroca Date: Sun, 23 Nov 2025 22:31:41 -0300 Subject: [PATCH] =?UTF-8?q?Adi=C3=A7=C3=A3o=20da=20barra=20de=20pesquisa?= =?UTF-8?q?=20agenda=20consulta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/schedule/schedule-form.tsx | 334 +++++++++++++++----------- 1 file changed, 192 insertions(+), 142 deletions(-) diff --git a/components/schedule/schedule-form.tsx b/components/schedule/schedule-form.tsx index 89ffb05..ecdfba5 100644 --- a/components/schedule/schedule-form.tsx +++ b/components/schedule/schedule-form.tsx @@ -13,10 +13,25 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Textarea } from "@/components/ui/textarea"; import { Calendar as CalendarShadcn } from "@/components/ui/calendar"; import { format, addDays } from "date-fns"; -import { User, StickyNote, Calendar } from "lucide-react"; -import {smsService } from "@/services/Sms.mjs" +import { User, StickyNote, Check, ChevronsUpDown } from "lucide-react"; +import { smsService } from "@/services/Sms.mjs"; import { toast } from "@/hooks/use-toast"; +import { cn } from "@/lib/utils"; +// Componentes do Combobox (Barra de Pesquisa) +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; export default function ScheduleForm() { // Estado do usuário e role @@ -26,8 +41,12 @@ export default function ScheduleForm() { // Listas e seleções const [patients, setPatients] = useState([]); const [selectedPatient, setSelectedPatient] = useState(""); + const [openPatientCombobox, setOpenPatientCombobox] = useState(false); + const [doctors, setDoctors] = useState([]); const [selectedDoctor, setSelectedDoctor] = useState(""); + const [openDoctorCombobox, setOpenDoctorCombobox] = useState(false); // Novo estado para médico + const [selectedDate, setSelectedDate] = useState(""); const [selectedTime, setSelectedTime] = useState(""); const [notes, setNotes] = useState(""); @@ -204,123 +223,86 @@ export default function ScheduleForm() { } }, []); - useEffect(() => { - if (selectedDoctor && selectedDate) fetchAvailableSlots(selectedDoctor, selectedDate); - }, [selectedDoctor, selectedDate, fetchAvailableSlots]); - // 🔹 Submeter agendamento - // 🔹 Submeter agendamento - // 🔹 Submeter agendamento -// 🔹 Submeter agendamento -// 🔹 Submeter agendamento -const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); - const isSecretaryLike = ["secretaria", "admin", "gestor"].includes(role); - const patientId = isSecretaryLike ? selectedPatient : userId; + const isSecretaryLike = ["secretaria", "admin", "gestor"].includes(role); + const patientId = isSecretaryLike ? selectedPatient : userId; - if (!patientId || !selectedDoctor || !selectedDate || !selectedTime) { - toast({ title: "Campos obrigatórios", description: "Preencha todos os campos." }); - return; - } + if (!patientId || !selectedDoctor || !selectedDate || !selectedTime) { + toast({ title: "Campos obrigatórios", description: "Preencha todos os campos." }); + return; + } - try { - const body = { - doctor_id: selectedDoctor, - patient_id: patientId, - scheduled_at: `${selectedDate}T${selectedTime}:00`, - duration_minutes: Number(duracao), - notes, - appointment_type: tipoConsulta, - }; + try { + const body = { + doctor_id: selectedDoctor, + patient_id: patientId, + scheduled_at: `${selectedDate}T${selectedTime}:00`, + duration_minutes: Number(duracao), + notes, + appointment_type: tipoConsulta, + }; - // ✅ mantém o fluxo original de criação (funcional) - await appointmentsService.create(body); + await appointmentsService.create(body); - const dateFormatted = selectedDate.split("-").reverse().join("/"); + const dateFormatted = selectedDate.split("-").reverse().join("/"); - toast({ - title: "Consulta agendada!", - description: `Consulta marcada para ${dateFormatted} às ${selectedTime} com o(a) médico(a) ${ - doctors.find((d) => d.id === selectedDoctor)?.full_name || "" - }.`, - }); + toast({ + title: "Consulta agendada!", + description: `Consulta marcada para ${dateFormatted} às ${selectedTime} com o(a) médico(a) ${ + doctors.find((d) => d.id === selectedDoctor)?.full_name || "" + }.`, + }); -let phoneNumber = "+5511999999999"; // fallback - -try { - if (isSecretaryLike) { - // Secretária/admin → telefone do paciente selecionado - const patient = patients.find((p: any) => p.id === patientId); - - // Pacientes criados no sistema podem ter phone ou phone_mobile - const rawPhone = patient?.phone || patient?.phone_mobile || null; - - if (rawPhone) phoneNumber = rawPhone; - } else { - // Paciente → telefone vem do perfil do próprio usuário logado - const me = await usersService.getMe(); - - -const rawPhone = - me?.profile?.phone || - (typeof me?.profile === "object" && "phone_mobile" in me.profile ? (me.profile as any).phone_mobile : null) || - (typeof me === "object" && "user_metadata" in me ? (me as any).user_metadata?.phone : null) || - null; - - if (rawPhone) phoneNumber = rawPhone; - } - - // 🔹 Normaliza para formato internacional (+55) - if (phoneNumber) { - phoneNumber = phoneNumber.replace(/\D/g, ""); - if (!phoneNumber.startsWith("55")) phoneNumber = `55${phoneNumber}`; - phoneNumber = `+${phoneNumber}`; - } - - console.log("📞 Telefone usado:", phoneNumber); -} catch (err) { - console.warn("⚠️ Não foi possível obter telefone do paciente:", err); -} - - - // 💬 envia o SMS de confirmação - // 💬 Envia o SMS de lembrete (sem mostrar nada ao paciente) -// 💬 Envia o SMS de lembrete (somente loga no console, não mostra no sistema) -try { - const smsRes = await smsService.sendSms({ - phone_number: phoneNumber, - message: `Lembrete: sua consulta é em ${dateFormatted} às ${selectedTime} na Clínica MediConnect.`, - patient_id: patientId, - }); - - if (smsRes?.success) { - console.log("✅ SMS enviado com sucesso:", smsRes.message_sid); - } else { - console.warn("⚠️ Falha no envio do SMS:", smsRes); - } -} catch (smsErr) { - console.error("❌ Erro ao enviar SMS:", smsErr); -} - - - - - // 🧹 limpa os campos - setSelectedDoctor(""); - setSelectedDate(""); - setSelectedTime(""); - setNotes(""); - setSelectedPatient(""); - } catch (err) { - console.error("❌ Erro ao agendar consulta:", err); - toast({ title: "Erro", description: "Falha ao agendar consulta." }); - } -}; + let phoneNumber = "+5511999999999"; + try { + if (isSecretaryLike) { + const patient = patients.find((p: any) => p.id === patientId); + const rawPhone = patient?.phone || patient?.phone_mobile || null; + if (rawPhone) phoneNumber = rawPhone; + } else { + const me = await usersService.getMe(); + const rawPhone = + me?.profile?.phone || + (typeof me?.profile === "object" && "phone_mobile" in me.profile ? (me.profile as any).phone_mobile : null) || + (typeof me === "object" && "user_metadata" in me ? (me as any).user_metadata?.phone : null) || + null; + if (rawPhone) phoneNumber = rawPhone; + } + if (phoneNumber) { + phoneNumber = phoneNumber.replace(/\D/g, ""); + if (!phoneNumber.startsWith("55")) phoneNumber = `55${phoneNumber}`; + phoneNumber = `+${phoneNumber}`; + } + } catch (err) { + console.warn("⚠️ Não foi possível obter telefone do paciente:", err); + } + try { + const smsRes = await smsService.sendSms({ + phone_number: phoneNumber, + message: `Lembrete: sua consulta é em ${dateFormatted} às ${selectedTime} na Clínica MediConnect.`, + patient_id: patientId, + }); + if (smsRes?.success) console.log("✅ SMS enviado:", smsRes.message_sid); + } catch (smsErr) { + console.error("❌ Erro ao enviar SMS:", smsErr); + } + setSelectedDoctor(""); + setSelectedDate(""); + setSelectedTime(""); + setNotes(""); + setSelectedPatient(""); + } catch (err) { + console.error("❌ Erro ao agendar consulta:", err); + toast({ title: "Erro", description: "Falha ao agendar consulta." }); + } + }; // 🔹 Tooltip no calendário useEffect(() => { @@ -360,45 +342,113 @@ try {
-
- {/* Se secretária/gestor/admin → mostrar campo Paciente */} +
{/* Ajuste: maior espaçamento vertical geral */} + + {/* Se secretária/gestor/admin → COMBOBOX de Paciente */} {["secretaria", "gestor", "admin"].includes(role) && ( -
+
{/* Ajuste: gap entre Label e Input */} - + + + + + + + + + Nenhum paciente encontrado. + + {patients.map((patient) => ( + { + setSelectedPatient(patient.id === selectedPatient ? "" : patient.id); + setOpenPatientCombobox(false); + }} + > + + {patient.full_name} + + ))} + + + + +
)} -
+ {/* COMBOBOX de Médico (Nova funcionalidade) */} +
{/* Ajuste: gap entre Label e Input */} - + + + + + + + + + Nenhum médico encontrado. + + {doctors.map((doctor) => ( + { + setSelectedDoctor(doctor.id === selectedDoctor ? "" : doctor.id); + setOpenDoctorCombobox(false); + }} + > + +
+ {doctor.full_name} + {doctor.specialty} +
+
+ ))} +
+
+
+
+
-
+
-
+