diff --git a/app/frontend/src/app/settings/page.tsx b/app/frontend/src/app/settings/page.tsx index f0c27699e..a7687721e 100644 --- a/app/frontend/src/app/settings/page.tsx +++ b/app/frontend/src/app/settings/page.tsx @@ -1,16 +1,19 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import Image from "next/image"; import Link from "next/link"; import { NetworkBadge } from "@/components/NetworkBadge"; import { LocaleSwitcher } from "@/components/LocaleSwitcher"; import '@/lib/i18n'; import { useTranslation } from "react-i18next"; +import { useApi } from "@/hooks/useApi"; +import { getProfile, saveProfile } from "@/lib/api"; +import { validateProfile, type Profile, type ProfileValidationErrors } from "@/types/profile"; export default function Settings() { const { t } = useTranslation(); - const [form, setForm] = useState({ + const [form, setForm] = useState({ username: "john_doe", primaryColor: "#6366f1", avatarUrl: "", @@ -20,10 +23,49 @@ export default function Settings() { githubHandle: "", }); + const [errors, setErrors] = useState({}); + const [successMessage, setSuccessMessage] = useState(null); const [showPreview, setShowPreview] = useState(false); - const handleSave = () => { - // TODO: Call API to save profile + const { error: apiError, loading, callApi } = useApi(); + + useEffect(() => { + let active = true; + const loadData = async () => { + try { + const data = await getProfile("john_doe"); + if (active && data) { + setForm(data); + } + } catch (err) { + console.error("Failed to load profile settings", err); + } + }; + loadData(); + return () => { + active = false; + }; + }, []); + + const handleSave = async () => { + setSuccessMessage(null); + setErrors({}); + + const validation = validateProfile(form); + if (!validation.isValid) { + setErrors(validation.errors); + return; + } + + try { + await callApi(() => saveProfile(form)); + setSuccessMessage("Settings saved successfully!"); + setTimeout(() => { + setSuccessMessage(null); + }, 5000); + } catch (err) { + console.error("Save profile error", err); + } }; return ( @@ -118,6 +160,18 @@ export default function Settings() { + {successMessage && ( +
+ {successMessage} +
+ )} + + {apiError && ( +
+ ⚠️ {apiError} +
+ )} +
{/* Settings Form */}
@@ -151,6 +205,9 @@ export default function Settings() { placeholder="#6366f1" />
+ {errors.primaryColor && ( +

{errors.primaryColor}

+ )}
@@ -166,6 +223,9 @@ export default function Settings() { className="w-full px-3 sm:px-4 py-2.5 sm:py-3 rounded-xl bg-white/5 border border-white/10 text-white text-sm sm:text-base" placeholder="https://example.com/avatar.jpg" /> + {errors.avatarUrl && ( +

{errors.avatarUrl}

+ )}
@@ -183,6 +243,9 @@ export default function Settings() {

{form.bio.length}/160 characters

+ {errors.bio && ( +

{errors.bio}

+ )}
@@ -223,6 +286,9 @@ export default function Settings() { maxLength={15} /> + {errors.twitterHandle && ( +

{errors.twitterHandle}

+ )}
@@ -239,6 +305,9 @@ export default function Settings() { placeholder="user#1234" maxLength={32} /> + {errors.discordHandle && ( +

{errors.discordHandle}

+ )}
@@ -255,6 +324,9 @@ export default function Settings() { placeholder="stellar" maxLength={39} /> + {errors.githubHandle && ( +

{errors.githubHandle}

+ )}
@@ -263,9 +335,17 @@ export default function Settings() {