Files
ToBePlayed-Frontend/src/pages/SettingsPage.jsx
T
lobo 43c4862606
Build, Test & Push Frontend / quality-check (push) Successful in 34s
Build, Test & Push Frontend / docker (push) Successful in 23s
feat(ui): add follow button, follows card, and inbox page
2026-10-06 16:22:22 +02:00

88 lines
3.4 KiB
React

import {useEffect, useRef, useState} from 'react';
import {useSearchParams} from 'react-router-dom';
import {useTranslation} from 'react-i18next';
import {toast} from 'sonner';
import {Skeleton} from '@/components/ui/skeleton';
import AccountInfoCard from '../components/AccountInfoCard.jsx';
import AppearanceCard from '../components/AppearanceCard.jsx';
import BuildVersionCard from '../components/BuildVersionCard.jsx';
import ChangePasswordCard from '../components/ChangePasswordCard.jsx';
import DeleteAccountCard from '../components/DeleteAccountCard.jsx';
import FollowsCard from '../components/FollowsCard.jsx';
import PreferencesCard from '../components/PreferencesCard.jsx';
import ProfileCard from '../components/ProfileCard.jsx';
import SteamAccountCard from '../components/SteamAccountCard.jsx';
import {useCurrentUserContext} from '../context/CurrentUserContext.jsx';
import useSettingsLoad from '../hooks/useSettingsLoad.js';
// The `steam` query parameter Auth adds when "Sign in through Steam" sends the user back.
const STEAM_LINK_TOASTS = {
linked: {show: toast.success, key: 'SETTINGS.STEAM_LINK.LINKED'},
'in-use': {show: toast.error, key: 'SETTINGS.STEAM_LINK.IN_USE'},
cancelled: {show: toast.info, key: 'SETTINGS.STEAM_LINK.CANCELLED'},
failed: {show: toast.error, key: 'SETTINGS.STEAM_LINK.FAILED'},
};
export default function SettingsPage() {
const {t} = useTranslation();
const {user: profile, updateUser: updateProfile} = useCurrentUserContext();
const [searchParams, setSearchParams] = useSearchParams();
// Read once: removing the parameter below must not load the profile again.
const [steamOutcome] = useState(() => searchParams.get('steam'));
const {isLoading, loadError, displayName} = useSettingsLoad(steamOutcome);
// A language change gives a new `t` and runs the effect again; the toast shows once.
const steamToastShown = useRef(false);
useEffect(() => {
const outcome = STEAM_LINK_TOASTS[steamOutcome];
if (!outcome || steamToastShown.current) return;
steamToastShown.current = true;
outcome.show(t(outcome.key));
setSearchParams((params) => {
params.delete('steam');
return params;
}, {replace: true});
}, [steamOutcome, setSearchParams, t]);
if (isLoading) {
return (
<div className="w-full max-w-2xl mx-auto p-4 md:p-8 space-y-6">
<Skeleton className="h-9 w-48"/>
<Skeleton className="h-56 rounded-xl"/>
<Skeleton className="h-40 rounded-xl"/>
<Skeleton className="h-44 rounded-xl"/>
</div>
);
}
if (loadError) {
return <div className="py-24 text-center text-destructive">{t(loadError)}</div>;
}
return (
<div className="w-full max-w-2xl mx-auto p-4 md:p-8 space-y-6">
<h1 className="text-3xl font-bold tracking-tight">{t('SETTINGS.TITLE')}</h1>
<AccountInfoCard/>
<PreferencesCard/>
<AppearanceCard/>
<SteamAccountCard steamId={profile?.steamId} verified={!!profile?.steamIdVerified}
onUnlinked={() => updateProfile((p) => ({...p, steamId: null, steamIdVerified: false}))}/>
<ProfileCard displayName={displayName}/>
<FollowsCard/>
<BuildVersionCard/>
<ChangePasswordCard/>
<DeleteAccountCard email={profile?.email}/>
</div>
);
}