fix(timetable): eliminate ?day URL flicker by deriving isFlatEvent from event_type instead of subEvents length (B7)
Phase A finding A5 traced this race in the browser logs:
GET .../performances?day={festival_id} → 200, 0 results ← wrong day
GET .../children → 200, 3 sub_events
GET .../performances?day={subevent_id} → 200, 13 results ← correct
The pre-fix `isFlatEvent` was:
computed(() => !subEvents.value || subEvents.value.length === 0)
While `subEvents` was still loading (undefined), `!undefined` is `true`,
so isFlatEvent erroneously returned `true` for festivals during the
loading window. dayOptions then took the flat-event branch and seeded
validSubEventIds with the FESTIVAL id. useActiveDay's corrective watcher
rewrote the URL to `?day={festival_id}` and fired a wasted query that
returned zero results (correct semantics — performances live at sub-event
level — but waste + visible URL flicker).
Fix:
computed(() => eventDetail.value?.event_type === 'event')
EventResource always serialises event_type (verified at
api/app/Http/Resources/Api/V1/EventResource.php:26). EventTabsNav
already consumes event_type / is_festival from the same shape
(apps/app/src/components/events/EventTabsNav.vue:175,266) so this is
the canonical signal, not a one-off addition.
New behavior trace:
- Both queries pending → eventDetail=undefined → isFlatEvent=false
→ festival branch returns (subEvents ?? []).map(...)
→ validSubEventIds=[] → activeDayId=null
→ usePerformances.enabled=false → NO fetch
- subEvents resolves first → festival branch populates dayOptions
→ fetch fires with correct sub-event id
- eventDetail resolves first to flat event → flat branch fires
→ fetch with eventDetail.id (correct)
- eventDetail resolves first to festival → still false until subEvents
→ no false-positive flat-event fetch
402 tests still pass; typecheck + lint + production build all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -51,7 +51,12 @@ const eventIdRef = eventId
|
||||
const { data: eventDetail } = useEventDetail(orgId, eventId)
|
||||
const { data: subEvents } = useEventChildren(orgId, eventId)
|
||||
|
||||
const isFlatEvent = computed(() => !subEvents.value || subEvents.value.length === 0)
|
||||
// Authoritative once eventDetail loads (single-row endpoint, fast).
|
||||
// Pre-load it returns `false`, which keeps dayOptions empty until we
|
||||
// actually know whether this is a flat event or a festival — avoids the
|
||||
// `?day={festival_id}` URL flicker that occurred when subEvents was
|
||||
// still pending (it was being read as "no children → flat event").
|
||||
const isFlatEvent = computed(() => eventDetail.value?.event_type === 'event')
|
||||
|
||||
const dayOptions = computed(() => {
|
||||
if (isFlatEvent.value && eventDetail.value)
|
||||
|
||||
Reference in New Issue
Block a user