Skip to content

Commit c8591da

Browse files
committed
Removed patch in vehicleTypeSelection
1 parent ca8deca commit c8591da

File tree

8 files changed

+198
-174
lines changed

8 files changed

+198
-174
lines changed

apps/demo-app/src/pages/VehicleTypeSelectionPage/VehicleTypeSelectionPage.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import { useMonkAppState } from '@monkvision/common';
55
import { Page } from '../pages';
66

77
export function VehicleTypeSelectionPage() {
8-
const { config, vehicleType, setVehicleType } = useMonkAppState();
8+
const { config, vehicleType, authToken, inspectionId, setVehicleType } = useMonkAppState();
99
const { i18n } = useTranslation();
1010

1111
if (vehicleType || !config.allowVehicleTypeSelection) {
1212
return <Navigate to={Page.PHOTO_CAPTURE} replace />;
1313
}
1414

15-
return <VehicleTypeSelection onSelectVehicleType={setVehicleType} lang={i18n.language} />;
15+
return (
16+
<VehicleTypeSelection
17+
onSelectVehicleType={setVehicleType}
18+
lang={i18n.language}
19+
inspectionId={inspectionId ?? ''}
20+
authToken={authToken ?? ''}
21+
apiDomain={config.apiDomain}
22+
/>
23+
);
1624
}

apps/drive-app/src/pages/VehicleTypeSelectionPage/VehicleTypeSelectionPage.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import { useMonkAppState } from '@monkvision/common';
55
import { Page } from '../pages';
66

77
export function VehicleTypeSelectionPage() {
8-
const { config, vehicleType, setVehicleType } = useMonkAppState();
8+
const { config, vehicleType, authToken, inspectionId, setVehicleType } = useMonkAppState();
99
const { i18n } = useTranslation();
1010

1111
if (vehicleType || !config.allowVehicleTypeSelection) {
1212
return <Navigate to={Page.PHOTO_CAPTURE} replace />;
1313
}
1414

15-
return <VehicleTypeSelection onSelectVehicleType={setVehicleType} lang={i18n.language} />;
15+
return (
16+
<VehicleTypeSelection
17+
onSelectVehicleType={setVehicleType}
18+
lang={i18n.language}
19+
inspectionId={inspectionId ?? ''}
20+
authToken={authToken ?? ''}
21+
apiDomain={config.apiDomain}
22+
/>
23+
);
1624
}

apps/lux-demo-app/src/pages/VehicleTypeSelectionPage/VehicleTypeSelectionPage.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import { useMonkAppState } from '@monkvision/common';
55
import { Page } from '../pages';
66

77
export function VehicleTypeSelectionPage() {
8-
const { config, vehicleType, setVehicleType } = useMonkAppState();
8+
const { config, vehicleType, authToken, inspectionId, setVehicleType } = useMonkAppState();
99
const { i18n } = useTranslation();
1010

1111
if (vehicleType || !config.allowVehicleTypeSelection) {
1212
return <Navigate to={Page.PHOTO_CAPTURE} replace />;
1313
}
1414

15-
return <VehicleTypeSelection onSelectVehicleType={setVehicleType} lang={i18n.language} />;
15+
return (
16+
<VehicleTypeSelection
17+
onSelectVehicleType={setVehicleType}
18+
lang={i18n.language}
19+
inspectionId={inspectionId ?? ''}
20+
authToken={authToken ?? ''}
21+
apiDomain={config.apiDomain}
22+
/>
23+
);
1624
}

apps/renault-demo-app/src/pages/VehicleTypeSelectionPage/VehicleTypeSelectionPage.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import { useMonkAppState } from '@monkvision/common';
55
import { Page } from '../pages';
66

77
export function VehicleTypeSelectionPage() {
8-
const { config, vehicleType, setVehicleType } = useMonkAppState();
8+
const { config, vehicleType, authToken, inspectionId, setVehicleType } = useMonkAppState();
99
const { i18n } = useTranslation();
1010

1111
if (vehicleType || !config.allowVehicleTypeSelection) {
1212
return <Navigate to={Page.PHOTO_CAPTURE} replace />;
1313
}
1414

15-
return <VehicleTypeSelection onSelectVehicleType={setVehicleType} lang={i18n.language} />;
15+
return (
16+
<VehicleTypeSelection
17+
onSelectVehicleType={setVehicleType}
18+
lang={i18n.language}
19+
inspectionId={inspectionId ?? ''}
20+
authToken={authToken ?? ''}
21+
apiDomain={config.apiDomain}
22+
/>
23+
);
1624
}

