asb_cloud_front/src/pages/Deposit.jsx

82 lines
2.5 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Map, Overlay } from 'pigeon-maps'
import { Link, useLocation } from 'react-router-dom'
import { useState, useEffect, memo } from 'react'
import { ClusterService } from '@api'
import { arrayOrDefault } from '@utils'
import { PointerIcon } from '@components/icons'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import '@styles/index.css'
const defaultViewParams = { center: [60.81226, 70.0562], zoom: 5 }
const calcViewParams = (clusters) => {
if ((clusters?.length ?? 0) <= 0)
return defaultViewParams
const center = clusters.reduce((sum, cluster) => {
sum[0] += (cluster.latitude / clusters.length)
sum[1] += (cluster.longitude / clusters.length)
return sum
}, [0, 0])
const maxDeg = clusters.reduce((max, cluster) => {
const dLatitude = Math.abs(center[0] - cluster.latitude)
const dLongitude = Math.abs(center[1] - cluster.longitude)
const d = dLatitude > dLongitude ? dLatitude : dLongitude
return d > max ? d : max
}, 0)
// zoom max = 20 (too close)
// zoom min = 1 (mega far)
// 4 - full Russia (161.6 deg)
// 13.5 - Khanty-Mansiysk
const zoom = Math.min(Math.max(5, 5 + 5 / (maxDeg + 0.5)), 15)
return { center, zoom }
}
export const Deposit = memo(() => {
const [clustersData, setClustersData] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [viewParams, setViewParams] = useState(defaultViewParams)
const location = useLocation()
useEffect(() => invokeWebApiWrapperAsync(
async () => {
const data = await ClusterService.getClusters()
setClustersData(arrayOrDefault(data))
setViewParams(calcViewParams(data))
},
setShowLoader,
`Не удалось загрузить список кустов`,
'Получить список кустов'
), [])
return (
<LoaderPortal show={showLoader}>
<div className={'h-100vh'}>
<Map {...viewParams}>
{clustersData.map(cluster => (
<Overlay
width={32}
anchor={[cluster.latitude, cluster.longitude]}
key={`${cluster.latitude} ${cluster.longitude}`}
>
<Link to={{ pathname: `/cluster/${cluster.id}`, state: { from: location.pathname }}}>
<PointerIcon state={'active'} width={48} height={59} />
<span>{cluster.caption}</span>
</Link>
</Overlay>
))}
</Map>
</div>
</LoaderPortal>
)
})
export default Deposit