Commit Graph

19 Commits

Author SHA1 Message Date
ec31646a93 fix: shift dialog info alert layout and full-width toggle
Made-with: Cursor
2026-04-14 22:58:33 +02:00
103d57c979 refactor: polish shift dialog with Vuexy-style alert and sticky footer
Made-with: Cursor
2026-04-14 22:54:47 +02:00
8afee801f8 feat: make shift dialog time-slot help collapsible
Made-with: Cursor
2026-04-14 22:47:20 +02:00
1c3ce547fa refactor: polish shift create dialog layout and hierarchy
Made-with: Cursor
2026-04-14 22:45:12 +02:00
1c6aed71fe fix: replace InfoTooltip v-tooltip with v-menu popover card
v-tooltip renders a forced-dark background unsuitable for multi-line
help content. Switch to v-menu + v-card which follows the app theme.
Use surface-variant background for the "Tip:" block.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:41:01 +02:00
cc7cbbf29d fix: use inline style for time slot dimming in teleported dropdown
VAutocomplete renders its dropdown list in a teleported overlay outside
the component DOM tree. Scoped :deep() CSS cannot reach teleported
content. Switch from class-based opacity to inline style on VListItem.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:37:48 +02:00
948965e664 fix: time slot dropdown group headers and dimming via boundary detection
VAutocomplete ignores interleaved fake header items — they were filtered
out before reaching the template. Replace with Approach A: keep only
real selectable items sorted by group, detect group boundaries in the
#item template by comparing adjacent groupName values, and render
VListSubheader before each new group.

- Remove _isGroupHeader from TimeSlotDropdownItem interface
- Rename groupTimeSlots → sortedItems (returns only selectable items)
- Add hasGroups computed for conditional header rendering
- Add isNewGroup(index) boundary detection in CreateShiftDialog
- Add scoped .time-slot-dimmed CSS class (opacity: 0.65)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:31:32 +02:00
7bc0f1a0c7 feat: fix time slot hierarchy — seeder, API include_children, frontend dropdown, navigation
Restructure the festival hierarchy end-to-end:

Seeder: Remove duplicate festival-level VOLUNTEER time slots, keep only CREW
operational slots. Rename sub-events to "Dag 1/2/3 — ..." pattern. Change
Nachtsecurity to Security (cross_event). EHBO/Security shifts now use sub-event
time slots via cross_event exception. Add flat event "Braderie Dorpstown 2026".

API: Add ?include_children=true to TimeSlotController for festivals, returning
all sub-event time slots with source and event_name fields. Update
StoreShiftRequest and UpdateShiftRequest to accept child time slots for
cross_event sections.

Frontend: Create useTimeSlotDropdown composable with 4-scenario dropdown logic.
Replace AppSelect with VAutocomplete in CreateShiftDialog with grouped items,
dimmed festival slots, and info tooltips. Add InfoTooltip reusable component.
Show festival context labels on cross_event sections in sub-event section lists.
Add read-only festival time slots on sub-event time-slots page. Add cross_event
context banner with "Bekijk alle diensten" link.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:07:37 +02:00
cf02500453 fix: shift edit time slot dropdown loading state and test coverage
The time slot dropdown in the shift edit dialog could flash the
"create a time slot first" alert during loading, and show raw ULIDs
when time slot data hadn't loaded yet. Fixed by:
- Adding loading state indicator to the time slot dropdown
- Using the shift's existing time_slot object as a fallback item
  while the full list is fetching
- Showing the dropdown (with loading spinner) instead of the
  misleading "no time slots" alert during fetch

Added test coverage for time_slot_id validation on shift updates:
- Update with valid same-event time slot (200)
- Update with cross-org time slot (422)
- Update on sub-event with parent festival time slot (200)
- Store/update responses include nested time_slot object

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 20:46:36 +02:00
7932e53daf security: A01-13 — nest all event routes under organisation prefix
Move all authenticated organiser-facing event sub-resource routes from
/events/{event}/... to /organisations/{organisation}/events/{event}/...
to enforce multi-tenancy at the routing layer.

