Skip to content

feat: bulk event creation and multi-cohort support#15

Merged
AlexVOiceover merged 36 commits intomainfrom
feature/ap-23-bukl-event-creation
Jan 5, 2026
Merged

feat: bulk event creation and multi-cohort support#15
AlexVOiceover merged 36 commits intomainfrom
feature/ap-23-bukl-event-creation

Conversation

@AlexVOiceover
Copy link
Copy Markdown
Contributor

Overview

Major feature release adding bulk event creation with calendar picker, multi-cohort event support, and significant admin UI improvements. Events can now target multiple cohorts and/or be marked as "Open" for external attendees.


Changes

Bulk Event Creation (AP-23)

  • Calendar picker for selecting multiple dates at once
  • Series creation modal with shared settings (time, cohort, event type)
  • Auto-generated check-in codes for public events

Multi-Cohort Support

  • Events can now belong to multiple cohorts (schema: cohortIdcohortIds[])
  • Dropdown with checkboxes replaces native multi-select for better UX
  • "Open" option in audience dropdown controls public event visibility
  • Updated API endpoints and check-in access control

Admin Events UI

  • Inline editing replaces separate edit pages
  • Expandable roster view with color-coded attendance status
  • Sortable columns (name, date, type, cohort, attendance)
  • Cohort filtering dropdown
  • Mark-for-delete pattern with batch deletion
  • Calendar view synced with event list (click to scroll/select)
  • Fixed-width audience column with text truncation

Attendance Tracking

  • Late check-in auto-detection based on event start time
  • Status values aligned with Airtable (Present, Absent, Late, Excused)
  • Roster shows all attendees including non-cohort and external

- Add CalendarPicker component for multi-date selection
- Refactor /admin/events page with mode state (list/single/series)
- Move single event form inline, add series creation form
- Add case-insensitive event type validation for Airtable robustness
- Fix EVENT_TYPES to match Airtable's exact casing ("Regular Class")
- Redirect /admin/events/new to main events page
- Add attendanceCount to Event interface and listEvents
- Add apprenticeCount to Cohort interface and listCohorts
- Display "X/Y" attendance ratio in events table (Y = cohort size)
- Show just count for open events without cohort
- Add /api/events/[id]/roster endpoint returning attendees and check-in state
- Add getApprenticesByCohortId function to fetch cohort members
- Add expandable rows in events table showing attendance roster
- Display check-in status with visual indicators (green check / gray dash)
Replace check/cross icons with readable text: 'Checked in at [time]' or 'Not checked in'
…ed status

- Display roster as table with Name, Type, and Status columns
- Color-code type: blue for Apprentice, purple for Guest
- Color-code status: green for Checked in, red for Not checked in
… Late, Excused)

