diff --git a/admin/src/pages/ShiftsPage.tsx b/admin/src/pages/ShiftsPage.tsx index 2ea4d652..3ef27e22 100644 --- a/admin/src/pages/ShiftsPage.tsx +++ b/admin/src/pages/ShiftsPage.tsx @@ -144,6 +144,16 @@ export default function ShiftsPage() { // Cuts for area dropdown const [cuts, setCuts] = useState([]); + const [ticketedEvents, setTicketedEvents] = useState>([]); // Calendar view state const [activeTab, setActiveTab] = useState<'table' | 'calendar'>('table'); @@ -208,6 +218,15 @@ export default function ShiftsPage() { } }, []); + const fetchTicketedEvents = useCallback(async () => { + try { + const { data } = await api.get('/ticketed-events/admin', { params: { limit: 100 } }); + setTicketedEvents(data.events ?? data.items ?? data ?? []); + } catch { + // Non-critical — picker stays empty + } + }, []); + const fetchCalendarData = useCallback(async (month: dayjs.Dayjs) => { setCalendarLoading(true); try { @@ -251,6 +270,7 @@ export default function ShiftsPage() { fetchShifts({ page: 1 }); fetchStats(); fetchCuts(); + fetchTicketedEvents(); }, [debouncedSearch, statusFilter, kindFilter]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { @@ -279,6 +299,10 @@ export default function ShiftsPage() { isPublic: values.isPublic || false, cutId: values.cutId || undefined, kind: (values.kind as ShiftKind) || 'CANVASS', + ticketedEventId: + values.kind === 'EVENT_STAFFING' + ? ((values.ticketedEventId as string) || undefined) + : undefined, }; await api.post('/map/shifts', payload); message.success(`${SHIFT_KIND_LABELS[payload.kind]} shift created`); @@ -336,6 +360,12 @@ export default function ShiftsPage() { if (values.status !== undefined) payload.status = values.status; if (values.cutId !== undefined) payload.cutId = values.cutId || null; if (values.kind !== undefined) payload.kind = values.kind; + if (values.kind === 'EVENT_STAFFING') { + payload.ticketedEventId = (values.ticketedEventId as string) || null; + } else if (values.kind !== undefined) { + // Changing away from EVENT_STAFFING clears the link + payload.ticketedEventId = null; + } await api.put(`/map/shifts/${editingShift.id}`, payload); message.success('Shift updated'); @@ -414,6 +444,7 @@ export default function ShiftsPage() { status: shift.status, cutId: shift.cutId, kind: shift.kind || 'CANVASS', + ticketedEventId: shift.ticketedEventId || undefined, }); setEditDrawerOpen(true); }; @@ -538,14 +569,22 @@ export default function ShiftsPage() { title: 'Kind', dataIndex: 'kind', key: 'kind', - width: 130, - render: (kind: ShiftKind) => { + width: 150, + render: (kind: ShiftKind, record: Shift) => { const k = kind || 'CANVASS'; - return ( + const tag = ( {SHIFT_KIND_LABELS[k]} ); + if (record.ticketedEvent) { + return ( + + {tag} + + ); + } + return tag; }, responsive: ['md'], }, @@ -713,8 +752,54 @@ export default function ShiftsPage() { ), }))} + onChange={(value) => { + // Clear event link when leaving EVENT_STAFFING + if (value !== 'EVENT_STAFFING') { + (isEdit ? editForm : createForm).setFieldValue('ticketedEventId', undefined); + } + }} /> + prev.kind !== curr.kind}> + {({ getFieldValue }) => + getFieldValue('kind') === 'EVENT_STAFFING' ? ( + +