SelectonGroup/SelectionTrip.tsx
unknown
plain_text
2 years ago
16 kB
5
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...