import { useCallback, useEffect, useRef, useState } from "react"; import { getProfile, updateProfile, uploadAvatar } from "../api/profile"; import { EmptyState, ErrorState, LoadingState } from "../components/data-states"; import { Icon } from "../components/icon"; import { useAuth } from "../state/auth"; import { useAsyncData } from "../hooks/use-async-data"; import type { UserProfile } from "../api/profile"; type ProfileStatus = "loading" | "ready" | "error" | "saving"; export const ProfilePage = () => { const { refreshSession } = useAuth(); const { data: profile, status: loadStatus, reload } = useAsyncData(getProfile, []); const [displayStatus, setDisplayStatus] = useState("loading"); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [error, setError] = useState(null); const fileInputRef = useRef(null); // Sync loaded profile into form fields useEffect(() => { if (profile) { setName(profile.name); setEmail(profile.email); setDisplayStatus("ready"); setError(null); } }, [profile]); useEffect(() => { if (loadStatus === "error") { setDisplayStatus("error"); } }, [loadStatus]); const handleSave = useCallback(async () => { if (!name.trim()) { setError("Name cannot be empty"); return; } if (!email.includes("@")) { setError("Please enter a valid email"); return; } setDisplayStatus("saving"); setError(null); try { await updateProfile({ name: name.trim(), email: email.trim() }); await refreshSession(); setDisplayStatus("ready"); } catch { setError("Failed to update profile"); setDisplayStatus("ready"); } }, [name, email, refreshSession]); const handleAvatarChange = useCallback( async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; if (!file.type.startsWith("image/")) { setError("Please upload an image file (PNG or JPEG)"); return; } if (file.size > 2 * 1024 * 1024) { setError("File too large. Maximum size is 2MB."); return; } setDisplayStatus("saving"); setError(null); try { await uploadAvatar(file); await refreshSession(); reload(); setDisplayStatus("ready"); } catch { setError("Failed to upload avatar"); setDisplayStatus("ready"); } }, [refreshSession, reload] ); const avatarUrl = profile?.avatar_url ?? null; return (

Profile

{displayStatus === "loading" && } {displayStatus === "error" && } {(displayStatus === "ready" || displayStatus === "saving") && profile && (
{avatarUrl ? ( Avatar ) : (
{profile.name.charAt(0).toUpperCase()}
)}
setName(e.target.value)} type="text" value={name} />
setEmail(e.target.value)} type="email" value={email} />
{error &&

{error}

}
)}
); };