15bacacafa
A session followed the browser, not the account: log in, open a frame, log out, come back as a guest — the same photo stood on the stage, because the studio's own store (localStorage knobs + the photo in IndexedDB) outlived the cookie with nothing to clear it. clearSession() now drops both, and the three log-out buttons call it. The studio's own button reloads after the delete has committed — a reload mid- delete aborts the transaction, so the promise resolves on tx.oncomplete, not on the request. The account's frames are untouched: they reopen from MY PHOTOS.
60 lines
1.9 KiB
TypeScript
60 lines
1.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { api, type User } from './api';
|
|
import { clearSession } from './engine/session';
|
|
import { useI18n } from './i18n/I18nProvider';
|
|
import { Profile } from './ui/Profile';
|
|
import { Avatar } from './ui/Avatar';
|
|
|
|
// The member's own page: the same form the admin drawer holds, reachable
|
|
// without the moderation screen. No router — main.tsx picks it by pathname.
|
|
export function ProfilePage() {
|
|
const { t } = useI18n();
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [loaded, setLoaded] = useState(false);
|
|
const [note, setNote] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
api.me()
|
|
.then((r) => setUser(r.user))
|
|
.catch(() => undefined)
|
|
.finally(() => setLoaded(true));
|
|
}, []);
|
|
|
|
return (
|
|
<div className="adm">
|
|
<header className="adm-bar">
|
|
<a className="adm-brand" href="/">
|
|
<img src="/assets/RecipesCamIcon.png" alt="" width="26" height="26" />
|
|
<span>Recipes<em>Cam</em></span>
|
|
</a>
|
|
<b className="adm-title">{t('profile.title')}</b>
|
|
<span className="adm-spacer" />
|
|
<Avatar user={user} />
|
|
<a className="btn ghost" data-key="profile-home" href="/">{t('nav.back')}</a>
|
|
<button
|
|
type="button"
|
|
className="btn ghost"
|
|
data-key="profile-logout"
|
|
onClick={async () => {
|
|
await api.logout().catch(() => undefined);
|
|
await clearSession();
|
|
window.location.assign('/');
|
|
}}
|
|
>
|
|
{t('nav.logout')}
|
|
</button>
|
|
</header>
|
|
|
|
{note ? <p className="hint adm-note">{note}</p> : null}
|
|
|
|
{user ? (
|
|
<Profile onSaved={setNote} onUser={setUser} />
|
|
) : loaded ? (
|
|
<p className="adm-note">
|
|
<a className="btn primary" href="/?auth=login">{t('nav.login')}</a>
|
|
</p>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|