SpeedLimitSection\index.tsx
src\ui\components\widgets\SpeedLimitSection\index.tsxAnonymous
typescript
06/26/2024 4:40 PM
18.1 KB
15
Indexable
import { useSpeedLimitStore } from '@Contexts'
import { useSearchParams } from '@Hooks'
import { LoadingSpinner, RvTable } from '@Shared'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useLocation } from 'react-router-dom'
import SpeedLimitFiller from './components/SpeedLimitFiller'
import { useSpeedLimitFilter } from './hooks'
import { useSpeedLimitReviewTable } from './hooks'
import { useSpeedLimitReducer } from './reducer'
import { ActionTypes, speedLimitItemType } from './types'
import PopupModel from './components/PopupModel'
import { CButton, CCard } from '@coreui/react'
import { Icons } from '@Assets/icons/Icons'
import { useDispatch, useSelector } from 'react-redux'
import {
MapContainer,
TileLayer,
Polyline,
Marker,
Popup,
useMap,
Tooltip,
useMapEvents
} from 'react-leaflet'
import {
MAP_URLS,
MAP_ATTRIBUTION,
DEFAULT_MAP_CENTER,
DEFAULT_ZOOM_LEVEL,
SCROLL_WHEEL_ZOOM
} from '../../../components/widgets/Map/constants/config.js'
import React from 'react'
import Controls from '../../../components/widgets/Map/components/Controls/Controls.js'
import StationList from '../../../components/widgets/Map/components/Station/StationList.js'
import {
getRoutesByRailroad,
getStationsByRouteId,
getTSOSpeedLimitsByRouteId,
getTrackCoordsByRouteId,
getZoneSpeedLimitsByRouteId
} from '../../../../../src/graphQL/Api.js'
import Station from '../../../components/widgets/Map/components/Station/Station.js'
import L from 'leaflet'
import {
fetchTSOSpeedLimitsByRouteId,
fetchZoneSpeedLimitsByRouteId,
fetchStationsByRouteId
} from '@Redux/slices/portalDataSlice'
import { divIcon } from 'leaflet'
import classNames from 'classnames'
interface selectedItemType {
item: speedLimitItemType
index: number
}
interface Station {
station: string
lat: number
lng: number
abbreviation: string
}
const SpeedLimitSection = () => {
const [fakeLoading, setFakeLoading] = useState(false)
const [isFirstLoad, setIsFirstLoad] = useState(true)
const location = useLocation()
const dispatch = useDispatch()
const searchParams = useSearchParams()
const {
data: { railroadId }
} = useSelector((state: any) => state.userInfo)
const {
deleteTSOSpeedLimitById: { loading: deleteTSOSpeedLimitByIdLoading }
} = useSelector((state: any) => state.portalAction)
const speedLimitStore = useSpeedLimitStore
const speedLimitData = useSpeedLimitStore.use.speedLimits()
const fetchData = useSpeedLimitStore.use.fetchData()
const deleteTSOSpeedLimit = useSpeedLimitStore.use.deleteTSOSpeedLimit()
const [state, actions] = useSpeedLimitReducer()
const { routes } = useSpeedLimitFilter(state, actions)
const { fields, customCells, data, loading } = useSpeedLimitReviewTable(
state,
actions
)
const {
type,
actionType,
page,
routeId,
isDeleteModal,
temporarySpeedLimitIdDelete,
errorModal
} = state
const [stations, setStations] = useState<Station[]>([])
const [trackData, setTrackData] = useState([])
const [milepostMarkers, setMilepostMarkers] = useState([])
const [tsoSpeedLimitsData, setTSOSpeedLimits] = useState([])
const [zoneSpeedLimitsData, setZoneSpeedLimits] = useState([])
const handleDeleteSpeedLimit = () => {
const payload = {
temporarySpeedLimitIdDelete,
onSuccess: () => {
const routeIdParam = searchParams.getSearchParam('route-id')
const directionParam = searchParams.getSearchParam('direction')
const endDestinationId = routeIdParam
?.split('_')
.filter(item => item !== directionParam)
actions.onSelectedDeleteItem(null)
actions.onChangeIsOpenModalDelete(false)
if (routeIdParam) {
dispatch(
fetchTSOSpeedLimitsByRouteId({
routeId: routeIdParam,
railroadId: railroadId,
startDestinationId: directionParam!,
endDestinationId: endDestinationId![0]
})
)
}
actions.onChangeActionType(ActionTypes.View)
},
onFailure: (error: string) => {
actions.onIsOpenError(error)
actions.onChangeIsOpenModalDelete(false)
}
}
deleteTSOSpeedLimit(payload)
}
const showData = useCallback(() => {
const typeArr = type?.split(',')
const updateSpeedLimits =
data?.filter(
(speedLimit: speedLimitItemType) =>
typeArr.includes(speedLimit?.type!) || type === ''
) || []
speedLimitStore.setState({ speedLimits: updateSpeedLimits })
setFakeLoading(true)
setTimeout(() => {
setFakeLoading(false)
}, 300)
}, [data, type])
const onChangePage = useCallback(
(e: any) => {
if (!isFirstLoad) {
setTimeout(() => {
actions.onChangePage(e.toString())
}, 20)
}
},
[isFirstLoad]
)
const handleRowClick = (item: speedLimitItemType, index: number) => {}
useEffect(() => {
const pageParam = searchParams.getSearchParam('page')
pageParam && actions.onChangePage(pageParam)
if (data && isFirstLoad) {
setTimeout(() => {
setIsFirstLoad(false)
}, 500)
}
// if (data && !isFirstLoad ) {
// setTimeout(() => {
// actions.onChangePage('')
// }, 100)
// }
}, [data])
useEffect(() => {
data && showData()
actions.onChangeActionType(ActionTypes.View)
}, [data, type])
useEffect(() => {
const page = searchParams.getSearchParam('page')
if (actionType === ActionTypes.Add && data) {
// onChangePage(1)
actions.onChangePage('')
searchParams.delSearchParam('page')
const newSpeedLimitData = [{}, ...(speedLimitData ?? [])]
speedLimitStore.setState({ speedLimits: newSpeedLimitData })
if (page && page !== '1') {
setFakeLoading(true)
setTimeout(() => {
setFakeLoading(false)
}, 100)
}
}
}, [actionType])
// ---------------------------
useEffect(() => {
const fetchTrackData = async () => {
try {
const trackLatLongData = await getTrackCoordsByRouteId({
railroadId: 'VIA',
routeId: 'TRTO_OTTW',
startDestinationId: 'TRTO',
endDestinationId: 'OTTW'
})
setTrackData(trackLatLongData)
// console.log('trackData:', trackLatLongData)
} catch (error) {
console.error('Error fetching track data:', error)
}
}
const fetchStationsData = async () => {
try {
const stationsData = await getStationsByRouteId({
railroadId: 'VIA',
routeId: 'TRTO_OTTW'
})
// console.log('Station Data:', stationsData)
setStations(stationsData)
} catch (error) {
console.error('Error fetching track data:', error)
}
}
const fetchRoutesData = async () => {
try {
// console.log('🚀 BEFORE Routes CALL:')
const routesData = await getRoutesByRailroad('VIA')
// console.log('🚀 ROUTES Data:', routesData)
} catch (error) {
console.error('Error fetching ROUTES data:', error)
}
}
const fetchTSOSpeedLimitsData = async () => {
try {
// console.log('🚀 BEFORE TSO CALL:')
const tsoSpeedLimitsData = await getTSOSpeedLimitsByRouteId({
railroadId: 'VIA',
routeId: 'TRTO_OTTW',
startDestinationId: 'TRTO',
endDestinationId: 'OTTW'
})
// console.log('🚀 TSO Speed Limits Data:', tsoSpeedLimitsData)
setTSOSpeedLimits(tsoSpeedLimitsData)
} catch (error) {
console.error('Error fetching TSO speed limits data:', error)
}
}
const fetchZoneSpeedLimitsData = async () => {
try {
// console.log('🚀 BEFORE ZONE LIMIT CALL')
const zoneSpeedLimitsData = await getZoneSpeedLimitsByRouteId({
railroadId: 'VIA',
routeId: 'TRTO_OTTW',
startDestinationId: 'TRTO',
endDestinationId: 'OTTW'
})
// console.log('🚀 Zone Speed Limits Data:', zoneSpeedLimitsData)
setZoneSpeedLimits(zoneSpeedLimitsData)
} catch (error) {
console.error('Error fetching Zone speed limits data:', error)
}
}
fetchRoutesData()
fetchTrackData()
fetchStationsData()
fetchTSOSpeedLimitsData()
fetchZoneSpeedLimitsData()
}, [])
const customIcon = divIcon({
className: 'w-full h-full bg-[#555555] rounded-full',
iconSize: [12, 12]
})
const bounds =
stations.length > 0
? L.latLngBounds(stations.map(station => [station.lat, station.lng]))
: L.latLngBounds([
[0, 0],
[0, 0]
])
const FitBounds = ({ bounds }: { bounds: L.LatLngBounds }) => {
const map = useMap()
useEffect(() => {
if (bounds.isValid()) {
map.fitBounds(bounds)
} else {
console.error('Bounds are not valid.')
}
}, [map, bounds])
return null
}
const [showMarkers, setShowMarkers] = useState(true)
const toggleMarkers = () => {
setShowMarkers(prevShowMarkers => !prevShowMarkers)
}
return (
<div id="rv-portal">
<h4>Speed limit</h4>
<SpeedLimitFiller state={state} actions={actions} />
{loading ? (
<LoadingSpinner classNames="my-5" />
) : fakeLoading ? (
<LoadingSpinner classNames="my-5" />
) : (
<RvTable
items={speedLimitData}
fields={fields}
itemsPerPage={5}
sorter={false}
striped={false}
onRowClick={(item, index) => {
handleRowClick(item, index)
}}
customizedCells={customCells}
sorterValue={undefined}
onPageChange={onChangePage}
activePage={parseInt(state.page) ?? 1}
/>
)}
<button onClick={toggleMarkers}>
{showMarkers ? 'Hide Stations' : 'Show Stations'}
</button>
<CCard
style={{
width: '100%',
height: '70vh'
}}
>
<MapContainer
center={[43.64606677, -79.37180328]}
zoom={DEFAULT_ZOOM_LEVEL}
doubleClickZoom={false}
scrollWheelZoom={SCROLL_WHEEL_ZOOM}
>
<Controls />
<TileLayer
attribution={MAP_ATTRIBUTION}
url={MAP_URLS.MAPBOX_BASIC}
/>
{showMarkers &&
stations.map(({ abbreviation, lat, lng }) => (
<Marker
key={abbreviation}
position={[lat, lng]}
icon={customIcon}
>
<Tooltip>{abbreviation}</Tooltip>
<div className="relative h-[12px] w-[12px]"></div>
</Marker>
))}
<Polyline
positions={trackData.map(({ gps_coordinates: { lat, lng } }) => [
lat,
lng
])}
color="#57a7f2"
/>
<FitBounds bounds={bounds} />
</MapContainer>
</CCard>
<PopupModel isOpen={isDeleteModal}>
<div className="flex flex-col gap-2 px-4 py-4">
<div className="flex gap-2 justify-start">
<Icons.Warning className="w-[42px] h-[42px]" />
<div>
<div className=" mb-1">
<span className="font-medium text-2xl ">
Delete Speed Limit
</span>
</div>
<div>
<span className="w-full font-normal text-[16px]">
Are you sure you want to delete speed limit
</span>
</div>
</div>
</div>
</div>
<div className="flex justify-end gap-2 px-4 pb-4">
<CButton
color="secondary"
onClick={() => {
actions.onChangeIsOpenModalDelete(false)
actions.onSelectedDeleteItem(null)
}}
>
Cancel
</CButton>
<CButton
color="danger"
disabled={deleteTSOSpeedLimitByIdLoading}
onClick={handleDeleteSpeedLimit}
>
<div className="flex justify-center items-center gap-2">
{deleteTSOSpeedLimitByIdLoading && (
<LoadingSpinner width={20} height={20} color="white" />
)}
Delete
</div>
</CButton>
</div>
</PopupModel>
<PopupModel isOpen={!!errorModal}>
<div className="flex flex-col gap-2 px-4 py-4">
<div className="flex gap-2 justify-start">
<div>
<div className=" flex justify-start items-center gap-2 mb-1">
<Icons.Error className="w-[42px] h-[42px]" />
<span className="font-medium text-2xl ">Error</span>
</div>
<div>
<span className="w-full font-normal text-[16px]">
{errorModal}
</span>
</div>
</div>
</div>
</div>
<div className="flex justify-end gap-2 px-4 pb-4">
<CButton
color="secondary"
onClick={() => {
actions.onIsOpenError('')
}}
>
Close
</CButton>
</div>
</PopupModel>
</div>
)
}
export default SpeedLimitSection
Editor is loading...
Leave a Comment