Skip to content

feat(schedule): publishable schedules via reveal-level enum#48

Merged
chiptus merged 16 commits into
mainfrom
feat/46/schedule-reveal-level
Jun 1, 2026
Merged

feat(schedule): publishable schedules via reveal-level enum#48
chiptus merged 16 commits into
mainfrom
feat/46/schedule-reveal-level

Conversation

@chiptus
Copy link
Copy Markdown
Owner

@chiptus chiptus commented May 30, 2026

Adds a schedule_reveal_level enum (draft < days < stages < full) on festival_editions so the Core Team can release the schedule progressively, independently of edition.published. Field visibility is masked client-side (per docs/adr/0001-schedule-reveal-level.md); admin controls live in the edition edit dialog and on the Schedule tab.

Closes #46.

Manual verification

Prereq: apply the new migration (supabase/migrations/20260530000000_add_schedule_reveal_level.sql) and regenerate types.

Admin

  1. Sign in as a Core Team / admin user.
  2. Open Admin → Festivals → [festival] → Editions, click Edit on an edition.
  3. Confirm a new Schedule reveal dropdown is visible with options draft / days / stages / full. Toggle the Published switch off — the hint "Configured but not active — edition is not published" should appear when the level is above draft.
  4. Save with level draft.
  5. As the same admin, open the edition → Schedule tab.
  6. Confirm a panel at the top of the tab shows three buttons: Reveal days, Reveal stages, Reveal times.
  7. Click Reveal days → it becomes a "Days revealed" badge with an undo arrow next to it; only Reveal stages is the next active button. Click through to Reveal times, then use the undo arrows to demote back down to draft.
  8. Open Admin → Festivals → [festival] → Import Schedule, upload a CSV, advance to the review step. With reveal level at draft there should be no banner above the commit button. Bump the level on the edition to days (or higher) and re-enter the wizard — the warning "Schedule is days revealed. Committing will update what the public sees immediately…" should now appear above the commit button.

Public (incognito or signed out)

  1. Open the same edition page. The Schedule tab in the nav should have a small amber dot in its corner whenever the level is below full.
  2. With level draft: open the Schedule tab → "Schedule not yet published." On the Artists tab, set cards should show no stage badge and no time/day text.
  3. Set the edition's level to days. Reload. Schedule tab now reads "Day-by-day lineup is out — exact times coming soon." On the Artists tab, set cards should show a day label (e.g. "Fri, Aug 1") but no stage badge and no time-of-day.
  4. Set the edition's level to stages. Reload. Schedule tab reads "Stages assigned — exact times coming soon." Artist-tab set cards should show day and the stage badge, but still no time-of-day.
  5. Set the edition's level to full. Reload. The Schedule tab renders the full timeline / list as before, the amber dot disappears, and set cards show day + stage + time range.

Generated by Claude Code

