refactor(frontend): migrate Profile.tsx to the banner system
Load/save/delete failures now call showError instead of setting local error state. The profile-not-loaded-yet fallback gains a profileLoadFailed boolean so it can still distinguish "loading" from "failed to load" without the error text itself, which now lives only in the (transient) banner.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { api, BASE_URL } from "../api/client";
|
||||
import { showError } from "../banner";
|
||||
import { ColorField } from "../components/ColorField";
|
||||
import { GarminConnection } from "../components/GarminConnection";
|
||||
import { NullableNumberField } from "../components/NullableNumberField";
|
||||
@@ -87,7 +88,7 @@ const AUTO_SAVE_DELAY_MS = 600;
|
||||
|
||||
export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
|
||||
const [profile, setProfile] = useState<ProfileType | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [profileLoadFailed, setProfileLoadFailed] = useState(false);
|
||||
const [saved, setSaved] = useState(false);
|
||||
// Mirrors `profile` synchronously (state updates don't apply until the
|
||||
// next render), so set() always debounces from the latest edit rather
|
||||
@@ -100,7 +101,10 @@ export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
api.getProfile().then(setProfile).catch((e) => setError(String(e)));
|
||||
api.getProfile().then(setProfile).catch((e) => {
|
||||
showError(String(e));
|
||||
setProfileLoadFailed(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Flush a still-pending debounced save on unmount (e.g. the user edits a
|
||||
@@ -121,11 +125,10 @@ export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
|
||||
const updated = await api.updateProfile(next);
|
||||
profileRef.current = updated;
|
||||
setProfile(updated);
|
||||
setError(null);
|
||||
setSaved(true);
|
||||
onSaved?.(updated);
|
||||
} catch (e) {
|
||||
setError(String(e));
|
||||
showError(String(e));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +156,6 @@ export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
|
||||
|
||||
async function deleteAccount() {
|
||||
setDeleting(true);
|
||||
setError(null);
|
||||
try {
|
||||
await api.deleteProfile();
|
||||
// Deletion doesn't clear the session cookie -- follow with a real
|
||||
@@ -166,7 +168,7 @@ export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
} catch (e) {
|
||||
setError(String(e));
|
||||
showError(String(e));
|
||||
setDeleting(false);
|
||||
}
|
||||
}
|
||||
@@ -174,14 +176,13 @@ export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
|
||||
if (!profile) {
|
||||
return (
|
||||
<div className="page">
|
||||
{error ? <p className="error">{error}</p> : <p>Loading...</p>}
|
||||
{profileLoadFailed ? <p className="empty-state">Couldn't load profile.</p> : <p>Loading...</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="page profile-page">
|
||||
{error && <p className="error">{error}</p>}
|
||||
{saved && <p className="garmin-connection-message">Saved.</p>}
|
||||
|
||||
<fieldset className="kind-editor">
|
||||
|
||||
Reference in New Issue
Block a user