import { useCallback, useEffect, useRef, useState } from "react"; import { getProfile, updateProfile, uploadAvatar } from "../api/profile"; import { Icon } from "../components/icon"; import { useAuth } from "../state/auth"; import type { UserProfile } from "../api/profile"; type ProfileStatus = "loading" | "ready" | "error" | "saving"; export const ProfilePage = () => { const { refreshSession } = useAuth(); const [status, setStatus] = useState("loading"); const [profile, setProfile] = useState(null); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [error, setError] = useState(null); const fileInputRef = useRef(null); const loadProfile = useCallback(async () => { setStatus("loading"); setError(null); try { const data = await getProfile(); setProfile(data); setName(data.name); setEmail(data.email); setStatus("ready"); } catch { setProfile(null); setStatus("error"); } }, []); useEffect(() => { void loadProfile(); }, [loadProfile]); const handleSave = useCallback(async () => { if (!name.trim()) { setError("Name cannot be empty"); return; } if (!email.includes("@")) { setError("Please enter a valid email"); return; } setStatus("saving"); setError(null); try { const updated = await updateProfile({ name: name.trim(), email: email.trim() }); setProfile(updated); await refreshSession(); setStatus("ready"); } catch { setError("Failed to update profile"); setStatus("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; } setStatus("saving"); setError(null); try { const updated = await uploadAvatar(file); setProfile(updated); await refreshSession(); setStatus("ready"); } catch { setError("Failed to upload avatar"); setStatus("ready"); } }, [refreshSession] ); const avatarUrl = profile?.avatar_url ?? null; return (

Profile

{status === "loading" &&

Loading profile...

} {status === "error" && (

Failed to load profile

)} {(status === "ready" || status === "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}

}
)}
); };