Skip to content

Winebob updates#6

Open
cphrealestate wants to merge 408 commits intoAustin1serb:mainfrom
cphrealestate:main
Open

Winebob updates#6
cphrealestate wants to merge 408 commits intoAustin1serb:mainfrom
cphrealestate:main

Conversation

@cphrealestate
Copy link
Copy Markdown

No description provided.

@cphrealestate
Copy link
Copy Markdown
Author

d

1 similar comment
@cphrealestate
Copy link
Copy Markdown
Author

d

cphrealestate and others added 28 commits April 7, 2026 17:09
…-cGspg

feat: /explore page — map preview with signup CTA overlay
Replace vertical explore badge + city stack with clean horizontal
pill bar in the same position as filter pills:

[← Piedmont] [Barolo] [Barbaresco] [Asti] [Alba]

- Region name as first cherry pill with ← arrow (tap = back to world)
- Cities as dark glass pills (tap = fly to city)
- Horizontal scroll if many cities
- Replaces filter pills when exploring (same position, swaps)
- No more "EXPLORING" badge, no vertical stack
- Same pattern on both desktop and mobile

Desktop: pills at bottom of map
Mobile: pills under search bar (where filter pills normally are)

https://claude.ai/code/session_01EB6Vp51HXDch3sCNXXLKdj
…-cGspg

fix: hide region polygons when exploring — use setPaintProperty opaci…
Root causes:
1. setPaintProperty ran before map layers were loaded (mapLoaded ref)
2. flyToCoords and exploreRegion effects fought each other

Fixes:
- mapLoaded ref tracks when on("load") fires
- setRegionVisibility helper function with try/catch
- prevExploreRef prevents re-triggering on same region
- flyToCoords effect is completely separate from explore effect
- flyToCoords only does flyTo, never touches region visibility
- exploreRegion only runs when region actually changes

https://claude.ai/code/session_01EB6Vp51HXDch3sCNXXLKdj
…-cGspg

design: city hopping as horizontal pill bar, remove explore badge
Run: DATABASE_URL=... npx tsx prisma/seed-wines.ts

Wines by region:
- France: Bordeaux (10), Burgundy (6), Champagne (4), Rhône (3), Loire (2)
- Italy: Piedmont (5), Tuscany (5), Veneto (2), Sicily (2)
- Spain: Rioja (4), Ribera (2), Priorat (1)
- Portugal: Douro (3), Alentejo (2)
- Germany: Mosel (3), Rheingau (1)
- USA: Napa (6), Sonoma (2), Oregon (2)
- Argentina: Mendoza (4)
- Chile: Maipo/Colchagua (4)
- Australia: Barossa (3), Margaret River (2)
- New Zealand: Marlborough (3)
- South Africa: Stellenbosch (4)

All real producers: Château Margaux, DRC, Dom Pérignon, Sassicaia,
Penfolds Grange, Opus One, Vega Sicilia, etc.

Uses findFirst to skip duplicates on re-run.

