// Caminho: app/patient/profile/page.tsx "use client"; import { useState, useEffect, useRef } from "react"; import Sidebar from "@/components/Sidebar"; import { useAuthLayout } from "@/hooks/useAuthLayout"; import { patientsService } from "@/services/patientsApi.mjs"; import { usersService } from "@/services/usersApi.mjs"; // Adicionado import import { api } from "@/services/api.mjs"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { User, Mail, Phone, Calendar, Upload } from "lucide-react"; import { toast } from "@/hooks/use-toast"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; interface PatientProfileData { name: string; email: string; phone: string; cpf: string; birthDate: string; cep: string; street: string; number: string; city: string; avatarFullUrl?: string; } export default function PatientProfile() { const { user, isLoading: isAuthLoading } = useAuthLayout({ requiredRole: ["paciente", "admin", "medico", "gestor", "secretaria"], }); const [patientData, setPatientData] = useState( null ); const [isEditing, setIsEditing] = useState(false); const [isSaving, setIsSaving] = useState(false); const fileInputRef = useRef(null); const getInitials = (name: string) => { if (!name) return "U"; return name .split(" ") .map((n) => n[0]) .slice(0, 2) .join("") .toUpperCase(); }; // Função auxiliar para construir URL do avatar const buildAvatarUrl = (path: string | null | undefined) => { if (!path) return undefined; const baseUrl = "https://yuanqfswhberkoevtmfr.supabase.co"; const cleanPath = path.startsWith('/') ? path.slice(1) : path; const separator = cleanPath.includes('?') ? '&' : '?'; return `${baseUrl}/storage/v1/object/avatars/${cleanPath}${separator}t=${new Date().getTime()}`; }; useEffect(() => { if (user?.id) { const loadData = async () => { try { // 1. Busca dados médicos (Tabela Patients) const patientDetails = await patientsService.getById(user.id); // 2. Busca dados de sistema frescos (Tabela Profiles via getMe) // Isso garante que pegamos o avatar real do banco, não do cache local const userSystemData = await usersService.getMe(); const freshAvatarPath = userSystemData?.profile?.avatar_url; const freshAvatarUrl = buildAvatarUrl(freshAvatarPath); setPatientData({ name: patientDetails.full_name || user.name, email: user.email, phone: patientDetails.phone_mobile || "", cpf: patientDetails.cpf || "", birthDate: patientDetails.birth_date || "", cep: patientDetails.cep || "", street: patientDetails.street || "", number: patientDetails.number || "", city: patientDetails.city || "", avatarFullUrl: freshAvatarUrl, // Usa a URL fresca do banco }); } catch (error) { console.error("Erro ao buscar detalhes:", error); toast({ title: "Erro", description: "Não foi possível carregar seus dados completos.", variant: "destructive", }); } }; loadData(); } }, [user?.id, user?.email, user?.name]); // Removi user.avatarFullUrl para não depender do cache const handleInputChange = ( field: keyof PatientProfileData, value: string ) => { setPatientData((prev) => (prev ? { ...prev, [field]: value } : null)); }; const updateLocalSession = (updates: { full_name?: string; avatar_url?: string }) => { try { const storedUserString = localStorage.getItem("user_info"); if (storedUserString) { const storedUser = JSON.parse(storedUserString); if (!storedUser.user_metadata) storedUser.user_metadata = {}; if (updates.full_name) storedUser.user_metadata.full_name = updates.full_name; if (updates.avatar_url) storedUser.user_metadata.avatar_url = updates.avatar_url; if (!storedUser.profile) storedUser.profile = {}; if (updates.full_name) storedUser.profile.full_name = updates.full_name; if (updates.avatar_url) storedUser.profile.avatar_url = updates.avatar_url; localStorage.setItem("user_info", JSON.stringify(storedUser)); } } catch (e) { console.error("Erro ao atualizar sessão local:", e); } }; const handleSave = async () => { if (!patientData || !user) return; setIsSaving(true); try { const patientPayload = { full_name: patientData.name, cpf: patientData.cpf, birth_date: patientData.birthDate, phone_mobile: patientData.phone, cep: patientData.cep, street: patientData.street, number: patientData.number, city: patientData.city, }; await patientsService.update(user.id, patientPayload); await api.patch(`/rest/v1/profiles?id=eq.${user.id}`, { full_name: patientData.name, }); updateLocalSession({ full_name: patientData.name }); toast({ title: "Sucesso!", description: "Seus dados foram atualizados. A página será recarregada.", }); setIsEditing(false); setTimeout(() => window.location.reload(), 1000); } catch (error) { console.error("Erro ao salvar dados:", error); toast({ title: "Erro", description: "Não foi possível salvar suas alterações.", variant: "destructive", }); } finally { setIsSaving(false); } }; const handleAvatarClick = () => { fileInputRef.current?.click(); }; const handleAvatarUpload = async ( event: React.ChangeEvent ) => { const file = event.target.files?.[0]; if (!file || !user) return; const fileExt = file.name.split(".").pop(); const filePath = `${user.id}/avatar.${fileExt}`; try { await api.storage.upload("avatars", filePath, file); await api.patch(`/rest/v1/profiles?id=eq.${user.id}`, { avatar_url: filePath, }); const newFullUrl = buildAvatarUrl(filePath); setPatientData((prev) => prev ? { ...prev, avatarFullUrl: newFullUrl } : null ); updateLocalSession({ avatar_url: filePath }); toast({ title: "Sucesso!", description: "Sua foto de perfil foi atualizada.", }); setTimeout(() => window.location.reload(), 1000); } catch (error) { console.error("Erro no upload do avatar:", error); toast({ title: "Erro de Upload", description: "Não foi possível enviar sua foto.", variant: "destructive", }); } }; if (isAuthLoading || !patientData) { return (

Carregando seus dados...

); } return (

Meus Dados

Gerencie suas informações pessoais

Informações Pessoais
handleInputChange("name", e.target.value) } disabled={!isEditing} />
handleInputChange("cpf", e.target.value)} disabled={!isEditing} />
handleInputChange("birthDate", e.target.value) } disabled={!isEditing} />
Contato e Endereço
handleInputChange("phone", e.target.value) } disabled={!isEditing} />
handleInputChange("cep", e.target.value)} disabled={!isEditing} />
handleInputChange("street", e.target.value) } disabled={!isEditing} />
handleInputChange("number", e.target.value) } disabled={!isEditing} />
handleInputChange("city", e.target.value) } disabled={!isEditing} />
Resumo do Perfil
{getInitials(patientData.name)}

{patientData.name}

Paciente

{patientData.email}
{patientData.phone || "Não informado"}
{patientData.birthDate ? new Date(patientData.birthDate).toLocaleDateString( "pt-BR", { timeZone: "UTC" } ) : "Não informado"}
); }