From 5647412e3444be96951e2f81adaa0051c8da2245 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 09:16:36 +0000 Subject: [PATCH] Projekte: Reiter-Liste der sechs Ansichten als getestete Funktion Co-Authored-By: Claude Sonnet 5.5 --- src/lib/projectList.js | 16 ++++++++++++++++ tests/unit/projectList.test.mjs | 20 +++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/lib/projectList.js b/src/lib/projectList.js index 53fac4f..57627d1 100644 --- a/src/lib/projectList.js +++ b/src/lib/projectList.js @@ -29,6 +29,22 @@ export function projectsInView(projects, filter, { isAdmin = false } = {}) { export const VIEW_LABELS = { all: 'Aktive Projekte', templates: 'Vorlagen', archived: 'Archiviert', everything: 'Alle inkl. Archiv' } +/** + * Reiter der Projektliste (Reihenfolge wie die bisherige Filter-Auswahl), je mit Zaehler aus + * `projectCounts`. Die IDs sind die Filterwerte der Seite; die Vorlagen-Ansicht gibt es nur fuer Admins. + */ +export function projectTabs(counts, { isAdmin = false } = {}) { + const tab = (id, label) => ({ id, label, count: counts?.[id] ?? 0 }) + return [ + tab('all', VIEW_LABELS.all), + tab('unassigned', 'Unzugeordnet'), + tab('assigned', 'Zugeordnet'), + ...(isAdmin ? [tab('templates', VIEW_LABELS.templates)] : []), + tab('archived', VIEW_LABELS.archived), + tab('everything', VIEW_LABELS.everything), + ] +} + // Ansichten, die ein Projekt zeigen koennen - die Vorlagen-Ansicht gibt es nur fuer Admins const viewsFor = (isAdmin) => ['all', ...(isAdmin ? ['templates'] : []), 'archived', 'everything'] diff --git a/tests/unit/projectList.test.mjs b/tests/unit/projectList.test.mjs index ef6a5ed..e05c8c1 100644 --- a/tests/unit/projectList.test.mjs +++ b/tests/unit/projectList.test.mjs @@ -2,7 +2,7 @@ import test from 'node:test' import assert from 'node:assert/strict' import { loadModule } from './load.mjs' -const { projectCounts, projectsInView, viewShowing, matchesSearch, hiddenMatches } = await loadModule('src/lib/projectList.js') +const { projectCounts, projectsInView, projectTabs, viewShowing, matchesSearch, hiddenMatches } = await loadModule('src/lib/projectList.js') const P = [ { $id: 'a' }, @@ -76,3 +76,21 @@ test('hiddenMatches: Treffer, die die aktuelle Ansicht ausblendet', () => { assert.deepEqual(hiddenMatches(list, 'everything', shk, { isAdmin: true }), [], 'zeigt schon alles') assert.deepEqual(hiddenMatches(list, 'all', (p) => matchesSearch(p, 'olz'), { isAdmin: true }), []) }) + +const counts = { all: 5, unassigned: 2, assigned: 3, archived: 4, templates: 1, everything: 10 } +test('projectTabs: sechs Reiter für Admins, Wortlaut und Zähler', () => { + assert.deepEqual(projectTabs(counts, { isAdmin: true }), [ + { id: 'all', label: 'Aktive Projekte', count: 5 }, + { id: 'unassigned', label: 'Unzugeordnet', count: 2 }, + { id: 'assigned', label: 'Zugeordnet', count: 3 }, + { id: 'templates', label: 'Vorlagen', count: 1 }, + { id: 'archived', label: 'Archiviert', count: 4 }, + { id: 'everything', label: 'Alle inkl. Archiv', count: 10 }, + ]) +}) +test('projectTabs: ohne Admin keine Vorlagen, Zähler passen zur Ansicht', () => { + assert.deepEqual(projectTabs(counts).map((t) => t.id), ['all', 'unassigned', 'assigned', 'archived', 'everything']) + for (const t of projectTabs(projectCounts(P, { isAdmin: true }), { isAdmin: true })) { + assert.equal(t.count, projectsInView(P, t.id, { isAdmin: true }).length) + } +})