From f8f5f8214af85a354bec84f90753e924256b56a6 Mon Sep 17 00:00:00 2001 From: Gabriel Lira Figueira Date: Wed, 5 Nov 2025 01:35:44 -0300 Subject: [PATCH] =?UTF-8?q?feat(admin,=20patient):=20implementa=20cria?= =?UTF-8?q?=C3=A7=C3=A3o=20condicional=20e=20corrige=20layouts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refatora o formulário de criação de usuários no painel do manager para lidar com a lógica de múltiplos endpoints, diferenciando a criação de médicos das demais roles. - Adiciona campos condicionais para CRM e especialidade na UI. - Implementa a chamada ao endpoint `/functions/v1/create-doctor` para a role "medico". - Ajusta o payload para o endpoint `/create-user-with-password` para as outras roles. fix(patient): corrige renderização duplicada do layout nas páginas de agendamento e consultas, removendo o wrapper redundante do `PatientLayout`. refactor(services): ajusta os serviços `doctorsApi` e `usersApi` para alinhar com os schemas de dados corretos da API. --- app/manager/usuario/novo/page.tsx | 100 ++++++++++++++++++++++++++---- app/patient/appointments/page.tsx | 12 +++- app/patient/schedule/page.tsx | 6 +- components/patient-layout.tsx | 2 +- services/doctorsApi.mjs | 7 ++- services/usersApi.mjs | 3 +- 6 files changed, 106 insertions(+), 24 deletions(-) diff --git a/app/manager/usuario/novo/page.tsx b/app/manager/usuario/novo/page.tsx index 77dae32..1e63d72 100644 --- a/app/manager/usuario/novo/page.tsx +++ b/app/manager/usuario/novo/page.tsx @@ -1,3 +1,5 @@ +// /app/manager/usuario/novo/page.tsx + "use client"; import { useState } from "react"; @@ -9,7 +11,8 @@ import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Save, Loader2, Pause } from "lucide-react"; import ManagerLayout from "@/components/manager-layout"; -import { usersService } from "services/usersApi.mjs"; +import { usersService } from "@/services/usersApi.mjs"; +import { doctorsService } from "@/services/doctorsApi.mjs"; // Importação adicionada import { login } from "services/api.mjs"; interface UserFormData { @@ -20,6 +23,10 @@ interface UserFormData { senha: string; confirmarSenha: string; cpf: string; + // Novos campos para Médico + crm: string; + crm_uf: string; + specialty: string; } const defaultFormData: UserFormData = { @@ -30,6 +37,10 @@ const defaultFormData: UserFormData = { senha: "", confirmarSenha: "", cpf: "", + // Valores iniciais para campos de Médico + crm: "", + crm_uf: "", + specialty: "", }; const cleanNumber = (value: string): string => value.replace(/\D/g, ""); @@ -47,7 +58,13 @@ export default function NovoUsuarioPage() { const [error, setError] = useState(null); const handleInputChange = (key: keyof UserFormData, value: string) => { - const updatedValue = key === "telefone" ? formatPhone(value) : value; + let updatedValue = value; + if (key === "telefone") { + updatedValue = formatPhone(value); + } else if (key === "crm_uf") { + // Converte UF para maiúsculas + updatedValue = value.toUpperCase(); + } setFormData((prev) => ({ ...prev, [key]: updatedValue })); }; @@ -65,22 +82,56 @@ export default function NovoUsuarioPage() { return; } + // Validação adicional para Médico + if (formData.papel === "medico") { + if (!formData.crm || !formData.crm_uf) { + setError("Para a função 'Médico', o CRM e a UF do CRM são obrigatórios."); + return; + } + } + setIsSaving(true); try { - const payload = { - full_name: formData.nomeCompleto, - email: formData.email.trim().toLowerCase(), - phone: formData.telefone || null, - role: formData.papel, - password: formData.senha, - cpf: formData.cpf, - }; + if (formData.papel === "medico") { + // Lógica para criação de Médico + const doctorPayload = { + email: formData.email.trim().toLowerCase(), + full_name: formData.nomeCompleto, + cpf: formData.cpf, + crm: formData.crm, + crm_uf: formData.crm_uf, + specialty: formData.specialty || null, + phone_mobile: formData.telefone || null, // Usando phone_mobile conforme o schema + }; - console.log("📤 Enviando payload:"); - console.log(payload); + console.log("📤 Enviando payload para Médico:"); + console.log(doctorPayload); - await usersService.create_user(payload); + // Chamada ao endpoint específico para criação de médico + await doctorsService.create(doctorPayload); + + } else { + // Lógica para criação de Outras Roles + const isPatient = formData.papel === "paciente"; + + const userPayload = { + email: formData.email.trim().toLowerCase(), + password: formData.senha, + full_name: formData.nomeCompleto, + phone: formData.telefone || null, + role: formData.papel, + cpf: formData.cpf, + create_patient_record: isPatient, // true se a role for 'paciente' + phone_mobile: isPatient ? formData.telefone || null : undefined, // Enviar phone_mobile se for paciente + }; + + console.log("📤 Enviando payload para Usuário Comum:"); + console.log(userPayload); + + // Chamada ao endpoint padrão para criação de usuário + await usersService.create_user(userPayload); + } router.push("/manager/usuario"); } catch (e: any) { @@ -91,6 +142,8 @@ export default function NovoUsuarioPage() { } }; + const isMedico = formData.papel === "medico"; + return (
@@ -140,6 +193,27 @@ export default function NovoUsuarioPage() {
+ {/* Campos Condicionais para Médico */} + {isMedico && ( + <> +
+ + handleInputChange("crm", e.target.value)} placeholder="Número do CRM" required /> +
+ +
+ + handleInputChange("crm_uf", e.target.value)} placeholder="Ex: SP" maxLength={2} required /> +
+ +
+ + handleInputChange("specialty", e.target.value)} placeholder="Ex: Cardiologia" /> +
+ + )} + {/* Fim dos Campos Condicionais */} +
handleInputChange("senha", e.target.value)} placeholder="Mínimo 8 caracteres" minLength={8} required /> diff --git a/app/patient/appointments/page.tsx b/app/patient/appointments/page.tsx index 78f2d8b..5a56fc2 100644 --- a/app/patient/appointments/page.tsx +++ b/app/patient/appointments/page.tsx @@ -182,8 +182,8 @@ export default function PatientAppointments() {
-

Minhas Consultas

-

Veja, reagende ou cancele suas consultas

+

Minhas Consultas

+

Veja, reagende ou cancele suas consultas

@@ -244,7 +244,13 @@ export default function PatientAppointments() { )) ) : ( -

Você ainda não possui consultas agendadas.

+ + + Nenhuma Consulta Encontrada + + Você ainda não possui consultas agendadas. Use o menu "Agendar Consulta" para começar. + + )}
diff --git a/app/patient/schedule/page.tsx b/app/patient/schedule/page.tsx index f6a4f0f..448692d 100644 --- a/app/patient/schedule/page.tsx +++ b/app/patient/schedule/page.tsx @@ -134,8 +134,8 @@ export default function ScheduleAppointment() { {/* Médico */}
- + @@ -168,7 +168,7 @@ export default function ScheduleAppointment() {
diff --git a/services/doctorsApi.mjs b/services/doctorsApi.mjs index 5d918a0..45fd58d 100644 --- a/services/doctorsApi.mjs +++ b/services/doctorsApi.mjs @@ -3,7 +3,10 @@ import { api } from "./api.mjs"; export const doctorsService = { list: () => api.get("/rest/v1/doctors"), getById: (id) => api.get(`/rest/v1/doctors?id=eq.${id}`).then(data => data[0]), - create: (data) => api.post("/functions/v1/create-doctor", data), + async create(data) { + // Esta é a função usada no page.tsx para criar médicos + return await api.post("/functions/v1/create-doctor", data); + }, update: (id, data) => api.patch(`/rest/v1/doctors?id=eq.${id}`, data), delete: (id) => api.delete(`/rest/v1/doctors?id=eq.${id}`), -}; \ No newline at end of file +}; diff --git a/services/usersApi.mjs b/services/usersApi.mjs index e9b84be..396ea16 100644 --- a/services/usersApi.mjs +++ b/services/usersApi.mjs @@ -1,5 +1,3 @@ -// SUBSTITUA O OBJETO INTEIRO EM services/usersApi.mjs - import { api } from "./api.mjs"; export const usersService = { @@ -19,6 +17,7 @@ export const usersService = { }, async create_user(data) { + // Esta é a função usada no page.tsx para criar usuários que não são médicos return await api.post(`/functions/v1/create-user-with-password`, data); },