From bb5b331b066c8d04340f4c95b74a5d69a08ab1fd Mon Sep 17 00:00:00 2001 From: BunyodL Date: Fri, 2 May 2025 14:35:33 +0500 Subject: [PATCH] update: make marker clickable, add scroll-to-ivew behavior --- public/map/oriyo-inactive-marker.png | Bin 0 -> 11441 bytes src/features/map/ui/gas-station-map.tsx | 50 +++++++++++++++++++----- src/features/map/ui/yandex-map.tsx | 30 ++++++++++---- 3 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 public/map/oriyo-inactive-marker.png diff --git a/public/map/oriyo-inactive-marker.png b/public/map/oriyo-inactive-marker.png new file mode 100644 index 0000000000000000000000000000000000000000..28ec21abd5d592d33abef408e3a9fc3f8defdb81 GIT binary patch literal 11441 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 literal 0 HcmV?d00001 diff --git a/src/features/map/ui/gas-station-map.tsx b/src/features/map/ui/gas-station-map.tsx index 6bfa874..8de342c 100644 --- a/src/features/map/ui/gas-station-map.tsx +++ b/src/features/map/ui/gas-station-map.tsx @@ -8,7 +8,7 @@ import { List, MapPin, } from 'lucide-react'; -import { useMemo, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { Stations } from '@/app/api-utlities/@types'; @@ -46,7 +46,6 @@ interface FilterPanelProps { setActiveFilterTab: (tab: string) => void; resetFilters: () => void; resetCities: () => void; - t: (key: string) => string; } // Пропсы для панели списка станций @@ -58,7 +57,6 @@ interface StationListPanelProps { activeFilters: string[]; activeCities: string[]; setSelectedStation: (id: number | null) => void; - t: (key: string) => string; filterToFieldMap: { [key: string]: keyof Stations[number] }; allFilters: string[]; resetFilters: () => void; @@ -80,8 +78,9 @@ function FilterPanel({ setActiveFilterTab, resetFilters, resetCities, - t, }: FilterPanelProps) { + const { t } = useTextController(); + return (
(null); + + useEffect(() => { + if (!selectedStation || !scrollContainerRef.current) return; + + const selectedStationItem = document.getElementById( + `station_${selectedStation}`, + ); + + if (selectedStationItem) { + const container = scrollContainerRef.current; + const itemRect = selectedStationItem.getBoundingClientRect(); + const containerRect = container.getBoundingClientRect(); + + // Calculate the item's position relative to the container + const itemTopRelativeToContainer = + itemRect.top - containerRect.top + container.scrollTop - 10; + + // Scroll the container to bring the item into view + container.scrollTo({ + top: itemTopRelativeToContainer, + behavior: 'smooth', + }); + } + }, [selectedStation]); + return (
{stations.length}
-
+
{stations.length > 0 ? (
{stations.map((station) => { @@ -240,6 +269,7 @@ function StationListPanel({ return (
{/* Station list panel */} @@ -466,7 +495,6 @@ export default function GasStationMap({ stations }: GasStationMapProps) { activeFilters={activeFilters} activeCities={activeCities} setSelectedStation={setSelectedStation} - t={t} filterToFieldMap={filterToFieldMap} allFilters={allFilters} resetFilters={resetFilters} @@ -475,7 +503,11 @@ export default function GasStationMap({ stations }: GasStationMapProps) { {/* Map */}
- +
{/* Control buttons */} diff --git a/src/features/map/ui/yandex-map.tsx b/src/features/map/ui/yandex-map.tsx index 93b667a..c735b9d 100644 --- a/src/features/map/ui/yandex-map.tsx +++ b/src/features/map/ui/yandex-map.tsx @@ -1,17 +1,21 @@ -'use client'; - import { Map, Placemark, YMaps } from '@pbe/react-yandex-maps'; -import React from 'react'; +import React, { Dispatch, SetStateAction } from 'react'; import { Point } from '../model'; type YandexMapProps = { points: Point[]; + selectedStation: number | null; + setSelectedStation: Dispatch>; }; const mapCenter = [55.751574, 37.573856]; -export const YandexMap = ({ points }: YandexMapProps) => { +export const YandexMap = ({ + points, + selectedStation, + setSelectedStation, +}: YandexMapProps) => { return ( { > { geometry={point.coordinates} options={{ iconLayout: 'default#image', - iconImageHref: '/map/oriyo-marker.png', - iconImageSize: [64, 64], + iconImageHref: + !selectedStation || selectedStation === point.id + ? '/map/oriyo-marker.png' + : '/map/oriyo-inactive-marker.png', + iconImageSize: selectedStation === point.id ? [70, 70] : [64, 64], iconImageOffset: [-24, -36], }} + onClick={() => + setSelectedStation(() => { + if (selectedStation !== null && selectedStation === point.id) { + return null; + } + + return point.id; + }) + } /> ))}