Skip to content

feat(movieland): publish opening hours from the park's own calendar - #522

Merged
cubehouse merged 1 commit into
mainfrom
feat/movieland-schedules
Aug 27, 2026
Merged

feat(movieland): publish opening hours from the park's own calendar#522
cubehouse merged 1 commit into
mainfrom
feat/movieland-schedules

Conversation

@cubehouse

Copy link
Copy Markdown
Member

Movieland shipped in #518 with buildSchedules() returning []. The Helpy app feed genuinely has no calendar in it — its service worker whitelists exactly five data files (points_caneva, points_movieland, shows, lampioni, restaurant_*) and none of them carries opening hours.

The hours are on the park website, in two halves that only mean something together:

  • the schedule page carries a colour legend, data-cid"10:00 - 19:00"
  • bootstrap/template_calendar_data/{ctx}/{id}/{year}/{month} maps each date onto one of those colours

This adds both fetches, the parsers that join them, and buildSchedules() over a rolling four-month window. The published 2026 season comes out as 244 days, 76 of them open, each carrying the event it belongs to as description (Movy Night, Halloween Night, American Beer Fest, Natale all'improvviso).

What the fixtures pin down

All four are live responses captured on 2026-08-27, chosen for the things that can go wrong:

Case Why it matters
31/10 is 10.00 - 24.00 ISO has no hour 24. It becomes 00:00 on 1 November.
24/10 vs 30/10 European summer time ends 25/10, so the same 10:00 opening is +02:00 then +01:00. The offset has to be resolved per day, not once.
December Out of season: no days of its own, but the payload still nests a populated prev_month. Walking it would republish November's hours under December.
Legend markup Shared with marketing tiles ("Acquista un biglietto...") that carry no hours and never appear in the calendar.

Also: an empty result returns [], not [{id, schedule: []}]. The second form reaches the sync as a schedule wipe rather than a no-op.

Configuration

webBase defaults to empty. With no origin configured buildSchedules() returns [] without touching the network, so a build with no configuration behaves exactly as it does today and npm run dev -- movieland stays green.

The site refuses parksapi's own HTTP client with a 403, so calendarPageUrl() / calendarMonthUrl() are public: a caller that has to fetch these with its own client builds the same URL instead of keeping a second copy of the path that can drift.

Verification

  • 37 unit tests, fixtures are real captured responses
  • mutation-tested: dropping the next-day rollover, reading the month in the host timezone, walking prev_month, removing the empty-schedule guard, and losing the year rollover each fail at least one test
  • end-to-end against the live site through the real getSchedules(): 76 open days, 2026-10-31T10:00:00+01:00 → 2026-11-01T00:00:00+01:00
  • full suite green (2144 tests)

🤖 Generated with Claude Code

https://claude.ai/code/session_01PpfPiCvc6nDju6ptPQ9M8d

buildSchedules() returned [] because the Helpy app feed carries no
calendar — its service worker whitelists five data files and none of them
is one. The hours are on the park website instead, split across two
halves that only mean something together: the schedule page carries a
colour legend (data-cid -> "10:00 - 19:00") and a per-month endpoint maps
each date onto one of those colours.

Adds the two fetches, the parsers that join them, and buildSchedules()
over a rolling four-month window. The 2026 season comes out as 244 days,
76 of them open, with the event each day belongs to as the description.

Four things the fixtures pin down, all of them live responses:

  - 31/10 is "10.00 - 24.00", an hour ISO cannot express. It becomes
    00:00 on 1 November.
  - the same 10:00 opening is +02:00 on 24 October and +01:00 on 30
    October, so the offset has to be resolved per day.
  - an out-of-season month returns no days of its own but still nests a
    populated prev_month; reading it would republish November's hours
    under December.
  - the legend markup is shared with marketing tiles that carry no hours.

An empty result is returned as [] rather than [{id, schedule: []}]: the
latter reaches the sync as a schedule wipe.

webBase defaults to empty, so a build with no configuration keeps today's
behaviour exactly and never calls the site.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PpfPiCvc6nDju6ptPQ9M8d
@cubehouse
cubehouse merged commit 2c98322 into main Aug 27, 2026
4 checks passed
@cubehouse
cubehouse deleted the feat/movieland-schedules branch August 27, 2026 15:18
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