@@ -3,26 +3,39 @@ import {
3
3
i18nWrap ,
4
4
useI18nSync ,
5
5
useLoadingState ,
6
- useMonkAppState ,
7
6
useMonkTheme ,
8
7
useResponsiveStyle ,
9
8
} from '@monkvision/common' ;
10
- import { VehicleType } from '@monkvision/types' ;
9
+ import { AllOrNone , VehicleType } from '@monkvision/types' ;
11
10
import { RefObject , useEffect , useMemo , useRef , useState } from 'react' ;
12
- import { decodeMonkJwt , useMonkApi } from '@monkvision/network' ;
11
+ import { decodeMonkJwt , MonkApiConfig , useMonkApi } from '@monkvision/network' ;
13
12
import { useMonitoring } from '@monkvision/monitoring' ;
14
13
import { useAnalytics } from '@monkvision/analytics' ;
15
14
import { styles } from './VehicleTypeSelection.styles' ;
16
15
import { i18nVehicleTypeSelection } from './i18n' ;
17
16
import { Button } from '../Button' ;
18
- import { getInitialSelectedVehicleType , getVehicleTypes } from './utils' ;
17
+ import {
18
+ getInitialSelectedVehicleType ,
19
+ getVehicleTypeFromInspection ,
20
+ getVehicleTypes ,
21
+ } from './utils' ;
19
22
import { VehicleTypeSelectionCard } from './VehicleTypeSelectionCard' ;
20
23
import { Spinner } from '../Spinner' ;
21
24
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
+
22
35
/**
23
36
* Props accepted by the VehicleTypeSelection component.
24
37
*/
25
- export interface VehicleTypeSelectionProps {
38
+ export type VehicleTypeSelectionProps = {
26
39
/**
27
40
* The initially selected vehicle type.
28
41
*
@@ -46,16 +59,7 @@ export interface VehicleTypeSelectionProps {
46
59
* @default en
47
60
*/
48
61
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 > ;
59
63
60
64
function scrollToSelectedVehicleType (
61
65
ref : RefObject < HTMLDivElement > ,
@@ -73,126 +77,105 @@ function scrollToSelectedVehicleType(
73
77
/**
74
78
* A single page component that allows the user to select a vehicle type.
75
79
*/
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 ( ) ;
105
101
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 ] ) ;
112
113
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 ;
117
119
}
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 ) ;
122
127
}
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
+ } ;
131
130
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 ] ) ;
144
133
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 ] ) ;
156
141
157
- const loadingContainer = loading . isLoading ? styles [ 'loadingContainer' ] : { } ;
142
+ const loadingContainer = loading . isLoading ? styles [ 'loadingContainer' ] : { } ;
158
143
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
+ ) ) }
191
175
</ div >
192
- </ >
193
- ) }
194
- </ div >
195
- ) ;
196
- } ,
197
- i18nVehicleTypeSelection ,
198
- ) ;
176
+ </ div >
177
+ </ >
178
+ ) }
179
+ </ div >
180
+ ) ;
181
+ } , i18nVehicleTypeSelection ) ;
0 commit comments