fix: Navigation now uses actual current location

Pass current location from useLocationSharing hook to navigateTo
instead of using stale data from the Zustand store. This fixes the
"Enable location sharing to get directions" error when already sharing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-29 02:46:07 +01:00
parent b8adffc4ad
commit 1dddf16c6a
3 changed files with 55 additions and 24 deletions

View File

@ -2,7 +2,7 @@
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import type { Participant, MapViewport, Waypoint } from '@/types'; import type { Participant, MapViewport, Waypoint, ParticipantLocation } from '@/types';
import { isInC3NavArea } from '@/lib/c3nav'; import { isInC3NavArea } from '@/lib/c3nav';
import { useRoomStore } from '@/stores/room'; import { useRoomStore } from '@/stores/room';
import NavigationPanel from './NavigationPanel'; import NavigationPanel from './NavigationPanel';
@ -32,7 +32,7 @@ interface DualMapViewProps {
participants: Participant[]; participants: Participant[];
waypoints?: Waypoint[]; waypoints?: Waypoint[];
currentUserId?: string; currentUserId?: string;
currentLocation?: { latitude: number; longitude: number } | null; currentLocation?: ParticipantLocation | null;
eventId?: string; eventId?: string;
initialMode?: MapMode; initialMode?: MapMode;
onParticipantClick?: (participant: Participant) => void; onParticipantClick?: (participant: Participant) => void;
@ -152,6 +152,10 @@ export default function DualMapView({
<NavigationPanel <NavigationPanel
selectedParticipant={selectedParticipant} selectedParticipant={selectedParticipant}
selectedWaypoint={selectedWaypoint} selectedWaypoint={selectedWaypoint}
currentLocation={currentLocation}
allParticipants={participants}
waypoints={waypoints}
currentUserId={currentUserId}
onClose={closeNavigationPanel} onClose={closeNavigationPanel}
/> />
)} )}

View File

