Public Access
feat(settings): link the Steam account through Steam
A Steam card in the settings links, verifies or unlinks the Steam account through "Sign in through Steam". After the way back the page shows the outcome and refreshes the session, so Core gets the new Steam ID at once. Registration and settings no longer ask for a typed Steam ID.
This commit is contained in:
1 parent
23ab5a91e7
commit
ca75e6a530
13 files changed
+393
-86
No files matched your search
@@ -0,0 +1,98 @@
|
||||
import {useState} from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {BadgeCheck, CircleAlert, Gamepad2, Link2, Loader2, Unlink} from 'lucide-react';
|
||||
import {toast} from 'sonner';
|
||||
|
||||
import {Badge} from '@/components/ui/badge';
|
||||
import {Button} from '@/components/ui/button';
|
||||
import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card';
|
||||
import useSessionExpired from '../hooks/useSessionExpired.js';
|
||||
import {markSession} from '../utils/auth.js';
|
||||
import {startSteamLink, unlinkSteam} from '../utils/steamLink.js';
|
||||
|
||||
/**
|
||||
* The linked Steam account. A Steam ID comes only from "Sign in through Steam"; one typed in before that is shown
|
||||
* as not verified.
|
||||
*/
|
||||
export default function SteamAccountCard({steamId, verified, onUnlinked}) {
|
||||
const {t} = useTranslation();
|
||||
const expireSession = useSessionExpired();
|
||||
const [busy, setBusy] = useState(false);
|
||||
|
||||
const link = async () => {
|
||||
setBusy(true);
|
||||
try {
|
||||
const response = await startSteamLink();
|
||||
if (response.ok) return; // on the way to Steam: the button stays busy
|
||||
if (response.status === 401) {
|
||||
expireSession();
|
||||
} else {
|
||||
toast.error(t('SETTINGS.STEAM_LINK.ERROR'));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Steam link error:', err);
|
||||
toast.error(t('SETTINGS.STEAM_LINK.ERROR'));
|
||||
}
|
||||
setBusy(false);
|
||||
};
|
||||
|
||||
const unlink = async () => {
|
||||
setBusy(true);
|
||||
try {
|
||||
const response = await unlinkSteam();
|
||||
if (response.status === 401) {
|
||||
expireSession();
|
||||
return;
|
||||
}
|
||||
if (!response.ok) {
|
||||
toast.error(t('SETTINGS.STEAM_LINK.ERROR'));
|
||||
return;
|
||||
}
|
||||
// The new access cookie has no Steam ID; the new stamp makes the header load again.
|
||||
markSession();
|
||||
toast.success(t('SETTINGS.STEAM_LINK.UNLINKED'));
|
||||
onUnlinked();
|
||||
} catch (err) {
|
||||
console.error('Steam unlink error:', err);
|
||||
toast.error(t('INFO.ERROR.NETWORK_FAILURE'));
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2"><Gamepad2 className="size-4 text-primary"/>{t('SETTINGS.STEAM')}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{steamId ? (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span className="font-mono text-sm">{steamId}</span>
|
||||
{verified ? (
|
||||
<Badge variant="outline"><BadgeCheck className="size-3"/>{t('SETTINGS.STEAM_LINK.VERIFIED')}</Badge>
|
||||
) : (
|
||||
<Badge variant="outline"><CircleAlert className="size-3"/>{t('SETTINGS.STEAM_LINK.NOT_VERIFIED')}</Badge>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">{t('SETTINGS.STEAM_LINK.NONE')}</p>
|
||||
)}
|
||||
{steamId && !verified && (
|
||||
<p className="text-sm text-muted-foreground">{t('SETTINGS.STEAM_LINK.VERIFY_HINT')}</p>
|
||||
)}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button type="button" variant={steamId && verified ? 'outline' : 'default'} onClick={link} disabled={busy}>
|
||||
{busy ? <Loader2 className="animate-spin"/> : <Link2/>}
|
||||
{t(!steamId ? 'SETTINGS.STEAM_LINK.LINK' : verified ? 'SETTINGS.STEAM_LINK.CHANGE' : 'SETTINGS.STEAM_LINK.VERIFY')}
|
||||
</Button>
|
||||
{steamId && (
|
||||
<Button type="button" variant="outline" onClick={unlink} disabled={busy}>
|
||||
<Unlink/>{t('SETTINGS.STEAM_LINK.UNLINK')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user