Skip to content

Align venue card actions and hide venues with no beer inventory - #132

Merged
spizeck merged 1 commit into
mainfrom
fix/venue-cards-130
Sep 24, 2026
Merged

spizeck merged 1 commit into
mainfrom
fix/venue-cards-130

Conversation

@spizeck

@spizeck spizeck commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

Two related /where-to-buy fixes:

  1. Venue action rows now bottom-align across a grid row — cards are flex flex-col with the actions wrapper on mt-auto pt-4, so Directions / Website / Instagram / Facebook line up regardless of how many beer lines each card shows.
  2. Venues with no current beer inventory no longer render publicly. A venue counts as stocked when it lists at least one beer under tapBeerSlugs or canBeerSlugs — the same predicate VenueCard uses to render its On Tap / In Can lines. carriesBeerSlugs alone does not count (it produces no visible inventory). Filtering happens at the page data boundary in where-to-buy/page.tsx, before carriedBeerOptions, distinctIslands, and VenueDirectory — so unstocked venues cannot affect counts, island groups, filter options, empty states, or analytics, and cannot be resurrected via query-string filters.

Closes #130

Changes

  • lib/venue-filters.ts — new venueIsStocked helper; hasAnyFormatData now delegates to it.
  • app/(pages)/where-to-buy/page.tsx — venues.filter(venueIsStocked) right after getVenues().
  • app/(pages)/where-to-buy-fixture/page.tsx — same filter so the test route exercises the production rule.
  • components/venue-card.tsx — card root flex h-full flex-col; actions mt-4 → mt-auto pt-4.
  • lib/where-to-buy-fixture.ts — Quiet Cafe now lists pilsner on tap (preserves the Where to Buy fragments Saba venues into multiple sections with lowercase headings #116 three-locality coverage); Bottle Shop gains a website link; new Fixture Empty Cantina (Statia, valid name/location/type/links, zero beer) as the Island Flavor-style regression venue.
  • tests/lib/venue-filters.test.ts — new venueIsStocked describe covering tap-only / can-only / both / neither / carries-only, plus downstream island/group/beer-option exclusion; fixture-based expectations updated.
  • smoke-tests/where-to-buy-filters.spec.ts — new tests: empty venue absent + Statia group/option absent + ?island=statia sanitizes away; action-row top alignment ≤1px at 1280px. Updated counts for Quiet Cafe's new beer.

Verification

  • npm ci
  • npm run check:react-versions — react/react-dom 19.3.0 match
  • npx tsc --noEmit — clean
  • npm run lint — clean (pre-existing TSSatisfiesExpression parser note only)
  • npm test — 355/355 pass
  • npm run test:rules — 29/29 pass
  • npm run build — clean
  • npx playwright test — 123/123 pass (includes 2 new tests)
  • npm run check:md-links — all links resolve
  • npm audit --omit=dev — 0 vulnerabilities
  • Vercel preview reviewed (for UI changes)

Browser-verified at 1280px: Tavern (2 beer lines) and Bottle Shop (1 line) action rows both at y=588 — 0px delta. The new alignment test fails against the old implementation (28px misalignment). At 375px, stacking is natural with no horizontal overflow.

Risk / deployment notes

  • No production Firestore data changed — this is a display rule; unstocked venues still exist in the collection and in admin.
  • If every public venue were unstocked, the page falls back to the existing "No partner locations are listed right now" state.
  • Analytics unchanged — hidden venues simply emit nothing because they don't render.
  • No secrets, credentials, or private data were committed.

Generated with Devin

Summary by Sourcery

Hide venues without visible beer inventory and align venue card actions across grid rows.

New Features:

  • Hide public venues that have no beer listed under On Tap or In Can formats.
  • Align venue action links consistently across cards in the venue grid.

Bug Fixes:

  • Prevent unstocked venues from contributing to island groups, beer filters, venue counts, empty states, or query-filter results.

Enhancements:

  • Centralize the stocked-venue predicate for consistent filtering across production pages and tests.

Tests:

  • Add unit and smoke coverage for stocked-venue filtering, downstream filter exclusion, query-string behavior, and action-row alignment.

Exclude venues with no On Tap or In Can beer at the /where-to-buy page
boundary so they never reach grouping, filter options, or counts — a
venue showing no inventory (e.g. Island Flavor) no longer renders.

Bottom-align card action rows with a flex column + mt-auto so buttons
line up across a grid row regardless of beer-list length.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@vercel

vercel Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated
deepdivebrewing-web Ready Ready Preview Sep 24, 2026 1:23pm UTC

Request Review

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @spizeck, this account has used its review budget of 1,500,000 diff characters for the last 7 days.

You can request another review in 46 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Sep 24, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR centralizes a format-based stocked-venue rule and applies it at the public page data boundary, preventing empty venues from affecting rendering or derived filters, while updating fixture/test coverage and making venue action rows bottom-align across cards of different content heights.

Sequence diagram for public venue directory data preparation

sequenceDiagram
    participant Page as WhereToBuyPage
    participant VenueSource as getVenues
    participant Filter as venueIsStocked
    participant Options as carriedBeerOptions
    participant Islands as distinctIslands
    participant Directory as VenueDirectory

    Page->>VenueSource: getVenues()
    VenueSource-->>Page: fetchedVenues
    Page->>Filter: venueIsStocked(venue)
    Filter-->>Page: stocked venues
    Page->>Options: carriedBeerOptions(venues, beers)
    Page->>Islands: distinctIslands(venues)
    Page->>Directory: render filtered venues and derived data
Loading

Flow diagram for stocked venue filtering

flowchart LR
    A[getVenues] --> B[venueIsStocked]
    B -->|tapBeerSlugs or canBeerSlugs present| C[Public venues]
    B -->|neither format has beer| D[Excluded venues]
    C --> E[carriedBeerOptions]
    C --> F[distinctIslands]
    C --> G[VenueDirectory]
    D -.-> H[No public rendering or derived filters]
Loading

File-Level Changes

Change Details Files
Centralize and apply the public stocked-venue predicate before deriving any page data.
  • Added venueIsStocked, based only on tap and can beer slugs, and reused it from hasAnyFormatData.
  • Filtered production and fixture venue lists immediately after loading them.
  • Added unit coverage for format combinations, carries-only venues, and downstream island, group, option, and count exclusion.
lib/venue-filters.ts
app/(pages)/where-to-buy/page.tsx
app/(pages)/where-to-buy-fixture/page.tsx
tests/lib/venue-filters.test.ts
Align venue card action rows within grid rows while preserving natural mobile stacking.
  • Made card containers full-height flex columns.
  • Used an auto top margin and padding on the action wrapper to push actions to the card bottom.
  • Added a 1280px browser regression check for cards with different inventory heights.
components/venue-card.tsx
smoke-tests/where-to-buy-filters.spec.ts
Expand and adjust fixture coverage to exercise stocked and unstocked venue behavior.
  • Added inventory to Quiet Cafe to preserve multi-locality Saba coverage.
  • Added a website link to Bottle Shop for action-row comparison.
  • Added an empty Statia venue with valid metadata and links to verify it is excluded publicly.
  • Updated smoke-test expectations and added checks for hidden venue, absent island/filter option, query sanitization, and action alignment.
lib/where-to-buy-fixture.ts
smoke-tests/where-to-buy-filters.spec.ts
tests/lib/venue-filters.test.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#130 Make venue card action rows align at the bottom across cards in the same grid row without fixed or copy-dependent heights. ✅
#130 Exclude publicly displayed venues that have no beer in either tapBeerSlugs or canBeerSlugs, treating at least one entry in either list as stocked. ✅
#130 Apply the stocked-venue exclusion before island grouping, filter-option generation, counts, rendering, and query-string filtering, while preserving existing analytics behavior. ✅

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@spizeck
spizeck merged commit 67d3f89 into main Sep 24, 2026
4 checks passed
@spizeck
spizeck deleted the fix/venue-cards-130 branch September 24, 2026 13:57

This branch was successfully deployed

1 active deployment
Preview — 184b84c2 Deployed Sep 24, 2026 by vercel[bot]
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.

Align venue card actions and hide venues with no current beer inventory

1 participant