Changes:
- Routes: restructured api.php to nest all event sub-resources under
  the existing organisation prefix group
- Controllers: added Organisation parameter and VerifiesOrganisationEvent
  trait to all 12 affected controllers (sections, time-slots, shifts,
  persons, crowd-lists, locations, shift-assignments, registration-fields,
  availabilities, field-values, section-preferences, stats)
- Tests: updated all 20 feature test files with new route paths
- Frontend: updated 8 API composables and 20 Vue components/pages
- API.md: updated documentation to reflect new route structure

Portal routes, public routes (volunteer-register), and invitation routes
remain unchanged as they operate without organisation context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 08:16:36 +02:00
d2f282eb4c feat: split name into first_name + last_name across users, persons, and companies
Cross-cutting migration affecting the entire stack:
- Database: 3 migrations splitting name columns with data migration
- Models: first_name/last_name on User, Person; contact_first_name/contact_last_name on Company; backward-compatible name accessors
- API: all resources return first_name, last_name, full_name; assignablePersons endpoint updated
- Requests: validation rules updated for all person/user/company forms
- Services: VolunteerRegistrationService, ShiftAssignmentService, InvitationService updated
- Frontend: TypeScript types, Zod schemas, all forms split into Voornaam/Achternaam fields
- Display: all person/user name references use full_name; initials use first_name[0]+last_name[0]
- Tests: all 371 tests passing
- Docs: SCHEMA.md and API.md updated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:04:55 +02:00
968e17c6d6 feat: smart assign person dialog with conflict details and assignable-persons endpoint
Add GET /events/{event}/shifts/{shift}/assignable-persons endpoint that
returns approved persons with availability status, conflict details, and
already-assigned flags. Improve ShiftAssignmentService conflict errors to
include section name, time slot, and time range. Replace both assign
dialogs with a new AssignPersonDialog featuring search, crowd type
filtering, availability toggle, and inline conflict warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:32:31 +02:00
c21bc085e9 feat: registration section preferences with show_in_registration filtering and deduplication
Add show_in_registration and registration_description columns to festival_sections.
Registration form now shows deduplicated sections by name (across sub-events),
filtered by show_in_registration=true, grouped by category with card-based UI.
Section preferences use section_name instead of section_id.
Add GET/PUT registration-settings endpoints for festival-level bulk management.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:03:54 +02:00
e70904741d feat(app): dedicated Tijdsloten tab with grouped view and fill rates
Extract time slots from Secties & Shifts into a dedicated Tijdsloten tab.
New tab groups time slots by date with Dutch date headers, person type
filter pills, fill rate progress bars, and sections count. Includes
duplicate, edit, and delete actions with confirmation dialog.

- Create types/timeSlot.ts with enriched TimeSlot interface
- Add Tijdsloten tab to EventTabsNav between Publiekslijsten and Secties
- Create time-slots page with loading, error, and empty states
- Remove time slots panel from SectionsShiftsPanel
- Update CreateShiftDialog to navigate to time slots tab

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:47:36 +02:00
9b7aa92e84 fix: remove resetForm from onSuccess to prevent validation flash in dialogs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:03:02 +02:00
03ca1a50a7 feat: local sections in sub-events can use festival-level time slots
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:16:32 +02:00
37fecf7181 fix: auth race condition on refresh, section edit dialog, time slot duplicate, autocomplete disable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:16:22 +02:00
10bd55b8ae feat: festival/series model with sub-events, cross-event sections, tab navigation, SectionsShiftsPanel extraction
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:15:19 +02:00
6848bc2c49 feat: schema v1.7 + sections/shifts frontend
- Universeel festival/event model (parent_event_id, event_type)
- event_person_activations pivot tabel
- Event model: parent/children relaties + helper scopes
- DevSeeder: festival structuur met sub-events
- Sections & Shifts frontend (twee-kolom layout)
- BACKLOG.md aangemaakt met 22 gedocumenteerde wensen
2026-04-08 07:23:56 +02:00