https://claude.ai/code/session_01EB6Vp51HXDch3sCNXXLKdj
Added 69 more wines:
- More Bordeaux Super Seconds (Cos d'Estournel, Palmer, Ducru)
- More Burgundy (Armand Rousseau, Bonneau du Martray, William Fèvre)
- More Rhône (Chave, Chapoutier, Guigal La Mouline)
- Alsace (Trimbach, Zind-Humbrecht) + Provence rosé
- More Piedmont (Massolino, Aldo Conterno) + Gavi
- More Tuscany (Solaia, Masseto, Flaccianello)
- More Spain (Clos Erasmus, Albariño Pazo de Señorans)
- More Portugal (Quinta do Crasto, Vale Meão, Mouchão)
- More Germany (Molitor, Schloss Johannisberg, von Buhl)
- More USA (Harlan, Scarecrow, Ridge Monte Bello, Beaux Frères)
- More Argentina (Cheval des Andes, Colomé)
- More Chile (Clos Apalta, Errazuriz)
- More Australia (Two Hands, Jim Barry, Tyrrell's)
- More NZ (Felton Road, Kumeu River)
- More SA (Sadie Family Columella + Palladius, Ken Forrester)
- Rest of world: Austria, Greece, Lebanon, Hungary, Georgia

https://claude.ai/code/session_01EB6Vp51HXDch3sCNXXLKdj
Data model:
- New Winery Prisma model: name, slug, description, history,
  founded, owner, coordinates, region, featured (paid), verified,
  visitBooking, annualBottles, vineyardSize, grapeVarieties

Mock data: 18 real wineries across 10 regions:
- Château Margaux, Lafite, Lynch-Bages (Bordeaux)
- DRC, Louis Jadot (Burgundy)
- Dom Pérignon (Champagne)
- Gaja, Giacomo Conterno (Piedmont)
- Tenuta San Guido, Antinori (Tuscany)
- López de Heredia, Vega Sicilia (Spain)
- Opus One, Ridge (USA)
- Quinta do Noval (Portugal)
- Penfolds (Australia)
- Cloudy Bay (New Zealand)
- Kanonkop (South Africa)

Map markers:
- Featured wineries: gold (#C8A255), visible from zoom 5, larger
  circles with white stroke, "★ Featured Winery" in popup
- Regular wineries: cherry (#74070E), visible from zoom 7, smaller
- Labels from zoom 8, gold text for featured, brown for regular
- Click popup: 🏰 icon, name, region, founded year, description

https://claude.ai/code/session_01EB6Vp51HXDch3sCNXXLKdj
Two fixes in WineRegionMap:

1. Region burgundy overlay persisting after zoom: setRegionVisibility now
   sets layout visibility to "none" (not just opacity to 0) on both fill
   and border layers. Also applies visibility on map re-init via ref so
   regions stay hidden if already exploring when map recreates.

2. POI dots not clickable: poiLayers referenced non-existent "poi-winery"
   layer. Changed to actual layer IDs (poi-food, poi-hotel, poi-shops)
   with per-type icons, accent colors, and address display in popups.

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
The explore page city pills had no onClick handlers — clicking them
did nothing. Now they fly the map to the selected city coordinates
with active state highlighting. Also reset city/flyTo state properly
on region change and world view return.

Removed unused onCityClick prop from WineRegionMap (city hopping
works via flyToCoords).

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
Changed mobile bottom sheet default from "collapsed" (140px card with
featured wine) to "peek" (44px drag handle only). The map is now fully
visible on load. Users swipe up to reveal the wine list (half → full).

The wine card was disrupting the mobile map display by covering a
significant portion of the screen on initial load.

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
Login page was hardcoded to redirect to /arena after every login,
regardless of where the user came from. Now reads callbackUrl from
query params so the redirect matches the user's intent:

- Explore map → login → navigates to /wines (cellar with map)
- Host a tasting → login → navigates to /arena (via middleware)
- Direct login → defaults to /arena

Updated explore page sign-up/login links to pass callbackUrl=/wines.
OAuth buttons (Google/Apple) also use the dynamic callbackUrl.

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
1. Wrap useSearchParams() in Suspense boundary to fix Next.js 16
   prerender error on /login page.

2. Remove setSheet("half") from onRegionClick so the wine list
   stays hidden when tapping a region on mobile — map stays
   full-screen, user swipes up only when they want the list.

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
Phase 1: Fix map re-initialization on prop changes
- Moved regionCounts and onRegionClick into refs so the map
  useEffect has [] deps. Previously the entire map (WebGL context,
  tiles, layers) was destroyed and recreated whenever regionCounts
  changed — the single biggest performance issue.

Phase 2: Single map instance on wines page
- Desktop and mobile now share one <WineRegionMap> instead of
  rendering two separate instances. Halves tile requests, GPU
  memory, and WebGL contexts.

Phase 3: GPU-accelerated bottom sheet animation
- Replaced height animation (triggers layout reflow every frame)
  with transform: translateY() (compositor thread, 60fps).

Phase 4: Disable 3D terrain on mobile
- Terrain (DEM tiles + draping passes) skipped on touch devices
  and small screens to save GPU and battery.

Phase 5: Popup mousemove optimization
- setHTML() only called when hovered feature changes, not on
  every pixel of mouse movement. setLngLat() (cheap CSS transform)
  still updates position every frame.

All optimizations verified against Mapbox official docs, GitHub
issues, and web performance standards.

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- Double dot radius at all zoom levels (3→9px, was 1.5→7px)
- Increase opacity (0.6→1.0, was 0.3→0.8) with white stroke rings
- Show labels at zoom 10 instead of 11, with darker text and white halos
- Lower wine shops minzoom to 8 (was 9)
- Use DIN Pro Medium font for better label legibility

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- Replace custom inline style with Mapbox Standard Style (3D buildings,
  dynamic lighting, fog/atmosphere, globe view — all included for free)
- Use slot system: wine regions in 'bottom', POI dots in 'middle',
  labels in 'top' for proper z-ordering with Standard's built-in layers
- Add emissive-strength to all custom layers for correct appearance
  under Standard's lighting engine
- Add cinematic tour feature: camera sweeps through a region's sub-cities
  with rotating bearing, 60° pitch, and smooth flyTo animations
- Tour is abortable (AbortController) and auto-cleans up
- Add tour UI button in explore page (Play/Stop toggle)
- Increase maxZoom to 17 (Standard supports detailed zoom)
- Use 'dawn' light preset for warm wine-country feel

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- Fix build: replace mapboxgl.FlyToOptions (not exported) with
  Parameters<mapboxgl.Map["flyTo"]>[0]
- Add satellite prop to WineRegionMap: swaps between Standard and
  Standard Satellite via setStyle, custom layers re-added on style.load
- Refactor layer setup into addCustomLayers() for reuse after style swap
- Add satellite/map toggle button in explore page top-right
- Guard addSource/addLayer with getSource/getLayer checks for idempotency

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- Add explicit mapbox-streets-v8 source ("wb-streets") for POI data —
  Standard's "composite" source doesn't reliably expose poi_label for
  custom layers
- Turn off Standard's built-in POI labels and road labels to reduce
  clutter — we render our own wine-relevant POIs
- Move POI dots to "top" slot so they render above Standard's buildings
- Increase dot sizes (4→12px range, was 3→9px) and stroke widths
- Use DIN Pro Bold for POI labels with larger sizes
- Boost wine region fill opacity (0.35 base, was 0.25) and border width
  (2px base, was 1.5px) so regions pop against Standard's rich base map
- Move region fill/border to "middle" slot for better visibility
- Increase region label sizes and opacity for world-view legibility

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
The tour and satellite features were only on /explore but the user
primarily uses /wines. Added to both mobile and desktop layouts:

- Satellite toggle button next to search bar (mobile) and in top-left (desktop)
- "Tour" pill button in city hopping bar when exploring a region
- Tour auto-stops when clicking a city or leaving the region
- All props wired through to WineRegionMap

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- Track activeCity state for highlighted city pill
- Reset city/tour state on region change and back-to-world
- City pills now highlight cherry when active (matching explore page)
- Full feature parity: tour, satellite, city hopping, active highlight

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
Tour button and city hopping pills only appeared for regions with
sub-cities defined. Added sub-cities for all 18 missing regions:
Loire Valley, Rhone Valley, Alsace, Provence, Veneto, Sicily,
Ribera del Duero, Priorat, Alentejo, Rheingau, Sonoma,
Willamette Valley, Mendoza, Maipo Valley, Colchagua Valley,
Barossa Valley, Margaret River, Marlborough, Stellenbosch

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
…or all 27 regions

Expand TourStop type with tagline, grapes[], and notableWines[] fields.
Each sub-city across all 27 wine regions now has curated content for
cinematic tour stops.

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- New TourInfoCard component: shows stop name, tagline, grape pills,
  notable wines, and "Explore wines" deep link during cinematic tours
- Tour pacing: 3.5s flight duration, 5.5s dwell at each stop (was 2.5s/1.5s)
- Card fades in after camera settles, clears before next flight
- onTourStop callback fires with TourStop data or null (in-flight)
- Wired up in both explore page and wines page (desktop + mobile)

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
Layer System:
- MapLayerDrawer: FAB + expandable panel with grouped layer toggles
- useMapLayers hook: state management with localStorage persistence
- Mutual exclusion for "heavy-overlay" layers (weather/flavor genome)
- 4 layers defined: Vintage Weather, Flavor Genome, Live Activity, Draw Flight

New Prisma Models:
- WineTasting: personal tasting log with ratings
- WineWishlist: wines to try next
- ProducerFollow: favorite producers
- TastingFlight: saved drawn flight paths
- WineCheckIn: live heatmap drinking sessions
- RegionFlavorProfile: 6-axis flavor data per region

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
- My Cellar: horizontal scroll of favorited wines with type color bars
- Taste Profile: wine type distribution bar + top grapes from favorites
- Tasting History: recent events with status badges and guest counts
- Wishlist: horizontal scroll (from new WineWishlist model, graceful fallback)
- Regions Explored: progress bar showing X/27 regions with region pills
- Settings: collapsible section to reduce default page length
- Fetch createdAt from User model for "Member since" display
- New model queries wrapped in try/catch for pre-migration safety

https://claude.ai/code/session_01D2q8p4zqEdfUWbBu5iMNrd
cphrealestate and others added 30 commits April 9, 2026 14:49
…apbox-qwuDI

feat(vintage-weather): add wine picker directly in weather layer
React.useMemo for vintageWines was placed AFTER `if (!active) return null`,
violating Rules of Hooks. When the layer was deactivated, the hook was
skipped, causing React to crash with a hooks ordering mismatch.

Move the useMemo above the early return so hooks are always called in
the same order regardless of the active state.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(vintage-weather): move useMemo above early return to fix crash
The wine picker in VintageWeatherLayer was empty because closing the
RegionDetailPanel set regionDetail to null, which cleared the wines
data passed to the weather layer.

Fix: separate panel visibility (showRegionPanel) from the data
(regionDetail). Closing the panel now only hides it — the wine data
stays available for the weather layer's picker.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(vintage-weather): preserve wine data when region panel is closed
When zoomed into wine regions, premium wineries now appear as
highlighted polygon areas on the map with gold borders and labels.
Clicking one opens a rich, slideable detail card.

Château Margaux (Bordeaux, Premier Grand Cru Classé) is the first
showcase entry with:
- Estate polygon marking the château grounds
- 5-page slideable card (Estate, Terroir, Winemaking, Visit, Wines)
- Stats grid on each page (classification, soil, grape %, aging, etc.)
- Individual wine cards with ratings and descriptions
- Swipe + arrow key navigation between pages
- Page indicator dots
- Fly-to animation on click (zoom 15, pitch 60)

The polygon layers fade in starting at zoom 13 and become prominent
at zoom 15+, so they don't clutter the zoomed-out view.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

feat(map): add winery showcase layer with Château Margaux
The wine picker was always empty because it depended on regionDetail
which gets nulled when the RegionDetailPanel is closed.

Fix: VintageWeatherLayer now fetches wines directly from a new
GET /api/wines?region=X endpoint when active. This makes the wine
picker self-contained — it works regardless of panel state.

New: /api/wines API route returning wines by region (id, name,
producer, vintage, type). Cached 5 min.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

feat(map): add winery showcase layer with Château Margaux
Polygon was ~700m northwest of the actual château. Updated center
and polygon vertices to match the real coordinates from mockWineries
(lat: 45.0444, lng: -0.6687).

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
Two bugs preventing the showcase layer from appearing:

1. No map-readiness polling: useEffect checked mapRef.current once,
   got null (map not yet created), and never retried. Added polling
   with setInterval like FlavorGenomeLayer does.

2. No slot:top: In Mapbox Standard style, custom layers without a
   slot render under 3D buildings. Added slot:"top" to fill, border,
   and label layers so they appear above everything.

Also: brighter gold fill color + higher opacity for better visibility.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

Claude/fix flavor genome mapbox qwu di
…ndering

The standalone WineryShowcaseLayer couldn't reliably add Mapbox layers
because it ran outside the map's initialization lifecycle. Layers were
either added too early (map not ready) or rendered below the basemap.

Fix: move showcase source + layers into WineRegionMap's addCustomLayers()
which is called at the correct time during map initialization. This uses
the exact same pattern as wine-regions and wineries layers (which work).

WineryShowcaseLayer now only handles click interaction and the detail
card UI — it polls for the "showcase-fill" layer to exist, then
attaches click/hover handlers.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(showcase): move layer creation into WineRegionMap for reliable re…
Build failed because showcase code was placed outside addCustomLayers()
where 'm' parameter doesn't exist (it used map.current instead).
Moved the showcase source+layers into the correct function body and
removed the duplicate code from the outer scope.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(showcase): move layers into addCustomLayers(m) function body
The WineryShowcaseLayer click handler never attached because it tried
to find the "showcase-fill" layer from outside the map lifecycle.

Fix: move all click/hover handling into WineRegionMap alongside the
existing winery click handlers (same proven pattern). WineRegionMap
now accepts onShowcaseClick callback, ExploreClient manages the
selected showcase winery state, and WineryShowcaseLayer is reduced
to a pure UI component that just renders the detail card.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(showcase): move click handler into WineRegionMap for reliable events
Two Props types existed: the old one (mapRef) at line 14 shadowed
the new one (selectedId, onClose) at line 255. Removed the old one
and cleaned up unused imports.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

Claude/fix flavor genome mapbox qwu di
Two bugs fixed:

1. Click handler never fired: was set up OUTSIDE style.load callback,
   before the showcase-fill layer existed. Mapbox ignores handlers for
   non-existent layers. Moved click/hover handlers INSIDE addCustomLayers
   right after layer creation.

2. Labels repeated 6x: polygon source + symbol layer = Mapbox places
   labels at each tile boundary. Created separate point source
   (showcase-labels) using winery center coordinates for single labels.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(showcase): fix click handler timing + deduplicate labels
The winery circle marker sat on top of the showcase polygon, capturing
clicks and showing the generic popup instead of the showcase card.

Fix: in the winery click handler, check if the clicked winery matches
a showcase entry (by slug or name). If so, fire onShowcaseClick and
return early — skipping the generic popup entirely.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(showcase): redirect winery marker clicks to showcase card
The experience/tasting popup (€250 badge) was also intercepting
clicks at Château Margaux. Added the same showcase redirect in
the experiences-badge click handler: if the experience's wineryName
matches a showcase winery, open the showcase card instead.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

fix(showcase): redirect experience badge clicks to showcase card
Match showcase wineries by winerySlug (more reliable than name
matching which can fail due to encoding differences).

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
Instead of hijacking clicks from winery markers and experience badges,
showcase wineries now show a radial fan-out menu with 3 options:

- ★ Estate Tour → opens the showcase detail card (slideable pages)
- 🍷 View Wines → navigates to /producers/{slug}
- 📍 Book Tasting → navigates to /experiences?search={name}

The fan menu appears centered on the map when clicking the showcase
polygon. Each button fans out at -50°, 0°, +50° with a staggered
pop-in animation. Clicking outside dismisses the menu.

Removed all the redirect hacks from winery/experience click handlers
since they're no longer needed — each handler works independently.

https://claude.ai/code/session_0122SL18zrThTnKPo4rGqV5Z
…apbox-qwuDI

Claude/fix flavor genome mapbox qwu di
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.

2 participants