packages/common-ui-web/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,4 +618,6 @@ function VehicleSelectionPage() {
618618
| availableVehicleTypes | VehicleType[] | A list of available vehicle type to choose from. The order of the list will be modified to always follow the same order. | | `[SUV, CUV, SEDAN, HATCHBACK, VAN, MINIVAN, PICKUP]` |
619619
| onSelectVehicleType | (type: VehicleType) => void | Callback called when the user has selected a vehicle type. | | The center-most vehicle type in the list. |
620620
| lang | string | The language to use by the component. | | `en` |
621-
| patchInspection | boolean | Boolean indicating if the patch vehicle inspection feature is enabled. | | `true` |
621+
| inspectionId | string | The ID of the inspection. | | |
622+
| apiDomain | string | The domain of the Monk API. | | |
623+
| authToken | string | The authentication token used to communicate with the API. | | |

packages/common-ui-web/src/components/VehicleTypeSelection/VehicleTypeSelection.tsx

Lines changed: 112 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,39 @@ import {
33
i18nWrap,
44
useI18nSync,
55
useLoadingState,
6-
useMonkAppState,
76
useMonkTheme,
87
useResponsiveStyle,
98
} from '@monkvision/common';
10-
import { VehicleType } from '@monkvision/types';
9+
import { AllOrNone, VehicleType } from '@monkvision/types';
1110
import { RefObject, useEffect, useMemo, useRef, useState } from 'react';
12-
import { decodeMonkJwt, useMonkApi } from '@monkvision/network';
11+
import { decodeMonkJwt, MonkApiConfig, useMonkApi } from '@monkvision/network';
1312
import { useMonitoring } from '@monkvision/monitoring';
1413
import { useAnalytics } from '@monkvision/analytics';
1514
import { styles } from './VehicleTypeSelection.styles';
1615
import { i18nVehicleTypeSelection } from './i18n';
1716
import { Button } from '../Button';
18-
import { getInitialSelectedVehicleType, getVehicleTypes } from './utils';
17+
import {
18+
getInitialSelectedVehicleType,
19+
getVehicleTypeFromInspection,
20+
getVehicleTypes,
21+
} from './utils';
1922
import { VehicleTypeSelectionCard } from './VehicleTypeSelectionCard';
2023
import { Spinner } from '../Spinner';
2124

25+
/**
26+
* Props used to check if a vehicle type is already defined before displaying vehicle type selection.
27+
*/
28+
export interface MonkApiProps extends MonkApiConfig {
29+
/**
30+
* The ID of the inspection.
31+
*/
32+
inspectionId: string;
33+
}
34+
2235
/**
2336
* Props accepted by the VehicleTypeSelection component.
2437
*/
25-
export interface VehicleTypeSelectionProps {
38+
export type VehicleTypeSelectionProps = {
2639
/**
2740
* The initially selected vehicle type.
2841
*
@@ -46,16 +59,7 @@ export interface VehicleTypeSelectionProps {
4659
* @default en
4760
*/
4861
lang?: string;
49-
/**
50-
* Boolean indicating if the patch vehicle inspection feature is enabled. If true, it will trigger 2 actions:
51-
* - At the start, it will check if a vehicle type is defined. If so, it will immediately
52-
* call the 'onSelectVehicleType' callback.
53-
* - When the 'confirm button' is pressed by the user, it will make a request to the API to PATCH the vehicle type of the inspection.
54-
*
55-
* @default true
56-
*/
57-
patchInspection?: boolean;
58-
}
62+
} & AllOrNone<MonkApiProps>;
5963

6064
function scrollToSelectedVehicleType(
6165
ref: RefObject<HTMLDivElement>,
@@ -73,126 +77,105 @@ function scrollToSelectedVehicleType(
7377
/**
7478
* A single page component that allows the user to select a vehicle type.
7579
*/
76-
export const VehicleTypeSelection = i18nWrap(
77-
({
78-
availableVehicleTypes,
79-
selectedVehicleType,
80-
onSelectVehicleType,
81-
lang,
82-
patchInspection = true,
83-
}: VehicleTypeSelectionProps) => {
84-
useI18nSync(lang);
85-
const { config, authToken, inspectionId } = useMonkAppState();
86-
const { updateInspectionVehicle, getInspection } = useMonkApi({
87-
authToken: authToken ?? '',
88-
apiDomain: config.apiDomain,
89-
});
90-
const loading = useLoadingState(true);
91-
const { handleError, setTags, setUserId } = useMonitoring();
92-
const analytics = useAnalytics();
93-
const [initialScroll, setInitialScroll] = useState(true);
94-
const vehicleTypes = useMemo(
95-
() => getVehicleTypes(availableVehicleTypes),
96-
[availableVehicleTypes],
97-
);
98-
const [selected, setSelected] = useState(
99-
getInitialSelectedVehicleType(vehicleTypes, selectedVehicleType),
100-
);
101-
const { t } = useTranslation();
102-
const { rootStyles } = useMonkTheme();
103-
const sliderRef = useRef<HTMLDivElement>(null);
104-
const { responsive } = useResponsiveStyle();
80+
export const VehicleTypeSelection = i18nWrap((props: VehicleTypeSelectionProps) => {
81+
useI18nSync(props.lang);
82+
const { getInspection } = useMonkApi({
83+
authToken: props.authToken ?? '',
84+
apiDomain: props.apiDomain ?? '',
85+
});
86+
const loading = useLoadingState(true);
87+
const { handleError, setTags, setUserId } = useMonitoring();
88+
const analytics = useAnalytics();
89+
const [initialScroll, setInitialScroll] = useState(true);
90+
const vehicleTypes = useMemo(
91+
() => getVehicleTypes(props.availableVehicleTypes),
92+
[props.availableVehicleTypes],
93+
);
94+
const [selected, setSelected] = useState(
95+
getInitialSelectedVehicleType(vehicleTypes, props.selectedVehicleType),
96+
);
97+
const { t } = useTranslation();
98+
const { rootStyles } = useMonkTheme();
99+
const sliderRef = useRef<HTMLDivElement>(null);
100+
const { responsive } = useResponsiveStyle();
105101

106-
const onValidate = (type: VehicleType) => {
107-
if (patchInspection && inspectionId) {
108-
updateInspectionVehicle({ inspectionId, vehicle: { type } });
109-
}
110-
onSelectVehicleType?.(type);
111-
};
102+
useEffect(() => {
103+
if (props.inspectionId) {
104+
setTags({ inspectionId: props.inspectionId });
105+
analytics.setUserId(props.inspectionId);
106+
}
107+
const userId = props.authToken ? decodeMonkJwt(props.authToken) : undefined;
108+
if (userId?.sub) {
109+
setUserId(userId.sub);
110+
analytics.setUserProperties({ authToken: userId.sub });
111+
}
112+
}, [props.inspectionId, props.authToken, analytics, setTags, setUserId]);
112113

113-
useEffect(() => {
114-
if (inspectionId) {
115-
setTags({ inspectionId });
116-
analytics.setUserId(inspectionId);
114+
useEffect(() => {
115+
const fetchInspection = async () => {
116+
if (!props.inspectionId) {
117+
loading.onSuccess();
118+
return;
117119
}
118-
const userId = authToken ? decodeMonkJwt(authToken) : undefined;
119-
if (userId?.sub) {
120-
setUserId(userId.sub);
121-
analytics.setUserProperties({ authToken: userId.sub });
120+
loading.start();
121+
const fetchedInspection = await getInspection({
122+
id: props.inspectionId,
123+
});
124+
const vehicleType = getVehicleTypeFromInspection(fetchedInspection);
125+
if (vehicleType && props.availableVehicleTypes?.includes(vehicleType)) {
126+
props.onSelectVehicleType?.(vehicleType);
122127
}
123-
}, [inspectionId, authToken, analytics, setTags, setUserId]);
124-
125-
useEffect(() => {
126-
const fetchInspection = async () => {
127-
if (patchInspection && inspectionId) {
128-
const fetchedInspection = await getInspection({
129-
id: inspectionId,
130-
});
128+
loading.onSuccess();
129+
};
131130

132-
const vehicle = fetchedInspection.entities.vehicles.find(
133-
(v) => v.inspectionId === inspectionId,
134-
);
135-
const vehicleTypeFoundInInspection = Object.values(VehicleType).find(
136-
(vehicleType) => vehicleType === vehicle?.type,
137-
);
138-
if (vehicleTypeFoundInInspection) {
139-
onSelectVehicleType?.(vehicleTypeFoundInInspection);
140-
}
141-
}
142-
loading.onSuccess();
143-
};
131+
fetchInspection().catch(handleError);
132+
}, [props.inspectionId]);
144133

145-
loading.start();
146-
fetchInspection().catch(handleError);
147-
}, [patchInspection, inspectionId]);
148-
149-
useEffect(() => {
150-
const index = vehicleTypes.indexOf(selected);
151-
if (index >= 0 && !loading.isLoading) {
152-
scrollToSelectedVehicleType(sliderRef, index, !initialScroll);
153-
setInitialScroll(false);
154-
}
155-
}, [vehicleTypes, selected, loading]);
134+
useEffect(() => {
135+
const index = vehicleTypes.indexOf(selected);
136+
if (index >= 0 && !loading.isLoading) {
137+
scrollToSelectedVehicleType(sliderRef, index, !initialScroll);
138+
setInitialScroll(false);
139+
}
140+
}, [vehicleTypes, selected, loading]);
156141

157-
const loadingContainer = loading.isLoading ? styles['loadingContainer'] : {};
142+
const loadingContainer = loading.isLoading ? styles['loadingContainer'] : {};
158143

159-
return (
160-
<div
161-
style={{
162-
...rootStyles,
163-
...styles['container'],
164-
...loadingContainer,
165-
...responsive(styles['containerSmall']),
166-
}}
167-
>
168-
{loading.isLoading && <Spinner size={80} />}
169-
{!loading.isLoading && !loading.error && (
170-
<>
171-
<div style={styles['title']}>{t('header.title')}</div>
172-
<Button style={styles['button']} onClick={() => onValidate(selected)}>
173-
{t('header.confirm')}
174-
</Button>
175-
<div
176-
style={{
177-
...styles['sliderContainer'],
178-
...responsive(styles['sliderContainerSmall']),
179-
}}
180-
>
181-
<div style={styles['slider']} ref={sliderRef}>
182-
{vehicleTypes.map((v) => (
183-
<VehicleTypeSelectionCard
184-
key={v}
185-
vehicleType={v}
186-
isSelected={selected === v}
187-
onClick={() => setSelected(v)}
188-
/>
189-
))}
190-
</div>
144+
return (
145+
<div
146+
style={{
147+
...rootStyles,
148+
...styles['container'],
149+
...loadingContainer,
150+
...responsive(styles['containerSmall']),
151+
}}
152+
>
153+
{loading.isLoading && <Spinner size={80} />}
154+
{!loading.isLoading && !loading.error && (
155+
<>
156+
<div style={styles['title']}>{t('header.title')}</div>
157+
<Button style={styles['button']} onClick={() => props.onSelectVehicleType?.(selected)}>
158+
{t('header.confirm')}
159+
</Button>
160+
<div
161+
style={{
162+
...styles['sliderContainer'],
163+
...responsive(styles['sliderContainerSmall']),
164+
}}
165+
>
166+
<div style={styles['slider']} ref={sliderRef}>
167+
{vehicleTypes.map((v) => (
168+
<VehicleTypeSelectionCard
169+
key={v}
170+
vehicleType={v}
171+
isSelected={selected === v}
172+
onClick={() => setSelected(v)}
173+
/>
174+
))}
191175
</div>
192-
</>
193-
)}
194-
</div>
195-
);
196-
},
197-
i18nVehicleTypeSelection,
198-
);
176+
</div>
177+
</>
178+
)}
179+
</div>
180+
);
181+
}, i18nVehicleTypeSelection);

0 commit comments

Comments
 (0)