Skip to content

Admin Portal Implementation Tasks

This document provides a sequenced, comprehensive task list for AI-assisted implementation of the HNS Admin Portal (Symfony Twig + Alpine.js frontend).

Overview

Attribute Value
Technology PHP 8.2+ / Symfony 7.x / Twig
Frontend Alpine.js + Tailwind CSS
Canvas Library Konva.js (for stadium visualization)
Authentication MFA via Drupal SSO
Reference Architecture Overview
API Spec API Specification

Portal Responsibilities

The Admin Portal serves HNS staff for:

  • Match lifecycle management (create, configure, publish, close, cancel)
  • Stadium configuration (sectors, seat maps, pricing)
  • Seat inventory operations (status changes, bulk operations)
  • Quota management (creation, allocation, monitoring)
  • Customer support operations (lookup, transfer, refund)
  • Blacklist management (import, search, violation monitoring)
  • Reporting and analytics (sales, financial, attendance)
  • Access control (barcode export, attendance import)
File Scope
Ticketing Backend Tasks Backend API implementation
Visual Stadium Editor Tasks Konva.js seat map designer (part of Admin Portal)

Task Legend

Symbol Status
Not started
🟡 In progress
Complete
Blocked

Implementation Sequence

Tasks are organized in dependency order:

  1. Phase 1: Foundation - Project setup, authentication, layout
  2. Phase 2: Match Management - CRUD, stadium config, sales phases
  3. Phase 3: Inventory Operations - Seat status, bulk ops, visualization
  4. Phase 4: Distribution - Quotas, customer support
  5. Phase 5: Security & Reporting - Blacklist, reports, access control

Phase 1: Foundation

1.1 Project Setup

Symfony Bundle Configuration

