mirror of https://gitlab.com/m3f_usm/SmartStopAPK
feat: some code reafactor + change page and buses list interval is added
parent
465a220a97
commit
5782b43b3b
|
@ -3,6 +3,7 @@ import useDevices from '../useDevices';
|
|||
import AuthRepositoryImpl from '../../repositories/AuthRepositoryImpl';
|
||||
import DevicesRepositoryImpl from '../../repositories/DevicesRepositoryImpl';
|
||||
|
||||
jest.useFakeTimers();
|
||||
describe('useDevices tests', () => {
|
||||
beforeAll(() => {
|
||||
jest.spyOn(AuthRepositoryImpl.prototype, 'auth').mockResolvedValue('token');
|
||||
|
@ -96,7 +97,6 @@ describe('useDevices tests', () => {
|
|||
const mockDate = new Date('2023-01-01T14:00:00Z');
|
||||
const spy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
|
||||
const {result} = renderHook(() => useDevices());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.state.lines).toMatchObject([
|
||||
{
|
||||
|
|
|
@ -6,15 +6,10 @@ 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';
|
||||
import RemoteConfigKeys from '../../utils/RemoteConfigKeys';
|
||||
|
||||
export enum Status {
|
||||
LOADING = 'LOADING',
|
||||
SUCCESS = 'SUCCESS',
|
||||
ERROR = 'ERROR',
|
||||
}
|
||||
import {Line} from '../../presentation/components/Table';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
interface State {
|
||||
status: Status;
|
||||
|
@ -40,8 +35,11 @@ const useDevices = () => {
|
|||
const baseURL = remoteConfig().getString(RemoteConfigKeys.BASE_URL);
|
||||
const username = remoteConfig().getString(RemoteConfigKeys.USER);
|
||||
const password = remoteConfig().getString(RemoteConfigKeys.PASS);
|
||||
const updateInterval = remoteConfig().getNumber(
|
||||
RemoteConfigKeys.UPDATE_INTERVAL,
|
||||
const changePageInterval = remoteConfig().getNumber(
|
||||
RemoteConfigKeys.CHANGE_PAGE_INTERVAL,
|
||||
);
|
||||
const updateBusesListInterval = remoteConfig().getNumber(
|
||||
RemoteConfigKeys.UPDATE_BUSES_LIST_INTERVAL,
|
||||
);
|
||||
|
||||
const deviceApi = useMemo(() => new DevicesAPI(baseURL), [baseURL]);
|
||||
|
@ -182,7 +180,19 @@ const useDevices = () => {
|
|||
};
|
||||
|
||||
init();
|
||||
}, [authRepository, devicesRepository, password, username]);
|
||||
|
||||
const interval = setInterval(init, updateBusesListInterval);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [
|
||||
authRepository,
|
||||
devicesRepository,
|
||||
password,
|
||||
username,
|
||||
updateBusesListInterval,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setDisplayedLines(state.lines, state.stopMessage, state.stopName);
|
||||
|
@ -201,12 +211,12 @@ const useDevices = () => {
|
|||
: (prevState.currentIndex || 1 + 21) % state.lines.length,
|
||||
};
|
||||
});
|
||||
}, 5000);
|
||||
}, changePageInterval);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [state.lines, state.status, updateInterval]);
|
||||
}, [state.lines, state.status, changePageInterval]);
|
||||
|
||||
return {state};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
import {useCallback, useEffect, useState} from 'react';
|
||||
import remoteConfig from '@react-native-firebase/remote-config';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
const useRemoteConfig = () => {
|
||||
const [status, setStatus] = useState(Status.LOADING);
|
||||
|
||||
const getString = useCallback(
|
||||
(key: string) => remoteConfig().getString(key),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
try {
|
||||
await remoteConfig().setConfigSettings({
|
||||
minimumFetchIntervalMillis: 3600000,
|
||||
});
|
||||
|
||||
// TODO: Add default values for remote config
|
||||
await remoteConfig().setDefaults({
|
||||
BASE_URL: '',
|
||||
HEADER_IMAGE_URL: '',
|
||||
USER: '',
|
||||
PASS: '',
|
||||
CHANGE_PAGE_INTERVAL: 0,
|
||||
UPDATE_BUSES_LIST_INTERVAL: 0,
|
||||
});
|
||||
|
||||
const isActivated = await remoteConfig().fetchAndActivate();
|
||||
|
||||
if (isActivated) {
|
||||
setStatus(Status.SUCCESS);
|
||||
}
|
||||
} catch (error) {
|
||||
setStatus(Status.ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
}, []);
|
||||
|
||||
return {status, getString};
|
||||
};
|
||||
|
||||
export default useRemoteConfig;
|
|
@ -0,0 +1,24 @@
|
|||
import {View, ActivityIndicator, StyleProp} from 'react-native';
|
||||
import {ViewStyle} from 'react-native';
|
||||
import Table, {Line} from './Table';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
interface BusListProps {
|
||||
buses: Line[];
|
||||
status: Status;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
const BusList = ({buses, status, style}: BusListProps) => {
|
||||
return (
|
||||
<View style={style}>
|
||||
{status === Status.LOADING ? (
|
||||
<ActivityIndicator testID="LOADING" />
|
||||
) : (
|
||||
<Table data={buses} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default BusList;
|
|
@ -21,7 +21,7 @@ const Header = ({title, subTitle, style, image}: HeaderProps) => {
|
|||
<View style={styles.iconContainer}>
|
||||
<Image
|
||||
source={{
|
||||
uri: 'https://cdn-icons-png.flaticon.com/512/8371/8371047.png',
|
||||
uri: image,
|
||||
}}
|
||||
style={styles.icon}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
import {View, Text, StyleSheet} from 'react-native';
|
||||
|
||||
export interface Line {
|
||||
lineNumber: string;
|
||||
lineLetter: string;
|
||||
letterColor: string;
|
||||
backgroundColor: string;
|
||||
estimatedArrivalTimeInMinutes: string;
|
||||
lineDescription: string;
|
||||
}
|
||||
|
||||
export interface TableProps {
|
||||
data: Line[];
|
||||
}
|
||||
|
||||
const Table = ({data}: TableProps) => {
|
||||
const rows = 7;
|
||||
const columns = 3;
|
||||
|
||||
const baseTableData: Line[][] = Array.from({length: rows}, () =>
|
||||
new Array(columns).fill({
|
||||
lineNumber: '',
|
||||
lineLetter: '',
|
||||
letterColor: '',
|
||||
backgroundColor: '',
|
||||
estimatedArrivalTimeInMinutes: '',
|
||||
}),
|
||||
);
|
||||
|
||||
data.map((item, index) => {
|
||||
const row = Math.floor(index / columns);
|
||||
const column = index % columns;
|
||||
baseTableData[row][column] = item;
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={tableStyles.table}>
|
||||
{baseTableData.map((row, rowIndex) => (
|
||||
<View key={rowIndex} style={tableStyles.row}>
|
||||
{row.map((cell, cellIndex) => {
|
||||
if (cell.lineNumber === '') {
|
||||
return <View style={tableStyles.cell} key={cellIndex} />;
|
||||
}
|
||||
|
||||
const [first, second] = cell.lineDescription.split('-');
|
||||
|
||||
return (
|
||||
<View style={[tableStyles.cell]} key={cellIndex}>
|
||||
<View style={tableStyles.lineInformationContainer}>
|
||||
<Text style={tableStyles.lineNumber}>{cell.lineNumber}</Text>
|
||||
<View
|
||||
style={[
|
||||
tableStyles.letterContainer,
|
||||
{backgroundColor: `#${cell.backgroundColor}` || 'grey'},
|
||||
]}>
|
||||
<Text style={tableStyles.lineLetter}>
|
||||
{cell.lineLetter}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
tableStyles.timeContainer,
|
||||
{backgroundColor: `#${cell.backgroundColor}` || 'grey'},
|
||||
]}>
|
||||
<Text style={tableStyles.time} numberOfLines={1}>
|
||||
{first}
|
||||
</Text>
|
||||
<Text style={tableStyles.time} numberOfLines={1}>
|
||||
{second}
|
||||
</Text>
|
||||
<Text style={tableStyles.time}>
|
||||
{cell.estimatedArrivalTimeInMinutes}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const tableStyles = StyleSheet.create({
|
||||
table: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
row: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
cell: {
|
||||
flex: 1,
|
||||
borderWidth: 1,
|
||||
flexDirection: 'column',
|
||||
borderColor: 'grey',
|
||||
},
|
||||
lineInformationContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
timeContainer: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'blue',
|
||||
},
|
||||
lineNumber: {
|
||||
fontSize: 20,
|
||||
marginRight: 8,
|
||||
fontWeight: 'bold',
|
||||
color: 'grey',
|
||||
},
|
||||
lineLetter: {
|
||||
fontSize: 14,
|
||||
color: 'white',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
letterContainer: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 50,
|
||||
},
|
||||
time: {
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
},
|
||||
lineDescription: {
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
},
|
||||
});
|
||||
|
||||
export default Table;
|
|
@ -0,0 +1,149 @@
|
|||
export default [
|
||||
{
|
||||
backgroundColor: 'b10086',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'N',
|
||||
lineNumber: '10',
|
||||
lineDescription: 'Vía Láctea - Los Bloques',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0d7215',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'O',
|
||||
lineNumber: '10',
|
||||
lineDescription: 'Vía Láctea - Pobl. Porvenir',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0071ca',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'P',
|
||||
lineNumber: '10',
|
||||
lineDescription: 'Vía Láctea - Leonera',
|
||||
},
|
||||
{
|
||||
backgroundColor: '4e0963',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'L',
|
||||
lineNumber: '10',
|
||||
lineDescription: 'Vía Láctea - Los Bloques',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ad0101',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'Q',
|
||||
lineNumber: '11',
|
||||
lineDescription: 'Vía Futuro - Los Bloques',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'b10086',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'R',
|
||||
lineNumber: '11',
|
||||
lineDescription: 'Vía Futuro - Porvenir',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ce5504',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'S',
|
||||
lineNumber: '13',
|
||||
lineDescription: 'Vía Siglo XXI - Leonera',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ce5504',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'T',
|
||||
lineNumber: '14',
|
||||
lineDescription: 'Chiguayante Sur - Coquimbo',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'cc9b00',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'U',
|
||||
lineNumber: '14',
|
||||
lineDescription: 'Chiguayante Sur - Los Altos',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ad0101',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'V',
|
||||
lineNumber: '16',
|
||||
lineDescription: 'Vía Universo - Leonera',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0d7215',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'W',
|
||||
lineNumber: '17',
|
||||
lineDescription: 'Expresos Chiguayante - Leonera',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ce5504',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'X',
|
||||
lineNumber: '17',
|
||||
lineDescription: 'Expresos Chiguayante - Leonera',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0071ca',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'Y',
|
||||
lineNumber: '18',
|
||||
lineDescription: 'Buses Palomares - Hualqui',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'b10086',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'M',
|
||||
lineNumber: '20',
|
||||
lineDescription: 'Nueva Llacolén - San Pedro Costa',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0071ca',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'A',
|
||||
lineNumber: '20',
|
||||
lineDescription: 'Nueva Llacolén - Boca Sur',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ce5504',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'B',
|
||||
lineNumber: '21',
|
||||
lineDescription: 'Riviera Biobío - Candelaria',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0071ca',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'F',
|
||||
lineNumber: '24',
|
||||
lineDescription: 'San Remo - Candelaria',
|
||||
},
|
||||
{
|
||||
backgroundColor: '0d7215',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'Q',
|
||||
lineNumber: '30',
|
||||
lineDescription: 'Ruta Las Playas - Higueras',
|
||||
},
|
||||
{
|
||||
backgroundColor: '049684',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'R',
|
||||
lineNumber: '30',
|
||||
lineDescription: 'Ruta Las Playas - Higueras',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ce5504',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'Y',
|
||||
lineNumber: '57',
|
||||
lineDescription: 'Denavi Sur - Cosmito',
|
||||
},
|
||||
{
|
||||
backgroundColor: 'ce5504',
|
||||
estimatedArrivalTimeInMinutes: 'Más de 10 minutos',
|
||||
lineLetter: 'P',
|
||||
lineNumber: '57',
|
||||
lineDescription: 'Denavi Sur - San Vicente',
|
||||
},
|
||||
];
|
|
@ -0,0 +1,27 @@
|
|||
import {render} from '@testing-library/react-native';
|
||||
import BusList from '../BusList';
|
||||
import Status from '../../../utils/Status';
|
||||
|
||||
describe('BusList tests', () => {
|
||||
it('should be defined', () => {
|
||||
expect(BusList).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render correctly with status LOADING', () => {
|
||||
const {toJSON, getByTestId} = render(
|
||||
<BusList buses={[]} status={Status.LOADING} />,
|
||||
);
|
||||
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
expect(getByTestId('LOADING')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render correctly with status SUCCESS', () => {
|
||||
const {toJSON, queryByTestId} = render(
|
||||
<BusList buses={[]} status={Status.SUCCESS} />,
|
||||
);
|
||||
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
expect(queryByTestId('LOADING')).toBeNull();
|
||||
});
|
||||
});
|
|
@ -7,13 +7,17 @@ describe('Header tests', () => {
|
|||
});
|
||||
|
||||
it('should render correctly', () => {
|
||||
const {toJSON} = render(<Header title="Title" subTitle="Subtitle" />);
|
||||
const {toJSON} = render(
|
||||
<Header title="Title" subTitle="Subtitle" image="https://urlimage.cl" />,
|
||||
);
|
||||
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render a title and a subtitle', () => {
|
||||
const {getByText} = render(<Header title="Title" subTitle="Subtitle" />);
|
||||
const {getByText} = render(
|
||||
<Header title="Title" subTitle="Subtitle" image="https://urlimage.cl" />,
|
||||
);
|
||||
|
||||
expect(getByText('Title')).toBeDefined();
|
||||
expect(getByText('Subtitle')).toBeDefined();
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import {render} from '@testing-library/react-native';
|
||||
import Table, {Line} from '../Table';
|
||||
import lineListMock from '../__mocks__/LineList';
|
||||
|
||||
describe('Table tests', () => {
|
||||
it('should be defined', () => {
|
||||
expect(Table).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render correctly', () => {
|
||||
const {toJSON} = render(<Table data={lineListMock as Line[]} />);
|
||||
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render correctly with empty data', () => {
|
||||
const {toJSON} = render(<Table data={[]} />);
|
||||
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,296 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BusList tests should render correctly with status LOADING 1`] = `
|
||||
<View>
|
||||
<ActivityIndicator
|
||||
testID="LOADING"
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`BusList tests should render correctly with status SUCCESS 1`] = `
|
||||
<View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "white",
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
|
@ -29,7 +29,7 @@ exports[`Header tests should render correctly 1`] = `
|
|||
<Image
|
||||
source={
|
||||
{
|
||||
"uri": "https://cdn-icons-png.flaticon.com/512/8371/8371047.png",
|
||||
"uri": "https://urlimage.cl",
|
||||
}
|
||||
}
|
||||
style={
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,131 +1,25 @@
|
|||
import {ActivityIndicator, StyleSheet, View} from 'react-native';
|
||||
import Container from '../components/Container';
|
||||
import Header from '../components/Header';
|
||||
import {Text} from 'react-native';
|
||||
import useDevices, {Status} from '../../infraestructure/hooks/useDevices';
|
||||
import useDevices from '../../infraestructure/hooks/useDevices';
|
||||
import Banner from '../components/Banner';
|
||||
import {useEffect, useState} from 'react';
|
||||
import remoteConfig from '@react-native-firebase/remote-config';
|
||||
import RemoteConfigKeys from '../../utils/RemoteConfigKeys';
|
||||
import BusList from '../components/BusList';
|
||||
import useRemoteConfig from '../../infraestructure/hooks/useRemoteConfig';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
export interface Line {
|
||||
lineNumber: string;
|
||||
lineLetter: string;
|
||||
letterColor: string;
|
||||
backgroundColor: string;
|
||||
estimatedArrivalTimeInMinutes: string;
|
||||
lineDescription: string;
|
||||
}
|
||||
|
||||
interface TableProps {
|
||||
data: Line[];
|
||||
}
|
||||
|
||||
const Table = ({data}: TableProps) => {
|
||||
const rows = 7;
|
||||
const columns = 3;
|
||||
|
||||
const baseTableData: Line[][] = Array.from({length: rows}, () =>
|
||||
new Array(columns).fill({
|
||||
lineNumber: '',
|
||||
lineLetter: '',
|
||||
letterColor: '',
|
||||
backgroundColor: '',
|
||||
estimatedArrivalTimeInMinutes: '',
|
||||
}),
|
||||
);
|
||||
|
||||
data.map((item, index) => {
|
||||
const row = Math.floor(index / columns);
|
||||
const column = index % columns;
|
||||
baseTableData[row][column] = item;
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={tableStyles.table}>
|
||||
{baseTableData.map((row, rowIndex) => (
|
||||
<View key={rowIndex} style={tableStyles.row}>
|
||||
{row.map((cell, cellIndex) => {
|
||||
if (cell.lineNumber === '') {
|
||||
return <View style={tableStyles.cell} key={cellIndex} />;
|
||||
}
|
||||
|
||||
const [first, second] = cell.lineDescription.split('-');
|
||||
|
||||
return (
|
||||
<View style={[tableStyles.cell]} key={cellIndex}>
|
||||
<View style={tableStyles.lineInformationContainer}>
|
||||
<Text style={tableStyles.lineNumber}>{cell.lineNumber}</Text>
|
||||
<View
|
||||
style={[
|
||||
tableStyles.letterContainer,
|
||||
{backgroundColor: `#${cell.backgroundColor}` || 'grey'},
|
||||
]}>
|
||||
<Text style={tableStyles.lineLetter}>
|
||||
{cell.lineLetter}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
tableStyles.timeContainer,
|
||||
{backgroundColor: `#${cell.backgroundColor}` || 'grey'},
|
||||
]}>
|
||||
<Text style={tableStyles.time} numberOfLines={1}>
|
||||
{first}
|
||||
</Text>
|
||||
<Text style={tableStyles.time} numberOfLines={1}>
|
||||
{second}
|
||||
</Text>
|
||||
<Text style={tableStyles.time}>
|
||||
{cell.estimatedArrivalTimeInMinutes}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
const BANNER_TEXT = 'Buses que se detienen en esta parada';
|
||||
|
||||
const BusStopInfoScreen = () => {
|
||||
const {
|
||||
state: {status, displayedLines, stopName},
|
||||
} = useDevices();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const image = remoteConfig().getString(RemoteConfigKeys.HEADER_IMAGE_URL);
|
||||
const {status, displayedLines, stopName} = useDevices().state;
|
||||
const {status: remoteConfigStatus, getString} = useRemoteConfig();
|
||||
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
await remoteConfig().setConfigSettings({
|
||||
minimumFetchIntervalMillis: 3600000,
|
||||
});
|
||||
const image = getString(RemoteConfigKeys.HEADER_IMAGE_URL);
|
||||
const [first, second] = stopName.split('-');
|
||||
const title = first ? first.trim() : '';
|
||||
const subTitle = second ? second.trim() : '';
|
||||
|
||||
await remoteConfig().setDefaults({
|
||||
BASE_URL: '',
|
||||
HEADER_IMAGE_URL: '',
|
||||
UPDATE_INTERVAL: 0,
|
||||
USER: '',
|
||||
PASS: '',
|
||||
});
|
||||
|
||||
const isActivated = await remoteConfig().fetchAndActivate();
|
||||
|
||||
if (isActivated) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
}, []);
|
||||
|
||||
const splitStopName = stopName.split('-');
|
||||
let title = splitStopName[0] ? `${splitStopName[0].trim()}` : '';
|
||||
const subTitle = splitStopName[1] ? `${splitStopName[1].trim()}` : '';
|
||||
|
||||
if (isLoading) {
|
||||
if (remoteConfigStatus === Status.LOADING) {
|
||||
return (
|
||||
<Container style={styles.container}>
|
||||
<ActivityIndicator />
|
||||
|
@ -141,18 +35,12 @@ const BusStopInfoScreen = () => {
|
|||
title={title}
|
||||
image={image}
|
||||
/>
|
||||
<Banner
|
||||
style={styles.bannerContainer}
|
||||
text="Buses que se detienen en esta parada"
|
||||
<Banner style={styles.bannerContainer} text={BANNER_TEXT} />
|
||||
<BusList
|
||||
buses={displayedLines}
|
||||
style={styles.bodyContainer}
|
||||
status={status}
|
||||
/>
|
||||
|
||||
<View style={styles.bodyContainer}>
|
||||
{status === Status.LOADING ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<Table data={displayedLines} />
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.footerContainer}>
|
||||
{/* {TODO implement footer} */}
|
||||
</View>
|
||||
|
@ -176,67 +64,10 @@ const styles = StyleSheet.create({
|
|||
flex: 10,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
busContainer: {
|
||||
backgroundColor: 'brown',
|
||||
flexDirection: 'column',
|
||||
},
|
||||
footerContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: 'grey',
|
||||
},
|
||||
});
|
||||
|
||||
const tableStyles = StyleSheet.create({
|
||||
table: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
row: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
cell: {
|
||||
flex: 1,
|
||||
borderWidth: 1,
|
||||
flexDirection: 'column',
|
||||
borderColor: 'grey',
|
||||
},
|
||||
lineInformationContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
timeContainer: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'blue',
|
||||
},
|
||||
lineNumber: {
|
||||
fontSize: 20,
|
||||
marginRight: 8,
|
||||
fontWeight: 'bold',
|
||||
color: 'grey',
|
||||
},
|
||||
lineLetter: {
|
||||
fontSize: 14,
|
||||
color: 'white',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
letterContainer: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 50,
|
||||
},
|
||||
time: {
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
},
|
||||
lineDescription: {
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
},
|
||||
});
|
||||
|
||||
export default BusStopInfoScreen;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
enum RemoteConfigKeys {
|
||||
BASE_URL = 'BASE_URL',
|
||||
HEADER_IMAGE_URL = 'HEADER_IMAGE_URL',
|
||||
UPDATE_INTERVAL = 'UPDATE_INTERVAL',
|
||||
CHANGE_PAGE_INTERVAL = 'CHANGE_PAGE_INTERVAL',
|
||||
UPDATE_BUSES_LIST_INTERVAL = 'UPDATE_BUSES_LIST_INTERVAL',
|
||||
USER = 'USER',
|
||||
PASS = 'PASSWORD',
|
||||
}
|
||||
|
||||
export default RemoteConfigKeys;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
enum Status {
|
||||
LOADING,
|
||||
SUCCESS,
|
||||
ERROR,
|
||||
}
|
||||
|
||||
export default Status;
|
Loading…
Reference in New Issue