"use client"; import React, { useEffect, useState } from "react" import ManagerLayout from "@/components/manager-layout"; import Link from "next/link" import { Button } from "@/components/ui/button" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Plus, Edit, Trash2, Eye, Calendar, Filter } from "lucide-react" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog" export default function DoctorsPage() { const [detailsDialogOpen, setDetailsDialogOpen] = useState(false) const [doctorDetails, setDoctorDetails] = useState(null) const openDetailsDialog = async (doctorId: string) => { setDetailsDialogOpen(true) setDoctorDetails(null) try { const res = await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${doctorId}`) if (!res.ok) throw new Error(`HTTP ${res.status}`) const json = await res.json() setDoctorDetails(json?.data ?? null) } catch (e: any) { setDoctorDetails({ error: e?.message || "Erro ao buscar detalhes" }) } } const [searchTerm, setSearchTerm] = useState("") const [especialidadeFilter, setEspecialidadeFilter] = useState("all") const [statusFilter, setStatusFilter] = useState("all") const [doctors, setDoctors] = useState([]) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) const [doctorToDelete, setDoctorToDelete] = useState(null) const [page, setPage] = useState(1) const [hasNext, setHasNext] = useState(true) const [isFetching, setIsFetching] = useState(false) const observerRef = React.useRef(null) const fetchMedicos = React.useCallback(async (pageToFetch: number) => { if (isFetching || !hasNext) return setIsFetching(true) setError(null) try { const res = await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes?page=${pageToFetch}&limit=20`) if (!res.ok) throw new Error(`HTTP ${res.status}`) const json = await res.json() const items = Array.isArray(json?.data) ? json.data : [] const mapped = items.map((p: any) => ({ id: String(p.id ?? ""), nome: p.nome ?? "", crm: p.crm ?? "", // mock não tem crm, pode deixar vazio especialidade: p.especialidade ?? "", // mock não tem especialidade, pode deixar vazio telefone: p?.contato?.celular ?? p?.contato?.telefone1 ?? p?.telefone ?? "", cidade: p?.endereco?.cidade ?? p?.cidade ?? "", estado: p?.endereco?.estado ?? p?.estado ?? "", ultimoAtendimento: p.ultimo_atendimento ?? p.ultimoAtendimento ?? "", proximoAtendimento: p.proximo_atendimento ?? p.proximoAtendimento ?? "", status: p.status ?? "", })) setDoctors((prev) => [...prev, ...mapped]) setHasNext(Boolean(json?.pagination?.has_next)) setPage(pageToFetch + 1) } catch (e: any) { setError(e?.message || "Erro ao buscar médicos") } finally { setIsFetching(false) } }, [isFetching, hasNext]) React.useEffect(() => { fetchMedicos(page) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) React.useEffect(() => { if (!observerRef.current || !hasNext) return const observer = new window.IntersectionObserver((entries) => { if (entries[0].isIntersecting && !isFetching && hasNext) { fetchMedicos(page) } }) observer.observe(observerRef.current) return () => { if (observerRef.current) observer.unobserve(observerRef.current) } }, [fetchMedicos, page, hasNext, isFetching]) const handleDeleteDoctor = async (doctorId: string) => { try { await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${doctorId}`, { method: "DELETE", }) } catch { } setDoctors((prev) => prev.filter((doctor) => String(doctor.id) !== String(doctorId))) setDeleteDialogOpen(false) setDoctorToDelete(null) } const openDeleteDialog = (doctorId: string) => { setDoctorToDelete(doctorId) setDeleteDialogOpen(true) } const filteredDoctors = doctors.filter((doctor) => { const matchesSearch = doctor.nome.toLowerCase().includes(searchTerm.toLowerCase()) || doctor.crm.toLowerCase().includes(searchTerm.toLowerCase()) || doctor.telefone.includes(searchTerm) const matchesEspecialidade = especialidadeFilter === "all" || doctor.especialidade === especialidadeFilter const matchesStatus = statusFilter === "all" || doctor.status === statusFilter return matchesSearch && matchesEspecialidade && matchesStatus }) return (
{/* ...layout e filtros... */}

Médicos

Gerencie as informações dos médicos

{/* ...filtros... */}
Especialidade
Status
{error ? ( ) : filteredDoctors.length === 0 ? ( ) : ( filteredDoctors.map((doctor) => ( )) )}
Nome CRM Telefone Cidade Estado Último atendimento Próximo atendimento Ações
{`Erro: ${error}`}
Nenhum registro encontrado
{doctor.nome?.charAt(0) || "?"}
{doctor.nome}
{doctor.crm} {doctor.telefone} {doctor.cidade} {doctor.estado} {doctor.ultimoAtendimento} {doctor.proximoAtendimento}
Ações
openDetailsDialog(String(doctor.id))}> Ver detalhes Editar Ver agenda openDeleteDialog(String(doctor.id))}> Excluir
{isFetching && (
Carregando mais médicos...
)}
Confirmar exclusão Tem certeza que deseja excluir este médico? Esta ação não pode ser desfeita. Cancelar doctorToDelete && handleDeleteDoctor(doctorToDelete)} className="bg-red-600 hover:bg-red-700" > Excluir {/* Modal de detalhes do médico */} Detalhes do Médico {doctorDetails === null ? (
Carregando...
) : doctorDetails?.error ? (
{doctorDetails.error}
) : (
Nome: {doctorDetails.nome}
Telefone: {doctorDetails?.contato?.celular ?? doctorDetails?.contato?.telefone1 ?? doctorDetails?.telefone ?? ""}
Cidade: {doctorDetails?.endereco?.cidade ?? doctorDetails?.cidade ?? ""}
Estado: {doctorDetails?.endereco?.estado ?? doctorDetails?.estado ?? ""}
Convênio: {doctorDetails.convenio ?? ""}
VIP: {doctorDetails.vip ? "Sim" : "Não"}
Status: {doctorDetails.status ?? ""}
Último atendimento: {doctorDetails.ultimo_atendimento ?? doctorDetails.ultimoAtendimento ?? ""}
Próximo atendimento: {doctorDetails.proximo_atendimento ?? doctorDetails.proximoAtendimento ?? ""}
)}
Fechar
); }