Skip to content

Hero Card Category Icon โ€‹

Date: 2026-03-30 Status: Approved Related: PR #322, Issue #323

Problem โ€‹

The HeroOfferCard has a 56x56 icon area on the right side that displays a hardcoded <Flame> lucide-react icon. This was a scaffold placeholder with no documented intent. The icon should be meaningful and data-driven.

Decision โ€‹

Replace the static Flame icon with a venue category icon mapped from offer.venue.category. This leverages existing venue data with no new form fields or data requirements.

Future options (venue photo upload, lantern count) are tracked in Issue #323 as a merchant-configurable per-offer setting, conditional on hero placement.

Design โ€‹

Category Icon Mapping โ€‹

A categoryIconMap already exists in VenuesMap.jsx (lines 698-711) mapping venue categories to lucide-react icons (Coffee, Beer, Utensils, etc.). This map is currently not exported.

Approach: Extract the map into a shared utility so both VenuesMap and HeroOfferCard can use it.

  • New export from apps/web/src/lib/venueConfig.js: getCategoryIcon(category) โ€” returns a lucide-react icon component
  • Returns Flame as fallback (preserves the amber/lantern motif when category is unknown)
  • VenuesMap.jsx imports from venueConfig.js instead of defining its own local copy

Icon Mapping โ€‹

CategoryIconLucide Component
cafe, coffee_shopCoffee cupCoffee
bar, pubBeer glassBeer
food, restaurantFork/knifeUtensils
activitiesGamepadGamepad2
libraryBookBookOpen
music, shopMusic noteMusic
(fallback)FlameFlame

Components Changed โ€‹

  1. apps/web/src/lib/venueConfig.js โ€” Add getCategoryIcon(category) export with the icon map
  2. apps/web/src/components/dashboard/OfferCards.jsx โ€” HeroOfferCard calls getCategoryIcon(offer.venue?.category) instead of hardcoding <Flame>
  3. apps/web/src/components/VenuesMap.jsx โ€” Replace local categoryIconMap / getCategoryIcon with import from venueConfig.js
  4. apps/web/src/lib/offerNormalizer.js โ€” Add category to the preview venue object (e.g. category: 'cafe') so the preview renders a meaningful icon

Preview Behavior โ€‹

In the merchant OfferForm preview, the hero card shows the fallback icon (Flame) since the preview venue doesn't have a real category. This is acceptable โ€” the merchant will see the actual category icon in production. The offerNormalizer can optionally accept a category override via options.venue.category.

Fallback Chain โ€‹

offer.venue.category โ†’ getCategoryIcon() โ†’ matched lucide icon, or Flame if unrecognized/missing.

Out of Scope โ€‹

  • New form fields (no "Card icon" selector โ€” deferred to Issue #323)
  • Venue photo upload or lantern count display
  • Changes to non-hero placements (inline, chat, feed don't have this icon area)

Built with VitePress