Skip to content

refactor(widgets): share festival status badge and sheet handle - #501

Merged
richardthe3rd merged 3 commits into
mainfrom
fix/499-dedupe-festival-status-badge
Jul 26, 2026
Merged

refactor(widgets): share festival status badge and sheet handle#501
richardthe3rd merged 3 commits into
mainfrom
fix/499-dedupe-festival-status-badge

Conversation

@richardthe3rd

Copy link
Copy Markdown
Owner

Fixes #499

The festival status badge was implemented twice with byte-identical colours but divergent user-visible labels, and festival_menu_sheets.dart did not import festival_header.dart at all.

Decision: keep both label sets

FestivalStatusBadge gains a compact flag (default false) that drives both wording and geometry, so neither surface changes what the user sees:

compact: true (app bar) compact: false (festival cards)
labels LIVE / SOON / RECENT / PAST LIVE / COMING SOON / MOST RECENT / PAST
padding h6 v1 h8 v2
radius / fontSize 8 / 9 12 / 10

_styleFor is now the single source of truth, returning (compactLabel, longLabel, spokenLabel, light, dark). The public spokenLabel() API and its exact spoken values (live now, starting soon, most recent, past) are unchanged.

Changes

  • FestivalCard._buildStatusBadge deleted, including the Builder it used purely to obtain a context that FestivalCard.build already had. Its margin: right 8 became a SizedBox(width: 8) at the call site, so card spacing is unchanged.
  • The filter sheets' private _SheetHandle is promoted to a shared SheetHandle in its own file and exported from widgets.dart. The three hand-rolled 32×4 drag-handle containers in festival_menu_sheets.dart now use it, as do the four existing call sites in drink_filter_sheets.dart.
  • SheetHandle takes an explicit handleKey that lands on the inner Container. Forwarding the widget's own key there instead would make find.byKey match two widgets and break the existing tester.widget<Container>(...) assertions with Bad state: Too many elements; a separate named parameter keeps key behaving normally for a shared widget.

Testing

./bin/mise run check green (analyzer clean, full suite passing). Also verified green on the union with #500, which touches the same widgets.dart barrel.

  • festival_header_test.dart — compact vs default-long labels across all four FestivalStatus values; existing FestivalHeader semantics coverage untouched
  • festival_menu_sheets_test.dart — the existing COMING SOON / MOST RECENT and three drag-handle-key assertions pass unedited, which is the regression guard for the copy decision; one FestivalStatusBadge widget-type assertion added
  • sheet_handle_test.dart (new) — geometry, centring, handleKey forwarding to a single Container, normal key behaviour, theme colour

Not verified: on-device/browser rendering. The badge geometry is asserted in tests but has not been eyeballed on a real device.


Generated by Claude Code

claude added 2 commits July 26, 2026 13:28
Fold FestivalCard._buildStatusBadge into FestivalStatusBadge behind a
compact flag so both surfaces keep their current labels and geometry
from one source of truth. Promote the filter sheets' private
_SheetHandle to a shared SheetHandle and use it for the three
hand-rolled festival/settings/theme sheet handles.

Fixes #499
Replace the constructor that accepted `key` and forwarded it to the
inner Container while passing null to super. Swallowing `key` made
SheetHandle(key: k) silently unkeyed, which is surprising for a shared
widget. An explicit `handleKey` keeps the three drag-handle test
assertions matching a single Container and leaves `key` behaving
normally.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017B31wKKL578bV18hcpXyE2
Copilot AI review requested due to automatic review settings July 26, 2026 13:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors widget duplication by centralizing the festival status badge logic and the modal-sheet drag handle into shared widgets, keeping existing user-visible copy on both surfaces (compact app-bar vs long card labels).

Changes:

  • Deduplicates festival status badge implementation via FestivalStatusBadge(compact: ...), keeping both label sets and consolidating colors/labels in _styleFor.
  • Promotes the bottom-sheet drag handle into a shared SheetHandle widget and replaces hand-rolled handles across sheets.
  • Updates/extends widget tests to lock in the compact vs long label behavior and the shared-handle geometry/keying behavior.

Reviewed changes

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

Show a summary per file
File Description
test/widgets/sheet_handle_test.dart Adds tests for SheetHandle geometry, centering, theme color, and key forwarding (noting a few brittle finders).
test/widgets/festival_menu_sheets_test.dart Adds a regression assertion that festival cards use the shared FestivalStatusBadge.
test/widgets/festival_header_test.dart Expands coverage to assert compact/long/default labels for all FestivalStatus values.
lib/widgets/widgets.dart Exports sheet_handle.dart from the widgets barrel.
lib/widgets/sheet_handle.dart Introduces the shared SheetHandle widget with explicit handleKey forwarding.
lib/widgets/festival_menu_sheets.dart Replaces bespoke status badge + hand-rolled sheet handles with shared widgets.
lib/widgets/festival_header.dart Adds compact mode to FestivalStatusBadge, updates header call site, and consolidates styling via _styleFor.
lib/widgets/drink_filter_sheets.dart Removes the private _SheetHandle and switches filter sheets to the shared SheetHandle.
Comments suppressed due to low confidence (2)

test/widgets/sheet_handle_test.dart:30

  • This ancestor lookup keys off find.byType(Container), which may match multiple Containers over time. Scoping it to the Container that belongs to SheetHandle makes the test less fragile.
          of: find.byType(Container),

test/widgets/sheet_handle_test.dart:81

  • As above, find.byType(Container) is prone to becoming ambiguous if additional Container widgets appear in the tree. Scope the finder to a descendant of SheetHandle and assert a single match.
      final container = tester.widget<Container>(find.byType(Container));

Comment thread test/widgets/sheet_handle_test.dart Outdated
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Cloudflare Pages Preview

Your preview deployment is ready!

Preview URL: https://fix-499-dedupe-festival-stat.staging-cambeerfestival.pages.dev

This preview will be automatically updated when you push new commits to this PR.

find.byType(Container) matched the whole pumped tree, so the assertions
would become ambiguous if the test scaffolding ever gained a Container
of its own. Scope to SheetHandle's descendants and assert a single
match before reading the widget.

Addresses review feedback on #501.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017B31wKKL578bV18hcpXyE2
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Cloudflare Pages Preview

Your preview deployment is ready!

Preview URL: https://fix-499-dedupe-festival-stat.staging-cambeerfestival.pages.dev

This preview will be automatically updated when you push new commits to this PR.

@richardthe3rd
richardthe3rd merged commit eded56f into main Jul 26, 2026
14 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 26, 2026
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.

Festival status badge is implemented twice with divergent labels

3 participants