Sezione Campus: layout dedicato, route protette e documentazione

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 15:40:07 +02:00
parent 7baebebc09
commit c4107b84a5
15 changed files with 565 additions and 52 deletions
+2 -2
View File
@@ -8,8 +8,8 @@ if (!username || !password) {
console.error('Uso: npm run create-user -- <username> <password> [role]');
process.exit(1);
}
if (!['admin', 'superuser', 'user'].includes(role)) {
console.error('Ruolo non valido. Ammessi: admin, superuser, user');
if (!['admin', 'superuser', 'user', 'campus'].includes(role)) {
console.error('Ruolo non valido. Ammessi: admin, superuser, user, campus');
process.exit(1);
}
const path = process.env.DB_PATH ?? 'data/insanitylab.db';
+12 -12
View File
@@ -63,7 +63,6 @@ async function main() {
// 1. parsing di tutte le guide, capitolo per capitolo
const chapters = [];
const written = new Set();
const flat = []; // ordine globale di lettura, per prev/next
for (const [num, title, sub, slugs] of CHAPTERS) {
const lessons = [];
for (const [i, slug] of slugs.entries()) {
@@ -81,27 +80,28 @@ async function main() {
chapter: num,
};
lessons.push(entry);
flat.push(entry);
}
chapters.push({ num, title, sub, color: CH_COLORS[num - 1], lessons });
}
// 2. prev/next lungo l'ordine globale, e area di appartenenza
const areaOf = new Map();
for (const [slug, , , , chapterNums] of AREAS)
for (const n of chapterNums) areaOf.set(n, slug);
flat.forEach((l, i) => {
l.area = areaOf.get(l.chapter);
l.prev = flat[i - 1] ? { slug: flat[i - 1].slug, area: areaOf.get(flat[i - 1].chapter), title: flat[i - 1].titleShort } : null;
l.next = flat[i + 1] ? { slug: flat[i + 1].slug, area: areaOf.get(flat[i + 1].chapter), title: flat[i + 1].titleShort } : null;
});
const byNum = new Map(chapters.map((c) => [c.num, c]));
const areas = AREAS.map(([slug, title, sub, color, chapterNums]) => ({
slug, title, sub, color,
chapters: chapterNums.map((n) => byNum.get(n)).filter(Boolean),
}));
// 2. prev/next nell'ordine in cui l'utente naviga: aree → capitoli → guide,
// che non coincide con l'ordine dei capitoli (le aree li raggruppano).
const flat = [];
for (const area of areas)
for (const ch of area.chapters)
for (const l of ch.lessons) { l.area = area.slug; flat.push(l); }
const linkTo = (l) => (l ? { slug: l.slug, area: l.area, title: l.titleShort } : null);
flat.forEach((l, i) => {
l.prev = linkTo(flat[i - 1]);
l.next = linkTo(flat[i + 1]);
});
await writeFile(join(OUT_DIR, 'nav.json'), JSON.stringify({ areas, count: flat.length }, null, 2));
// 3. rimozione dei frammenti orfani