SpeedLimitSection\index.tsx
src\ui\components\widgets\SpeedLimitSection\index.tsxunknown
typescript
a year ago
14 kB
4
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