Status Task Verification
Create AdminBundle with Twig templates directory ls src/AdminBundle/templates/ shows structure
Configure Tailwind CSS with HNS brand colors (#B90202 primary) Build outputs correct CSS
Install and configure Alpine.js Alpine directives work in templates
Create base layout template (base.html.twig) Layout renders with header/sidebar
Configure asset compilation (Webpack Encore or Vite) npm run build succeeds
Set up route prefix /admin/* with firewall Routes resolve correctly

Design System Setup

Status Task Verification
Create color palette Tailwind config (HNS red, status colors) Colors available in classes
Create typography scale (headings, body, labels) Font sizes consistent
Create spacing scale following 4px grid Spacing utilities work
Create shadow/elevation tokens Shadows render correctly
Document design tokens in docs/styleguide.md Guide accessible

1.2 Authentication & Authorization

MFA Authentication

Status Task Verification
Implement Drupal SSO integration for admin login SSO redirect works
Create login page with HNS branding Page renders correctly
Implement MFA challenge step (TOTP) MFA prompt appears
Handle MFA verification and session creation Session created after MFA
Implement logout with SSO session termination Logout clears all sessions
Add session timeout warning (5 min before expiry) Warning modal appears
Implement session refresh on activity Session extends on interaction

Role-Based Access Control

Status Task Verification
Define admin roles enum (Super Admin, Match Manager, Support Agent, Reports Viewer) Enum created
Create role hierarchy configuration Hierarchy documented
Implement @IsGranted annotations on controllers Access denied for wrong role
Create Twig is_granted() checks for UI elements Buttons hidden for unauthorized
Implement role-based menu filtering Sidebar shows only permitted items
Add audit logging for all admin actions Audit events dispatched to Loki

1.3 Layout & Navigation

Main Layout

Status Task Verification
Create header component (logo, user menu, notifications) Header renders
Create collapsible sidebar navigation Sidebar toggles
Create breadcrumb component Breadcrumbs show path
Create main content area with responsive padding Content area responsive
Create footer with version info Footer shows version
Implement dark mode toggle (optional) Theme switches
Status Task Verification
Create sidebar menu items with icons Menu renders with icons
Implement active state highlighting Current page highlighted
Create collapsible menu sections Sections expand/collapse
Add menu item badges (counts, alerts) Badges display
Implement keyboard navigation Tab/arrow keys work

Menu Structure:

Dashboard
Matches
├── All Matches
├── Create Match
└── Calendar View
Stadiums
├── Templates
├── Seat Maps (→ Visual Editor)
└── Snake Configuration
Inventory
├── Seat Status
├── Bulk Operations
└── Visualization
Quotas
├── All Quotas
├── Create Quota
└── Import CSV
Support
├── Ticket Lookup
├── Transfers
└── Refunds
Blacklist
├── Search
├── Import
└── Violations
Reports
├── Sales
├── Financial
└── Attendance
Settings
└── Access Control Export

1.4 Shared Components

Form Components

Status Task Verification
Create text input component with validation states Input renders with error state
Create select/dropdown component Dropdown works
Create date picker component (flatpickr or similar) Date selection works
Create date-time picker with timezone support DateTime selection works
Create checkbox and radio button components Checkboxes work
Create file upload component with drag-drop File upload works
Create form validation service (client-side) Validation runs on submit
Create form error summary component Errors summarized

Data Display Components

Status Task Verification
Create data table component with sorting Columns sortable
Add table filtering (search, column filters) Filters work
Add table pagination Pagination works
Add table row selection (single, multi) Selection works
Add table export (CSV, Excel) Export downloads
Create card component for summary stats Cards render
Create badge/tag component for statuses Badges show colors
Create progress bar component Progress displays

Feedback Components

Status Task Verification
Create toast notification system Toasts appear
Create modal dialog component Modals open/close
Create confirmation dialog (delete, dangerous actions) Confirmation required
Create loading spinner/skeleton Loading states show
Create empty state component Empty states render
Create error boundary component Errors caught gracefully

Phase 2: Match Management (E2)

2.1 Match List & Dashboard

Match Listing

Status Task Verification
Create matches index page (/admin/matches) Page renders
Implement data table with match list Table shows matches
Add status filter (Draft, Published, Active, Closed, Cancelled) Filter works
Add date range filter Date filter works
Add search by team name Search works
Show match status badges with colors Badges colored correctly
Add quick actions (Edit, View, Configure Stadium) Actions work
Implement row click to view details Navigation works

Match Calendar View

Status Task Verification
Create calendar page (/admin/matches/calendar) Calendar renders
Implement month/week/day views Views switch
Show matches on calendar with status colors Matches visible
Click match to view/edit Navigation works
Add drag-drop to reschedule (with confirmation) Reschedule works

2.2 Match CRUD

Create Match

Status Task Verification
Create match form page (/admin/matches/create) Form renders
Add home team selector (Croatia fixed for HOME matches) Selector works
Add away team input/selector Team entry works
Add competition input Competition saved
Add kick-off date-time picker DateTime works
Add match type selector (HOME/AWAY) Type selection works
Add venue selector (for HOME: Croatian stadiums) Venue selection works
~~Add queue enabled toggle~~ REMOVED — queue is auto-scaling microservice, not per-match toggle
Implement form validation Validation runs
Submit to POST /admin/matches API called, redirect to edit

Edit Match

Status Task Verification
Create match edit page (/admin/matches/{id}/edit) Page loads with data
Pre-populate form with existing data Fields filled
Add status change dropdown Status managed via detail page lifecycle actions
Validate status transitions Backend validates transitions
Add notification preference (notify/silent on save) Preference saved
Show warning when changing published match Warning displayed
Submit to PUT /admin/matches/{id} API called

Match Details View

Status Task Verification
Create match detail page (/admin/matches/{id}) Page renders
Show match info card (teams, venue, kickoff) Info displayed
Show sales summary (tickets sold, revenue) Summary shows (placeholder)
Show inventory summary by sector Sector breakdown shown
Show sales phase timeline Phases displayed
Add action buttons (Edit, Configure Stadium, Publish, Cancel) Actions work
Add tabs for sections (Details, Stadium, Phases, Inventory) Tabs navigate

2.3 Sales Phase Configuration

Sales Phase List

Status Task Verification
Create sales phases section on match edit page Section renders
Show timeline visualization of phases Timeline visible
List phases with start/end times Phases listed
Show phase type badges (Loyalty, General, Quota Only) Badges colored
Add/Edit/Delete phase buttons Buttons work

Sales Phase Form

Status Task Verification
Create phase form modal Modal opens
Add phase type selector Type selectable
Add start/end date-time pickers Dates selectable
Add ticket limit input Limit saved
Add eligibility rules builder (JSON) Rules configurable
Validate no overlap with other phases Overlap prevented
Submit to POST/PUT /admin/matches/{id}/sales-phases API called

2.4 Stadium Configuration

Stadium Template Selection

Status Task Verification
Create stadium config page (/admin/matches/{id}/stadium) Page renders
Show stadium template selector (for HOME matches) Templates listed
Show "Create New" option (for AWAY matches) Option available
Preview selected template (sectors, capacity) Preview shows
Confirm template copy to match Copy creates config
Show import from previous match option Import works

Sector Configuration

Status Task Verification
List match sectors with configuration Sectors listed
Show sector capacity (total, sellable, technical) Capacities shown
Add availability toggle (Active/Closed/Maintenance) Toggle works
Add purpose selector (General, Away Fans, VIP, Press, Free) Selector works
Add price category assignment Category assigned (base price)
Link to seat map editor for sector Link navigates
Bulk update selected sectors Bulk update works

Price Categories

Status Task Verification
Create price categories section Section renders
List existing categories with colors Categories listed
Add create category form (name, price, currency, color) Creation works
Edit/delete categories Edit/delete work
Prevent delete if category assigned to sectors Delete blocked

Stadium Validation

Status Task Verification
Add "Validate Configuration" button Button visible
Call POST /admin/matches/{id}/stadium/validate API called
Display validation errors (unassigned sectors, pricing gaps) Errors shown
Display validation warnings Warnings shown
Show configuration summary (capacity, sectors) Summary displayed
Lock configuration button (after validation passes) Lock works

Visual Stadium Editor Integration

Separate Task File

The Visual Stadium Editor (Konva.js canvas) has its own comprehensive task file: Visual Stadium Editor Tasks

Integration points with Admin Portal:

Status Task Verification
Add "Design Seat Map" button on sector row Button visible
Navigate to /admin/stadiums/{stadiumId}/sectors/{sectorId}/seat-map Navigation works
Pass sector context to editor component Context loaded
Handle editor save callback (refresh sector data) Data refreshes
Show seat map status badge (None/Draft/Active) Status shown
Show seat count from seat map Count displayed

2.5 Match Lifecycle Actions

Publish Match

Status Task Verification
Add "Publish" button (visible for DRAFT matches) Button visible
Show pre-publish checklist (stadium configured, phases set) Checklist shown
Require all checklist items passed Publish blocked if incomplete
Confirmation modal with summary Modal shows
Call PUT /admin/matches/{id} with status=PUBLISHED API called
Show success notification Toast appears

Cancel Match

Status Task Verification
Add "Cancel Match" button (visible for PUBLISHED/ACTIVE) Button visible
Show cancellation impact summary (tickets to refund) Summary shown
Require Super Admin approval for published matches ROLE_SUPER_ADMIN on route
Add cancellation reason input Reason required
Confirmation modal with warning Modal shows warning
Call POST /admin/matches/{id}/cancel API called
Show progress for refund processing Progress displayed

Close Match

Status Task Verification
Add "Close Match" button (visible for ACTIVE, after kickoff) Button visible
Show attendance import option Option available
If no attendance: require reason Attendance input shown
Call POST /admin/matches/{id}/close API called
Show loyalty points calculation trigger Progress shown

Phase 3: Inventory Operations (E3)

3.1 Seat Inventory View

Inventory Dashboard

Status Task Verification
Create inventory page (/admin/matches/{id}/inventory) Page renders
Show match header with summary stats Stats displayed
Show sector cards with status breakdown Cards show counts
Add status filter (show only Available, Sold, etc.) Filter works
Add sector selector Selector works
Real-time update toggle (auto-refresh) Auto-refresh works

Seat Grid View

Status Task Verification
Create seat grid component for sector Grid renders
Color-code seats by status (10 colors) Colors correct
Show row labels on left Labels visible
Show seat numbers on hover Tooltip shows
Click seat to select Selection works
Shift+click for range select Range works
Ctrl+click to toggle Toggle works
Show selection count Count displayed

Stadium Visualization

For full Konva.js canvas visualization with zoom/pan, see Visual Stadium Editor Tasks - Section 7: Inventory Mode


3.2 Seat Status Operations

Individual Seat Change

Status Task Verification
Click seat to open detail modal Modal opens
Show seat info (sector, row, seat, current status) Info displayed
Show ticket info if sold (holder, order, purchase date) Ticket info shown
Add status change dropdown Dropdown shows valid transitions
Require reason for status change Reason required
Show warning for locked seats (in cart) Warning displayed
Call PUT /admin/seats/{id}/status API called
Update grid after change Grid refreshes

Bulk Seat Operations

Status Task Verification
Add "Bulk Operations" panel when seats selected Panel appears
Show selected seats summary Summary displayed
Add new status dropdown Status selectable
Add reason input Reason enterable
Add optional current status filter Filter available
Show preview of affected seats Preview shown
Call POST /admin/seats/bulk-status API called
Show progress bar for large operations Progress visible
Show results (updated, skipped) Results displayed

Selection Tools

Status Task Verification
Add "Select by Row Range" tool Tool available
Input from row, to row Inputs work
Add "Select by Status" tool Tool available
Checkbox for each status to include Checkboxes work
Add "Select All" / "Clear Selection" buttons Buttons work
Add "Invert Selection" button Inversion works

3.3 Seat Search & Lookup

Search Interface

Status Task Verification
Create seat search page (/admin/seats/search) Page renders
Add search by seat number input Search works
Add search by ticket holder email Search works
Add search by order ID Search works
Add search by quota ID Search works
Add match filter Filter works
Add status filter Filter works
Add date range filter (purchase date) Filter works

Search Results

Status Task Verification
Display results in data table Table shows results
Show seat info (match, sector, row, seat) Info displayed
Show status badge Badge colored
Show ticket holder name (if sold) Name shown
Add action buttons (View Details, Change Status) Actions work
Click row to open detail modal Modal opens
Export search results Export works

Phase 4: Distribution (E7, E10)

4.1 Quota Management

Quota List

Status Task Verification
Create quotas index page (/admin/quotas) Page renders
Show data table with quotas Table displays
Add match filter Filter works
Add status filter (Active, Claimed, Expired) Filter works
Add organization filter Filter works
Show quota summary (allocated, claimed, remaining) Summary shown
Add quick actions (View, Edit, Resend Invite) Actions work

Create Quota

Status Task Verification
Create quota form page (/admin/quotas/create) Form renders
Add match selector Match selectable
Add organization/partner name input Name saved
Add contact email input Email saved
Add quantity input Quantity saved
Add sector selector Sector selectable
Add price category assignment Category assigned
Add deferred payment toggle Toggle works
Add delegation enabled toggle Toggle works
Add expiration date picker Date saved
Submit to POST /admin/quotas API called
Show seat allocation result Result displayed

Quota Detail

Status Task Verification
Create quota detail page (/admin/quotas/{id}) Page renders
Show quota info card Info displayed
Show allocation breakdown (claimed, unclaimed, expired) Breakdown shown
List tickets in quota with holder info Tickets listed
Show sub-quotas if delegation enabled Sub-quotas listed
Add "Resend Invitation" button Button works
Add "Cancel Quota" button Button works
Add "Extend Expiration" button Button works

CSV Import

Status Task Verification
Create CSV import page (/admin/quotas/import) Page renders
Show CSV template download link Download works
Add file upload with drag-drop Upload works
Validate CSV structure Validation runs
Show preview of quotas to create Preview displayed
Show validation errors per row Errors highlighted
Confirm import button Import executes
Show import results (created, failed) Results displayed

4.2 Customer Support Operations

Ticket Lookup

Status Task Verification
Create support lookup page (/admin/support/lookup) Page renders
Add search by barcode/QR value Search works
Add search by order ID Search works
Add search by email Search works
Add search by OIB Search works
Display ticket details Details shown
Show ticket holder info Holder info shown
Show order history History displayed
Add action buttons (Transfer, Refund, Reissue) Actions available

Ticket Transfer

Status Task Verification
Create transfer form modal Modal opens
Input new holder details (name, OIB/passport) Fields available
Input new delivery email Email input works
Run blacklist check on submit Check runs
Show blacklist warning if matched Warning displayed
Require transfer reason Reason required
Call POST /admin/tickets/{id}/transfer API called
Show transfer confirmation Confirmation shown
Trigger notification to new holder Notification sent

Ticket Refund

Status Task Verification
Create refund form modal Modal opens
Show refund amount calculation Amount calculated
Show service fee deduction (if applicable) Fee shown
Require refund reason Reason required
Confirm refund action Confirmation required
Call POST /admin/tickets/{id}/refund API called
Show refund processing status Status displayed
Handle partial refund option Partial works

Emergency Ticket Printing

Status Task Verification
Add "Print Ticket" button on ticket detail Button visible
Generate printable ticket PDF PDF generated
Include barcode/QR on print Code visible
Log print action to audit Audit event dispatched to Loki

Phase 5: Security & Reporting (E11, E14, E13)

5.1 Blacklist Management

Status Task Verification
Create blacklist search page (/admin/blacklist) Page renders
Add search by OIB Search works
Add search by name (optional field) Search works
Show results with entry details Results displayed
Show entry status (Active, Removed) Status shown
Add action buttons (View, Remove) Actions work

Blacklist Entry Management

Minimal Required Fields

Only OIB is required. First name and last name are optional.

Status Task Verification
Create entry form modal Modal opens
Input OIB (required, with checksum validation) OIB validated
Input first name (optional) Name saved
Input last name (optional) Name saved
Submit to POST /admin/blacklist API called
Show impact on existing tickets Impact displayed

Blacklist CSV Import

Status Task Verification
Create import page (/admin/blacklist/import) Page renders
Download CSV template Template downloads
Upload and validate CSV Validation runs
Show preview with validation errors Preview shown
Import valid entries Import executes
Show import summary Summary displayed

Violation Monitoring

Status Task Verification
Create violations report page (/admin/blacklist/violations) Page renders
Show attempted purchases blocked by blacklist List displayed
Filter by date range Filter works
Filter by match Filter works
Show violator details (OIB, name) Details shown
Show violation timestamp and context Context shown
Export violations report Export works

5.2 Reporting & Analytics

Sales Reports

Status Task Verification
Create sales report page (/admin/reports/sales) Page renders
Add match selector Selector works
Add date range filter Filter works
Show summary cards (total tickets, revenue, avg price) Cards display
Show sales by sector chart Chart renders
Show sales by channel chart (App, Quota, Petrol) Chart renders
Show sales timeline chart Chart renders
Export to Excel Export works

Real-Time Match Dashboard

Status Task Verification
Create match dashboard page (/admin/reports/match/{id}/dashboard) Page renders
Show live ticket sold count Count updates
Show live revenue Revenue updates
Show inventory by sector (visual) Visualization shows
Show queue status (if active) Queue stats shown
Auto-refresh every 30 seconds Refresh works
Show sales velocity (tickets/minute) Velocity calculated

Financial Reconciliation

Status Task Verification
Create financial report page (/admin/reports/financial) Page renders
Add date range filter Filter works
Show revenue summary (gross, fees, net) Summary shown
Show payment method breakdown Breakdown shown
Show refunds summary Refunds shown
Show invoices/credit notes list List displayed
Export to Excel Export works
Generate PDF report PDF generates

5.3 Access Control Export/Import

Barcode Export

Status Task Verification
Create export page (/admin/matches/{id}/export) Page renders
Show export options Options displayed
Add "Export Barcodes" button Button visible
Include buffer codes for late sales Buffer included
Generate Excel file Excel downloads
Show filename with match ID and timestamp Filename correct
Log export action Audit event dispatched to Loki

Attendee Export (Away Matches)

Status Task Verification
Add "Export Attendees" button (AWAY matches only) Button visible
Include holder names and seat assignments Data included
Filter by sector option Filter works
Generate Excel file Excel downloads

Attendance Import

Status Task Verification
Create import section on match close page Section renders
Upload attendance Excel file Upload works
Parse and validate barcodes Parsing works
Show preview (matched, unmatched) Preview shown
Show unmatched barcodes list List displayed
Confirm import Import executes
Update ticket attendance status Status updated
Trigger loyalty points calculation Trigger works

5.4 Stadium Template Management

Template List

Status Task Verification
Create stadiums index page (/admin/stadiums) Page renders
Show data table with templates Table displays
Filter by type (HOME/AWAY) Filter works
Show capacity and sector count Info displayed
Add action buttons (View, Edit Sectors) Actions work

Template Sectors

Status Task Verification
Create sectors page (/admin/stadiums/{id}/sectors) Page renders
List sectors with capacity Sectors listed
Show seat map status per sector Status shown
Add "Design Seat Map" link Link works
Add "Configure Snake" link Link works
Add/Edit/Delete sector actions Actions work

Snake Algorithm Configuration

Status Task Verification
Create snake config page (/admin/sectors/{id}/snake) Page renders
Show best row selector Selector works
Show traversal direction toggle Toggle works
Show within-row strategy selector Selector works
Preview fill order visualization Preview works
Save configuration Save works

5.5 Petrol Management (E12-F4)

Feature: E12-F4: Petrol Deeplink & QR Code Admin Management

Flow: Admin Petrol Setup

Petrol Overview (already partially implemented)

Status Task Verification
Create Petrol admin controller (/admin/petrol) Route registered
Implement /admin/petrol/api/overview proxy Returns pin/reservation/sales summary
Implement /admin/petrol/api/pins proxy with filters List renders

Petrol Quotas (Unified Section)

Status Task Verification
Add "Petrol Quotas" sub-route under /admin/petrol/quotas with list + create + detail views Routes render
Build Create Petrol Quota form in Petrol section (match, recipient email, sectors, quantity, algorithm, expiration) Form POSTs to backend /admin/petrol/quotas
Hide the forced flags (quota_type, deferred_payment, subquota, transfer) from the form — backend enforces Flags forced server-side; form doesn't expose them
Build Petrol quotas list with inline QR thumbnail Thumbnail renders
SVG + PNG (≥600×600) download actions per row Files download, decode to hns://petrol-sales/{quota-id}
Copy-to-clipboard for deeplink URL Copies to clipboard
Columns: match, recipient, counters (allocated/reserved/sold), quota status, deferred-payment status, created/expires All columns present
Filters: match, quota status, deferred-payment status, date range Filters work
Cancel action per row with standard quota cancellation options Cancels via backend
Generic Quota section: show Petrol quotas read-only with "Managed in Petrol section →" link Mutations disabled from generic list
Generic Create Quota form: reject / redirect if Petrol type picked Blocked with redirect
Restrict Petrol section access to ROLE_MATCH_MANAGER 403 for other roles
Wire audit events on Petrol quota create / cancel through backend Audit entries present in Loki

Phase 6: Settings & System

6.1 User Management (Super Admin)

Status Task Verification
Create admin users page (/admin/settings/users) Page renders
List admin users with roles Users listed
Add user form (email, role) Form works
Edit user role Edit works
Deactivate user Deactivation works
View user audit log Audit shown

6.2 Audit Trail (via Grafana)

Architecture

Audit logs are stored in Grafana Loki. The admin audit page provides access via embedded Grafana dashboards. See Audit Logging Infrastructure.

Status Task Verification
Create audit log page (/admin/settings/audit) with Grafana embed Page renders Grafana dashboard
Configure Grafana viewer access for embedded dashboards Embed loads without separate login
Filter by user (Grafana variable) Filter works
Filter by action type (Grafana variable) Filter works
Filter by date range (Grafana variable) Filter works
Filter by entity (match, ticket, quota) Filter works
Show action details in drill-down panel Details displayed
Export audit log via Grafana CSV export Export works

6.3 System Settings

Status Task Verification
Create settings page (/admin/settings) Page renders
Configure cart timeout (minutes) Setting saved
Configure queue window (minutes) Setting saved
Configure QR visibility hours before match Setting saved
Configure ticket limit per transaction Setting saved
Configure support window cutoff (hours before match) Setting saved

Testing Checklist

Functional Testing

Status Task Verification
Test all CRUD operations for matches All operations work
Test stadium configuration workflow Workflow completes
Test quota creation and claiming simulation Quota workflow works
Test bulk seat operations Bulk ops complete
Test search and filtering All filters work
Test export/import functionality Files generate correctly

Access Control Testing

Status Task Verification
Test role-based menu visibility Menu items correct per role
Test route protection by role Unauthorized returns 403
Test action buttons hidden for unauthorized Buttons hidden
Test Super Admin bypass Super Admin sees all

Browser Testing

Status Task Verification
Test in Chrome (latest) All features work

Last Updated: February 2026