|
@@ -2,17 +2,16 @@
|
|
|
|
|
|
|
|
import { useEffect, useRef, useState, useCallback } from 'react'
|
|
import { useEffect, useRef, useState, useCallback } from 'react'
|
|
|
|
|
|
|
|
-/** Константа-идентификатор маркера посетителя */
|
|
|
|
|
-const VISITOR_MARKER_ID = 'visitor-me'
|
|
|
|
|
import { createYandexMapProvider, type MapProvider, type MapBounds } from '@/lib/map'
|
|
import { createYandexMapProvider, type MapProvider, type MapBounds } from '@/lib/map'
|
|
|
import { useAuth } from '@/hooks/useAuth'
|
|
import { useAuth } from '@/hooks/useAuth'
|
|
|
|
|
+import { useWebSocket } from '@/hooks/useWebSocket'
|
|
|
import type { Place } from '@/types'
|
|
import type { Place } from '@/types'
|
|
|
import { api } from '@/lib/api'
|
|
import { api } from '@/lib/api'
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Основной компонент карты. Инициализирует Яндекс.Карту, загружает места,
|
|
* Основной компонент карты. Инициализирует Яндекс.Карту, загружает места,
|
|
|
* отображает маркеры и показывает карточку места при клике.
|
|
* отображает маркеры и показывает карточку места при клике.
|
|
|
- * Для неавторизованных пользователей каждую минуту обновляет геолокацию.
|
|
|
|
|
|
|
+ * Для неавторизованных пользователей через WebSocket показывает точки других посетителей на карте.
|
|
|
*/
|
|
*/
|
|
|
export default function MapView() {
|
|
export default function MapView() {
|
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
@@ -84,26 +83,20 @@ export default function MapView() {
|
|
|
}
|
|
}
|
|
|
}, [places])
|
|
}, [places])
|
|
|
|
|
|
|
|
- /** Добавляет/обновляет маркер геолокации посетителя. Удаляет старый перед созданием нового. */
|
|
|
|
|
- const handleAddVisitorDot = useCallback(() => {
|
|
|
|
|
- if (!mapRef.current || !navigator.geolocation) return
|
|
|
|
|
- navigator.geolocation.getCurrentPosition((pos) => {
|
|
|
|
|
- const provider = mapRef.current
|
|
|
|
|
- if (!provider) return
|
|
|
|
|
- provider.removeMarker(VISITOR_MARKER_ID)
|
|
|
|
|
- provider.addMarker(VISITOR_MARKER_ID, pos.coords.latitude, pos.coords.longitude, {
|
|
|
|
|
- type: 'visitor',
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }, [])
|
|
|
|
|
|
|
+ const { visitors } = useWebSocket(!user)
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
- if (!user) {
|
|
|
|
|
- handleAddVisitorDot()
|
|
|
|
|
- const interval = setInterval(handleAddVisitorDot, 60000)
|
|
|
|
|
- return () => clearInterval(interval)
|
|
|
|
|
|
|
+ if (!mapRef.current) return
|
|
|
|
|
+ const provider = mapRef.current
|
|
|
|
|
+
|
|
|
|
|
+ visitors.forEach((v, i) => {
|
|
|
|
|
+ provider.addMarker(`ws-visitor-${i}`, v.lat, v.lng, { type: 'visitor' })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ visitors.forEach((_, i) => provider.removeMarker(`ws-visitor-${i}`))
|
|
|
}
|
|
}
|
|
|
- }, [user, handleAddVisitorDot])
|
|
|
|
|
|
|
+ }, [visitors])
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<div className="relative h-full w-full">
|
|
<div className="relative h-full w-full">
|