@mychoice/mychoice-sdk-modules 2.2.30 → 2.2.31
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/cjs/index.js +111 -66
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +111 -66
- package/dist/esm/index.js.map +1 -1
- package/package.json +4 -4
package/dist/esm/index.js
CHANGED
|
@@ -216,10 +216,20 @@ const BlockVehLinks = () => {
|
|
|
216
216
|
payload: { driverIndex, vehicleIndex },
|
|
217
217
|
});
|
|
218
218
|
};
|
|
219
|
+
const primaryOf = (vehicleIndex) => vehlinks.find((l) => l.vehicleIndex === vehicleIndex && l.priority === DriverPriorityTypes.Prn)?.driverIndex ?? -1;
|
|
220
|
+
const getTwoDriverSystemAllocation = () => {
|
|
221
|
+
if (drivers.length !== 2 || vehicles.length !== 3)
|
|
222
|
+
return { driverIndex: -1, vehicleIndex: -1 };
|
|
223
|
+
const firstTwo = [primaryOf(0), primaryOf(1)];
|
|
224
|
+
if (firstTwo.some((driverIndex) => driverIndex < 0) || new Set(firstTwo).size === drivers.length) {
|
|
225
|
+
return { driverIndex: -1, vehicleIndex: -1 };
|
|
226
|
+
}
|
|
227
|
+
const driverIndex = drivers.findIndex((_driver, index) => !firstTwo.includes(index));
|
|
228
|
+
return { driverIndex, vehicleIndex: 2 };
|
|
229
|
+
};
|
|
219
230
|
useEffect(() => {
|
|
220
231
|
if (!equalCounts || drivers.length <= 1)
|
|
221
232
|
return;
|
|
222
|
-
const primaryOf = (vehicleIndex) => vehlinks.find((l) => l.vehicleIndex === vehicleIndex && l.priority === DriverPriorityTypes.Prn)?.driverIndex ?? -1;
|
|
223
233
|
const askedDrivers = new Set();
|
|
224
234
|
for (let vehicleIndex = 0; vehicleIndex < askedVehicleCount; vehicleIndex += 1) {
|
|
225
235
|
const po = primaryOf(vehicleIndex);
|
|
@@ -237,6 +247,40 @@ const BlockVehLinks = () => {
|
|
|
237
247
|
return;
|
|
238
248
|
assignPrimary(remainingDriver, lastVehicleIndex);
|
|
239
249
|
}, [equalCounts, askedVehicleCount, vehlinks, drivers, vehicles]);
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
const { driverIndex, vehicleIndex } = getTwoDriverSystemAllocation();
|
|
252
|
+
if (driverIndex >= 0 && vehicleIndex >= 0 && primaryOf(vehicleIndex) !== driverIndex) {
|
|
253
|
+
assignPrimary(driverIndex, vehicleIndex);
|
|
254
|
+
}
|
|
255
|
+
}, [vehlinks, drivers, vehicles]);
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
if (vehicles.length <= drivers.length || drivers.length <= 1)
|
|
258
|
+
return;
|
|
259
|
+
for (let vehicleIndex = 0; vehicleIndex < vehicles.length; vehicleIndex += 1) {
|
|
260
|
+
if (primaryOf(vehicleIndex) < 0)
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const usedDrivers = new Set(vehicles.map((_, vehicleIndex) => primaryOf(vehicleIndex)));
|
|
264
|
+
const unusedDriver = drivers.findIndex((_, driverIndex) => !usedDrivers.has(driverIndex));
|
|
265
|
+
if (unusedDriver < 0)
|
|
266
|
+
return;
|
|
267
|
+
// Target the last vehicle whose PO is a duplicate, so we never strand another driver.
|
|
268
|
+
const poCounts = new Map();
|
|
269
|
+
vehicles.forEach((_v, vehicleIndex) => {
|
|
270
|
+
const po = primaryOf(vehicleIndex);
|
|
271
|
+
poCounts.set(po, (poCounts.get(po) ?? 0) + 1);
|
|
272
|
+
});
|
|
273
|
+
let target = -1;
|
|
274
|
+
for (let vehicleIndex = vehicles.length - 1; vehicleIndex >= 0; vehicleIndex -= 1) {
|
|
275
|
+
if ((poCounts.get(primaryOf(vehicleIndex)) ?? 0) > 1) {
|
|
276
|
+
target = vehicleIndex;
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (target < 0)
|
|
281
|
+
return;
|
|
282
|
+
assignPrimary(unusedDriver, target);
|
|
283
|
+
}, [vehlinks, drivers, vehicles]);
|
|
240
284
|
if (drivers.length <= 1) {
|
|
241
285
|
return null;
|
|
242
286
|
}
|
|
@@ -260,6 +304,7 @@ const BlockVehLinks = () => {
|
|
|
260
304
|
.map((driver, index) => ({ driver, index }))
|
|
261
305
|
.filter(({ index }) => !primaryDriverIndices.includes(index));
|
|
262
306
|
const vehiclesToAsk = vehicles.slice(0, askedVehicleCount);
|
|
307
|
+
const { vehicleIndex: systemAllocatedVehicleIndex } = getTwoDriverSystemAllocation();
|
|
263
308
|
const primaryQuestionsAnswered = vehiclesToAsk.every((_vehicle, vehicleIndex) => vehlinks.some((l) => l.vehicleIndex === vehicleIndex
|
|
264
309
|
&& l.priority === DriverPriorityTypes.Prn
|
|
265
310
|
&& l.driverIndex >= 0));
|
|
@@ -269,6 +314,8 @@ const BlockVehLinks = () => {
|
|
|
269
314
|
&& primaryQuestionsAnswered
|
|
270
315
|
&& primaryQuestionsAreUnique;
|
|
271
316
|
return (jsxs(Fragment, { children: [jsx(LabelFormBox, { title: "Since there are multiple drivers in this quote, please tell us who drives which vehicle the most. Please provide an answer that most accurately describes your situation." }), vehiclesToAsk.map((vehicle, vehicleIndex) => {
|
|
317
|
+
if (vehicleIndex === systemAllocatedVehicleIndex)
|
|
318
|
+
return null;
|
|
272
319
|
const { year, make, model } = vehicle;
|
|
273
320
|
const selectedPrimary = vehlinks.find((l) => l.vehicleIndex === vehicleIndex && l.priority === DriverPriorityTypes.Prn);
|
|
274
321
|
const isPrimaryAnswered = selectedPrimary !== undefined && selectedPrimary.driverIndex >= 0;
|
|
@@ -277,8 +324,7 @@ const BlockVehLinks = () => {
|
|
|
277
324
|
&& l.priority === DriverPriorityTypes.Prn
|
|
278
325
|
&& l.driverIndex >= 0)
|
|
279
326
|
.map((l) => l.driverIndex));
|
|
280
|
-
const
|
|
281
|
-
const canRepeatPrimary = vehicles.length > drivers.length && allDriversHavePrimary;
|
|
327
|
+
const canRepeatPrimary = vehicles.length > drivers.length;
|
|
282
328
|
const primaryOptions = drivers
|
|
283
329
|
.map((driver, driverIndex) => ({ name: driver.firstName, value: driverIndex }))
|
|
284
330
|
.filter(({ value }) => canRepeatPrimary
|
|
@@ -1222,6 +1268,10 @@ const SectionDriverInfo = () => {
|
|
|
1222
1268
|
month: birthMonth,
|
|
1223
1269
|
year: birthYear,
|
|
1224
1270
|
};
|
|
1271
|
+
const policyEffectiveDate = discountState.policyStartYear && discountState.policyStartMonth
|
|
1272
|
+
&& discountState.policyStartDay
|
|
1273
|
+
? `${discountState.policyStartYear}-${discountState.policyStartMonth}-${discountState.policyStartDay}`
|
|
1274
|
+
: discountState.policyStart;
|
|
1225
1275
|
useEffect(() => {
|
|
1226
1276
|
if (discountState.quoterInfo.firstName !== driverState.items[0].firstName) {
|
|
1227
1277
|
dispatchDiscountState({
|
|
@@ -1246,19 +1296,19 @@ const SectionDriverInfo = () => {
|
|
|
1246
1296
|
if (dateType === DateTypes.Day) {
|
|
1247
1297
|
dispatchDriverInfoState({
|
|
1248
1298
|
type: StoreFormCarDriverInfoActionTypes.FormCarDriverBirthDaySelect,
|
|
1249
|
-
payload: { birthDay: value, config: configState },
|
|
1299
|
+
payload: { birthDay: value, config: configState, appType },
|
|
1250
1300
|
});
|
|
1251
1301
|
}
|
|
1252
1302
|
if (dateType === DateTypes.Month) {
|
|
1253
1303
|
dispatchDriverInfoState({
|
|
1254
1304
|
type: StoreFormCarDriverInfoActionTypes.FormCarDriverBirthMonthSelect,
|
|
1255
|
-
payload: { birthMonth: value, config: configState },
|
|
1305
|
+
payload: { birthMonth: value, config: configState, appType },
|
|
1256
1306
|
});
|
|
1257
1307
|
}
|
|
1258
1308
|
if (dateType === DateTypes.Year) {
|
|
1259
1309
|
dispatchDriverInfoState({
|
|
1260
1310
|
type: StoreFormCarDriverInfoActionTypes.FormCarDriverBirthYearSelect,
|
|
1261
|
-
payload: { birthYear: value, config: configState },
|
|
1311
|
+
payload: { birthYear: value, config: configState, appType },
|
|
1262
1312
|
});
|
|
1263
1313
|
}
|
|
1264
1314
|
};
|
|
@@ -1280,11 +1330,13 @@ const SectionDriverInfo = () => {
|
|
|
1280
1330
|
payload: { applicantRelationship: value },
|
|
1281
1331
|
});
|
|
1282
1332
|
};
|
|
1283
|
-
return (jsxs("div", { className: `form-section ${mychoiceCls}`, children: [mychoiceCls && jsx("h2", { className: "section-title", children: "Time for a micro autobiography \u2013 tell us about you." }), jsx(InputFormBox, { name: "firstName", title: "What is your legal first name?", onChange: handleFirstNameChange, defaultValue: firstName, description: "The name on a policy should match the one on your official driver\u2019s licence.", placeholder: "Driver First Name", error: !firstName && driverState.inValidation, errorMessage: getErrorMessage(firstName, driverState.inValidation) }), jsx(SelectFormBox, { options: maritalStatusOptions, name: "maritalStatus", onChange: handleMaritalStatusChange, defaultValue: getSelectedOption(maritalStatusOptions, maritalStatus), title: "What is your marital status?", placeholder: "Select from the list", description: "If you are married, it may have a positive effect on your car insurance premiums and coverage. In some provinces, the law now considers same-sex partners to have a common-law marriage, so you will need to check your local regulations. If you are divorced or widowed, select single.", autoSelectIfValueIsOutOfOptions: false, error: !maritalStatus && driverState.inValidation, errorMessage: getErrorMessage(maritalStatus, driverState.inValidation) }), jsx(DateSelectFormBox, { name: "dateOfBirth", dateNames: ['birthYear', 'birthMonth', 'birthDay'], onDateChange: handleDateOfBirthChange, defaultValue: defaultDateOfBirth, title: "When were you born?", description: "Insurers generally consider your age and driving experience when calculating a vehicle insurance quote. The safest drivers are often those who are over thirty, but each insurer will have their own parameters. The youngest and oldest drivers have the greatest liability reflected in their premiums due to inexperience or health complications, respectively.", errorMessage: getDateErrorMessage([birthDay || '', birthMonth || '', birthYear || ''], driverState.inValidation), error: driverState.inValidation, maxDate: subYearsFromDate(
|
|
1333
|
+
return (jsxs("div", { className: `form-section ${mychoiceCls}`, children: [mychoiceCls && jsx("h2", { className: "section-title", children: "Time for a micro autobiography \u2013 tell us about you." }), jsx(InputFormBox, { name: "firstName", title: "What is your legal first name?", onChange: handleFirstNameChange, defaultValue: firstName, description: "The name on a policy should match the one on your official driver\u2019s licence.", placeholder: "Driver First Name", error: !firstName && driverState.inValidation, errorMessage: getErrorMessage(firstName, driverState.inValidation) }), jsx(SelectFormBox, { options: maritalStatusOptions, name: "maritalStatus", onChange: handleMaritalStatusChange, defaultValue: getSelectedOption(maritalStatusOptions, maritalStatus), title: "What is your marital status?", placeholder: "Select from the list", description: "If you are married, it may have a positive effect on your car insurance premiums and coverage. In some provinces, the law now considers same-sex partners to have a common-law marriage, so you will need to check your local regulations. If you are divorced or widowed, select single.", autoSelectIfValueIsOutOfOptions: false, error: !maritalStatus && driverState.inValidation, errorMessage: getErrorMessage(maritalStatus, driverState.inValidation) }), jsx(DateSelectFormBox, { name: "dateOfBirth", dateNames: ['birthYear', 'birthMonth', 'birthDay'], onDateChange: handleDateOfBirthChange, defaultValue: defaultDateOfBirth, title: "When were you born?", description: "Insurers generally consider your age and driving experience when calculating a vehicle insurance quote. The safest drivers are often those who are over thirty, but each insurer will have their own parameters. The youngest and oldest drivers have the greatest liability reflected in their premiums due to inexperience or health complications, respectively.", errorMessage: getDateErrorMessage([birthDay || '', birthMonth || '', birthYear || ''], driverState.inValidation), error: driverState.inValidation, maxDate: subYearsFromDate(policyEffectiveDate, configState.licenceConfig.minLicenceAge || 16), isDay: true }), jsx(SwitchButtonBox, { name: "occupation", items: occupationOptions, onChange: handleOccupationChange, defaultValue: getSelectedOption(occupationOptions, occupation), title: "Are you currently employed or unemployed?", description: "Your employment status reflects your driving frequency, and insurers consider this in your policy." }), jsx(SwitchButtonBox, { items: genderOptions, onChange: handleGenderChange, name: "gender", defaultValue: getSelectedOption(genderOptions, gender), title: "What is your gender?", description: "The gender on the policy should match your official driver\u2019s licence. Some insurers analyze a driver's sex when creating a policy. Men are typically considered higher risk than female drivers, but the statistics supporting this idea vary from province to province. On average, men and women pay roughly the same for insurance, though." }), driverState.activeIndex > 0 && (jsx(SelectFormBox, { options: applicantRelationshipOptions, name: "applicantRelationship", onChange: handleApplicantRelationshipChange, defaultValue: getSelectedOption(applicantRelationshipOptions, applicantRelationship), title: "Relationship to applicant", placeholder: "Select...", autoSelectIfValueIsOutOfOptions: false, error: !applicantRelationship && driverState.inValidation, errorMessage: getErrorMessage(applicantRelationship, driverState.inValidation) }))] }));
|
|
1284
1334
|
};
|
|
1285
1335
|
|
|
1286
1336
|
// Max months between consecutive Ontario GDL licence classes (spec 1-2 e/f)
|
|
1287
1337
|
const ON_MAX_MONTHS_BETWEEN_CLASSES = 60;
|
|
1338
|
+
const ON_MIN_MONTHS_G1_TO_G2 = 8;
|
|
1339
|
+
const ON_MIN_MONTHS_G1_TO_G = 20;
|
|
1288
1340
|
const SectionDriverLicence = () => {
|
|
1289
1341
|
const { appConfigState: { appType }, } = useStoreAppConfig();
|
|
1290
1342
|
const [driverEducation, setDriverEducation] = useState(false);
|
|
@@ -1310,7 +1362,11 @@ const SectionDriverLicence = () => {
|
|
|
1310
1362
|
? (!!ontarioQ1Date && checkDateIsSpecial(ontarioQ1Date, configState.minDates.g.specialDate))
|
|
1311
1363
|
: checkDateIsSpecial(defaultMinDate, configState.minDates.g.specialDate);
|
|
1312
1364
|
const driverName = firstName || driverNameDefault;
|
|
1365
|
+
const { policyStart, policyStartYear, policyStartMonth, policyStartDay, } = discountState;
|
|
1313
1366
|
const today = getFormattedDate('', 'yyyy-MM-dd');
|
|
1367
|
+
const policyEffectiveDate = policyStartYear && policyStartMonth && policyStartDay
|
|
1368
|
+
? `${policyStartYear}-${policyStartMonth}-${policyStartDay}`
|
|
1369
|
+
: policyStart || today;
|
|
1314
1370
|
const { g, g1, g2, minLicenceAge } = configState.licenceConfig;
|
|
1315
1371
|
const licenceTypeOptions = [
|
|
1316
1372
|
{ value: g.name, name: g.title },
|
|
@@ -1346,36 +1402,6 @@ const SectionDriverLicence = () => {
|
|
|
1346
1402
|
}
|
|
1347
1403
|
}
|
|
1348
1404
|
}, [g2LicenceYear, g2LicenceMonth, licenceType, useOntarioFlow]);
|
|
1349
|
-
// If the user picks their birth month in their 16th year and birthDay > 1,
|
|
1350
|
-
// selecting that month would imply a date before their actual birthday (since dates are assumed
|
|
1351
|
-
// as the 1st). Auto-advance the Q1 month to birthMonth + 1.
|
|
1352
|
-
useEffect(() => {
|
|
1353
|
-
if (!useOntarioFlow || !birthDate || !ontarioQ1Year || !ontarioQ1Month)
|
|
1354
|
-
return;
|
|
1355
|
-
const birthDayNum = parseInt(birthDay || '1', 10);
|
|
1356
|
-
if (birthDayNum <= 1)
|
|
1357
|
-
return;
|
|
1358
|
-
const birthYearNum = parseInt(birthYear || '0', 10);
|
|
1359
|
-
if (parseInt(ontarioQ1Year, 10) !== birthYearNum + 16 || ontarioQ1Month !== birthMonth)
|
|
1360
|
-
return;
|
|
1361
|
-
const q1SlotForCorrection = DriverLicenceTypes.G1;
|
|
1362
|
-
let correctedMonth = parseInt(birthMonth || '1', 10) + 1;
|
|
1363
|
-
let correctedYear = birthYearNum + 16;
|
|
1364
|
-
if (correctedMonth > 12) {
|
|
1365
|
-
correctedMonth = 1;
|
|
1366
|
-
correctedYear += 1;
|
|
1367
|
-
}
|
|
1368
|
-
dispatchDriverLicenceState({
|
|
1369
|
-
type: StoreFormCarDriverLicenceActionTypes.FormCarDriverLicenceMonthSelect,
|
|
1370
|
-
payload: { value: String(correctedMonth).padStart(2, '0'), config: configState, type: q1SlotForCorrection },
|
|
1371
|
-
});
|
|
1372
|
-
if (correctedYear !== birthYearNum + 16) {
|
|
1373
|
-
dispatchDriverLicenceState({
|
|
1374
|
-
type: StoreFormCarDriverLicenceActionTypes.FormCarDriverLicenceYearSelect,
|
|
1375
|
-
payload: { value: String(correctedYear), config: configState, type: q1SlotForCorrection },
|
|
1376
|
-
});
|
|
1377
|
-
}
|
|
1378
|
-
}, [ontarioQ1Year, ontarioQ1Month]);
|
|
1379
1405
|
// ── helpers ────────────────────────────────────────────────
|
|
1380
1406
|
const getMinDate = (type) => {
|
|
1381
1407
|
switch (type) {
|
|
@@ -1416,11 +1442,11 @@ const SectionDriverLicence = () => {
|
|
|
1416
1442
|
});
|
|
1417
1443
|
// Build a YYYY-MM-01 string from stored year/month, returns '' if either missing
|
|
1418
1444
|
const toDate = (year, month) => (year && month ? `${year}-${month}-01` : '');
|
|
1419
|
-
const validateLicenceDate = (year, month, minDate) => {
|
|
1420
|
-
const dateStr = toDate(year, month);
|
|
1445
|
+
const validateLicenceDate = (year, month, minDate, dateOverride) => {
|
|
1446
|
+
const dateStr = dateOverride || toDate(year, month);
|
|
1421
1447
|
if (!dateStr)
|
|
1422
1448
|
return '';
|
|
1423
|
-
if (compareDates(dateStr,
|
|
1449
|
+
if (compareDates(dateStr, policyEffectiveDate) > 0)
|
|
1424
1450
|
return 'License dates cannot be in the future';
|
|
1425
1451
|
if (minDate && compareDates(dateStr, minDate) < 0) {
|
|
1426
1452
|
return 'This license date must be equal or later than the prior license date. Please check your selection';
|
|
@@ -1439,11 +1465,11 @@ const SectionDriverLicence = () => {
|
|
|
1439
1465
|
return '';
|
|
1440
1466
|
};
|
|
1441
1467
|
// In the Ontario flow, firstLicenceAge is never entered, so gOneMin is stale/empty.
|
|
1442
|
-
// Compute
|
|
1468
|
+
// Compute the minimum from DOB + 16 and validate it against the policy effective date.
|
|
1443
1469
|
const getG1MinDate = () => {
|
|
1444
1470
|
if (useOntarioFlow && birthDate) {
|
|
1445
1471
|
const computed = addYearsToDate(birthDate, 16);
|
|
1446
|
-
return compareDates(computed,
|
|
1472
|
+
return compareDates(computed, policyEffectiveDate) > 0 ? policyEffectiveDate : computed;
|
|
1447
1473
|
}
|
|
1448
1474
|
return gOneMin;
|
|
1449
1475
|
};
|
|
@@ -1521,18 +1547,30 @@ const SectionDriverLicence = () => {
|
|
|
1521
1547
|
const q1Year = getLicenceYear(q1SlotType);
|
|
1522
1548
|
const q1Month = getLicenceMonth(q1SlotType);
|
|
1523
1549
|
const q1Date = toDate(q1Year, q1Month);
|
|
1550
|
+
const g2Date = toDate(g2LicenceYear, g2LicenceMonth);
|
|
1551
|
+
const gDate = toDate(gLicenceYear, gLicenceMonth);
|
|
1552
|
+
// Thresholds per the licensing flow: G1 < 5 years (4y11m = 59 months); G2/G < 3 years (2y11m = 35 months).
|
|
1553
|
+
const q1BirthdayDate = birthDate
|
|
1554
|
+
&& q1Year === String(Number(birthYear) + 16)
|
|
1555
|
+
&& q1Month === birthMonth
|
|
1556
|
+
? `${q1Year}-${birthMonth}-${birthDay}`
|
|
1557
|
+
: q1Date;
|
|
1558
|
+
const q1MonthsFromEffective = q1BirthdayDate
|
|
1559
|
+
? getDifferenceInMonths(policyEffectiveDate, q1BirthdayDate)
|
|
1560
|
+
: Infinity;
|
|
1561
|
+
// A G2 requires at least 8 months after G1; a G requires another 12 months.
|
|
1562
|
+
const canHaveG2 = !!q1Date && q1MonthsFromEffective >= ON_MIN_MONTHS_G1_TO_G2;
|
|
1563
|
+
const canHaveG = !!q1Date && q1MonthsFromEffective >= ON_MIN_MONTHS_G1_TO_G;
|
|
1524
1564
|
// ── path booleans ──
|
|
1525
|
-
const
|
|
1565
|
+
const showG2Question = firstClass === DriverLicenceTypes.G1 && canHaveG2;
|
|
1566
|
+
const showG2Date = showG2Question && receivedG2 === true;
|
|
1526
1567
|
// G question shows after G2 date entered (G1→G2 path) OR after No-G2 answer (G1→No G2 path)
|
|
1527
1568
|
const showGQuestionAfterG1 = firstClass === DriverLicenceTypes.G1
|
|
1569
|
+
&& canHaveG
|
|
1528
1570
|
&& (receivedG2 === false || showG2Date);
|
|
1571
|
+
const showGQuestionAfterG2 = firstClass === DriverLicenceTypes.G2 && canHaveG;
|
|
1529
1572
|
const showGDateAfterG1 = showGQuestionAfterG1 && receivedG === true;
|
|
1530
|
-
const showGDateAfterG2 =
|
|
1531
|
-
const g2Date = toDate(g2LicenceYear, g2LicenceMonth);
|
|
1532
|
-
const gDate = toDate(gLicenceYear, gLicenceMonth);
|
|
1533
|
-
// Thresholds per the licensing flow: G1 < 5 years (4y11m = 59 months); G2/G < 3 years (2y11m = 35 months).
|
|
1534
|
-
const policyStart = discountState.policyStart || today;
|
|
1535
|
-
const q1MonthsFromEffective = q1Date ? getDifferenceInMonths(policyStart, q1Date) : Infinity;
|
|
1573
|
+
const showGDateAfterG2 = showGQuestionAfterG2 && receivedG === true;
|
|
1536
1574
|
// G1 branch: ask once, based on the first licence date (< 5 years / 60 months).
|
|
1537
1575
|
const showDtcG1Only = firstClass === DriverLicenceTypes.G1
|
|
1538
1576
|
&& !!q1Date
|
|
@@ -1548,39 +1586,46 @@ const SectionDriverLicence = () => {
|
|
|
1548
1586
|
// ── Validation error messages ──
|
|
1549
1587
|
const q1MinDate = getG1MinDate();
|
|
1550
1588
|
const q1ChronoError = driverState.inValidation
|
|
1551
|
-
? validateLicenceDate(q1Year, q1Month, q1MinDate)
|
|
1589
|
+
? validateLicenceDate(q1Year, q1Month, q1MinDate, q1BirthdayDate)
|
|
1552
1590
|
: '';
|
|
1553
|
-
const q1FutureError =
|
|
1591
|
+
const q1FutureError = q1BirthdayDate && compareDates(q1BirthdayDate, policyEffectiveDate) > 0
|
|
1554
1592
|
? 'License dates cannot be in the future' : '';
|
|
1555
1593
|
const q1Error = q1FutureError || q1ChronoError || getDateErrorMessage(['01', q1Month, q1Year], driverState.inValidation);
|
|
1556
1594
|
const g2ChronoError = driverState.inValidation
|
|
1557
|
-
? validateLicenceDate(g2LicenceYear, g2LicenceMonth,
|
|
1595
|
+
? validateLicenceDate(g2LicenceYear, g2LicenceMonth, q1BirthdayDate)
|
|
1558
1596
|
: '';
|
|
1559
|
-
const g260MonthError = validate60Months(
|
|
1560
|
-
const g2FutureError = g2Date && compareDates(g2Date,
|
|
1597
|
+
const g260MonthError = validate60Months(q1BirthdayDate?.slice(0, 4), q1BirthdayDate?.slice(5, 7), g2LicenceYear, g2LicenceMonth);
|
|
1598
|
+
const g2FutureError = g2Date && compareDates(g2Date, policyEffectiveDate) > 0 ? 'License dates cannot be in the future' : '';
|
|
1561
1599
|
const g2Error = g2FutureError || g260MonthError || g2ChronoError || getDateErrorMessage(['01', g2LicenceMonth, g2LicenceYear], driverState.inValidation);
|
|
1562
1600
|
// G preceding date: G2 date if on G1→G2→G path, else Q1 date
|
|
1563
|
-
const gPrecedingDate = showGDateAfterG1 && showG2Date ? g2Date :
|
|
1601
|
+
const gPrecedingDate = showGDateAfterG1 && showG2Date ? g2Date : q1BirthdayDate;
|
|
1564
1602
|
const gChronoError = driverState.inValidation
|
|
1565
1603
|
? validateLicenceDate(gLicenceYear, gLicenceMonth, gPrecedingDate)
|
|
1566
1604
|
: '';
|
|
1567
|
-
const g60MonthError = validate60Months(
|
|
1568
|
-
const gFutureError = gDate && compareDates(gDate,
|
|
1605
|
+
const g60MonthError = validate60Months(q1BirthdayDate?.slice(0, 4), q1BirthdayDate?.slice(5, 7), gLicenceYear, gLicenceMonth);
|
|
1606
|
+
const gFutureError = gDate && compareDates(gDate, policyEffectiveDate) > 0 ? 'License dates cannot be in the future' : '';
|
|
1569
1607
|
const gError = gFutureError || g60MonthError || gChronoError || getDateErrorMessage(['01', gLicenceMonth, gLicenceYear], driverState.inValidation);
|
|
1570
|
-
// ── Min dates (
|
|
1571
|
-
const g2MinRaw =
|
|
1572
|
-
const g2MinDate = compareDates(g2MinRaw,
|
|
1608
|
+
// ── Min dates (capped to the policy effective date so a future policy remains selectable) ──
|
|
1609
|
+
const g2MinRaw = q1BirthdayDate && compareDates(q1BirthdayDate, gTwoMin) > 0 ? q1BirthdayDate : gTwoMin;
|
|
1610
|
+
const g2MinDate = compareDates(g2MinRaw, policyEffectiveDate) > 0 ? policyEffectiveDate : g2MinRaw;
|
|
1573
1611
|
const gMinRaw = gPrecedingDate && compareDates(gPrecedingDate, gMin) > 0 ? gPrecedingDate : gMin;
|
|
1574
|
-
const gMinDate = compareDates(gMinRaw,
|
|
1612
|
+
const gMinDate = compareDates(gMinRaw, policyEffectiveDate) > 0 ? policyEffectiveDate : gMinRaw;
|
|
1613
|
+
const getMonthPickerMinDate = (minDate) => {
|
|
1614
|
+
if (!minDate || getFormattedDate(minDate, 'dd') === '01')
|
|
1615
|
+
return minDate;
|
|
1616
|
+
return addMonthsToDate(minDate, 1);
|
|
1617
|
+
};
|
|
1618
|
+
const g2PickerMinDate = getMonthPickerMinDate(g2MinDate);
|
|
1619
|
+
const gPickerMinDate = getMonthPickerMinDate(gMinDate);
|
|
1575
1620
|
const getMax60Date = (refDate) => {
|
|
1576
1621
|
if (!refDate)
|
|
1577
|
-
return
|
|
1622
|
+
return policyEffectiveDate;
|
|
1578
1623
|
const max60 = addMonthsToDate(refDate, ON_MAX_MONTHS_BETWEEN_CLASSES);
|
|
1579
|
-
return compareDates(
|
|
1624
|
+
return compareDates(policyEffectiveDate, max60) > 0 ? max60 : policyEffectiveDate;
|
|
1580
1625
|
};
|
|
1581
|
-
const g2MaxDate = getMax60Date(
|
|
1582
|
-
const gMaxDate = getMax60Date(
|
|
1583
|
-
return (jsxs("div", { className: `form-section ${mychoiceCls}`, children: [jsx(DateSelectFormBox, { name: "firstLicenceDate", dateNames: ['firstLicenceYear', 'firstLicenceMonth'], onDateChange: handleLicenceDateChange(q1SlotType), defaultValue: getDefaultLicenceDate(q1SlotType), title: `When did ${driverName} first receive their drivers license in Canada?`, description: "Select the year and month in which you received your first license to drive an automobile in Canada. This would include a beginners, intermediate or full license.", errorMessage: q1Error, error: driverState.inValidation, minDate: q1MinDate, maxDate:
|
|
1626
|
+
const g2MaxDate = getMax60Date(q1BirthdayDate);
|
|
1627
|
+
const gMaxDate = getMax60Date(q1BirthdayDate);
|
|
1628
|
+
return (jsxs("div", { className: `form-section ${mychoiceCls}`, children: [jsx(DateSelectFormBox, { name: "firstLicenceDate", dateNames: ['firstLicenceYear', 'firstLicenceMonth'], onDateChange: handleLicenceDateChange(q1SlotType), defaultValue: getDefaultLicenceDate(q1SlotType), title: `When did ${driverName} first receive their drivers license in Canada?`, description: "Select the year and month in which you received your first license to drive an automobile in Canada. This would include a beginners, intermediate or full license.", errorMessage: q1Error, error: driverState.inValidation, minDate: q1MinDate, maxDate: policyEffectiveDate, disabled: !birthDate }), q1Date && (jsx(SelectFormBox, { options: isOnlyG ? ontarioOnlyGOptions : ontarioFirstClassOptions, name: "firstLicenceClass", onChange: handleLicenceTypeChange, defaultValue: getSelectedOption(isOnlyG ? ontarioOnlyGOptions : ontarioFirstClassOptions, firstClass), title: "What class of license was it?", placeholder: "Select from the list", description: "Drivers licensed in Ontario under the graduated licensing program would select G1 Beginner. If the driver was licensed outside Ontario or granted an exception for having driving experience from another jurisdiction then select the license class they first received. Select class G Full or equivalent if the driver was licensed in Ontario before 1994 or was licensed in another province. G equivalent classes in Canada are class 5.", autoSelectIfValueIsOutOfOptions: false })), firstClass === DriverLicenceTypes.G1 && (jsxs(Fragment, { children: [showDtcG1Only && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleTrainingChange, name: "passedDriverTraining", defaultValue: getSelectedOption(yesNoOptions, passedDriverTraining), title: `Has ${driverName} completed a gov't approved drivers education course within the past 3 years?` })), showG2Question && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleReceivedG2Change, name: "receivedG2", defaultValue: getSelectedOption(yesNoOptions, receivedG2), title: `Did ${driverName} receive a G2 license?` })), showG2Date && (jsx(DateSelectFormBox, { name: "g2LicenceDate", dateNames: ['g2LicenceYear', 'g2LicenceMonth'], onDateChange: handleLicenceDateChange(DriverLicenceTypes.G2), defaultValue: getDefaultLicenceDate(DriverLicenceTypes.G2), title: `When did ${driverName} receive this G2 license?`, errorMessage: g2Error, error: driverState.inValidation, minDate: g2PickerMinDate, maxDate: g2MaxDate })), showGQuestionAfterG1 && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleReceivedGChange, name: "receivedG", defaultValue: getSelectedOption(yesNoOptions, receivedG), title: `Did ${driverName} receive a G license?` })), showGDateAfterG1 && (jsx(DateSelectFormBox, { name: "gLicenceDate", dateNames: ['gLicenceYear', 'gLicenceMonth'], onDateChange: handleLicenceDateChange(DriverLicenceTypes.G), defaultValue: getDefaultLicenceDate(DriverLicenceTypes.G), title: `When did ${driverName} receive this G license?`, errorMessage: gError, error: driverState.inValidation, minDate: gPickerMinDate, maxDate: gMaxDate }))] })), firstClass === DriverLicenceTypes.G2 && (jsxs(Fragment, { children: [showDtcG2Only && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleTrainingChange, name: "passedDriverTraining", defaultValue: getSelectedOption(yesNoOptions, passedDriverTraining), title: `Has ${driverName} completed a gov't approved drivers education course within the past 3 years?` })), showGQuestionAfterG2 && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleReceivedGChange, name: "receivedG", defaultValue: getSelectedOption(yesNoOptions, receivedG), title: `Did ${driverName} receive a G license?` })), showGDateAfterG2 && (jsx(DateSelectFormBox, { name: "gLicenceDate", dateNames: ['gLicenceYear', 'gLicenceMonth'], onDateChange: handleLicenceDateChange(DriverLicenceTypes.G), defaultValue: getDefaultLicenceDate(DriverLicenceTypes.G), title: `When did ${driverName} receive this G license?`, errorMessage: gError, error: driverState.inValidation, minDate: gPickerMinDate, maxDate: gMaxDate }))] })), firstClass === DriverLicenceTypes.G && !isOnlyG && showDtcGFull && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleTrainingChange, name: "passedDriverTraining", defaultValue: getSelectedOption(yesNoOptions, passedDriverTraining), title: `Has ${driverName} completed a gov't approved drivers education course within the past 3 years?` })), isOnlyG && showDtcGFull && (jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handleTrainingChange, name: "passedDriverTraining", defaultValue: getSelectedOption(yesNoOptions, passedDriverTraining), title: `Has ${driverName} completed a gov't approved drivers education course within the past 3 years?` })), jsx(SwitchButtonBox, { items: yesNoOptions, onChange: handlePreviousLicenceChange, name: "previousLicence", defaultValue: getSelectedOption(yesNoOptions, previousLicence), title: `Has ${driverName} ever had a full license anywhere else in Canada or USA?`, description: "If you have driving experience outside Canada or the United States, it may lower your premium. Your insurer may require proof of insurance in these other locations or some proof of driving experience from the country you indicate (like a copy of a previous driver's licence)." })] }));
|
|
1584
1629
|
}
|
|
1585
1630
|
return (jsxs("div", { className: `form-section ${mychoiceCls}`, children: [jsx(InputFormBox, { name: "firstLicenceAge", title: getLicenceAgeTitle(), onChange: handleLicenceAgeChange, type: InputTypes.Number, defaultValue: firstLicenceAge, description: configState.toolTip.licenceAge, hintMessage: birthDate
|
|
1586
1631
|
? `${driverName} was licenced in ${Number(birthYear) + Number(firstLicenceAge)} - ${Number(birthYear) + Number(firstLicenceAge) + 1}`
|