'use client'; import { useState, useEffect, useCallback } from 'react'; import dynamic from 'next/dynamic'; import type { Participant, MapViewport, Waypoint } from '@/types'; import { isInC3NavArea } from '@/lib/c3nav'; import { useRoomStore } from '@/stores/room'; import NavigationPanel from './NavigationPanel'; // Dynamic imports to avoid SSR issues const MapView = dynamic(() => import('./MapView'), { ssr: false, loading: () => , }); const IndoorMapView = dynamic(() => import('./IndoorMapView'), { ssr: false, loading: () => , }); function MapLoading() { return (
Loading map...
); } type MapMode = 'outdoor' | 'indoor' | 'auto'; interface DualMapViewProps { participants: Participant[]; waypoints?: Waypoint[]; currentUserId?: string; currentLocation?: { latitude: number; longitude: number } | null; eventId?: string; initialMode?: MapMode; onParticipantClick?: (participant: Participant) => void; onWaypointClick?: (waypoint: Waypoint) => void; onIndoorPositionSet?: (position: { level: number; x: number; y: number }) => void; /** Whether location sharing is active */ isSharing?: boolean; /** Callback to toggle location sharing */ onToggleSharing?: () => void; } // CCC venue bounds (Hamburg Congress Center) const CCC_BOUNDS = { north: 53.558, south: 53.552, east: 9.995, west: 9.985, }; export default function DualMapView({ participants, waypoints = [], currentUserId, currentLocation, eventId = '38c3', initialMode = 'auto', onParticipantClick, onWaypointClick, onIndoorPositionSet, isSharing = false, onToggleSharing, }: DualMapViewProps) { const [mode, setMode] = useState(initialMode); const [activeView, setActiveView] = useState<'outdoor' | 'indoor'>('outdoor'); const [selectedParticipant, setSelectedParticipant] = useState(null); const [selectedWaypoint, setSelectedWaypoint] = useState(null); // Get route state from store const { activeRoute, clearRoute } = useRoomStore(); // Auto-detect indoor/outdoor based on location useEffect(() => { if (mode !== 'auto' || !currentLocation) return; const isIndoor = isInC3NavArea(currentLocation.latitude, currentLocation.longitude); setActiveView(isIndoor ? 'indoor' : 'outdoor'); }, [mode, currentLocation]); // Manual toggle const toggleView = useCallback(() => { setMode('outdoor'); // Switch to manual mode setActiveView((prev) => (prev === 'outdoor' ? 'indoor' : 'outdoor')); }, []); // Force outdoor const goOutdoor = useCallback(() => { setMode('outdoor'); setActiveView('outdoor'); }, []); // Force indoor const goIndoor = useCallback(() => { setMode('indoor'); setActiveView('indoor'); }, []); // Handle participant click - show navigation panel const handleParticipantClick = useCallback((participant: Participant) => { setSelectedParticipant(participant); setSelectedWaypoint(null); onParticipantClick?.(participant); }, [onParticipantClick]); // Handle waypoint click - show navigation panel const handleWaypointClick = useCallback((waypoint: Waypoint) => { setSelectedWaypoint(waypoint); setSelectedParticipant(null); onWaypointClick?.(waypoint); }, [onWaypointClick]); // Close navigation panel const closeNavigationPanel = useCallback(() => { setSelectedParticipant(null); setSelectedWaypoint(null); }, []); return (
{/* Map view */} {activeView === 'outdoor' ? ( ) : ( )} {/* Navigation panel for selected participant/waypoint */} {(selectedParticipant || selectedWaypoint) && ( )} {/* Location sharing button - floating inside map at bottom right for mobile visibility */} {onToggleSharing && ( )} {/* Indoor Map button - switch to indoor view */} {activeView === 'outdoor' && ( )} {/* Auto-mode indicator */} {mode === 'auto' && (
Auto-detecting location
)} {/* Venue proximity indicator */} {currentLocation && isInC3NavArea(currentLocation.latitude, currentLocation.longitude) && activeView === 'outdoor' && (
You're at the venue!
)}
); }