Visual Stadium Editor Implementation Tasks
This document provides a sequenced task list for AI-assisted implementation of the Visual Stadium Editor (Konva.js canvas-based seat map designer).
Part of Admin Portal
The Visual Stadium Editor is a component of the Admin Portal. For the complete Admin Portal implementation tasks (authentication, navigation, match management, etc.), see Admin Portal Tasks.
This file focuses specifically on the Konva.js canvas editor for designing seat maps.
Overview
Task Legend
| Symbol |
Status |
| ⬜ |
Not started |
| 🟡 |
In progress |
| ✅ |
Complete |
| ❌ |
Blocked |
1. Canvas Foundation
1.1 Konva.js Setup
| Status |
Task |
Verification |
| ✅ |
Install Konva.js and TypeScript types |
npm list konva shows version |
| ✅ |
Create base canvas component with Stage and Layer |
Canvas renders empty stage |
| ✅ |
Implement zoom controls (mouse wheel, +/- buttons) |
Zoom in/out works smoothly |
| ✅ |
Implement pan controls (drag with middle mouse, keyboard arrows) |
Can navigate large canvas |
| ✅ |
Add grid background (visual reference lines) |
Grid lines visible |
| ✅ |
Implement responsive canvas sizing |
Canvas fills container, resizes with window |
| ✅ |
Add zoom level indicator |
Current zoom % displayed |
| ✅ |
Implement zoom-to-fit button |
Canvas fits entire seat map |
1.2 Seat Rendering
| Status |
Task |
Verification |
| ✅ |
Create Seat shape class (configurable size/shape) |
Single seat renders |
| ✅ |
Implement seat color by type (standard, technical, accessibility, companion) |
Colors match design system |
| ✅ |
Implement seat color by status (available, sold, reserved, etc.) |
10 status colors work |
| ✅ |
Add seat hover effect (highlight border, cursor change) |
Hover feedback visible |
| ✅ |
Add seat selection effect (thicker border, glow) |
Selected seats highlighted |
| ✅ |
Implement seat label rendering (row/seat number) |
Labels visible at zoom |
| ✅ |
Add visibility toggle for labels (hide at low zoom) |
Labels auto-hide when zoomed out |
| ✅ |
Implement row label rendering (A, B, C or 1, 2, 3) |
Row labels visible on left |
| Status |
Task |
Verification |
| ✅ |
Create toolbar container (horizontal, icons with tooltips) |
Toolbar renders |
| ✅ |
Implement tool button styling (active state) |
Active tool highlighted |
| ✅ |
Add keyboard shortcuts for tools |
D=Draw, E=Erase, S=Select, F=Fill |
| ✅ |
Show current tool in status bar |
Tool name displayed |
2.2 Draw Mode (Pencil)
| Status |
Task |
Verification |
| ✅ |
Implement draw mode toggle |
Cursor changes to pencil |
| ✅ |
Click to add single seat at grid position |
Seat appears on click |
| ✅ |
Drag to add multiple seats (paint brush) |
Seats added along drag path |
| ✅ |
Snap to grid for consistent placement |
Seats align to grid cells |
| ✅ |
Prevent duplicate seats at same position |
No overlapping seats |
| ✅ |
Add visual preview while drawing |
Ghost seat shows where click will place |
2.3 Erase Mode (Eraser)
| Status |
Task |
Verification |
| ✅ |
Implement erase mode toggle |
Cursor changes to eraser |
| ✅ |
Click to remove single seat |
Seat disappears on click |
| ✅ |
Drag to remove multiple seats (erase path) |
Seats removed along drag path |
| ✅ |
Visual feedback for erasable area |
Seats turn red on hover in erase mode |
| ✅ |
Undo support for erase operations |
Ctrl+Z restores erased seats |
2.4 Select Mode
| Status |
Task |
Verification |
| ✅ |
Implement select mode toggle |
Cursor changes to pointer |
| ✅ |
Click to select single seat |
Seat selected, shows selection state |
| ✅ |
Shift+click to add to selection |
Multiple seats selected |
| ✅ |
Ctrl+click to toggle selection |
Click removes from selection |
| ✅ |
Drag to create selection box (marquee) |
Rectangle preview, selects enclosed seats |
| ✅ |
Ctrl+A to select all seats |
All seats selected |
| ✅ |
Escape to clear selection |
Selection cleared |
| ✅ |
Show selection count in status bar |
"N seats selected" displayed |
| Status |
Task |
Verification |
| ✅ |
Implement fill tool toggle |
Cursor shows fill icon |
| ✅ |
Click-drag to define rectangle |
Rectangle preview shown |
| ✅ |
Release to fill rectangle with seats |
Seats fill area |
| ✅ |
Shift modifier to create square |
Square constraint works |
| ✅ |
Respect existing seats (no overwrite option) |
Existing seats preserved optionally |
3. Seat Properties Panel
| Status |
Task |
Verification |
| ✅ |
Create collapsible properties panel (right side) |
Panel renders |
| ✅ |
Show panel only when seats selected |
Panel hidden with no selection |
| ✅ |
Display selected seat count |
"N seats selected" header |
| ✅ |
Show coordinates of single selected seat |
Row/col displayed for single selection |
3.2 Seat Type Assignment
| Status |
Task |
Verification |
| ✅ |
Create seat type selector (radio buttons/dropdown) |
Selector renders |
| ✅ |
Show current type if all selected seats same type |
Type pre-selected |
| ✅ |
Show "Mixed" if selected seats have different types |
Mixed indicator shown |
| ✅ |
Apply seat type to all selected seats |
Types change, colors update |
| ✅ |
Keyboard shortcuts for types |
1=Standard, 2=Technical, 3=Accessibility, 4=Companion |
3.3 Row Configuration
| Status |
Task |
Verification |
| ✅ |
Create row label input (configurable per-row) |
Labels editable |
| ✅ |
Implement alphabetic label generator (A, B, C, ..., Z, AA) |
Auto-generate works |
| ✅ |
Implement numeric label generator (1, 2, 3, ...) |
Auto-generate works |
| ✅ |
Numbering direction selector (LTR/RTL) |
Direction toggleable |
| ✅ |
Preview seat numbers based on direction |
Numbers update in real-time |
4. Grid Settings Modal
4.1 Dimensions Configuration
| Status |
Task |
Verification |
| ✅ |
Create grid settings modal |
Modal opens on gear icon click |
| ✅ |
Input for number of rows (1-100) |
Validation works |
| ✅ |
Input for max seats per row (1-100) |
Validation works |
| ✅ |
Preview dimensions before apply |
Shows "50 rows × 60 cols" |
| ✅ |
Warn if reducing dimensions will delete seats |
Warning shown |
| ✅ |
Apply dimensions change |
Grid resizes |
4.2 Row Labels Configuration
| Status |
Task |
Verification |
| ✅ |
Label style selector (Alphabetic/Numeric/Custom) |
Options available |
| ✅ |
Custom label input (comma-separated or one per line) |
Custom labels save |
| ✅ |
Validate custom labels (unique, not empty) |
Duplicates rejected |
| ✅ |
Preview labels in modal |
Shows A, B, C... or 1, 2, 3... |
5. Data Persistence
5.1 JSON Export
| Status |
Task |
Verification |
| ✅ |
Create JSON schema for seat map |
Schema documented |
| ✅ |
Implement exportToJSON() function |
Returns valid JSON |
| ✅ |
Include dimensions, seats array, row labels, numbering direction |
All fields present |
| ✅ |
Optimize JSON size (omit default values) |
Compact output |
| ✅ |
Validate JSON against schema before export |
Invalid maps rejected |
JSON Schema:
{
"dimensions": { "rows": 50, "cols": 50 },
"seats": [
{ "row": 0, "col": 0, "type": "standard" },
{ "row": 0, "col": 1, "type": "standard" }
],
"row_labels": ["A", "B", "C"],
"numbering_direction": "LTR"
}
5.2 JSON Import
| Status |
Task |
Verification |
| ✅ |
Implement loadFromJSON() function |
Seats render from JSON |
| ✅ |
Validate JSON schema on load |
Invalid JSON shows error |
| ✅ |
Handle missing optional fields with defaults |
Partial JSON loads |
| ✅ |
Clear canvas before loading |
Old seats removed |
| ✅ |
Auto-zoom to fit after load |
All seats visible |
5.3 Save/Load API Integration
| Status |
Task |
Verification |
| ✅ |
Implement Save button with loading state |
Button shows spinner |
| ✅ |
Call POST /admin/sectors/{id}/seat-map on new save |
API called |
| ✅ |
Call PUT /admin/sectors/{id}/seat-map on update |
API called |
| ✅ |
Handle 409 conflict error (seats already exist) |
Error message shown |
| ✅ |
Load seat map on page init (GET endpoint) |
Map loads on page open |
| ✅ |
Add unsaved changes detection |
Dirty flag tracked |
| ✅ |
Show browser prompt on leave with unsaved changes |
"Leave page?" warning |
| ✅ |
Show save status indicator |
"Saved ✓" / "Unsaved •" visible |
| ✅ |
Implement auto-save option (debounced) |
Auto-save after 30s inactivity |
6. Seat Generation
6.1 Generate Seats Dialog
| Status |
Task |
Verification |
| ✅ |
Create "Generate Seats" button |
Button visible in toolbar |
| ✅ |
Implement preview mode (checkbox) |
Preview toggle works |
| ✅ |
Show summary before generation |
Total/standard/technical counts |
| ✅ |
Display sample seat numbers |
First 10 seats shown |
| ✅ |
Call POST /admin/sectors/{id}/seats/generate |
API called |
| ✅ |
Handle force_regenerate option |
Checkbox to delete existing |
| ✅ |
Show success message with counts |
"Generated 1,234 seats" |
| ✅ |
Handle 409 conflict (tickets sold) |
Error message shown |
7. Inventory Mode (Read-Only Visualization)
7.1 Mode Toggle
| Status |
Task |
Verification |
| ✅ |
Create inventory mode toggle button |
Toggle in toolbar |
| ✅ |
Disable editing tools in inventory mode |
Draw/Erase grayed out |
| ✅ |
Load seat status from match_seat_inventory |
Status colors shown |
| ❌ |
Add match selector dropdown |
Can switch matches |
| ✅ |
Show "Design Mode" / "Inventory Mode" indicator |
Mode clearly visible |
7.2 Status Visualization
| Status |
Task |
Verification |
| ✅ |
Implement 10 status colors |
All colors render correctly |
| ✅ |
Add status legend component |
Legend shows all statuses |
| ✅ |
Implement legend filter (click to hide/show status) |
Status filtering works |
| ✅ |
Show status counts in legend |
"Available: 500, Sold: 300" |
| ✅ |
Auto-refresh status on interval (configurable) |
Refresh every 30s option |
7.3 Seat Details Modal
| Status |
Task |
Verification |
| ❌ |
Click seat to show detail modal |
Modal opens |
| ❌ |
Display seat info (sector, row, number, type, status) |
Info displayed |
| ❌ |
Show ticket holder info (if sold) |
Name, email visible |
| ❌ |
Show ticket info (order ID, purchase date) |
Order details visible |
| ❌ |
Add "Change Status" button (admin only) |
Button visible for admins |
| ❌ |
Implement status change dropdown |
Status options shown |
| ❌ |
Require reason for status change |
Reason input required |
| ❌ |
Call PUT /admin/seats/{id}/status |
API called |
| ❌ |
Update seat color after status change |
Color updates immediately |
8. Snake Algorithm Configuration
8.1 Snake Settings Panel
| Status |
Task |
Verification |
| ✅ |
Create snake config tab in properties panel |
Tab renders |
| ✅ |
Best row selector (dropdown 1 to N) |
Row selection works |
| ✅ |
Traversal direction toggle (TOP_TO_BOTTOM / BOTTOM_TO_TOP) |
Toggle works |
| ✅ |
Within-row strategy selector |
3 options available |
| ✅ |
Save config button |
Calls PUT /admin/sectors/{id}/snake-config |
| ✅ |
Load config on page init |
Existing config loaded |
8.2 Visual Preview
| Status |
Task |
Verification |
| ✅ |
Add "Preview Fill Order" button |
Button visible |
| ✅ |
Animate seats filling in snake order |
Seats highlight sequentially |
| ✅ |
Show seat numbers in fill order |
1, 2, 3... displayed |
| ✅ |
Control animation speed |
Slider or fast/slow buttons |
| ✅ |
Stop animation button |
Animation can be cancelled |
9. Undo/Redo System
9.1 History Management
| Status |
Task |
Verification |
| ✅ |
Implement history stack (max 50 states) |
States stored |
| ✅ |
Push state after each action |
State saved on draw/erase/type change |
| ✅ |
Implement undo (Ctrl+Z) |
Previous state restored |
| ✅ |
Implement redo (Ctrl+Shift+Z or Ctrl+Y) |
Undone state re-applied |
| ✅ |
Add undo/redo buttons to toolbar |
Buttons visible |
| ✅ |
Disable undo when at oldest state |
Button grayed out |
| ✅ |
Disable redo when at newest state |
Button grayed out |
| ✅ |
Clear redo stack on new action |
Redo clears after draw |
10. Admin Portal Integration
10.1 Twig Template
| Status |
Task |
Verification |
| ✅ |
Create templates/admin/stadium/seat-map-editor.html.twig |
Template renders |
| ✅ |
Include Konva.js and editor bundle |
Scripts load |
| ✅ |
Pass sector_id to Alpine.js component |
ID available in JS |
| ✅ |
Add breadcrumb navigation |
Stadium > Sector > Seat Map |
| ✅ |
Include back button to sector list |
Navigation works |
10.2 Sector List Integration
| Status |
Task |
Verification |
| ✅ |
Add "Design Seat Map" button to sector row |
Button visible |
| ✅ |
Show seat map status (None/Draft/Active) |
Status badge shown |
| ✅ |
Show seat count for sectors with maps |
"1,234 seats" displayed |
| ✅ |
Link to editor page |
Navigation works |
10.3 Access Control
| Status |
Task |
Verification |
| ✅ |
Check Stadium Manager role |
Non-admins see 403 |
| ❌ |
Audit log for seat map changes |
Log entries created |
| ✅ |
Read-only mode for lower roles |
View but no edit |
11.1 Large Seat Map Handling
| Status |
Task |
Verification |
| ❌ |
Implement viewport culling (only render visible seats) |
FPS stays high when zoomed in |
| ✅ |
Use Konva layer caching for static elements |
Background cached |
| ✅ |
Batch DOM updates during bulk operations |
No jank during fill |
| ❌ |
Test with 5000+ seats |
Smooth interaction |
| ❌ |
Test with 10000+ seats |
Acceptable performance |
11.2 Memory Management
| Status |
Task |
Verification |
| ✅ |
Limit history stack size |
Memory bounded |
| ✅ |
Clean up event listeners on unmount |
No memory leaks |
| ✅ |
Optimize JSON parsing for large maps |
Fast load times |
12. Testing
12.1 Unit Tests
| Status |
Task |
Verification |
| ❌ |
Test JSON export/import roundtrip |
Data integrity verified |
| ❌ |
Test seat numbering logic (LTR/RTL) |
Numbers correct |
| ❌ |
Test selection operations |
Selection state correct |
| ❌ |
Test undo/redo stack |
States restore correctly |
12.2 Integration Tests
| Status |
Task |
Verification |
| ❌ |
Test save to API |
Data persists |
| ❌ |
Test load from API |
Map renders correctly |
| ❌ |
Test seat generation |
Seats created in DB |
| ❌ |
Test status visualization |
Colors match statuses |
12.3 E2E Tests (Playwright)
| Status |
Task |
Verification |
| ❌ |
Test draw/erase workflow |
Seats appear/disappear |
| ❌ |
Test type classification |
Colors update |
| ❌ |
Test save/reload cycle |
Data persists |
| ❌ |
Test keyboard shortcuts |
All shortcuts work |
Status Color Reference
| Status |
Color Name |
Hex |
| Standard (Design) |
Light Gray |
#D1D5DB |
| Technical |
Purple |
#A855F7 |
| Accessibility |
Yellow |
#FCD34D |
| Companion |
Orange |
#FB923C |
| Available |
Green |
#22C55E |
| Sold |
Blue |
#3B82F6 |
| Reserved |
Yellow |
#EAB308 |
| Official |
Orange |
#F97316 |
| Blocked |
Red |
#EF4444 |
| Maintenance |
Gray |
#6B7280 |
| Quarantined |
Brown |
#92400E |
| Allocated |
Teal |
#14B8A6 |
| Inactive |
Dark Gray |
#1F2937 |
Last Updated: February 2026