|
|
@@ -13,7 +13,6 @@ export default function MapView() {
|
|
|
const mapRef = useRef<MapProvider | null>(null)
|
|
|
const { user, isLoading } = useAuth()
|
|
|
const [places, setPlaces] = useState<Place[]>([])
|
|
|
- const [selectedPlace, setSelectedPlace] = useState<Place | null>(null)
|
|
|
const [mapError, setMapError] = useState(false)
|
|
|
|
|
|
const fetchPlaces = useCallback(async (bounds?: MapBounds) => {
|
|
|
@@ -64,20 +63,17 @@ export default function MapView() {
|
|
|
const provider = mapRef.current
|
|
|
if (!provider || !provider.isReady()) return
|
|
|
|
|
|
- const isGuest = !user
|
|
|
places.forEach((place) => {
|
|
|
provider.addMarker(place.id, place.lat, place.lng, {
|
|
|
type: place.type as 'place' | 'studio',
|
|
|
- title: isGuest ? undefined : place.title,
|
|
|
- onClick: isGuest ? undefined : () => setSelectedPlace(place),
|
|
|
- ghost: isGuest,
|
|
|
+ ghost: true,
|
|
|
})
|
|
|
})
|
|
|
|
|
|
return () => {
|
|
|
places.forEach((place) => provider.removeMarker(place.id))
|
|
|
}
|
|
|
- }, [places, user])
|
|
|
+ }, [places])
|
|
|
|
|
|
return (
|
|
|
<div className="relative h-full w-full">
|
|
|
@@ -97,49 +93,8 @@ export default function MapView() {
|
|
|
<p className="text-sm">Зарегистрируйтесь, чтобы исследовать места для фотосъёмок</p>
|
|
|
</div>
|
|
|
)}
|
|
|
-
|
|
|
- {selectedPlace && (
|
|
|
- <PlaceCardModal
|
|
|
- place={selectedPlace}
|
|
|
- onClose={() => setSelectedPlace(null)}
|
|
|
- />
|
|
|
- )}
|
|
|
</div>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Модальная карточка места, отображаемая в нижней части экрана.
|
|
|
- * Показывает название, адрес, описание, теги и рейтинг места.
|
|
|
- * @param place - Данные выбранного места
|
|
|
- * @param onClose - Функция закрытия карточки
|
|
|
- */
|
|
|
-function PlaceCardModal({ place, onClose }: { place: Place; onClose: () => void }) {
|
|
|
- return (
|
|
|
- <div className="absolute bottom-0 left-0 right-0 z-20 max-h-[60vh] overflow-y-auto rounded-t-2xl bg-[#1e293b] p-6 shadow-xl">
|
|
|
- <button onClick={onClose} className="mb-4 text-white/60 hover:text-white">
|
|
|
- ✕
|
|
|
- </button>
|
|
|
- <h2 className="mb-2 text-xl font-bold text-white">{place.title}</h2>
|
|
|
- {place.address && (
|
|
|
- <p className="mb-2 text-sm text-white/60">{place.address}</p>
|
|
|
- )}
|
|
|
- {place.description && (
|
|
|
- <p className="mb-4 text-sm text-white/80">{place.description}</p>
|
|
|
- )}
|
|
|
- <div className="mb-4 flex flex-wrap gap-2">
|
|
|
- {place.tags?.map((tag) => (
|
|
|
- <span key={tag.id} className="rounded-full bg-white/10 px-3 py-1 text-xs text-white/80">
|
|
|
- {tag.name}
|
|
|
- </span>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- <div className="flex items-center gap-4 text-sm text-white/60">
|
|
|
- <span>★ {place.rating?.toFixed(1) || 'Нет оценок'}</span>
|
|
|
- {place.type === 'studio' && place.hourly_rate && (
|
|
|
- <span>{place.hourly_rate} ₽/час</span>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- )
|
|
|
-}
|
|
|
+
|