develop #83

Merged
M-Gabrielly merged 426 commits from develop into main 2025-12-04 04:13:15 +00:00
6 changed files with 23 additions and 44 deletions
Showing only changes of commit e389b0894e - Show all commits

View File

@ -56,7 +56,7 @@ import {
import { mockAppointments, mockProfessionals } from "@/lib/mocks/appointment-mocks"; import { mockAppointments, mockProfessionals } from "@/lib/mocks/appointment-mocks";
import { CalendarRegistrationForm } from "@/components/forms/calendar-registration-form"; import { CalendarRegistrationForm } from "@/components/forms/calendar-registration-form";
// --- Helper Functions ---
const formatDate = (date: string | Date) => { const formatDate = (date: string | Date) => {
if (!date) return ""; if (!date) return "";
return new Date(date).toLocaleDateString("pt-BR", { return new Date(date).toLocaleDateString("pt-BR", {
@ -73,14 +73,12 @@ const capitalize = (s: string) => {
return s.charAt(0).toUpperCase() + s.slice(1); return s.charAt(0).toUpperCase() + s.slice(1);
}; };
// --- Main Page Component ---
export default function ConsultasPage() { export default function ConsultasPage() {
const [appointments, setAppointments] = useState(mockAppointments); const [appointments, setAppointments] = useState(mockAppointments);
const [showForm, setShowForm] = useState(false); const [showForm, setShowForm] = useState(false);
const [editingAppointment, setEditingAppointment] = useState<any | null>(null); const [editingAppointment, setEditingAppointment] = useState<any | null>(null);
const [viewingAppointment, setViewingAppointment] = useState<any | null>(null); const [viewingAppointment, setViewingAppointment] = useState<any | null>(null);
// Converte o objeto da consulta para o formato esperado pelo formulário
const mapAppointmentToFormData = (appointment: any) => { const mapAppointmentToFormData = (appointment: any) => {
const professional = mockProfessionals.find(p => p.id === appointment.professional); const professional = mockProfessionals.find(p => p.id === appointment.professional);
const appointmentDate = new Date(appointment.time); const appointmentDate = new Date(appointment.time);
@ -89,14 +87,12 @@ export default function ConsultasPage() {
id: appointment.id, id: appointment.id,
patientName: appointment.patient, patientName: appointment.patient,
professionalName: professional ? professional.name : '', professionalName: professional ? professional.name : '',
appointmentDate: appointmentDate.toISOString().split('T')[0], // Formato YYYY-MM-DD appointmentDate: appointmentDate.toISOString().split('T')[0],
startTime: appointmentDate.toTimeString().split(' ')[0].substring(0, 5), // Formato HH:MM startTime: appointmentDate.toTimeString().split(' ')[0].substring(0, 5),
endTime: new Date(appointmentDate.getTime() + appointment.duration * 60000).toTimeString().split(' ')[0].substring(0, 5), endTime: new Date(appointmentDate.getTime() + appointment.duration * 60000).toTimeString().split(' ')[0].substring(0, 5),
status: appointment.status, status: appointment.status,
appointmentType: appointment.type, appointmentType: appointment.type,
notes: appointment.notes, notes: appointment.notes,
// Adicione outros campos do paciente aqui se necessário (cpf, rg, etc.)
// Eles não existem no mock de agendamento, então virão vazios
cpf: '', cpf: '',
rg: '', rg: '',
birthDate: '', birthDate: '',
@ -129,24 +125,22 @@ export default function ConsultasPage() {
}; };
const handleSave = (formData: any) => { const handleSave = (formData: any) => {
// Como o formulário edita campos que não estão na tabela,
// precisamos mapear de volta para o formato original do agendamento.
// Para a simulação, vamos atualizar apenas os campos que existem no mock.
const updatedAppointment = { const updatedAppointment = {
id: formData.id, id: formData.id,
patient: formData.patientName, patient: formData.patientName,
time: new Date(`${formData.appointmentDate}T${formData.startTime}`).toISOString(), time: new Date(`${formData.appointmentDate}T${formData.startTime}`).toISOString(),
duration: 30, // Duração não está no form, então mantemos um valor fixo duration: 30,
type: formData.appointmentType as any, type: formData.appointmentType as any,
status: formData.status as any, status: formData.status as any,
professional: appointments.find(a => a.id === formData.id)?.professional || '', // Mantém o ID do profissional professional: appointments.find(a => a.id === formData.id)?.professional || '',
notes: formData.notes, notes: formData.notes,
}; };
setAppointments(prev => setAppointments(prev =>
prev.map(a => a.id === updatedAppointment.id ? updatedAppointment : a) prev.map(a => a.id === updatedAppointment.id ? updatedAppointment : a)
); );
handleCancel(); // Fecha o formulário handleCancel();
}; };
if (showForm && editingAppointment) { if (showForm && editingAppointment) {

View File

@ -11,7 +11,7 @@ import { MoreHorizontal, Plus, Search, Edit, Trash2, ArrowLeft, Eye } from "luci
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { DoctorRegistrationForm } from "@/components/forms/doctor-registration-form"; import { DoctorRegistrationForm } from "@/components/forms/doctor-registration-form";
// >>> IMPORTES DA API <<<
import { listarMedicos, excluirMedico, Medico } from "@/lib/api"; import { listarMedicos, excluirMedico, Medico } from "@/lib/api";
export default function DoutoresPage() { export default function DoutoresPage() {
@ -22,7 +22,7 @@ export default function DoutoresPage() {
const [editingId, setEditingId] = useState<string | null>(null); const [editingId, setEditingId] = useState<string | null>(null);
const [viewingDoctor, setViewingDoctor] = useState<Medico | null>(null); const [viewingDoctor, setViewingDoctor] = useState<Medico | null>(null);
// Carrega da API
async function load() { async function load() {
setLoading(true); setLoading(true);
try { try {
@ -62,14 +62,14 @@ export default function DoutoresPage() {
setViewingDoctor(doctor); setViewingDoctor(doctor);
} }
// Excluir via API e recarregar
async function handleDelete(id: string) { async function handleDelete(id: string) {
if (!confirm("Excluir este médico?")) return; if (!confirm("Excluir este médico?")) return;
await excluirMedico(id); await excluirMedico(id);
await load(); await load();
} }
// Após salvar/criar/editar no form, fecha e recarrega
async function handleSaved() { async function handleSaved() {
setShowForm(false); setShowForm(false);
await load(); await load();

View File

@ -276,7 +276,7 @@ export default function PacientesPage() {
<div className="grid grid-cols-4 items-center gap-4"> <div className="grid grid-cols-4 items-center gap-4">
<Label className="text-right">Endereço</Label> <Label className="text-right">Endereço</Label>
<span className="col-span-3"> <span className="col-span-3">
{`${viewingPatient.endereco.logradouro}, ${viewingPatient.endereco.numero} - ${viewingPatient.endereco.bairro}, ${viewingPatient.endereco.cidade} - ${viewingPatient.endereco.estado}`} {`${viewingPatient.endereco?.logradouro || ''}, ${viewingPatient.endereco?.numero || ''} - ${viewingPatient.endereco?.bairro || ''}, ${viewingPatient.endereco?.cidade || ''} - ${viewingPatient.endereco?.estado || ''}`}
</span> </span>
</div> </div>
<div className="grid grid-cols-4 items-center gap-4"> <div className="grid grid-cols-4 items-center gap-4">

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { AppointmentForm } from "@/components/forms/appointment-form"; import { CalendarRegistrationForm } from "@/components/forms/calendar-registration-form";
import HeaderAgenda from "@/components/agenda/HeaderAgenda"; import HeaderAgenda from "@/components/agenda/HeaderAgenda";
import FooterAgenda from "@/components/agenda/FooterAgenda"; import FooterAgenda from "@/components/agenda/FooterAgenda";
@ -10,23 +10,22 @@ export default function NovoAgendamentoPage() {
const handleSave = (data: any) => { const handleSave = (data: any) => {
console.log("Salvando novo agendamento...", data); console.log("Salvando novo agendamento...", data);
// Aqui viria a chamada da API para criar um novo agendamento
alert("Novo agendamento salvo (simulado)!"); alert("Novo agendamento salvo (simulado)!");
router.push("/consultas"); // Volta para a lista após salvar router.push("/consultas");
}; };
const handleCancel = () => { const handleCancel = () => {
router.back(); // Simplesmente volta para a página anterior router.back();
}; };
return ( return (
<div className="min-h-screen flex flex-col bg-white"> <div className="min-h-screen flex flex-col bg-white">
<HeaderAgenda /> <HeaderAgenda />
<main className="flex-1 mx-auto w-full max-w-7xl px-8 py-8"> <main className="flex-1 mx-auto w-full max-w-7xl px-8 py-8">
<AppointmentForm <CalendarRegistrationForm
onSave={handleSave} onSave={handleSave}
onCancel={handleCancel} onCancel={handleCancel}
initialData={{}} // Passa um objeto vazio para o modo de criação initialData={{}}
/> />
</main> </main>
<FooterAgenda /> <FooterAgenda />

View File

@ -7,15 +7,10 @@ import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Calendar, Search, ChevronDown, Upload, FileDown, Tag } from "lucide-react"; import { Calendar, Search, ChevronDown, Upload, FileDown, Tag } from "lucide-react";
// Este é um formulário genérico para Criar e Editar um agendamento.
// Ele não tem Header ou Footer, apenas o conteúdo do formulário em si.
export function CalendarRegistrationForm({ initialData, onSave, onCancel }: any) { export function CalendarRegistrationForm({ initialData, onSave, onCancel }: any) {
const [formData, setFormData] = useState(initialData || {}); const [formData, setFormData] = useState(initialData || {});
useEffect(() => { useEffect(() => {
// Se os dados iniciais mudarem (ex: usuário clica em outro item para editar),
// atualizamos o estado do formulário.
setFormData(initialData || {}); setFormData(initialData || {});
}, [initialData]); }, [initialData]);
@ -31,7 +26,6 @@ export function CalendarRegistrationForm({ initialData, onSave, onCancel }: any)
return ( return (
<form onSubmit={handleSubmit} className="space-y-8"> <form onSubmit={handleSubmit} className="space-y-8">
{/* ==== INFORMAÇÕES DO PACIENTE ==== */}
<div className="border rounded-md p-6 space-y-4 bg-white"> <div className="border rounded-md p-6 space-y-4 bg-white">
<h2 className="font-medium">Informações do paciente</h2> <h2 className="font-medium">Informações do paciente</h2>
<div className="grid grid-cols-1 md:grid-cols-12 gap-4"> <div className="grid grid-cols-1 md:grid-cols-12 gap-4">
@ -40,7 +34,7 @@ export function CalendarRegistrationForm({ initialData, onSave, onCancel }: any)
<div className="relative"> <div className="relative">
<Search className="pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" /> <Search className="pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
<Input <Input
name="patientName" // Nome do campo para o estado name="patientName"
placeholder="Digite o nome do paciente" placeholder="Digite o nome do paciente"
className="h-10 pl-8" className="h-10 pl-8"
value={formData.patientName || ''} value={formData.patientName || ''}
@ -82,7 +76,7 @@ export function CalendarRegistrationForm({ initialData, onSave, onCancel }: any)
</div> </div>
</div> </div>
{/* ==== INFORMAÇÕES DO ATENDIMENTO ==== */} {}
<div className="border rounded-md p-6 space-y-4 bg-white"> <div className="border rounded-md p-6 space-y-4 bg-white">
<h2 className="font-medium">Informações do atendimento</h2> <h2 className="font-medium">Informações do atendimento</h2>
<div className="grid grid-cols-1 md:grid-cols-12 gap-6"> <div className="grid grid-cols-1 md:grid-cols-12 gap-6">
@ -137,7 +131,6 @@ export function CalendarRegistrationForm({ initialData, onSave, onCancel }: any)
</div> </div>
</div> </div>
{/* Botões de Ação */}
<div className="flex justify-end gap-2"> <div className="flex justify-end gap-2">
<Button type="button" variant="outline" onClick={onCancel}>Cancelar</Button> <Button type="button" variant="outline" onClick={onCancel}>Cancelar</Button>
<Button type="submit">Salvar</Button> <Button type="submit">Salvar</Button>

View File

@ -24,9 +24,7 @@ import {
MedicoInput, MedicoInput,
} from "@/lib/api"; } from "@/lib/api";
import { buscarCepAPI } from "@/lib/api"; // use o seu já existente import { buscarCepAPI } from "@/lib/api";
// Mock data and types since API is not used for now
type FormacaoAcademica = { type FormacaoAcademica = {
instituicao: string; instituicao: string;
@ -179,7 +177,6 @@ export function DoctorRegistrationForm({
if (mode === "edit" && doctorId) { if (mode === "edit" && doctorId) {
const medico = await buscarMedicoPorId(doctorId); const medico = await buscarMedicoPorId(doctorId);
if (!alive) return; if (!alive) return;
// mapeia API -> estado do formulário
setForm({ setForm({
photo: null, photo: null,
nome: medico.nome ?? "", nome: medico.nome ?? "",
@ -188,7 +185,7 @@ export function DoctorRegistrationForm({
estado_crm: medico.estado_crm ?? "", estado_crm: medico.estado_crm ?? "",
rqe: medico.rqe ?? "", rqe: medico.rqe ?? "",
formacao_academica: medico.formacao_academica ?? [], formacao_academica: medico.formacao_academica ?? [],
curriculo: null, // se a API devolver URL, você pode exibir ao lado curriculo: null,
especialidade: medico.especialidade ?? "", especialidade: medico.especialidade ?? "",
cpf: medico.cpf ?? "", cpf: medico.cpf ?? "",
rg: medico.rg ?? "", rg: medico.rg ?? "",
@ -213,7 +210,7 @@ export function DoctorRegistrationForm({
valor_consulta: medico.valor_consulta ? String(medico.valor_consulta) : "", valor_consulta: medico.valor_consulta ? String(medico.valor_consulta) : "",
}); });
// (Opcional) listar anexos que já existem no servidor
try { try {
const list = await listarAnexosMedico(doctorId); const list = await listarAnexosMedico(doctorId);
setServerAnexos(list ?? []); setServerAnexos(list ?? []);
@ -320,7 +317,6 @@ export function DoctorRegistrationForm({
setErrors((e) => ({ ...e, submit: "" })); setErrors((e) => ({ ...e, submit: "" }));
try { try {
// monta o payload esperado pela API
const payload: MedicoInput = { const payload: MedicoInput = {
nome: form.nome, nome: form.nome,
nome_social: form.nome_social || null, nome_social: form.nome_social || null,
@ -336,7 +332,7 @@ export function DoctorRegistrationForm({
estado_crm: form.estado_crm || null, estado_crm: form.estado_crm || null,
rqe: form.rqe || null, rqe: form.rqe || null,
formacao_academica: form.formacao_academica ?? [], formacao_academica: form.formacao_academica ?? [],
curriculo_url: null, // se quiser, suba arquivo do currículo num endpoint próprio e salve a URL aqui curriculo_url: null,
especialidade: form.especialidade, especialidade: form.especialidade,
observacoes: form.observacoes || null, observacoes: form.observacoes || null,
tipo_vinculo: form.tipo_vinculo || null, tipo_vinculo: form.tipo_vinculo || null,
@ -345,14 +341,12 @@ export function DoctorRegistrationForm({
valor_consulta: form.valor_consulta || null, valor_consulta: form.valor_consulta || null,
}; };
// cria ou atualiza
const saved = mode === "create" const saved = mode === "create"
? await criarMedico(payload) ? await criarMedico(payload)
: await atualizarMedico(doctorId as number, payload); : await atualizarMedico(doctorId as number, payload);
const medicoId = saved.id; const medicoId = saved.id;
// foto (opcional)
if (form.photo) { if (form.photo) {
try { try {
await uploadFotoMedico(medicoId, form.photo); await uploadFotoMedico(medicoId, form.photo);
@ -361,7 +355,6 @@ export function DoctorRegistrationForm({
} }
} }
// anexos locais (opcional)
if (form.anexos?.length) { if (form.anexos?.length) {
for (const f of form.anexos) { for (const f of form.anexos) {
try { try {