// Caminho: app/patient/dashboard/page.tsx "use client"; import type React from "react"; import { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Calendar, Clock, User, Plus, LucideIcon } from "lucide-react"; import Link from "next/link"; import { toast } from "sonner"; // Importando TODOS os serviços de API necessários import { usuariosApi } from "@/services/usuariosApi"; import { agendamentosApi, Appointment as ApiAppointment } from "@/services/agendamentosApi"; import { pacientesApi, Patient } from "@/services/pacientesApi"; // --- Componentes Reutilizáveis --- interface DashboardStatCardProps { title: string; value: string; description: string; icon: LucideIcon; } const DashboardStatCard: React.FC = ({ title, value, description, icon: Icon }) => ( {title}
{value}

{description}

); interface AppointmentDisplay { doctorName: string; specialty: string; date: string; time: string; } interface UpcomingAppointmentItemProps { appointment: AppointmentDisplay; } const UpcomingAppointmentItem: React.FC = ({ appointment }) => (

{appointment.doctorName}

{appointment.specialty}

{appointment.date}

{appointment.time}

); // --- Tipos e Dados Estáticos --- interface QuickAction { href: string; label: string; icon: LucideIcon; variant?: "outline"; } const quickActions: QuickAction[] = [ { href: "/patient/schedule", label: "Agendar Nova Consulta", icon: Plus, variant: "outline" }, { href: "/patient/appointments", label: "Ver Minhas Consultas", icon: Calendar, variant: "outline" }, { href: "/patient/profile", label: "Atualizar Dados", icon: User, variant: "outline" }, ]; // --- Componente da Página --- export default function PatientDashboard() { const [statsData, setStatsData] = useState([]); const [upcomingAppointments, setUpcomingAppointments] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const user = await usuariosApi.getCurrentUser(); if (!user || !user.id) { throw new Error("Usuário não autenticado."); } const [appointmentsResponse, patientResponse] = await Promise.allSettled([ agendamentosApi.listByPatient(user.id), pacientesApi.getById(user.id) ]); let appointments: ApiAppointment[] = []; if (appointmentsResponse.status === 'fulfilled') { appointments = appointmentsResponse.value; // LÓGICA DE FALLBACK PARA AGENDAMENTOS if (appointments.length === 0) { console.warn("Nenhum agendamento encontrado na API real. Buscando do mock..."); toast.info("Usando dados de exemplo para os agendamentos."); appointments = await agendamentosApi.getMockAppointments(); } } else { console.error("Falha ao buscar agendamentos:", appointmentsResponse.reason); setError("Não foi possível carregar seus agendamentos. Tentando usar dados de exemplo."); appointments = await agendamentosApi.getMockAppointments(); // Fallback em caso de erro } const upcoming = appointments .filter(appt => new Date(appt.scheduled_at) > new Date() && appt.status !== 'cancelled') .sort((a, b) => new Date(a.scheduled_at).getTime() - new Date(b.scheduled_at).getTime()); setUpcomingAppointments(upcoming); let patientData: Patient | null = null; if (patientResponse.status === 'fulfilled') { patientData = patientResponse.value; } else { console.warn("Paciente não encontrado na API real. Tentando buscar do mock...", patientResponse.reason); try { patientData = await pacientesApi.getMockPatient(); toast.info("Usando dados de exemplo para o perfil do paciente."); } catch (mockError) { console.error("Falha ao buscar dados do mock:", mockError); } } const nextAppointment = upcoming[0]; const appointmentsThisMonth = appointments.filter(appt => { const apptDate = new Date(appt.scheduled_at); const now = new Date(); return apptDate.getMonth() === now.getMonth() && apptDate.getFullYear() === now.getFullYear(); }); let profileCompleteness = 0; let profileDescription = "Dados não encontrados"; if (patientData) { const profileFields = ['nome_completo', 'cpf', 'email', 'telefone', 'data_nascimento', 'endereco', 'cidade', 'estado', 'cep', 'convenio']; const filledFields = profileFields.filter(field => patientData[field]).length; profileCompleteness = Math.round((filledFields / profileFields.length) * 100); profileDescription = profileCompleteness === 100 ? "Dados completos" : `${filledFields} de ${profileFields.length} campos preenchidos`; } setStatsData([ { title: "Próxima Consulta", value: nextAppointment ? new Date(nextAppointment.scheduled_at).toLocaleDateString('pt-BR', { day: '2-digit', month: 'short' }) : "Nenhuma", description: nextAppointment ? `${nextAppointment.doctors?.full_name || 'Médico'} - ${new Date(nextAppointment.scheduled_at).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}` : "Sem consultas futuras", icon: Calendar }, { title: "Consultas Este Mês", value: appointmentsThisMonth.length.toString(), description: `${appointmentsThisMonth.filter(a => a.status === 'completed').length} realizadas`, icon: Clock }, { title: "Perfil", value: `${profileCompleteness}%`, description: profileDescription, icon: User }, ]); } catch (err) { console.error("Erro geral ao carregar dados do dashboard:", err); setError("Não foi possível carregar as informações. Tente novamente mais tarde."); } finally { setIsLoading(false); } }; fetchData(); }, []); if (isLoading) { return
Carregando dashboard...
; } if (error) { return
{error}
; } return (

Dashboard

Bem-vindo ao seu portal de consultas médicas.

{statsData.map((stat) => ( ))}
Ações Rápidas Acesse rapidamente as principais funcionalidades. {quickActions.map((action) => { const Icon = action.icon; return ( ); })} Próximas Consultas Suas consultas agendadas para o futuro.
{upcomingAppointments.length > 0 ? ( upcomingAppointments.slice(0, 5).map((appointment) => ( )) ) : (

Você não tem nenhuma consulta agendada.

)}
); }