diff --git a/public/i18n/de.json b/public/i18n/de.json
index 8db92ba..aa5ff42 100644
--- a/public/i18n/de.json
+++ b/public/i18n/de.json
@@ -380,6 +380,7 @@
"LIGHT_MODE": "Helles Design",
"PLAY_NEXT": "Nächstes Spiel",
"STATS": "Statistik",
+ "COMMUNITY": "Community",
"POINTS": "Pile Points",
"ADMIN": "Admin",
"VIEW_AS": {
diff --git a/public/i18n/en.json b/public/i18n/en.json
index ddfd930..037de4f 100644
--- a/public/i18n/en.json
+++ b/public/i18n/en.json
@@ -380,6 +380,7 @@
"LIGHT_MODE": "Light mode",
"PLAY_NEXT": "Play next",
"STATS": "Stats",
+ "COMMUNITY": "Community",
"POINTS": "Pile Points",
"ADMIN": "Admin",
"VIEW_AS": {
diff --git a/src/components/AppHeader.jsx b/src/components/AppHeader.jsx
index e8aed81..857fb9c 100644
--- a/src/components/AppHeader.jsx
+++ b/src/components/AppHeader.jsx
@@ -1,7 +1,7 @@
import {useEffect, useState} from 'react';
import {Link, NavLink, useLocation, useNavigate} from 'react-router-dom';
import {useTranslation} from 'react-i18next';
-import {Bell, ChartColumn, Coins, Dices, Eye, Languages, LayoutDashboard, Library, Link2, LogOut, Mail, Megaphone, Moon, Newspaper, ScrollText, Search, Settings, Shield, Sun} from 'lucide-react';
+import {Bell, ChartColumn, Coins, Dices, Eye, Languages, LayoutDashboard, Library, Link2, LogOut, Mail, Megaphone, Moon, Newspaper, ScrollText, Search, Settings, Shield, Sun, Users} from 'lucide-react';
import {toast} from 'sonner';
import {Badge} from '@/components/ui/badge';
@@ -34,10 +34,11 @@ const NAV_ITEMS = [
{to: '/library', labelKey: 'NAV.LIBRARY', Icon: Library, alsoActiveOn: ['/wishlist', '/backlog']},
{to: '/play-next', labelKey: 'NAV.PLAY_NEXT', Icon: Dices},
{to: '/stats', labelKey: 'NAV.STATS', Icon: ChartColumn},
+ {to: '/', labelKey: 'NAV.COMMUNITY', Icon: Users, iconOnly: true},
];
const navLinkClass = (isActive) => cn(
- 'flex items-center gap-2 rounded-lg px-2 py-2 text-sm font-medium transition-colors sm:px-3',
+ 'flex items-center gap-2 rounded-lg px-1 py-2 text-sm font-medium transition-colors sm:px-3',
isActive
? 'bg-accent text-accent-foreground'
: 'text-muted-foreground hover:bg-muted hover:text-foreground',
@@ -128,23 +129,23 @@ export default function AppHeader({isAuthenticated, onLogout}) {
{isAuthenticated && (
- {NAV_ITEMS.map(({to, labelKey, Icon, alsoActiveOn = []}) => (
+ {NAV_ITEMS.map(({to, labelKey, Icon, alsoActiveOn = [], iconOnly}) => (
navLinkClass(isActive || alsoActiveOn.includes(pathname))}>
- {t(labelKey)}
+ {!iconOnly && {t(labelKey)} }
))}
)}
- {/* Below md the badge hangs on the header's bottom edge: in the row it would push the page sideways. */}
+ {/* The badge hangs on the header's bottom edge at every width: in the row it would push the page sideways. */}
{isAuthenticated && viewingAs && (
-
{t('NAV.VIEW_AS.BADGE', {role: t(`ROLES.${viewingAs}`)})}
+
{t('NAV.VIEW_AS.BADGE', {role: t(`ROLES.${viewingAs}`)})}
)}
{isAuthenticated && wallet && (
-
+
{wallet.balance}
)}
diff --git a/src/components/AppHeader.test.jsx b/src/components/AppHeader.test.jsx
index 7799129..831b9f9 100644
--- a/src/components/AppHeader.test.jsx
+++ b/src/components/AppHeader.test.jsx
@@ -16,11 +16,11 @@ afterEach(() => {
useTranslation().i18n.language = 'de';
});
-const loggedInAs = (me, routes = {}) => {
+const loggedInAs = (me, routes = {}, options = {}) => {
localStorage.setItem('tbp_session', '1');
fetchRoutes({'GET /api/users/me': json(200, me), 'GET /api/library/steam-profile': json(200, {}),
'GET /api/inbox': json(200, {results: [], unread: 0}), ...routes});
- renderWithProviders( {}}/>);
+ renderWithProviders( {}}/>, options);
};
const openMenu = () => fireEvent.keyDown(screen.getByRole('button', {name: 'NAV.MENU'}), {key: 'Enter'});
@@ -44,6 +44,29 @@ describe('AppHeader', () => {
screen.getByText('ToBePlayed').style.display = 'none';
expect(screen.getByRole('link', {name: 'ToBePlayed'})).toBeTruthy();
+ expect(screen.queryByTitle('NAV.COMMUNITY')).toBeNull();
+ });
+
+ it('links to the community stats when logged in', () => {
+ loggedInAs({role: 'USER', activeRole: 'USER'});
+
+ const link = screen.getByTitle('NAV.COMMUNITY');
+
+ expect(link.getAttribute('href')).toBe('/');
+ expect(link.getAttribute('aria-current')).toBe('page');
+ });
+
+ it('shows the community link as an icon without a text label', () => {
+ loggedInAs({role: 'USER', activeRole: 'USER'});
+
+ expect(screen.getByTitle('NAV.COMMUNITY').textContent).toBe('');
+ });
+
+ it('marks community active only on the landing page', () => {
+ loggedInAs({role: 'USER', activeRole: 'USER'}, {}, {entries: ['/dashboard']});
+
+ expect(screen.getByTitle('NAV.COMMUNITY').getAttribute('aria-current')).toBeNull();
+ expect(screen.getByTitle('NAV.DASHBOARD').getAttribute('aria-current')).toBe('page');
});
it('shows how many inbox notes are unread', async () => {