import type { NumberFormat, ProfileSettings } from "@elysium/types"; import { DEFAULT_PROFILE_SETTINGS } from "@elysium/types"; import { useEffect, useState } from "react"; import { updateProfile } from "../../api/client.js"; import { useGame } from "../../context/GameContext.js"; interface EditProfileModalProps { onClose: () => void; } interface StatToggle { key: keyof ProfileSettings; label: string; icon: string; } const CURRENT_RUN_TOGGLES: StatToggle[] = [ { key: "showCurrentGold", label: "Gold Earned This Run", icon: "πŸͺ™" }, { key: "showCurrentClicks", label: "Clicks This Run", icon: "πŸ‘†" }, { key: "showApotheosis", label: "Apotheosis Badge", icon: "✨" }, { key: "showTranscendence", label: "Transcendence Badge", icon: "🌌" }, { key: "showPrestige", label: "Prestige Level", icon: "⭐" }, { key: "showBossesDefeated", label: "Bosses Defeated", icon: "πŸ’€" }, { key: "showQuestsCompleted", label: "Quests Completed", icon: "πŸ“œ" }, { key: "showAdventurersRecruited", label: "Adventurers Recruited", icon: "βš”οΈ" }, { key: "showAchievementsUnlocked", label: "Achievements Unlocked", icon: "πŸ†" }, ]; const ALL_TIME_TOGGLES: StatToggle[] = [ { key: "showTotalGold", label: "Total Gold Earned", icon: "πŸͺ™" }, { key: "showTotalClicks", label: "Total Clicks", icon: "πŸ‘†" }, { key: "showLifetimeBossesDefeated", label: "Bosses Defeated", icon: "πŸ’€" }, { key: "showLifetimeQuestsCompleted", label: "Quests Completed", icon: "πŸ“œ" }, { key: "showLifetimeAdventurersRecruited", label: "Adventurers Recruited", icon: "βš”οΈ" }, { key: "showLifetimeAchievementsUnlocked", label: "Achievements Unlocked", icon: "πŸ†" }, { key: "showGuildFounded", label: "Guild Founded Date", icon: "πŸ“…" }, ]; export const EditProfileModal = ({ onClose }: EditProfileModalProps): React.JSX.Element => { const { state, numberFormat: currentNumberFormat, setNumberFormat } = useGame(); const player = state?.player; const [characterName, setCharacterName] = useState(player?.characterName ?? ""); const [bio, setBio] = useState(""); const [settings, setSettings] = useState({ ...DEFAULT_PROFILE_SETTINGS, numberFormat: currentNumberFormat, }); const [loadingProfile, setLoadingProfile] = useState(true); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [saved, setSaved] = useState(false); // Fetch current profile to auto-populate bio and settings useEffect(() => { if (!player?.discordId) return; fetch(`/api/profile/${player.discordId}`) .then(async (res) => { if (!res.ok) return; const data = (await res.json()) as { bio: string; profileSettings: ProfileSettings; characterName: string; }; setBio(data.bio ?? ""); setSettings({ ...DEFAULT_PROFILE_SETTINGS, ...data.profileSettings }); setCharacterName(data.characterName ?? player.characterName ?? ""); }) .catch(() => { // Fall back to local state if fetch fails β€” not a blocking error }) .finally(() => { setLoadingProfile(false); }); }, [player?.discordId, player?.characterName]); const handleSave = async (): Promise => { setSaving(true); setError(null); try { await updateProfile({ characterName, bio, profileSettings: settings }); setNumberFormat(settings.numberFormat); setSaved(true); setTimeout(onClose, 900); } catch (err: unknown) { setError(err instanceof Error ? err.message : "Failed to save"); } finally { setSaving(false); } }; const toggleSetting = (key: keyof ProfileSettings): void => { setSettings((prev) => ({ ...prev, [key]: !prev[key] })); }; return (

Edit Profile

{loadingProfile ? (

Loading your profile…

) : (
{ setCharacterName(e.target.value); }} /> {characterName.length} / 32