SmartStopAPK/src/infraestructure/hooks/useDevices.ts

213 lines
5.7 KiB
TypeScript

import {useCallback, useEffect, useMemo, useState} from 'react';
import DevicesRepositoryImpl from '../repositories/DevicesRepositoryImpl';
import DevicesAPI from '../api/clients/DevicesAPI';
import AuthRepositoryImpl from '../repositories/AuthRepositoryImpl';
import AuthAPI from '../api/clients/AuthAPI';
import LineDetail from '../../domain/repositories/LineDetail';
import {Line} from '../../presentation/screens/BusStopInfoScreen';
import BusStopInfoService from '../../domain/services/BusStopInfoService';
export enum Status {
LOADING = 'LOADING',
SUCCESS = 'SUCCESS',
ERROR = 'ERROR',
}
interface State {
status: Status;
lines: LineDetail[];
displayedLines: Line[];
currentIndex: number;
stopMessage: string;
stopName: string;
}
const DEVICE_ID = 'TTM543870hyt';
const BASE_URL = 'https://transporte.hz.kursor.cl';
const USER = 'usuario1';
const PASSWORD = 'usuario1';
const useDevices = () => {
const [state, setState] = useState<State>({
status: Status.LOADING,
currentIndex: 0,
stopMessage: '',
displayedLines: [],
lines: [],
stopName: 'Sin información - Sin información',
});
const baseUrl = BASE_URL; // TODO: remoteconfig ?
const username = USER;
const password = PASSWORD;
const deviceApi = useMemo(() => new DevicesAPI(baseUrl), [baseUrl]);
const authApi = useMemo(() => new AuthAPI(baseUrl), [baseUrl]);
const devicesRepository = useMemo(
() => new DevicesRepositoryImpl(deviceApi),
[deviceApi],
);
const authRepository = useMemo(
() => new AuthRepositoryImpl(authApi),
[authApi],
);
const setDisplayedLines = useCallback(
(lineDetails: LineDetail[], stopMessage: string, stopName: string) => {
if (!lineDetails || !stopName) {
return;
}
try {
let busStopInfoService = new BusStopInfoService(lineDetails);
const linesWithArrivals = lineDetails
.map(line => {
try {
busStopInfoService.getNextArraival(line.lineNumber);
return line;
} catch (error) {
return undefined;
}
})
.filter((line): line is LineDetail => line !== undefined);
busStopInfoService = new BusStopInfoService(linesWithArrivals);
const linesToDisplay: Line[] = busStopInfoService
.pruneBusList(state.currentIndex, 21) // result 7 * 3
.map(line => {
try {
const nextArraival = busStopInfoService.getNextArraival(
line.lineNumber,
);
const estimatedArrivalTimeInMinutes =
busStopInfoService.checkArraivalTime(nextArraival);
const lineLetter =
busStopInfoService.getLineLetterFromDescription(
line.description,
);
const lineNumber =
busStopInfoService.getLineNumberFromDescription(
line.description,
);
const lineDescription = busStopInfoService.getLineDescription(
line.description,
line.lineNumber,
);
return {
backgroundColor: line.backgroundColor,
estimatedArrivalTimeInMinutes,
letterColor: line.letterColor,
lineLetter,
lineNumber,
lineDescription,
};
} catch (error) {
return undefined;
}
})
.filter((line): line is Line => line !== undefined);
setState(prevState => {
const displayedLines =
linesToDisplay.length === 0
? prevState.displayedLines
: linesToDisplay;
return {
...prevState,
displayedLines,
stopMessage,
stopName,
lines: lineDetails,
};
});
} catch (error: unknown) {
setState(prevState => ({
...prevState,
status: Status.ERROR,
}));
}
},
[state.currentIndex],
);
useEffect(() => {
const init = async () => {
try {
const token = await authRepository.auth({username, password});
const {lineDetails, stopMessage} =
await devicesRepository.getDeviceInfo({
deviceId: DEVICE_ID,
token,
});
const {stopName} = await devicesRepository.whoAmI({
deviceId: DEVICE_ID,
token,
});
if (!lineDetails) {
setState((prevState: State) => ({
...prevState,
status: Status.ERROR,
}));
return;
}
setState((prevState: State) => ({
...prevState,
...{
lines: lineDetails,
stopMessage,
stopName,
status: Status.SUCCESS,
},
}));
} catch (error) {
setState((prevState: State) => ({
...prevState,
status: Status.ERROR,
}));
}
};
init();
}, [authRepository, devicesRepository, password, username]);
useEffect(() => {
setDisplayedLines(state.lines, state.stopMessage, state.stopName);
}, [setDisplayedLines, state.lines, state.stopMessage, state.stopName]);
useEffect(() => {
const interval = setInterval(() => {
setState(prevState => {
const isGreatherThanLinesLength =
(prevState.currentIndex || 1) + 21 >= state.lines.length;
return {
...prevState,
currentIndex: isGreatherThanLinesLength
? 0
: (prevState.currentIndex || 1 + 21) % state.lines.length,
};
});
}, 5000);
return () => {
clearInterval(interval);
};
}, [state.lines, state.status]);
return {state};
};
export default useDevices;