feat: add implementation plans for room editor refactor (core and visualization)
Some checks failed
Test / test (push) Failing after 1m40s

This commit is contained in:
2026-04-29 05:36:44 +02:00
parent 7212e982ef
commit 0b806b59be
2 changed files with 135 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
# Implementation Plan: Room Editor Refactor (Core & Logic)
**Objective:** Standardize the room layout data model, align backend/frontend types, and refactor the core editor logic for robustness and grid-based precision.
**Background:**
The current room implementation suffers from naming inconsistencies (`type` vs `kind`) and coordinate system mismatches (pixels vs grid units). The editor logic in `RoomCanvas.svelte` is basic and needs to be more robust to support professional room planning.
---
## 1. Data Model & Type Alignment
### Task 1: Standardize LayoutElement Naming
**Files to Modify:**
- `backend/src/models.rs`
- `frontend/src/lib/types.ts`
- `backend/demo/demo_seed.sql`
**Changes:**
- Unified field name `type` (using `#[serde(rename = "type")]` if necessary in Rust, or changing it consistently).
- Standardize coordinate units: All `x`, `y`, `width`, `height` values in the database will represent **grid units** (e.g., 1 unit = 40px) rather than raw pixels.
- Update `demo_seed.sql` to use these normalized grid units.
### Task 2: Backend Validation
**Files to Modify:**
- `backend/src/routes/rooms.rs`
**Changes:**
- Add validation logic to `POST /api/admin/rooms` and `PUT /api/admin/rooms/:id/layout`.
- Ensure all elements have unique IDs.
- Validate that `type` is one of the allowed strings (`seat`, `table`, `door`, `gap`).
---
## 2. Editor Core Refactor
### Task 3: RoomCanvas Logic Overhaul
**Files to Modify:**
- `frontend/src/lib/RoomCanvas.svelte`
**Changes:**
- **Grid Snap:** Implement mandatory snap-to-grid (0.5 or 1.0 unit increments) during dragging and resizing.
- **State Management:** Refactor internal dragging state to be cleaner and more predictable.
- **Selection:** Improve the selection highlight and event propagation.
- **Unit Separation:** Ensure the component strictly thinks in grid units, with the rendering layer handling the pixel scaling.
### Task 4: Editor UI Improvements
**Files to Modify:**
- `frontend/src/routes/admin/rooms/[roomId]/+page.svelte`
**Changes:**
- Add a "Snap to Grid" toggle.
- Add numeric inputs for precise coordinate editing (X, Y, W, H).
- Implement "duplicate element" functionality.
- Better error handling and visual feedback during saving.
---
## 3. Verification
### Automated Tests:
- `backend/src/routes/rooms.rs`: Add unit tests for layout validation.
- `frontend/tests/rooms.spec.ts`: Create a new Playwright test for room editing (creating elements, dragging, snapping, and saving).
### Manual Verification:
1. Create a new room.
2. Add a table and two seats.
3. Verify that dragging snaps to the grid.
4. Save and reload to ensure coordinates are preserved exactly.
5. Inspect the SQLite database to confirm coordinates are stored as small grid units (e.g., `2.5`) instead of large pixel values.

View File

@@ -0,0 +1,66 @@
# Implementation Plan: Room Editor Refactor (Unified Visualization)
**Objective:** Replace hardcoded seat maps with a unified, dynamic, and high-fidelity room visualization system that works across Admin and Student views.
**Background:**
Currently, the application uses a hardcoded `SeatMap.svelte` for Live Views and Student Check-ins, while using a dynamic `RoomCanvas.svelte` for editing. This leads to data mismatches and prevents users from using custom room layouts. This plan unifies the visualization layer.
---
## 1. Unified Visualization Component
### Task 1: Create `DynamicRoomView.svelte`
**Files to Create/Modify:**
- `frontend/src/lib/components/DynamicRoomView.svelte`
- (Optionally) Merge into `frontend/src/lib/RoomCanvas.svelte`
**Changes:**
- Create a read-only/interactive component that renders SVG layouts based on the `LayoutElement[]` data.
- **High Fidelity:** Implement the aesthetic details from the design handoff (rounded tables, specific seat styling, label positioning).
- **Responsive Scaling:** Implement an `autoScale` or `viewBox` based system so the room fills the available width on mobile and desktop without breaking coordinates.
- **Interaction Modes:**
- `mode="checkin"`: Seats are clickable for students.
- `mode="notes"`: Seats are clickable for tutors to open note editors.
- `mode="display"`: Read-only view for dashboard/monitoring.
---
## 2. Integration & Cleanup
### Task 2: Replace `SeatMap` in Admin Live View
**Files to Modify:**
- `frontend/src/routes/admin/live/[slotId]/+page.svelte`
**Changes:**
- Replace `SeatMap` with `DynamicRoomView`.
- Connect the `onSeatClick` event to the note-taking and manual attendance logic.
- Ensure attendance data (who sits where) is correctly overlaid on the dynamic layout.
### Task 3: Replace `SeatMap` in Student Check-in
**Files to Modify:**
- `frontend/src/routes/s/[code]/+page.svelte`
**Changes:**
- Replace `SeatMap` with `DynamicRoomView`.
- Connect seat selection to the `POST /api/checkin` API.
- Ensure the "current seat" (mySeatId) is visually highlighted in the dynamic view.
### Task 4: Deprecate `SeatMap.svelte`
**Files to Modify:**
- Delete `frontend/src/lib/components/SeatMap.svelte` once integration is verified.
---
## 3. Verification
### Automated Tests:
- `frontend/tests/checkin-dynamic.spec.ts`: E2E test to verify student check-in on a **custom-created** room layout.
- `frontend/tests/admin-live-dynamic.spec.ts`: E2E test to verify that tutors can see students on a **custom-created** room layout and click them to leave notes.
### Manual Verification:
1. Create a non-standard room layout in the Admin Editor (e.g., a "U" shape).
2. Create a session and slot using this room.
3. Open the Student Check-in link on a mobile device (browser simulation).
4. Verify the "U" shape is rendered correctly and scaled to fit the screen.
5. Check in as a student and verify the seat turns green.
6. Open the Tutor Live View on a desktop and verify the same student is visible on the same seat in the "U" shape.