@ -1,35 +1,53 @@
'use client'; 'use client';
import { useRoomStore } from '@/stores/room'; import { useRoomStore } from '@/stores/room';
import type { Participant, Waypoint } from '@/types'; import type { Participant, Waypoint, ParticipantLocation } from '@/types';
interface NavigationPanelProps { interface NavigationPanelProps {
selectedParticipant?: Participant | null; selectedParticipant?: Participant | null;
selectedWaypoint?: Waypoint | null; selectedWaypoint?: Waypoint | null;
currentLocation?: ParticipantLocation | null;
allParticipants: Participant[];
waypoints: Waypoint[];
currentUserId?: string;
onClose: () => void; onClose: () => void;
} }
export default function NavigationPanel({ export default function NavigationPanel({
selectedParticipant, selectedParticipant,
selectedWaypoint, selectedWaypoint,
currentLocation,
allParticipants,
waypoints,
currentUserId,
onClose, onClose,
}: NavigationPanelProps) { }: NavigationPanelProps) {
const { navigateTo, activeRoute, clearRoute, currentParticipantId } = useRoomStore(); const { navigateTo, activeRoute, clearRoute } = useRoomStore();
const target = selectedParticipant || selectedWaypoint; const target = selectedParticipant || selectedWaypoint;
if (!target) return null; if (!target) return null;
const isParticipant = !!selectedParticipant; const isParticipant = !!selectedParticipant;
const isSelf = isParticipant && selectedParticipant.id === currentParticipantId; const isSelf = isParticipant && selectedParticipant.id === currentUserId;
const hasLocation = isParticipant const hasLocation = isParticipant
? !!selectedParticipant.location ? !!selectedParticipant.location
: !!selectedWaypoint?.location; : !!selectedWaypoint?.location;
const handleNavigate = () => { const handleNavigate = () => {
if (isParticipant && selectedParticipant) { if (isParticipant && selectedParticipant) {
navigateTo({ type: 'participant', id: selectedParticipant.id }); navigateTo(
{ type: 'participant', id: selectedParticipant.id },
currentLocation || undefined,
allParticipants,
waypoints
);
} else if (selectedWaypoint) { } else if (selectedWaypoint) {
navigateTo({ type: 'waypoint', id: selectedWaypoint.id }); navigateTo(
{ type: 'waypoint', id: selectedWaypoint.id },
currentLocation || undefined,
allParticipants,
waypoints
);
} }
}; };

View File

@ -65,7 +65,12 @@ interface RoomState {
removeWaypoint: (waypointId: string) => void; removeWaypoint: (waypointId: string) => void;
// Route actions // Route actions
navigateTo: (target: { type: 'participant' | 'waypoint'; id: string }) => Promise<void>; navigateTo: (
target: { type: 'participant' | 'waypoint'; id: string },
currentLocation: ParticipantLocation | undefined,
allParticipants: Participant[],
waypoints: Waypoint[]
) => Promise<void>;
clearRoute: () => void; clearRoute: () => void;
// Internal // Internal
@ -192,12 +197,16 @@ export const useRoomStore = create<RoomState>((set, get) => ({
set({ room: { ...room } }); set({ room: { ...room } });
}, },
navigateTo: async (target: { type: 'participant' | 'waypoint'; id: string }) => { navigateTo: async (
const { participants, room, currentParticipantId } = get(); target: { type: 'participant' | 'waypoint'; id: string },
currentLocation: ParticipantLocation | undefined,
allParticipants: Participant[],
allWaypoints: Waypoint[]
) => {
const { room } = get();
// Get current user's location // Check current user's location (passed from hook, not store)
const currentUser = participants.find((p) => p.id === currentParticipantId); if (!currentLocation) {
if (!currentUser?.location) {
set({ set({
activeRoute: { activeRoute: {
id: nanoid(), id: nanoid(),
@ -214,12 +223,12 @@ export const useRoomStore = create<RoomState>((set, get) => ({
return; return;
} }
// Get destination // Get destination from passed participants/waypoints (not stale store data)
let destLocation: { latitude: number; longitude: number; indoor?: { level: number; x: number; y: number } } | null = null; let destLocation: { latitude: number; longitude: number; indoor?: { level: number; x: number; y: number } } | null = null;
let destName = ''; let destName = '';
if (target.type === 'participant') { if (target.type === 'participant') {
const participant = participants.find((p) => p.id === target.id); const participant = allParticipants.find((p) => p.id === target.id);
if (participant?.location) { if (participant?.location) {
destLocation = { destLocation = {
latitude: participant.location.latitude, latitude: participant.location.latitude,
@ -229,7 +238,7 @@ export const useRoomStore = create<RoomState>((set, get) => ({
destName = participant.name; destName = participant.name;
} }
} else if (target.type === 'waypoint') { } else if (target.type === 'waypoint') {
const waypoint = room?.waypoints.find((w) => w.id === target.id); const waypoint = allWaypoints.find((w) => w.id === target.id);
if (waypoint) { if (waypoint) {
destLocation = { destLocation = {
latitude: waypoint.location.latitude, latitude: waypoint.location.latitude,
@ -244,7 +253,7 @@ export const useRoomStore = create<RoomState>((set, get) => ({
set({ set({
activeRoute: { activeRoute: {
id: nanoid(), id: nanoid(),
from: { type: 'current', name: currentUser.name }, from: { type: 'current', name: 'You' },
to: { type: target.type, id: target.id, name: destName || 'Unknown' }, to: { type: target.type, id: target.id, name: destName || 'Unknown' },
segments: [], segments: [],
totalDistance: 0, totalDistance: 0,
@ -261,7 +270,7 @@ export const useRoomStore = create<RoomState>((set, get) => ({
set({ set({
activeRoute: { activeRoute: {
id: nanoid(), id: nanoid(),
from: { type: 'current', name: currentUser.name }, from: { type: 'current', name: 'You' },
to: { type: target.type, id: target.id, name: destName }, to: { type: target.type, id: target.id, name: destName },
segments: [], segments: [],
totalDistance: 0, totalDistance: 0,
@ -277,9 +286,9 @@ export const useRoomStore = create<RoomState>((set, get) => ({
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({
origin: { origin: {
latitude: currentUser.location.latitude, latitude: currentLocation.latitude,
longitude: currentUser.location.longitude, longitude: currentLocation.longitude,
indoor: currentUser.location.indoor, indoor: currentLocation.indoor,
}, },
destination: destLocation, destination: destLocation,
mode: 'walking', mode: 'walking',
@ -293,7 +302,7 @@ export const useRoomStore = create<RoomState>((set, get) => ({
set({ set({
activeRoute: { activeRoute: {
id: nanoid(), id: nanoid(),
from: { type: 'current', name: currentUser.name }, from: { type: 'current', name: 'You' },
to: { type: target.type, id: target.id, name: destName }, to: { type: target.type, id: target.id, name: destName },
segments: data.route.segments, segments: data.route.segments,
totalDistance: data.route.totalDistance, totalDistance: data.route.totalDistance,
@ -306,7 +315,7 @@ export const useRoomStore = create<RoomState>((set, get) => ({
set({ set({
activeRoute: { activeRoute: {
id: nanoid(), id: nanoid(),
from: { type: 'current', name: currentUser.name }, from: { type: 'current', name: 'You' },
to: { type: target.type, id: target.id, name: destName }, to: { type: target.type, id: target.id, name: destName },
segments: [], segments: [],
totalDistance: 0, totalDistance: 0,
@ -322,7 +331,7 @@ export const useRoomStore = create<RoomState>((set, get) => ({
set({ set({
activeRoute: { activeRoute: {
id: nanoid(), id: nanoid(),
from: { type: 'current', name: currentUser.name }, from: { type: 'current', name: 'You' },
to: { type: target.type, id: target.id, name: destName }, to: { type: target.type, id: target.id, name: destName },
segments: [], segments: [],
totalDistance: 0, totalDistance: 0,