@star-insure/sdk 1.1.34 → 1.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/forms/RegistrationSearchField.d.ts +2 -1
- package/dist/sdk.cjs.development.js +6 -4
- package/dist/sdk.cjs.development.js.map +1 -1
- package/dist/sdk.cjs.production.min.js +1 -1
- package/dist/sdk.cjs.production.min.js.map +1 -1
- package/dist/sdk.esm.js +6 -4
- package/dist/sdk.esm.js.map +1 -1
- package/dist/types/models/quotes/QuoteRequest.d.ts +1 -0
- package/dist/types/models/quotes/QuoteRequestPurchaseOption.d.ts +0 -1
- package/package.json +1 -1
- package/src/components/forms/RegistrationSearchField.tsx +219 -161
- package/src/types/models/quotes/QuoteRequest.ts +1 -0
- package/src/types/models/quotes/QuoteRequestPurchaseOption.ts +0 -1
|
@@ -1,187 +1,245 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { sanitiseVehicleType } from '../../lib';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ApiResponse,
|
|
5
|
+
FormStatus,
|
|
6
|
+
MotorwebVehicleResponse,
|
|
7
|
+
VehicleType,
|
|
8
|
+
} from '../../types';
|
|
4
9
|
import { useToast } from '../../lib/toast';
|
|
5
10
|
|
|
6
11
|
export interface VehicleData extends MotorwebVehicleResponse {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
make: string;
|
|
13
|
+
model: string;
|
|
14
|
+
year: string;
|
|
15
|
+
vehicle_type: VehicleType;
|
|
16
|
+
is_heavy: boolean;
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
export interface RegistrationSearchOnChange {
|
|
15
|
-
|
|
20
|
+
registration: string;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
interface Props {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
name?: string;
|
|
25
|
+
onChange?: (values: RegistrationSearchOnChange) => void;
|
|
26
|
+
onVehicleDataFound: (vehicleData: VehicleData) => void;
|
|
27
|
+
apiUrl?: string;
|
|
28
|
+
showOdometerReadingField?: boolean;
|
|
29
|
+
showConditionField?: boolean;
|
|
30
|
+
initialRegistrationValue?: string;
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
export const conditionOptions = [
|
|
33
|
+
export const conditionOptions = [
|
|
34
|
+
'POOR',
|
|
35
|
+
'FAIR',
|
|
36
|
+
'AVERAGE',
|
|
37
|
+
'GOOD',
|
|
38
|
+
'VERY_GOOD',
|
|
39
|
+
'AS_NEW',
|
|
40
|
+
'NEW',
|
|
41
|
+
];
|
|
28
42
|
|
|
29
43
|
export default function RegistrationSearchField({
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (e.currentTarget.name === 'odo_search') {
|
|
51
|
-
setOdo(e.currentTarget.value);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (e.currentTarget.name === 'condition_search') {
|
|
55
|
-
setCondition(e.currentTarget.value);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (onChange) {
|
|
59
|
-
onChange({ registration: e.currentTarget.value.toUpperCase() });
|
|
60
|
-
}
|
|
44
|
+
name = 'registration_search',
|
|
45
|
+
initialRegistrationValue = '',
|
|
46
|
+
onVehicleDataFound,
|
|
47
|
+
apiUrl = '/api/rego-search',
|
|
48
|
+
showOdometerReadingField = false,
|
|
49
|
+
showConditionField = false,
|
|
50
|
+
onChange,
|
|
51
|
+
}: Props) {
|
|
52
|
+
const [rego, setRego] = React.useState<string>(initialRegistrationValue);
|
|
53
|
+
const [odo, setOdo] = React.useState<string>('');
|
|
54
|
+
const [condition, setCondition] = React.useState<string>('GOOD');
|
|
55
|
+
|
|
56
|
+
const [status, setStatus] = React.useState<FormStatus>('idle');
|
|
57
|
+
const { addToast } = useToast();
|
|
58
|
+
|
|
59
|
+
function handleChange(
|
|
60
|
+
e: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
|
|
61
|
+
) {
|
|
62
|
+
if (e.currentTarget.name === 'registration_search') {
|
|
63
|
+
setRego(e.currentTarget.value?.toUpperCase() || '');
|
|
61
64
|
}
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
handleSearch();
|
|
66
|
-
}
|
|
66
|
+
if (e.currentTarget.name === 'odo_search') {
|
|
67
|
+
setOdo(e.currentTarget.value);
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const payload = {
|
|
73
|
-
registration: rego,
|
|
74
|
-
odometerReading: odo,
|
|
75
|
-
condition,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// Turn the payload in to a query string
|
|
79
|
-
// @ts-ignore
|
|
80
|
-
const query = new URLSearchParams(payload).toString();
|
|
81
|
-
|
|
82
|
-
const res = await fetch(`${apiUrl}?${query}`, {
|
|
83
|
-
headers: { 'Content-Type': 'application/json' }
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (!res.ok) {
|
|
87
|
-
addToast({ message: `There was an error with the provided registration.`, status: 'error', timeout: 3000 });
|
|
88
|
-
setStatus('error');
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const { data, ok }: ApiResponse<MotorwebVehicleResponse> = await res.json();
|
|
93
|
-
|
|
94
|
-
if (!ok || !data) {
|
|
95
|
-
addToast({ message: `Failed to find vehicle, please complete manually.`, status: 'error', timeout: 3000 });
|
|
96
|
-
setStatus('error');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const vehicleData = data.data.vehicle;
|
|
101
|
-
|
|
102
|
-
const make = vehicleData.make;
|
|
103
|
-
const model = vehicleData.model;
|
|
104
|
-
const year = vehicleData['year-of-manufacture'];
|
|
105
|
-
const weight = vehicleData['gross-vehicle-mass'] ? parseInt(vehicleData['gross-vehicle-mass'].replaceAll(',', '')) : 0;
|
|
106
|
-
const vehicleType = vehicleData['vehicle-type'];
|
|
107
|
-
|
|
108
|
-
if (!make || !model || !year || !vehicleType) {
|
|
109
|
-
addToast({ message: `We couldn't find all of your data, please complete manually.`, status: 'error', timeout: 3000 });
|
|
110
|
-
setStatus('error');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
onVehicleDataFound({
|
|
114
|
-
...data,
|
|
115
|
-
make: make || '',
|
|
116
|
-
model: model || '',
|
|
117
|
-
year: year || '',
|
|
118
|
-
vehicle_type: vehicleType ? sanitiseVehicleType(vehicleType) : 'car',
|
|
119
|
-
is_heavy: weight && weight > 3500 || false,
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
setStatus('success');
|
|
70
|
+
if (e.currentTarget.name === 'condition_search') {
|
|
71
|
+
setCondition(e.currentTarget.value);
|
|
123
72
|
}
|
|
124
73
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
74
|
+
if (onChange) {
|
|
75
|
+
onChange({ registration: e.currentTarget.value.toUpperCase() });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function handleKeydown(e: React.KeyboardEvent) {
|
|
80
|
+
if (e.key === 'Enter') {
|
|
81
|
+
handleSearch();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function handleSearch() {
|
|
86
|
+
setStatus('processing');
|
|
87
|
+
|
|
88
|
+
const payload = {
|
|
89
|
+
registration: rego,
|
|
90
|
+
odometerReading: odo,
|
|
91
|
+
condition,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Turn the payload in to a query string
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
const query = new URLSearchParams(payload).toString();
|
|
97
|
+
|
|
98
|
+
const res = await fetch(`${apiUrl}?${query}`, {
|
|
99
|
+
headers: { 'Content-Type': 'application/json' },
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
addToast({
|
|
104
|
+
message: `There was an error with the provided registration.`,
|
|
105
|
+
status: 'error',
|
|
106
|
+
timeout: 3000,
|
|
107
|
+
});
|
|
108
|
+
setStatus('error');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const { data, ok }: ApiResponse<MotorwebVehicleResponse> = await res.json();
|
|
113
|
+
|
|
114
|
+
if (!ok || !data) {
|
|
115
|
+
addToast({
|
|
116
|
+
message: `Failed to find vehicle, please complete manually.`,
|
|
117
|
+
status: 'error',
|
|
118
|
+
timeout: 3000,
|
|
119
|
+
});
|
|
120
|
+
setStatus('error');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const vehicleData = data.data.vehicle;
|
|
125
|
+
|
|
126
|
+
const make = vehicleData.make;
|
|
127
|
+
const model = vehicleData.model;
|
|
128
|
+
const year = vehicleData['year-of-manufacture'];
|
|
129
|
+
const weight = vehicleData['gross-vehicle-mass']
|
|
130
|
+
? parseInt(vehicleData['gross-vehicle-mass'].replaceAll(',', ''))
|
|
131
|
+
: 0;
|
|
132
|
+
const vehicleType = vehicleData['vehicle-type'];
|
|
133
|
+
|
|
134
|
+
if (!make || !model || !year || !vehicleType) {
|
|
135
|
+
addToast({
|
|
136
|
+
message: `We couldn't find all of your data, please complete manually.`,
|
|
137
|
+
status: 'error',
|
|
138
|
+
timeout: 3000,
|
|
139
|
+
});
|
|
140
|
+
setStatus('error');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
onVehicleDataFound({
|
|
144
|
+
...data,
|
|
145
|
+
make: make || '',
|
|
146
|
+
model: model || '',
|
|
147
|
+
year: year || '',
|
|
148
|
+
vehicle_type: vehicleType ? sanitiseVehicleType(vehicleType) : 'car',
|
|
149
|
+
is_heavy: (weight && weight > 3500) || false,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
setStatus('success');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<div className="w-full flex flex-col">
|
|
157
|
+
<div className="w-full flex flex-wrap gap-3 bg-gray-100 rounded-md p-3">
|
|
158
|
+
{showOdometerReadingField ||
|
|
159
|
+
(showConditionField && (
|
|
160
|
+
<div className="w-full grid grid-cols-2 gap-3">
|
|
161
|
+
{showOdometerReadingField && (
|
|
162
|
+
<label>
|
|
163
|
+
Approx. km travelled
|
|
164
|
+
<input
|
|
167
165
|
onKeyDown={handleKeydown}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
type="number"
|
|
167
|
+
name="odo_search"
|
|
168
|
+
id="odo_search"
|
|
169
|
+
value={odo}
|
|
170
|
+
onChange={handleChange}
|
|
171
|
+
className={`transition-all ${
|
|
172
|
+
status === 'processing'
|
|
173
|
+
? 'pointer-events-none opacity-50'
|
|
174
|
+
: ''
|
|
175
|
+
}`}
|
|
176
|
+
disabled={status === 'processing'}
|
|
177
|
+
/>
|
|
178
|
+
</label>
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
{showConditionField && (
|
|
182
|
+
<label>
|
|
183
|
+
Vehicle condition
|
|
184
|
+
<select
|
|
185
|
+
name="condition_search"
|
|
186
|
+
id="condition_search"
|
|
187
|
+
value={condition}
|
|
173
188
|
onChange={handleChange}
|
|
174
|
-
className={`
|
|
189
|
+
className={`transition-all ${
|
|
190
|
+
status === 'processing'
|
|
191
|
+
? 'pointer-events-none opacity-50'
|
|
192
|
+
: ''
|
|
193
|
+
}`}
|
|
175
194
|
disabled={status === 'processing'}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
</button>
|
|
195
|
+
>
|
|
196
|
+
{conditionOptions.map(conditionOption => (
|
|
197
|
+
<option key={conditionOption}>{conditionOption}</option>
|
|
198
|
+
))}
|
|
199
|
+
</select>
|
|
200
|
+
</label>
|
|
201
|
+
)}
|
|
184
202
|
</div>
|
|
185
|
-
|
|
186
|
-
|
|
203
|
+
))}
|
|
204
|
+
|
|
205
|
+
<input
|
|
206
|
+
onKeyDown={handleKeydown}
|
|
207
|
+
placeholder="Search for your rego"
|
|
208
|
+
type="text"
|
|
209
|
+
name={name}
|
|
210
|
+
id={name}
|
|
211
|
+
value={rego}
|
|
212
|
+
onChange={handleChange}
|
|
213
|
+
className={`flex-grow transition-all ${
|
|
214
|
+
status === 'processing' ? 'pointer-events-none opacity-50' : ''
|
|
215
|
+
}`}
|
|
216
|
+
disabled={status === 'processing'}
|
|
217
|
+
/>
|
|
218
|
+
|
|
219
|
+
<button
|
|
220
|
+
title="Search"
|
|
221
|
+
type="button"
|
|
222
|
+
onClick={handleSearch}
|
|
223
|
+
disabled={status === 'processing'}
|
|
224
|
+
className={`bg-teal px-4 py-3 rounded-md transition-all`}
|
|
225
|
+
>
|
|
226
|
+
<span className="sr-only">Search</span>
|
|
227
|
+
<svg
|
|
228
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
229
|
+
className="h-5 w-5 text-white"
|
|
230
|
+
fill="none"
|
|
231
|
+
viewBox="0 0 24 24"
|
|
232
|
+
stroke="currentColor"
|
|
233
|
+
strokeWidth="2"
|
|
234
|
+
>
|
|
235
|
+
<path
|
|
236
|
+
strokeLinecap="round"
|
|
237
|
+
strokeLinejoin="round"
|
|
238
|
+
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
239
|
+
/>
|
|
240
|
+
</svg>
|
|
241
|
+
</button>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
);
|
|
187
245
|
}
|