diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 59dfd01..7790719 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -228,6 +228,7 @@ Keep docs synced with code. When you change services/MQTT/API/UTC/env or dev/pro Documentation maintenance: keep this file aligned with real patterns; update when routes/session/UTC rules change. Avoid long prose; link exact paths. ## Frontend patterns (dashboard) +- **UI design rules**: Component choices, layout structure, button variants, badge colors, dialog patterns, toast conventions, and tab structure are defined in [`FRONTEND_DESIGN_RULES.md`](../FRONTEND_DESIGN_RULES.md). Follow that file for all dashboard work. - Vite React app; proxies `/api` and `/screenshots` to API in dev (`vite.config.ts`). - Uses Syncfusion components; Vite config pre-bundles specific packages to avoid alias issues. - Environment: `VITE_API_URL` provided at build/run; in dev compose, proxy handles `/api` so local fetches can use relative `/api/...` paths. @@ -235,7 +236,7 @@ Keep docs synced with code. When you change services/MQTT/API/UTC/env or dev/pro - **UTC Time Parsing**: API returns ISO strings without 'Z' suffix. Frontend appends 'Z' before parsing to ensure UTC interpretation: `const utcString = dateStr.endsWith('Z') ? dateStr : dateStr + 'Z'; new Date(utcString);`. Display uses `toLocaleTimeString('de-DE')` for German format. - Dev Container: When adding frontend deps, prefer `npm ci` and, if using named volumes, recreate dashboard `node_modules` volume so installs occur inside the container. -- Theming: Syncfusion Material 3 theme is used. All component CSS is imported centrally in `dashboard/src/main.tsx` (base, navigations, buttons, inputs, dropdowns, popups, kanban, grids, schedule, filemanager, notifications, layouts, lists, calendars, splitbuttons, icons). Tailwind CSS has been removed. +- Theming: All Syncfusion component CSS is imported centrally in `dashboard/src/main.tsx`. Theme conventions, component defaults, the full CSS import list, and Tailwind removal are documented in `FRONTEND_DESIGN_RULES.md`. - Scheduler (appointments page): top bar includes Group and Academic Period selectors (Syncfusion DropDownList). Selecting a period calls `POST /api/academic_periods/active`, moves the calendar to today’s month/day within the period year, and refreshes a right-aligned indicator row showing: - Holidays present in the current view (count) - Period label (display_name or name) with a badge indicating whether any holidays exist in that period (overlap check) diff --git a/ACADEMIC_PERIODS_CRUD_BUILD_PLAN.md b/ACADEMIC_PERIODS_CRUD_BUILD_PLAN.md new file mode 100644 index 0000000..25fc0f3 --- /dev/null +++ b/ACADEMIC_PERIODS_CRUD_BUILD_PLAN.md @@ -0,0 +1,361 @@ +# Academic Periods CRUD Build Plan + +## Goal + +Add full academic period lifecycle management to the settings page and backend, including safe archive and hard-delete behavior, recurrence spillover blockers, and a UI restructuring where `Perioden` becomes the first sub-tab under `Akademischer Kalender`. + +## Frontend Design Rules + +All UI implementation for this build must follow the project-wide frontend design rules: + +→ **[FRONTEND_DESIGN_RULES.md](FRONTEND_DESIGN_RULES.md)** + +Key points relevant to this build: +- Syncfusion Material3 components are the default for every UI element +- Use `DialogComponent` for all confirmations — never `window.confirm()` +- Follow the established card structure, button variants, badge colors, and tab patterns +- German strings only in all user-facing text +- No Tailwind classes + +## Agreed Rules + +### Permissions + +- Create: admin or higher +- Edit: admin or higher +- Archive: admin or higher +- Restore: admin or higher +- Hard delete: admin or higher +- Activate: admin or higher +- Editors do not activate periods by default because activation changes global system state + +### Lifecycle + +- Active: exactly one period at a time +- Inactive: saved period, not currently active +- Archived: retired period, hidden from normal operational selection +- Deleted: physically removed only when delete preconditions are satisfied + +### Validation + +- `name` is required, trimmed, and unique among non-archived periods +- `startDate` must be less than or equal to `endDate` +- `periodType` must be one of `schuljahr`, `semester`, `trimester` +- Overlaps are disallowed within the same `periodType` +- Overlaps across different `periodType` values are allowed +- Exactly one period may be active at a time + +### Archive Rules + +- Active periods cannot be archived +- A period cannot be archived if it still has operational dependencies +- Operational dependencies include recurring master events assigned to that period that still generate current or future occurrences + +### Restore Rules + +- Archived periods can be restored by admin or higher +- Restored periods return as inactive by default + +### Hard Delete Rules + +- Only archived and inactive periods can be hard-deleted +- Hard delete is blocked if linked events exist +- Hard delete is blocked if linked media exist +- Hard delete is blocked if recurring master events assigned to the period still have current or future scheduling relevance + +### Recurrence Spillover Rule + +- If a recurring master event belongs to an older period but still creates occurrences in the current or future timeframe, that older period is not eligible for archive or hard delete +- Admin must resolve the recurrence by ending, splitting, or reassigning the series before the period can be retired or deleted + +## Build-Oriented Task Plan + +### Phase 1: Lock The Contract + +Files: + +- `server/routes/academic_periods.py` +- `models/models.py` +- `dashboard/src/settings.tsx` + +Work: + +- Freeze lifecycle rules, validation rules, and blocker rules +- Freeze the settings tab order so `Perioden` comes before `Import & Liste` +- Confirm response shape for new endpoints + +Deliverable: + +- Stable implementation contract for backend and frontend work + +### Phase 2: Extend The Data Model + +Files: + +- `models/models.py` + +Work: + +- Add archive lifecycle fields to academic periods +- Recommended fields: `is_archived`, `archived_at`, `archived_by` + +Deliverable: + +- Academic periods can be retired safely and restored later + +### Phase 3: Add The Database Migration + +Files: + +- `server/alembic.ini` +- `server/alembic/` +- `server/initialize_database.py` + +Work: + +- Add Alembic migration for archive-related fields and any supporting indexes +- Ensure existing periods default to non-archived + +Deliverable: + +- Schema upgrade path for current installations + +### Phase 4: Expand The Backend API + +Files: + +- `server/routes/academic_periods.py` + +Work: + +- Implement full lifecycle endpoints: + - `GET /api/academic_periods` + - `GET /api/academic_periods/:id` + - `POST /api/academic_periods` + - `PUT /api/academic_periods/:id` + - `POST /api/academic_periods/:id/activate` + - `POST /api/academic_periods/:id/archive` + - `POST /api/academic_periods/:id/restore` + - `GET /api/academic_periods/:id/usage` + - `DELETE /api/academic_periods/:id` + +Deliverable: + +- Academic periods become a fully managed backend resource + +### Phase 5: Add Backend Validation And Guardrails + +Files: + +- `server/routes/academic_periods.py` +- `models/models.py` + +Work: + +- Enforce required fields, type checks, date checks, overlap checks, and one-active-period behavior +- Block archive and delete when dependency rules fail + +Deliverable: + +- Backend owns all business-critical safeguards + +### Phase 6: Implement Recurrence Spillover Detection + +Files: + +- `server/routes/academic_periods.py` +- `server/routes/events.py` +- `models/models.py` + +Work: + +- Detect recurring master events assigned to a period that still generate present or future occurrences +- Treat them as blockers for archive and hard delete + +Deliverable: + +- Old periods cannot be retired while they still affect the active schedule + +### Phase 7: Normalize API Serialization + +Files: + +- `server/routes/academic_periods.py` +- `server/serializers.py` + +Work: + +- Return academic period responses in camelCase consistently with the rest of the API + +Deliverable: + +- Frontend receives normalized API payloads without special-case mapping + +### Phase 8: Expand The Frontend API Client + +Files: + +- `dashboard/src/apiAcademicPeriods.ts` + +Work: + +- Add frontend client methods for create, update, activate, archive, restore, usage lookup, and hard delete + +Deliverable: + +- The settings page can manage academic periods through one dedicated API module + +### Phase 9: Reorder The Akademischer Kalender Sub-Tabs + +Files: + +- `dashboard/src/settings.tsx` + +Work: + +- Move `Perioden` to the first sub-tab +- Move `Import & Liste` to the second sub-tab +- Preserve controlled tab state behavior + +Deliverable: + +- The settings flow reflects setup before import work + +### Phase 10: Replace The Current Period Selector With A Management UI + +Files: + +- `dashboard/src/settings.tsx` + +Work: + +- Replace the selector-only period card with a proper management surface +- Show period metadata, active state, archived state, and available actions + +Deliverable: + +- The periods tab becomes a real administration UI + +### Phase 11: Add Create And Edit Flows + +Files: + +- `dashboard/src/settings.tsx` + +Work: + +- Add create and edit dialogs or form panels +- Validate input before save and surface backend errors clearly + +Deliverable: + +- Admins can maintain periods directly in settings + +### Phase 12: Add Archive, Restore, And Hard Delete UX + +Files: + +- `dashboard/src/settings.tsx` + +Work: + +- Fetch usage or preflight data before destructive actions +- Show exact blockers for linked events, linked media, and recurrence spillover +- Use explicit confirmation dialogs for archive and hard delete + +Deliverable: + +- Destructive actions are safe and understandable + +### Phase 13: Add Archived Visibility Controls + +Files: + +- `dashboard/src/settings.tsx` + +Work: + +- Hide archived periods by default or group them behind a toggle + +Deliverable: + +- Normal operational periods stay easy to manage while retired periods remain accessible + +### Phase 14: Add Backend Tests + +Files: + +- Backend academic period test targets to be identified during implementation + +Work: + +- Cover create, edit, activate, archive, restore, hard delete, overlap rejection, dependency blockers, and recurrence spillover blockers + +Deliverable: + +- Lifecycle rules are regression-safe + +### Phase 15: Add Frontend Verification + +Files: + +- `dashboard/src/settings.tsx` +- Frontend test targets to be identified during implementation + +Work: + +- Verify sub-tab order, CRUD refresh behavior, blocked action messaging, and activation behavior + +Deliverable: + +- Settings UX remains stable after the management upgrade + +### Phase 16: Update Documentation + +Files: + +- `.github/copilot-instructions.md` +- `README.md` +- `TECH-CHANGELOG.md` + +Work: + +- Document academic period lifecycle behavior, blocker rules, and updated settings tab order as appropriate + +Deliverable: + +- Repo guidance stays aligned with implemented behavior + +## Suggested Build Sequence + +1. Freeze rules and response shape +2. Change the model +3. Add the migration +4. Build backend endpoints +5. Add blocker logic and recurrence checks +6. Expand the frontend API client +7. Reorder sub-tabs +8. Build period management UI +9. Add destructive-action preflight UX +10. Add tests +11. Update documentation + +## Recommended Delivery Split + +1. Backend foundation + - Model + - Migration + - Routes + - Validation + - Blocker logic + +2. Frontend management + - API client + - Tab reorder + - Management UI + - Dialogs + - Usage messaging + +3. Verification and docs + - Tests + - Documentation diff --git a/FRONTEND_DESIGN_RULES.md b/FRONTEND_DESIGN_RULES.md new file mode 100644 index 0000000..ce4661c --- /dev/null +++ b/FRONTEND_DESIGN_RULES.md @@ -0,0 +1,328 @@ +# Frontend Design Rules + +This file is the single source of truth for UI implementation conventions in the dashboard (`dashboard/src/`). +It applies to all feature work, including new pages, settings tabs, dialogs, and management surfaces. + +When proposing or implementing frontend changes, follow these rules unless a specific exception is documented below. +This file should be updated whenever a new Syncfusion component is adopted, a color or pattern changes, or an exception is ratified. + +--- + +## 1. Component Library — Syncfusion First + +Use Syncfusion components as the default choice for every UI element. +The project uses the Syncfusion Material3 theme, registered globally in `dashboard/src/main.tsx`. + +The following CSS packages are imported there and cover all components currently in use: +`base`, `navigations`, `buttons`, `inputs`, `dropdowns`, `popups`, `kanban`, `grids`, `schedule`, `filemanager`, `notifications`, `layouts`, `lists`, `calendars`, `splitbuttons`, `icons`. +When adding a new Syncfusion component, add its CSS import here — and add the new npm package to `optimizeDeps.include` in `vite.config.ts` to avoid Vite import-analysis errors in development. + +Use non-Syncfusion elements only when: +- The Syncfusion equivalent does not exist (e.g., native `` for file upload) +- The Syncfusion component would require significantly more code than a simple HTML element for purely read-only or structural content (e.g., `