Commit Graph

276 Commits

Author SHA1 Message Date
schalli e967ea9660 feat(04-03): migrate sidebar to Link/usePathname, add search and refresh signal
Replace all raw <a> with Next.js Link. Add usePathname-based active
highlighting, SidebarSearch with category/module filtering, and
sidebarRefreshKey subscription for live activation updates. 26 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:21:27 +02:00
schalli fdf2c38f67 feat(04-02): add module detail page at /marketplace/[slug]
Compact detail view with back link, full description (no line-clamp),
status indicator, and activation controls. Reuses ActivationDialog for
deactivation. 3 tests pass, 21 total green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:25:00 +02:00
schalli 0f3379f263 feat(04-02): add TenantContextSelector, ActivationDialog, and asymmetric toggle UX
Super-Admin tenant dropdown fetches /tenants, sets selectedTenantId for
per-tenant activation. Deactivation gated by confirmation dialog;
activation immediate with toast. 18 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:23:04 +02:00
schalli 06fb52da82 feat(04-02): add search, status tabs, category chips, toast, and client-side filtering
Build MarketplaceSearch (debounced 300ms), StatusFilter (3 tabs with
counts), CategoryFilter (horizontal chip row), and Toast (Zustand store
+ container). Wire useMemo filtering into page with filtered-empty state.
All 14 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:20:08 +02:00
schalli fb6a340799 feat(04-01): implement marketplace page and marketplace-store
Create marketplace-store (Zustand) with sidebarRefreshKey signal and
tenant context. Build /marketplace page with parallel fetch, activation
Map, role gate, empty state, and responsive card grid. All 9 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 08:51:54 +02:00
schalli 0b7cf66abb test(04-01): add failing tests for marketplace page
- 4 tests: card grid rendering, activation status display,
  access-denied for non-admin, empty state
- Tests fail as expected (RED phase) - page and store not yet implemented
2026-06-22 14:48:39 +02:00
schalli 1e494b36ea feat(04-01): implement MarketplaceCard component and marketplace i18n namespace
- Add marketplace namespace to de.json and en.json with all copywriting contract strings
- Add sidebar.search and sidebar.noResults i18n keys
- Create MarketplaceCard with icon, name, localized description, category badge,
  status badge (role="status"), and activate/deactivate button
- All 5 unit tests pass (GREEN phase)
2026-06-22 14:47:53 +02:00
schalli a64f889251 test(04-01): add failing tests for MarketplaceCard component
- 5 tests: name+description rendering, category badge, activate button,
  activated status badge, onToggle callback
- Tests fail as expected (RED phase) - component not yet implemented
2026-06-22 14:46:30 +02:00
schalli e50b3c76c5 chore(04-01): install and configure Vitest test infrastructure for apps/web
- Add vitest, @testing-library/react, @testing-library/jest-dom, jsdom, @vitejs/plugin-react as dev deps
- Create vitest.config.ts with jsdom environment and @ path alias
- Create test setup file importing jest-dom/vitest matchers
- Add test scripts to apps/web and root package.json
- Add test task to turbo.json pipeline
2026-06-22 14:45:54 +02:00
schalli 576e311262 fix(03): strip TLD from domaincheck input before sending to API
Users naturally type full domains (e.g. "google.de") but the API
validates DNS labels only. Extract the label part before the first
dot to prevent 400 validation errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 09:37:39 +02:00
schalli 46a6e277b8 fix(03): login redirect + API internal URL for Docker networking
- Use window.location.href for full page reload after login (ensures auth state)
- Add API_INTERNAL_URL for server-side requests within Docker network
- Remove unnecessary credentials:'include' from SSR fetch calls
- Update planning state for Phase 03 progress

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 09:28:05 +02:00
schalli 9b2b1eafcb fix(03): show actual error message in domaincheck page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 14:43:27 +02:00
schalli b8ef870d1a fix(03): resolve tenant context for module activation
Controller now falls back to user.tenantId from JWT when
req.tenantId is null (SUPER_ADMIN without x-tenant-id header).
Also added error display to admin modules page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 14:38:37 +02:00
schalli dad9a779df fix(03): add module settings page, dynamic sidebar categories
- Admin modules page at /admin/modules with toggle switches
- Sidebar categories now fetch active modules from API dynamically
- Added "Module" link under admin section in sidebar
- Added i18n keys for module management (DE + EN)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 14:00:50 +02:00
schalli de63b10749 feat(03-03): expanded module view with dynamic routing and API client
- Create [moduleSlug] page that loads module component via MODULE_REGISTRY whitelist
- Only registered slugs trigger dynamic imports; unknown slugs show not-found state (T-03-09)
- Create api.ts with getActiveModules and getModuleBySlug utility functions
- Back-link navigation from expanded view to category page
2026-06-19 13:38:25 +02:00
schalli a191628fa5 feat(03-03): module loader utility with category page and lazy cards
- Create module-loader.ts with MODULE_REGISTRY mapping slugs to dynamic imports (ssr:false)
- Create [category] page fetching active modules from API, filtering by category
- Create ModuleCard component with icon, name, description, and link to expanded view
- Add i18n keys for modules namespace (de + en)
2026-06-19 13:36:09 +02:00
schalli 1d9fd2280d feat(03-02): add domaincheck frontend - input form, results display, i18n
- DomainInput component with text input and submit button
- ResultList component with green/red status badges (D-01)
- checkDomainAction fetches POST /modules/domaincheck/check with auth cookie
- Page renders within portal AppShell at /modules/domaincheck
- i18n keys added for both DE and EN locales
2026-06-19 13:27:55 +02:00
schalli 6e19591168 feat(02-04): LDAP admin UI with config, mapping editor, and sync trigger 2026-06-19 08:40:29 +02:00
schalli ac617f4fe5 feat(02-03): password reset flow, force-change interceptor, MailModule
- MailModule with SMTP transport configured from ENV variables
- MailService for password reset and welcome emails (plain text, i18n)
- Password reset flow: request-reset (public), reset-password (token-based)
- Change password for logged-in users with current password verification
- Admin reset password endpoint (ADMIN/SUPER_ADMIN only, D-03)
- ForcePasswordChangeInterceptor blocks all routes except change-password,
  logout, me when mustChangePassword=true (D-06, Pitfall 5)
