Compare commits
No commits in common. "c94140545cc3005d76981c4f8e87bf99e21e8971" and "4525b0b8c3bce9b63a9c291cd46250b4a2eb40f7" have entirely different histories.
c94140545c
...
4525b0b8c3
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@ -8,7 +8,7 @@ import {
|
|||||||
List,
|
List,
|
||||||
MapPin,
|
MapPin,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { Stations } from '@/app/api-utlities/@types';
|
import { Stations } from '@/app/api-utlities/@types';
|
||||||
|
|
||||||
@ -46,6 +46,7 @@ interface FilterPanelProps {
|
|||||||
setActiveFilterTab: (tab: string) => void;
|
setActiveFilterTab: (tab: string) => void;
|
||||||
resetFilters: () => void;
|
resetFilters: () => void;
|
||||||
resetCities: () => void;
|
resetCities: () => void;
|
||||||
|
t: (key: string) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Пропсы для панели списка станций
|
// Пропсы для панели списка станций
|
||||||
@ -57,6 +58,7 @@ interface StationListPanelProps {
|
|||||||
activeFilters: string[];
|
activeFilters: string[];
|
||||||
activeCities: string[];
|
activeCities: string[];
|
||||||
setSelectedStation: (id: number | null) => void;
|
setSelectedStation: (id: number | null) => void;
|
||||||
|
t: (key: string) => string;
|
||||||
filterToFieldMap: { [key: string]: keyof Stations[number] };
|
filterToFieldMap: { [key: string]: keyof Stations[number] };
|
||||||
allFilters: string[];
|
allFilters: string[];
|
||||||
resetFilters: () => void;
|
resetFilters: () => void;
|
||||||
@ -78,9 +80,8 @@ function FilterPanel({
|
|||||||
setActiveFilterTab,
|
setActiveFilterTab,
|
||||||
resetFilters,
|
resetFilters,
|
||||||
resetCities,
|
resetCities,
|
||||||
|
t,
|
||||||
}: FilterPanelProps) {
|
}: FilterPanelProps) {
|
||||||
const { t } = useTextController();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`absolute top-0 bottom-0 left-0 z-20 transform bg-white shadow-lg transition-transform duration-300 ${
|
className={`absolute top-0 bottom-0 left-0 z-20 transform bg-white shadow-lg transition-transform duration-300 ${
|
||||||
@ -206,38 +207,12 @@ function StationListPanel({
|
|||||||
activeFilters,
|
activeFilters,
|
||||||
activeCities,
|
activeCities,
|
||||||
setSelectedStation,
|
setSelectedStation,
|
||||||
|
t,
|
||||||
filterToFieldMap,
|
filterToFieldMap,
|
||||||
allFilters,
|
allFilters,
|
||||||
resetCities,
|
resetCities,
|
||||||
resetFilters,
|
resetFilters,
|
||||||
}: StationListPanelProps) {
|
}: StationListPanelProps) {
|
||||||
const { t } = useTextController();
|
|
||||||
const scrollContainerRef = useRef<HTMLDivElement | null>(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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`absolute top-0 right-0 bottom-0 z-20 transform bg-white shadow-lg transition-transform duration-300 ${
|
className={`absolute top-0 right-0 bottom-0 z-20 transform bg-white shadow-lg transition-transform duration-300 ${
|
||||||
@ -254,11 +229,7 @@ function StationListPanel({
|
|||||||
<Badge>{stations.length}</Badge>
|
<Badge>{stations.length}</Badge>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className='overflow-y-auto' style={{ height: 'calc(100% - 60px)' }}>
|
||||||
className='overflow-y-auto'
|
|
||||||
style={{ height: 'calc(100% - 60px)' }}
|
|
||||||
ref={scrollContainerRef}
|
|
||||||
>
|
|
||||||
{stations.length > 0 ? (
|
{stations.length > 0 ? (
|
||||||
<div className='p-2'>
|
<div className='p-2'>
|
||||||
{stations.map((station) => {
|
{stations.map((station) => {
|
||||||
@ -269,7 +240,6 @@ function StationListPanel({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={station.id}
|
key={station.id}
|
||||||
id={`station_${station.id}`}
|
|
||||||
className={`mb-2 cursor-pointer rounded-lg border p-3 transition-colors ${
|
className={`mb-2 cursor-pointer rounded-lg border p-3 transition-colors ${
|
||||||
selectedStation === station.id
|
selectedStation === station.id
|
||||||
? 'border-blue-500 bg-blue-50'
|
? 'border-blue-500 bg-blue-50'
|
||||||
@ -484,6 +454,7 @@ export default function GasStationMap({ stations }: GasStationMapProps) {
|
|||||||
setActiveFilterTab={setActiveFilterTab}
|
setActiveFilterTab={setActiveFilterTab}
|
||||||
resetFilters={resetFilters}
|
resetFilters={resetFilters}
|
||||||
resetCities={resetCities}
|
resetCities={resetCities}
|
||||||
|
t={t}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Station list panel */}
|
{/* Station list panel */}
|
||||||
@ -495,6 +466,7 @@ export default function GasStationMap({ stations }: GasStationMapProps) {
|
|||||||
activeFilters={activeFilters}
|
activeFilters={activeFilters}
|
||||||
activeCities={activeCities}
|
activeCities={activeCities}
|
||||||
setSelectedStation={setSelectedStation}
|
setSelectedStation={setSelectedStation}
|
||||||
|
t={t}
|
||||||
filterToFieldMap={filterToFieldMap}
|
filterToFieldMap={filterToFieldMap}
|
||||||
allFilters={allFilters}
|
allFilters={allFilters}
|
||||||
resetFilters={resetFilters}
|
resetFilters={resetFilters}
|
||||||
@ -503,11 +475,7 @@ export default function GasStationMap({ stations }: GasStationMapProps) {
|
|||||||
|
|
||||||
{/* Map */}
|
{/* Map */}
|
||||||
<div className='h-full w-full'>
|
<div className='h-full w-full'>
|
||||||
<YandexMap
|
<YandexMap points={points} />
|
||||||
points={points}
|
|
||||||
selectedStation={selectedStation}
|
|
||||||
setSelectedStation={setSelectedStation}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Control buttons */}
|
{/* Control buttons */}
|
||||||
|
|||||||
@ -1,21 +1,17 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
import { Map, Placemark, YMaps } from '@pbe/react-yandex-maps';
|
import { Map, Placemark, YMaps } from '@pbe/react-yandex-maps';
|
||||||
import React, { Dispatch, SetStateAction } from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Point } from '../model';
|
import { Point } from '../model';
|
||||||
|
|
||||||
type YandexMapProps = {
|
type YandexMapProps = {
|
||||||
points: Point[];
|
points: Point[];
|
||||||
selectedStation: number | null;
|
|
||||||
setSelectedStation: Dispatch<SetStateAction<number | null>>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapCenter = [55.751574, 37.573856];
|
const mapCenter = [55.751574, 37.573856];
|
||||||
|
|
||||||
export const YandexMap = ({
|
export const YandexMap = ({ points }: YandexMapProps) => {
|
||||||
points,
|
|
||||||
selectedStation,
|
|
||||||
setSelectedStation,
|
|
||||||
}: YandexMapProps) => {
|
|
||||||
return (
|
return (
|
||||||
<YMaps
|
<YMaps
|
||||||
query={{
|
query={{
|
||||||
@ -26,7 +22,7 @@ export const YandexMap = ({
|
|||||||
>
|
>
|
||||||
<Map
|
<Map
|
||||||
defaultState={{
|
defaultState={{
|
||||||
center: points[0]?.coordinates || mapCenter,
|
center: points[0].coordinates || mapCenter,
|
||||||
zoom: 11,
|
zoom: 11,
|
||||||
behaviors: ['drag', 'multiTouch', 'dblClickZoom', 'scrollZoom'],
|
behaviors: ['drag', 'multiTouch', 'dblClickZoom', 'scrollZoom'],
|
||||||
}}
|
}}
|
||||||
@ -45,22 +41,10 @@ export const YandexMap = ({
|
|||||||
geometry={point.coordinates}
|
geometry={point.coordinates}
|
||||||
options={{
|
options={{
|
||||||
iconLayout: 'default#image',
|
iconLayout: 'default#image',
|
||||||
iconImageHref:
|
iconImageHref: '/map/oriyo-marker.png',
|
||||||
!selectedStation || selectedStation === point.id
|
iconImageSize: [64, 64],
|
||||||
? '/map/oriyo-marker.png'
|
|
||||||
: '/map/oriyo-inactive-marker.png',
|
|
||||||
iconImageSize: selectedStation === point.id ? [70, 70] : [64, 64],
|
|
||||||
iconImageOffset: [-24, -36],
|
iconImageOffset: [-24, -36],
|
||||||
}}
|
}}
|
||||||
onClick={() =>
|
|
||||||
setSelectedStation(() => {
|
|
||||||
if (selectedStation !== null && selectedStation === point.id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return point.id;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Map>
|
</Map>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user