From 908767be153eec91844bc4089e002e07b39214a9 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Mon, 29 Dec 2025 03:03:16 +0100 Subject: [PATCH] feat: Show navigation panel when clicking user from list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When clicking a user from the participant list: 1. Map zooms to their location 2. Navigation panel appears with "Navigate here" option 3. Clicking "Navigate here" calculates route to that user The selectedParticipant state is now lifted to the page level and passed to DualMapView so both components stay in sync. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/app/[slug]/page.tsx | 4 +++- src/components/map/DualMapView.tsx | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/app/[slug]/page.tsx b/src/app/[slug]/page.tsx index 111cd86..d5f60ec 100644 --- a/src/app/[slug]/page.tsx +++ b/src/app/[slug]/page.tsx @@ -336,9 +336,11 @@ export default function RoomPage() { isSharing={isSharing} onToggleSharing={handleToggleSharing} zoomToLocation={zoomToLocation} + selectedParticipant={selectedParticipant} + onSelectedParticipantChange={setSelectedParticipant} onParticipantClick={(p) => { setSelectedParticipant(p); - setShowParticipants(true); + setShowParticipants(false); // Hide list to show map with navigation panel }} onWaypointClick={(w) => { setSelectedWaypoint(w); diff --git a/src/components/map/DualMapView.tsx b/src/components/map/DualMapView.tsx index c092377..205b9a1 100644 --- a/src/components/map/DualMapView.tsx +++ b/src/components/map/DualMapView.tsx @@ -44,6 +44,10 @@ interface DualMapViewProps { onToggleSharing?: () => void; /** Location to zoom/fly to */ zoomToLocation?: { latitude: number; longitude: number } | null; + /** Selected participant (for navigation panel) */ + selectedParticipant?: Participant | null; + /** Callback when selected participant changes */ + onSelectedParticipantChange?: (participant: Participant | null) => void; } // CCC venue bounds (Hamburg Congress Center) @@ -67,10 +71,15 @@ export default function DualMapView({ isSharing = false, onToggleSharing, zoomToLocation, + selectedParticipant: selectedParticipantProp, + onSelectedParticipantChange, }: DualMapViewProps) { const [mode, setMode] = useState(initialMode); const [activeView, setActiveView] = useState<'outdoor' | 'indoor'>('outdoor'); - const [selectedParticipant, setSelectedParticipant] = useState(null); + // Use prop if provided, otherwise manage internally + const [selectedParticipantInternal, setSelectedParticipantInternal] = useState(null); + const selectedParticipant = selectedParticipantProp !== undefined ? selectedParticipantProp : selectedParticipantInternal; + const setSelectedParticipant = onSelectedParticipantChange || setSelectedParticipantInternal; const [selectedWaypoint, setSelectedWaypoint] = useState(null); // Get route state from store @@ -107,20 +116,20 @@ export default function DualMapView({ setSelectedParticipant(participant); setSelectedWaypoint(null); onParticipantClick?.(participant); - }, [onParticipantClick]); + }, [onParticipantClick, setSelectedParticipant]); // Handle waypoint click - show navigation panel const handleWaypointClick = useCallback((waypoint: Waypoint) => { setSelectedWaypoint(waypoint); setSelectedParticipant(null); onWaypointClick?.(waypoint); - }, [onWaypointClick]); + }, [onWaypointClick, setSelectedParticipant]); // Close navigation panel const closeNavigationPanel = useCallback(() => { setSelectedParticipant(null); setSelectedWaypoint(null); - }, []); + }, [setSelectedParticipant]); return (