- Frontend: reset-password request page, token reset page, change-password page
- Forgot password link added to login page
- MailHog service added to docker-compose.dev.yml for dev email testing
- SMTP env vars added to docker-compose.yml (defaults to MailHog)
- Complete DE/EN i18n coverage for reset and change password flows
- SUS packages installed: @nestjs-modules/mailer, nodemailer, ldapts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:48:23 +02:00
schalli bfb04eac66 feat(02-02): user CRUD API + admin page, tenant CRUD API + admin page
- Create UserController with GET/POST/PATCH/DELETE endpoints at /users
  - ADMIN sees own-tenant users only; SUPER_ADMIN sees all (T-02-10)
  - ADMIN cannot escalate to SUPER_ADMIN role (T-02-08)
  - ADMIN cannot delete self or cross-tenant users
- Create TenantController with GET/POST/PATCH/DELETE at /tenants
  - SUPER_ADMIN-only access (D-10)
  - Tenant deletion blocked if active users exist (T-02-09)
- Create CreateUserDto, UpdateUserDto, CreateTenantDto with class-validator
- Create admin/users page with user table, create/edit/delete modals
- Create admin/tenants page with tenant table, create/edit/deactivate (SUPER_ADMIN only)
- Add admin section to sidebar: Verwaltung > Benutzer + Mandanten
  - Verwaltung visible for ADMIN/SUPER_ADMIN; Tenants link SUPER_ADMIN only
- Install @nestjs/mapped-types for PartialType DTO pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:38:54 +02:00
schalli e7b2a70fc9 feat(02-02): login page UI, header/sidebar auth wiring, i18n keys
- Create split-screen login page with branding left (#ffed00) and form right (D-01)
- Login form has username, password, and remember-me checkbox (D-02)
- Wire header user avatar with auth store: shows user initial, dropdown with role badge and logout
- Wire sidebar footer with auth store: shows user name, role, and initial
- Add auth, header role, and admin i18n keys to both de.json and en.json
- All new UI strings use t() function (no hardcoded text)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:34:43 +02:00
schalli cdf4d60038 feat(02-02): auth infrastructure -- route groups, middleware, session, auth-actions, auth store
- Create (auth) route group with standalone layout (no sidebar/header, D-04)
- Create (portal) route group wrapping children with AppShell
- Move dashboard page into (portal) route group
- Add Next.js middleware for JWT-based route protection using jose
- Create session.ts with verifySession/getSessionFromCookies helpers
- Create auth-actions.ts server actions: login, logout, fetchCurrentUser
- Create Zustand auth-store for client-side user state
- Install jose and zod dependencies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:32:53 +02:00
schalli a9018083b2 fix(01): remove traefik, lighten dark mode, fix sidebar accent color, move locale switcher to sidebar footer 2026-06-18 12:41:02 +02:00
schalli 6039387857 feat(01-02): portal layout with header, sidebar, theme toggle, locale switcher
- Zustand sidebar store with persist middleware (collapse/expand, mobile open)
- Sticky header with logo, breadcrumb, theme toggle, locale switcher, user avatar
- Collapsible sidebar with Dashboard/Marketplace nav, accordion categories, footer
- Mobile responsive: hamburger menu with overlay sidebar on small screens
- Theme toggle cycling light/dark/system with mounted guard
- Locale switcher setting NEXT_LOCALE cookie with router.refresh
- Empty dashboard state with grid icon, "Keine Widgets aktiv" text, add button
- AppShell composing header + sidebar + responsive main content area
- All user-visible strings via useTranslations (UI-03 compliance)
2026-06-18 10:27:46 +02:00
schalli f3791c6cdd feat(01-02): design token system, i18n framework, and theme provider setup
- OKLCH design tokens with yellow #ffed00 primary and dark gray-blue dark mode
- next-intl cookie-based locale with DE/EN message files
- next-themes provider with system/light/dark support
- Sidebar and header layout dimension tokens
- Root layout with ThemeProvider and NextIntlClientProvider wrappers
2026-06-18 10:22:42 +02:00
schalli 2c12878cb1 feat(01-01): Next.js app + Docker Compose stack with network segmentation
- Next.js 15 app with Tailwind CSS v4, standalone output for Docker
- Root layout with de locale, page with Tessera placeholder
- Multi-stage Dockerfile for web with monorepo root context
- Docker Compose with 4 services: traefik, web, api, db
- Three segregated networks: frontend-net, backend-net, data-net (internal)
- Traefik v2.11 reverse proxy routing / to web, /api to api
- API strip prefix middleware for clean routing
- PostgreSQL 16-alpine with health checks and named volume
- Fixed API Dockerfile for pnpm monorepo node_modules structure
- Fixed Next.js standalone path for monorepo (apps/web/server.js)
- Fixed Traefik Docker API version compatibility
- Network segmentation: web NOT on data-net, api NOT on frontend-net
2026-06-18 10:17:21 +02:00