// ARQUIVO COMPLETO PARA: 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 { 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 { Textarea } from "@/components/ui/textarea"; 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); useEffect(() => { if (user?.id) { const fetchPatientDetails = async () => { try { const patientDetails = await patientsService.getById(user.id); 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: user.avatarFullUrl, }); } catch (error) { console.error("Erro ao buscar detalhes do paciente:", error); toast({ title: "Erro", description: "Não foi possível carregar seus dados completos.", variant: "destructive" }); } }; fetchPatientDetails(); } }, [user]); const handleInputChange = (field: keyof PatientProfileData, value: string) => { setPatientData((prev) => (prev ? { ...prev, [field]: value } : null)); }; 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); toast({ title: "Sucesso!", description: "Seus dados foram atualizados." }); setIsEditing(false); } 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(); // *** A CORREÇÃO ESTÁ AQUI *** // O caminho salvo no banco de dados não deve conter o nome do bucket. 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 = `https://yuanqfswhberkoevtmfr.supabase.co/storage/v1/object/public/avatars/${filePath}?t=${new Date().getTime()}`; setPatientData((prev) => (prev ? { ...prev, avatarFullUrl: newFullUrl } : null)); toast({ title: "Sucesso!", description: "Sua foto de perfil foi atualizada." }); } 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
{patientData.name .split(" ") .map((n) => n[0]) .join("")}

{patientData.name}

Paciente

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