claude added 8 commits May 30, 2026 10:19
Captures the grilling outcome for "make schedules publishable" (#46):
- CONTEXT.md glossary with festival/edition/lineup/schedule/set/stage
  terminology and the resolved publish-state model (edition.published is
  separate from the schedule reveal level)
- ADR-0001 records the decision to model schedule visibility as an
  ordered enum (draft < days < stages < full) on festival_editions,
  with the rejected alternatives (boolean, independent flags,
  versioned schedules, per-day granularity)

https://claude.ai/code/session_01D6SJEwugBTwcYZt4ZzDQVC
We chose client-side hide over a public_sets view for simplicity.
The wire leak is acknowledged; server-side hardening is the
documented upgrade path.
Ordered enum draft < days < stages < full on festival_editions.
Defaults to draft for new editions. Existing editions with
published = true are backfilled to full so the migration does
not silently hide currently-visible schedules.
scheduleReveal exposes:
- isAtLeast(level, threshold) for ordered comparison
- canShowDay / canShowStage / canShowTime predicates for
  per-field visibility checks (used where the time-of-day
  vs date distinction matters and a null check isn't enough)
- maskSetForReveal for the common case of nulling embargoed
  fields on a set object before rendering
- New useScheduleReveal hook combining edition + admin status into
  canShowDay/canShowStage/canShowTime predicates
- formatDayOnly helper in timeUtils for the day-only display path
- SetMetadata, SetInfoCard, MultiArtistSetInfoCard, SetCardHeader,
  Timeline, ListSchedule now honour the level: stage badge appears
  at stages+, time range at full, date-only label at days/stages
- Schedule tab placeholder is now gated by canShowTime instead of
  edition.published (decoupling the lineup-published gate from the
  schedule-revealed gate)
- Schedule reveal dropdown in the edition edit dialog
  (FestivalEditionManagement) with all four levels and a hint
  when the edition isn't published yet
- ScheduleRevealAdminPanel on top of the Schedule tab with
  progressive Reveal Days / Reveal Stages / Reveal Times buttons.
  Each revealed step becomes a status badge with an undo button
  for demotion. Hidden for non-admins.
- Loosen useUpdateFestivalEdition's editionData type to the
  generated Update shape so callers can patch a single field
#46)

- ScheduleNotRevealedPlaceholder centralises the copy and varies it
  by level (draft / days / stages)
- ScheduleTabIndicator renders an amber dot on the Schedule tab
  icon (desktop + mobile) when the schedule isn't at 'full' yet
- Import wizard shows a 'Schedule is currently revealed at X' warning
  above the commit button when the current level is above draft,
  with a quick diff summary of what becomes public
…mment

- Extract the schedule reveal Select + hint into its own component
  next to FestivalEditionManagement
- Drop redundant comment in Timeline.tsx — the canShowTime check
  speaks for itself
@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
upline Ready Ready Preview, Comment Jun 1, 2026 5:35am

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 30, 2026

Deploy → stagingworkflow run
Last updated: 2026-06-01 05:35:26 UTC

  • DB migrations succeeded
  • ⏭️ Edge functions skipped (no changes)

…button (#46)

- Move reveal controls out of the user-facing Schedule tab; admins now
  see the same schedule view as regular users
- New ScheduleRevealControl on the admin edition header: single button
  that advances to the next level (Reveal days -> stages -> times),
  with an undo arrow for demotion
- Drop the isAdmin bypass from useScheduleReveal so the level rule is
  uniform; admin pages that need full visibility query sets directly
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds progressive schedule reveal support for festival editions, allowing schedule visibility to move through draft → days → stages → full independently from edition publishing while updating public/admin UI and import warnings.

Changes:

  • Adds the schedule_reveal_level enum/column, generated Supabase types, ADR/domain documentation, and reveal utility tests.
  • Masks schedule stage/time display across public set, artist, explore, schedule, and tab navigation surfaces.
  • Adds admin controls for reveal level management and import warnings when committing changes to an already revealed schedule.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
supabase/migrations/20260530000000_add_schedule_reveal_level.sql Adds enum/column and promotes existing published editions to full.
src/integrations/supabase/types.ts Regenerates Supabase types for the new enum/column.
src/lib/scheduleReveal.ts Defines reveal ordering, predicates, and set masking helper.
src/lib/scheduleReveal.test.ts Adds unit coverage for reveal behavior.
src/lib/timeUtils.ts Adds day-only date formatting.
src/hooks/useScheduleReveal.ts Exposes reveal predicates to UI components.
src/hooks/queries/festivals/editions/useCreateFestivalEdition.ts Allows create payloads to include reveal level.
src/hooks/queries/festivals/editions/useUpdateFestivalEdition.ts Broadens update payload typing for reveal-level updates.
src/pages/admin/festivals/FestivalEditionManagement.tsx Adds reveal dropdown to edition edit/create form.
src/pages/admin/festivals/ScheduleRevealLevelField.tsx Adds admin reveal-level select field.
src/pages/admin/festivals/ScheduleRevealControl.tsx Adds progressive reveal/demote control.
src/pages/admin/festivals/FestivalEdition.tsx Displays reveal controls in the admin edition header.
src/routes/admin/festivals/$festivalSlug/editions/$editionSlug/import.tsx Passes current reveal level to import wizard.
src/components/Admin/ScheduleImport/ScheduleImportWizard.tsx Threads reveal level through wizard state.
src/components/Admin/ScheduleImport/ReviewStage.tsx Passes reveal level to the diff review step.
src/components/Admin/ScheduleImport/DiffReviewStep.tsx Shows live-update warning when committing revealed schedules.
src/pages/EditionView/tabs/ScheduleTab/ScheduleNotRevealedPlaceholder.tsx Adds level-aware schedule placeholder copy.
src/pages/EditionView/tabs/ScheduleTab/list/ListSchedule.tsx Hides list schedule until exact times are revealed.
src/pages/EditionView/tabs/ScheduleTab/horizontal/Timeline.tsx Hides timeline until exact times are revealed.
src/pages/EditionView/tabs/ArtistsTab/SetCard/SetMetadata.tsx Masks stage/time metadata by reveal level.
src/pages/SetDetails/SetInfoCard.tsx Masks single-artist set stage/time metadata by reveal level.
src/pages/SetDetails/MultiArtistSetInfoCard.tsx Masks multi-artist set stage/time metadata by reveal level.
src/pages/ExploreSetPage/SetExploreCard/SetCardHeader.tsx Masks explore-card date/time/stage details by reveal level.
src/pages/EditionView/TabNavigation/ScheduleTabIndicator.tsx Adds not-fully-revealed schedule indicator.
src/pages/EditionView/TabNavigation/MobileTabButton.tsx Displays schedule indicator on mobile nav.
src/pages/EditionView/TabNavigation/DesktopTabButton.tsx Displays schedule indicator on desktop nav.
docs/adr/0001-schedule-reveal-level.md Documents reveal-level architecture and tradeoffs.
CONTEXT.md Adds shared domain glossary and publish-state definitions.

Comment thread src/hooks/queries/festivals/editions/useUpdateFestivalEdition.ts
Comment thread src/hooks/useScheduleReveal.ts
…rning (#46)

- useUpdateFestivalEdition was only invalidating festivalsKeys.all();
  the editions-by-slug cache lives under ["festival-editions"], so
  changing schedule_reveal_level from the admin control kept the old
  level visible until reload
- Extract the import-wizard live-commit alert into LiveCommitWarning
useScheduleReveal no longer threads admin status, so canShowDay/
canShowStage/canShowTime/maskSetForReveal no longer need the
parameter. Cleaner call sites and tests.
Comment thread src/pages/EditionView/TabNavigation/DesktopTabButton.tsx Outdated
TabConfig grows an optional Indicator component. Schedule tab wires
ScheduleTabIndicator there; Desktop/Mobile buttons render
config.Indicator generically instead of branching on config.key.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 1 comment.

Comment thread src/hooks/useScheduleReveal.ts
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 1 comment.

Comment thread src/hooks/useScheduleReveal.ts
The stage filter and date-asc sort in useSetFiltering still read
set.stage_id and set.time_start directly, so the embargoed fields
leaked through filter/sort even after the badges and time labels
were hidden in the cards.

- maskSetForReveal now truncates time_start to date-only at
  days/stages so sorting can't infer time-of-day ordering
- ArtistsTab masks the sets array before passing it into
  useSetFiltering, so the stage filter sees nulled stage_id at
  draft/days and the date sort sees day-granularity timestamps
  at days/stages
claude added 2 commits June 1, 2026 04:16
Reverted d326db9's data-layer mask in favour of a UI-layer fix:
DesktopFilters and MobileFilters now hide the stage filter
when canShowStage is false. Stays consistent with the user-facing
hide-in-display rule, and the stage filter no longer renders a
control that would silently return empty results at draft/days.
)

text-purple-200 disappears on the white admin CardHeader. Swap
to bg-purple-100 / text-purple-900 so the current-level label is
visible.
@chiptus chiptus deployed to staging June 1, 2026 05:35 — with GitHub Actions Active
@chiptus chiptus merged commit 309098d into main Jun 1, 2026
14 checks passed
@chiptus chiptus deleted the feat/46/schedule-reveal-level branch June 1, 2026 17:17
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.

Make schedules publishable

3 participants