SelectonGroup/SelectionTrip.tsx
unknown
plain_text
2 years ago
16 kB
4
Indexable
/* eslint-disable react-native/no-inline-styles */ import React, {useEffect, useState, useCallback} from 'react'; import { SafeAreaView, Text, View, ScrollView, useWindowDimensions, ActivityIndicator, } from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view'; // Navigation import {useNavigation} from '@react-navigation/native'; import ScreensName from '@Configs/navigator'; // Redux Selectors import {useDispatch, useSelector} from 'react-redux'; import {getOrientation, getActiveEnv} from '@Redux/common/selectors'; import {getStationList} from '@Redux/station/selectors'; import {getTripDispatch} from '@Redux/trip/selectors'; import {getConsistTrain, getTrainSelectionInfo} from '@Redux/train/selectors'; import {getTrackLoading} from '@Redux/track/selectors'; import { getIntermediateStations, validStationPair, } from '@Utils/intermediateStations'; import {getModelsLoading} from '@Redux/model/selectors'; // Redux Actions import { setAutoCenter, setUseTestData, setUseSimulatedTestData, setWaiting, setTravelDistance, resetUserInteractTime, setCurrentMilepost, } from '@Redux/common/actions'; import {setStopStation, getTrackGroupData} from '@Redux/track/actions'; import { cleanGpsList, clearModelEventList, clearSpeedHistory, generateRandomTripId, setCurrentTripKey, setTripDispatchUserInput, clearStationHistory, } from '@Redux/trip/actions'; import {getSpeedMultipleProfile} from '@Redux/speedProfile/actions'; import {getLocoModelList, setCurrentSpeed} from '@Redux/train/actions'; import {setStationActive} from '@Redux/station/actions'; import {getUserAuthorizationSelector} from '@Redux/auth/selectors'; // Hooks import useCheckAuthenticated from '@Hooks/useCheckAuthenticated'; import useKeyboardSubscription from '@Hooks/useKeyboardSubscription'; // Components import {ChevronRight, VerticalTripPath, VerticalTripPathList} from '@Svg'; import Header from '../Header'; import IntermediateStationList from './IntermediateStationList'; import DemoCheckboxes from './DemoCheckboxes'; // Types import {UseStateTuple} from '@Types'; import {Station} from '@Redux/station/type'; // Styles import styles from './styles'; import RefactorAutocompleteInput from '@Com/RefactorAutoCompleteInput'; const NextLoader = ({ width, height, envName, }: { width: number; height: number; envName: string; }): JSX.Element => { return ( <View style={[ styles.loading, {width, height: envName === 'production' ? height : height - 25}, ]}> <ActivityIndicator size={'large'} color={'#B20610'} /> </View> ); }; const SelectionTrip: React.FC<{}> = () => { const dispatch = useDispatch(); const navigation = useNavigation(); const {width, height} = useWindowDimensions(); const {keyboardStatus} = useKeyboardSubscription(); const orientation = useSelector(state => getOrientation(state)); // User auth & env const userAuthorization = useSelector(state => getUserAuthorizationSelector(state), ); const envName = useSelector(state => getActiveEnv(state)); // Loadings const trackLoading = useSelector(state => getTrackLoading(state)); const modelsLoading = useSelector(state => getModelsLoading(state)); // Dispatch, consist,... const tripDispatchData = useSelector(state => getTripDispatch(state)); const consistTrainData = useSelector(state => getConsistTrain(state)); const trainInfo = useSelector(state => getTrainSelectionInfo(state)); const [ready, setReady]: UseStateTuple<boolean> = useState(false); const [routeId, setRouteId]: UseStateTuple<string> = useState(''); // Selected start and end location const [startStationName, setStartStationName]: UseStateTuple<string> = useState(''); const [endStationName, setEndStationName]: UseStateTuple<string> = useState(''); // Station List const stationList = useSelector(state => getStationList(state)); // Create station list for Route dropdown const routeIdDropdownList = stationList?.routes.map((item: any) => { return item.route_name.toUpperCase(); }); // Selected route id value const selectedRouteId = stationList?.routes.find( e => e.route_name.toUpperCase() === routeId.toUpperCase(), )?.route_id || ''; // Get station list for selected route id const stationListByRouteId = stationList?.stations.filter( item => item.route_id === selectedRouteId, ); const stationNameList = stationListByRouteId.map( item => `${item.abbreviation} - ${item.location_name}`, ); // Filter start and end station dropdown lists const startStationDropdownList = stationNameList.filter((item: any) => { return ( item.toLowerCase().includes(startStationName.toLowerCase()) && !( endStationName !== '' && item.toLowerCase().includes(endStationName.toLowerCase()) ) ); }); const endStationDropdownList = stationNameList.filter((item: any) => { return ( item.toLowerCase().includes(endStationName.toLowerCase()) && !( startStationName !== '' && item.toLowerCase().includes(startStationName.toLowerCase()) ) ); }); // Intermediate stations const [intermediateStations, setIntermediateStations] = useState<Station[]>( [], ); const activeListStationRef = React.useRef(); useCheckAuthenticated(); // Prefill route ID and stations useEffect(() => { if (tripDispatchData?.startDestination) { const start = tripDispatchData?.startDestination; setStartStationName(`${start.id} - ${start.name}`); } if (tripDispatchData?.endDestination) { const end = tripDispatchData?.endDestination; setEndStationName(`${end.id} - ${end.name}`); } if (tripDispatchData?.routeId) { const matchingRoute = stationList?.routes.find( item => item.route_id === tripDispatchData.routeId, ); if (matchingRoute) { setRouteId(matchingRoute.route_name.toUpperCase()); } } }, [tripDispatchData]); // Load intermediate stations useEffect(() => { if (!validStationPair(startStationName, endStationName, stationNameList)) return setIntermediateStations([]); const startStation = stationListByRouteId.find( station => station.abbreviation === startStationName.split(' - ')[0], ); const endStation = stationListByRouteId.find( station => station.abbreviation === endStationName.split(' - ')[0], ); setIntermediateStations( getIntermediateStations(stationListByRouteId, startStation, endStation), ); }, [startStationName, endStationName]); const tryNavigate = useCallback(() => { if (consistTrainData) { navigation.navigate(ScreensName.SELECTION_TRAIN_CONSIST); } else { navigation.navigate(ScreensName.SELECTION_TRAIN_CONSIST); } }, [trainInfo, navigation, tripDispatchData]); useEffect(() => { if (ready && !modelsLoading && !trackLoading) { setReady(false); tryNavigate(); } }, [modelsLoading, ready, navigation, tryNavigate, trackLoading]); const getDataByStopStations = ( start: string, end: string, selectedIntermediateStationList: string[], ) => { const stops = [start, ...selectedIntermediateStationList, end]; // One single track data call dispatch( getTrackGroupData( start, end, selectedRouteId, userAuthorization?.railroadId, stops, ), ); // Call ETA query for each section for (let i = 0; i < stops?.length - 1; i++) { dispatch( setStopStation({ key: `${stops[i]}-${stops[i + 1]}`, order: i, }), ); dispatch( getSpeedMultipleProfile( stops[i], stops[i + 1], selectedRouteId, userAuthorization?.railroadId, i, ), ); } }; const clearTripStates = () => { if (envName !== 'dev') { dispatch(setUseTestData(false)); dispatch(setUseSimulatedTestData(false)); } dispatch(getLocoModelList(userAuthorization?.railroadId)); dispatch(cleanGpsList()); dispatch(clearModelEventList()); dispatch(clearSpeedHistory()); dispatch(clearStationHistory()); dispatch(resetUserInteractTime()); dispatch(setCurrentSpeed(0)); dispatch(setTravelDistance(0)); dispatch(setCurrentMilepost(null)); dispatch(setAutoCenter(true)); dispatch(setWaiting(false)); dispatch(generateRandomTripId()); }; const prepareDispatchData = ( start: string, end: string, selectedIntermediateStationList: string[], ) => { const allActiveStations = [start, ...selectedIntermediateStationList, end]; const dispatchData = allActiveStations .map((station, idx) => { if (idx !== allActiveStations.length - 1) { return { startLocationId: station, endLocationId: allActiveStations[idx + 1], }; } }) .slice(0, -1); const startStationSequenceId = stationListByRouteId?.filter( item => item.abbreviation === start, )[0].sequence_id; const endStationSequenceId = stationListByRouteId?.filter( item => item.abbreviation === end, )[0].sequence_id; const routeDirection = startStationSequenceId <= endStationSequenceId ? 'ASC' : 'DESC'; dispatch( setTripDispatchUserInput(dispatchData, selectedRouteId, routeDirection), ); }; const proceedToNextScreen = async (): Promise<void> => { clearTripStates(); const start = startStationName?.split(' - ')[0]; const end = endStationName?.split(' - ')[0]; // Prepare active station list const currentActiveList = ( activeListStationRef as any ).current.activeStationsList(); const selectedIntermediateStationList = intermediateStations .filter(item => currentActiveList?.includes(item.abbreviation)) .map(item => item.abbreviation); getDataByStopStations(start, end, selectedIntermediateStationList); // Set current trip key const currentTripKey = selectedIntermediateStationList?.length > 0 ? start + '-' + selectedIntermediateStationList[0] : start + '-' + end; dispatch(setCurrentTripKey(currentTripKey)); // Prepare dispatch Data prepareDispatchData(start, end, selectedIntermediateStationList); // Set active station list const activeIntermediateStationList = selectedIntermediateStationList.map( item => { const stationData = intermediateStations.find( e => e.abbreviation === item, ); return stationData; }, ); const activeStationList = { departure: start, destination: end, activeStationList: activeIntermediateStationList, }; dispatch(setStationActive(activeStationList)); setReady(true); }; return ( <SafeAreaView style={[styles.container]}> <Header /> <KeyboardAwareScrollView contentContainerStyle={styles.formContainer} keyboardShouldPersistTaps="always" extraHeight={150}> <ScrollView> <View style={styles.formComponent}> <Text style={styles.title}>Trip Selection</Text> <View style={styles.fieldsWidth}> {/* ROUTE ID */} <RefactorAutocompleteInput textFieldProps={{ placeholder: 'Choose Route', value: routeId, setValue: routeId => { setStartStationName(''); setEndStationName(''); setRouteId(routeId); }, }} label={'ROUTE'} data={routeIdDropdownList} iconRightShow={!!routeId} /> <View style={{ display: 'flex', flexDirection: 'row', paddingTop: 24, alignItems: 'flex-start', justifyContent: 'space-between', }}> {/* VERTICAL ICONS */} <View style={styles.iconPath}> {intermediateStations.length > 0 || validStationPair( startStationName, endStationName, stationNameList, ) ? ( <VerticalTripPathList height={370} /> ) : ( <VerticalTripPath width={18} /> )} </View> <View style={{ width: '100%', }}> {/* START STATION */} <RefactorAutocompleteInput textFieldProps={{ placeholder: 'Choose Station, Yard, Service Station, etc', value: startStationName, setValue: setStartStationName, }} label="DEPARTURE" data={startStationDropdownList} iconRightShow={!!startStationName} // containerStyles={{marginTop: 32}} isDisabled={ !startStationDropdownList || startStationDropdownList.length === 0 } /> {/* INTERMEDIATE STATIONS */} {validStationPair( startStationName, endStationName, stationNameList, ) ? ( <IntermediateStationList ref={activeListStationRef} intermediateStations={intermediateStations} /> ) : ( <></> )} {/* END STATION */} <RefactorAutocompleteInput textFieldProps={{ placeholder: 'Choose Station, Yard, Service Station, etc', value: endStationName, setValue: setEndStationName, }} label={'DESTINATION'} data={endStationDropdownList} iconRightShow={!!endStationName} containerStyles={{marginTop: 24}} isDisabled={ !endStationDropdownList || endStationDropdownList.length === 0 } /> </View> </View> {/* CHECKBOXES IN DEV MODE */} {envName === 'dev' && <DemoCheckboxes />} </View> </View> </ScrollView> </KeyboardAwareScrollView> {/* RIGHT NAVIGATION */} <View style={[ styles.buttonContainer, { right: 20, top: keyboardStatus ? orientation === 'portrait' ? (height - 64) / 2 - 140 : orientation === 'landscape' ? (height - 64) / 4 : 100 : (height - 64) / 2, }, !validStationPair(startStationName, endStationName, stationNameList) ? styles.buttonDisabled : null, ]}> <TouchableOpacity onPress={proceedToNextScreen} disabled={ !validStationPair(startStationName, endStationName, stationNameList) } testID="next-button" style={styles.button}> <ChevronRight color="#fff" /> </TouchableOpacity> </View> {/* NEXT LOADING ICON */} {(consistTrainData && modelsLoading) || trackLoading ? ( <NextLoader width={width} height={height} envName={envName} /> ) : null} </SafeAreaView> ); }; export default SelectionTrip;
Editor is loading...