feat(header): identità utente SSR, link Accedi / menu utente

This commit is contained in:
2026-07-05 22:03:07 +02:00
parent 6b85872515
commit 71cd1626e0
2 changed files with 40 additions and 8 deletions
+33
View File
@@ -1,7 +1,15 @@
--- ---
import { site } from '../data/site'; import { site } from '../data/site';
import { t, contentImageUrl } from '../lib/content'; import { t, contentImageUrl } from '../lib/content';
interface Props {
user: { username: string; role: string } | null;
showTags: boolean;
canTags: boolean;
}
const { user, canTags } = Astro.props;
const path = Astro.url.pathname; const path = Astro.url.pathname;
const loginHref = `/login?next=${encodeURIComponent(path)}`;
const areaHref = user?.role === 'superuser' ? '/admin/content' : '/admin';
--- ---
<header class="hdr" id="site-header"> <header class="hdr" id="site-header">
<div class="container hdr__in"> <div class="container hdr__in">
@@ -11,6 +19,22 @@ const path = Astro.url.pathname;
<a href={item.href} class:list={['hdr__link', { 'is-active': path === item.href || (item.href !== '/' && path.startsWith(item.href)) }]}>{t(`global.nav.${i + 1}.label`)}</a> <a href={item.href} class:list={['hdr__link', { 'is-active': path === item.href || (item.href !== '/' && path.startsWith(item.href)) }]}>{t(`global.nav.${i + 1}.label`)}</a>
))} ))}
</nav> </nav>
<div class="hdr__user">
{user ? (
<details class="umenu">
<summary class="umenu__btn">{user.username} ▾</summary>
<div class="umenu__panel">
<a href={areaHref}>Area riservata</a>
{canTags && (
<button type="button" class="umenu__tags" id="toggle-tags" data-slot="tags">Mostra tag</button>
)}
<a href="/admin/logout">Esci</a>
</div>
</details>
) : (
<a class="hdr__login" href={loginHref}>Accedi</a>
)}
</div>
<button class="hdr__burger" id="nav-toggle" aria-label="Apri menu" aria-expanded="false"> <button class="hdr__burger" id="nav-toggle" aria-label="Apri menu" aria-expanded="false">
<span></span><span></span><span></span> <span></span><span></span><span></span>
</button> </button>
@@ -32,6 +56,15 @@ const path = Astro.url.pathname;
.hdr__link { padding: 12px 0; } .hdr__link { padding: 12px 0; }
.hdr__burger { display: block; } .hdr__burger { display: block; }
} }
.hdr__user { display: flex; align-items: center; }
.hdr__login { font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; text-decoration: none; color: var(--c-heading); }
.hdr__login:hover { color: var(--c-accent-dark); }
.umenu { position: relative; }
.umenu__btn { cursor: pointer; list-style: none; font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--c-heading); }
.umenu__btn::-webkit-details-marker { display: none; }
.umenu__panel { position: absolute; right: 0; top: calc(100% + 8px); background: #fff; box-shadow: 0 8px 22px rgba(0,0,0,.12); min-width: 180px; display: flex; flex-direction: column; padding: 8px 0; z-index: 200; }
.umenu__panel a, .umenu__tags { padding: 10px 16px; text-align: left; background: none; border: 0; cursor: pointer; font: inherit; font-size: .8rem; text-decoration: none; color: var(--c-heading); }
.umenu__panel a:hover, .umenu__tags:hover { background: #f4f2ef; }
</style> </style>
<script> <script>
+7 -8
View File
@@ -14,12 +14,11 @@ import { getSessionUser, SESSION_COOKIE } from '../lib/auth';
interface Props { title: string; description?: string } interface Props { title: string; description?: string }
const { title, description = 'InsanityLab — Performance. Balance. Longevity. Allenamento personalizzato, piccoli gruppi e benessere a Bologna.' } = Astro.props; const { title, description = 'InsanityLab — Performance. Balance. Longevity. Allenamento personalizzato, piccoli gruppi e benessere a Bologna.' } = Astro.props;
// Overlay annotate: badge coi tag contenuto, solo per utenti loggati con ?annotate=1. const tok = Astro.cookies.get(SESSION_COOKIE)?.value;
let annotate = false; const user = tok ? getSessionUser(getDb(), tok) : null;
if (Astro.url.searchParams.get('annotate') === '1') { const canTags = !!user && (user.role === 'superuser' || user.role === 'admin');
const tok = Astro.cookies.get(SESSION_COOKIE)?.value; const wantTags = Astro.cookies.get('showtags')?.value === '1' || Astro.url.searchParams.get('annotate') === '1';
annotate = Boolean(tok && getSessionUser(getDb(), tok)); const showTags = canTags && wantTags;
}
--- ---
<!doctype html> <!doctype html>
<html lang="it"> <html lang="it">
@@ -37,7 +36,7 @@ if (Astro.url.searchParams.get('annotate') === '1') {
<script is:inline>document.documentElement.classList.add('js');</script> <script is:inline>document.documentElement.classList.add('js');</script>
</head> </head>
<body> <body>
<Header /> <Header user={user} showTags={showTags} canTags={canTags} />
<main><slot /></main> <main><slot /></main>
<Footer /> <Footer />
<script> <script>
@@ -74,7 +73,7 @@ if (Astro.url.searchParams.get('annotate') === '1') {
update(); update();
} }
</script> </script>
{annotate && ( {showTags && (
<style is:global> <style is:global>
[data-tag] { outline: 1px dashed #b8a98c; outline-offset: 2px; } [data-tag] { outline: 1px dashed #b8a98c; outline-offset: 2px; }
.tag-badge { position: absolute; z-index: 9999; background: #3a2929; color: #fff; .tag-badge { position: absolute; z-index: 9999; background: #3a2929; color: #fff;