- Update roster API to return actual attendance status from Airtable
- Display status with color-coded badges: green (Present), red (Absent), yellow (Late), blue (Excused)
- Sort roster by status priority: Present > Late > Excused > Absent
- Update schema.md to document status field values
Changed detection logic from requiring both name and email to checking
if the attendance record has no apprentice link (meaning it's external)
- Fix external attendees not appearing by using event.attendanceIds
  instead of broken filterByFormula on linked record fields
- Add getAttendanceByIds to fetch attendance records by RECORD_ID()
- Add getApprenticesByIds to fetch details for non-cohort apprentices
- Add attendanceIds to Event type from linked ATTENDANCE field
- Separate status badge and check-in time into distinct columns
- Add determineStatus() to compare check-in time with event start time
- Mark attendees as 'Late' when checking in after the event begins
- Parallelize attendance and cohort API calls with Promise.all
- Reduces roster load time from ~1.5s to ~0.9s
…ality

- Add Schedule-X calendar with color-coded event types (Regular Class, Workshop, Hackathon)
- Centralize event type colors in src/lib/types/event.ts for single source of truth
- Add Survey URL column to events table with link icon
- Replace separate form with inline editable row for creating events
- Add delete button (X) with confirmation dialog for each event
- Hide expand arrow only for events with exactly 0 attendance (no cohort)
- Events with 0/X attendance still expandable to see who hasn't checked in
- Add sortable table headers with icons (Name, Date/Time, Type, Cohort, Attendance)
- Default sort by date descending (newest first)
- Add "Hide past events" checkbox filter
- Style past events with subtle background color
- Fix attendance count to show only Present/Late (not Excused)
- Add staff ability to edit attendance status inline in roster view
- Create POST /api/attendance endpoint for staff to create attendance records
- Create PATCH /api/attendance/[id] endpoint for status updates
- Include attendanceId in roster entries for proper record targeting
- Recalculate attendance count when roster loads
- Replace Schedule-X calendar with @event-calendar/core library
- Enable multi-date selection via dateClick for series creation
- Show selected dates as green background events on calendar
- Unify calendar component for both list view and series form
- Add TypeScript declarations for @Event-calendar packages
- Fix variable declaration order for SSR compatibility
Move series creation form above calendar for better UX flow:
- Form appears immediately when clicking "Create Series" button
- User fills in details then selects dates on calendar below
- Selected dates shown as removable pills in form
- Panel slides in/out with 300ms transition
- Remove separate mode navigation for cleaner interface
- Click calendar event to scroll to corresponding row in table
- Add persistent selection indicator with blue outline
- Selection wraps both event row and expanded roster when present
- Auto-expand roster if event has attendance data
- Replace immediate delete with mark-for-delete toggle
- Show red delete icon when event is marked
- Display action bar with count and delete button when events marked
- Support batch deletion of multiple events
- Add cancel option to clear all marks
- Add inline edit row that replaces normal row when editing
- Click pencil icon to enter edit mode with yellow highlighted row
- Edit all fields: name, date/time, type, cohort, public, survey URL
- Save changes via PUT API and update local state without reload
- Cancel button to discard changes
- Delete [id]/+page.svelte and [id]/+page.server.ts (edit is now inline)
- Delete new/+page.server.ts (creation is now inline)
- All event CRUD operations now happen on the main events page
- Add endDateTime field to Event type and Airtable config
- Update events API endpoints to handle endDateTime
- Create DateTimePicker component using @svelte-plugins/datepicker
- Replace native datetime-local inputs with styled date picker
- Calendar now displays events with proper end times
- Create DatePicker component for date-only selection
- Update events page to use 3 separate inputs: date, start time, end time
- Add helper functions to combine/extract date and time values
- Fix datepicker styling to not show permanent blue border
- Auto-default end time to start + 4 hours

Events never span multiple days, so this UI is cleaner while
Airtable schema remains unchanged (dateTime + endDateTime fields).
- Create TimePicker component with hour/minute select dropdowns
- Limit minutes to 15-min increments (00, 15, 30, 45)
- Add minTime prop to disable earlier times on end time picker
- Replace native time inputs with TimePicker in all event forms
- Add red border on required name fields when empty
- Fix timezone bug: calendar date selection was off by one day
  during DST due to toISOString() converting to UTC
- Disable other table rows when creating new event (dimmed + non-clickable)
- Replace survey URL input with dropdown popover for easier pasting
- Show grey icon when no survey URL, blue when present
- Fix survey URL clearing: send null to API, update local state correctly
- Fix DST timezone bug in calendar date selection (toISOString → local methods)
- Show numeric code input when Public checkbox is checked
- Support creating and editing event codes (up to 6 digits)
- Properly convert and send code as number to API
- Load existing codes when editing public events
- Auto-generate random 4-digit code when Public is checked
- Remove spinner arrows from code number inputs
- Add check-in code field to series creation form
- Same code used for all events in a series
- Set max-h-[560px] on table container for vertical scrolling
- Add sticky header to keep column titles visible while scrolling
- Add border styling to the scrollable container
Support multiple cohorts per event:
- Event.cohortId -> Event.cohortIds: string[]
- Event.cohortName -> Event.cohortNames: string[]
- CreateEventInput.cohortId -> cohortIds
- UpdateEventInput.cohortId -> cohortIds
- listEvents/getEvent/getEventByCode return cohortIds array
- createEvent/updateEvent accept cohortIds array
- Update tests to use cohortIds arrays
- POST /api/events: Accept cohortIds array
- PUT /api/events/[id]: Accept cohortIds array
- GET /api/events/[id]/roster: Fetch apprentices from all cohorts
- Fix events state sync warning in admin page
- Rename Event import to AppEvent to avoid DOM conflict
Change cohort matching from === to .includes() so students
see events where their cohort is one of the event's cohorts
- Replace multi-select with dropdown checkboxes for cohort selection
- Add "Open" option to audience dropdown (controls isPublic flag)
- Rename "Cohort" column to "Audience", "Public" to "Code"
- Fix column width to prevent resizing based on content
- Add disabled state tooltip for save button when fields missing
- Show "Open" in green alongside cohort names in event list
@AlexVOiceover AlexVOiceover marked this pull request as ready for review January 5, 2026 13:01
@AlexVOiceover AlexVOiceover merged commit 5f4cdc6 into main Jan 5, 2026
2 checks passed
@AlexVOiceover AlexVOiceover deleted the feature/ap-23-bukl-event-creation branch January 7, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant