Public Access
feat(nav): add header navigation and show Steam ID on dashboard
Header links to Dashboard, Library and Settings. The logo, the login page and the landing page lead logged-in users to the dashboard. Expired tokens are removed, and a 403 on the dashboard logs out. Remove the dev dummy token.
This commit is contained in:
1 parent
44e23de6d6
commit
8fa605aff0
8 files changed
+124
-23
No files matched your search
+12
-1
@@ -56,7 +56,7 @@ const Dashboard = () => {
|
||||
if (data.steamId) {
|
||||
await fetchSteamCount();
|
||||
}
|
||||
} else if (profileResponse.status === 401) {
|
||||
} else if (profileResponse.status === 401 || profileResponse.status === 403) {
|
||||
localStorage.removeItem('tbp_jwt');
|
||||
navigate('/login');
|
||||
} else {
|
||||
@@ -107,6 +107,17 @@ const Dashboard = () => {
|
||||
<p className="text-lg text-slate-600 dark:text-slate-300">
|
||||
{userData?.dashboardMessage}
|
||||
</p>
|
||||
{userData?.steamId ? (
|
||||
<p className="mt-2 text-sm text-slate-500 dark:text-slate-400">
|
||||
<i className="mdi mdi-steam mr-1"></i>
|
||||
{t('SETTINGS.STEAM_ID')}: <span className="font-mono">{userData.steamId}</span>
|
||||
</p>
|
||||
) : (
|
||||
<Link to="/settings" className="mt-2 inline-block text-sm text-blue-600 dark:text-blue-400 hover:underline">
|
||||
<i className="mdi mdi-steam mr-1"></i>
|
||||
{t('DASHBOARD.NO_STEAM_ID')}
|
||||
</Link>
|
||||
)}
|
||||
{userData?.steamId && (
|
||||
<div className="mt-4">
|
||||
<SyncStatusBadge
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {getValidToken} from '../utils/auth.js';
|
||||
import StatCard from '../components/StatCard.jsx';
|
||||
|
||||
import usePublicStats from '../hooks/usePublicStats.js';
|
||||
@@ -25,9 +26,15 @@ export default function LandingPage() {
|
||||
<p className="text-lg text-slate-600 dark:text-slate-400 max-w-2xl mx-auto mb-8">
|
||||
{t('MAIN.DESCRIPTION')}
|
||||
</p>
|
||||
<Link to="/login" className="bg-blue-600 hover:bg-blue-500 text-white px-8 py-3 rounded-xl font-bold text-lg transition-all shadow-lg shadow-blue-500/30">
|
||||
{t('MAIN.GET_STARTED')}
|
||||
</Link>
|
||||
{getValidToken() ? (
|
||||
<Link to="/dashboard" className="bg-blue-600 hover:bg-blue-500 text-white px-8 py-3 rounded-xl font-bold text-lg transition-all shadow-lg shadow-blue-500/30">
|
||||
{t('NAV.TO_DASHBOARD')}
|
||||
</Link>
|
||||
) : (
|
||||
<Link to="/login" className="bg-blue-600 hover:bg-blue-500 text-white px-8 py-3 rounded-xl font-bold text-lg transition-all shadow-lg shadow-blue-500/30">
|
||||
{t('MAIN.GET_STARTED')}
|
||||
</Link>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="w-full max-w-5xl mb-16">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {useState} from 'react';
|
||||
import {Link, useNavigate} from 'react-router-dom';
|
||||
import {Link, Navigate, useNavigate} from 'react-router-dom';
|
||||
import {getValidToken} from '../utils/auth.js';
|
||||
|
||||
export default function LoginPage() {
|
||||
const {t} = useTranslation();
|
||||
@@ -38,10 +39,7 @@ export default function LoginPage() {
|
||||
if (response.ok) {
|
||||
// HTTP 200 OK
|
||||
localStorage.setItem('tbp_jwt', data.token);
|
||||
setFeedback({message: 'Login successful!', isError: false});
|
||||
setTimeout(() => {
|
||||
navigate('/dashboard');
|
||||
}, 500);
|
||||
navigate('/dashboard', {replace: true});
|
||||
} else {
|
||||
// HTTP 401 Unauthorized or other errors
|
||||
setFeedback({
|
||||
@@ -61,6 +59,10 @@ export default function LoginPage() {
|
||||
}
|
||||
};
|
||||
|
||||
if (getValidToken()) {
|
||||
return <Navigate to="/dashboard" replace/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-slate-50 dark:bg-slate-900 px-4">
|
||||
<div className="w-full max-w-md bg-white dark:bg-slate-800 rounded-xl shadow-lg p-8">
|
||||
|
||||
Reference in new issue
Block a user