@7365admin1/layer-common 3.0.26 → 3.0.28
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/CHANGELOG.md +13 -0
- package/components/AccessCardDetailsDialog.vue +98 -2
- package/components/AccessCardPreviewDialog.vue +37 -6
- package/components/AccessManagement.vue +10 -1
- package/components/BulletinBoardView.vue +368 -288
- package/components/EntryPassInformation.vue +55 -17
- package/components/HidReaderForm.vue +10 -16
- package/components/MemberInformation.vue +59 -1
- package/components/VisitorForm.vue +251 -22
- package/components/VisitorManagement.vue +790 -219
- package/composables/useAccessManagement.ts +8 -0
- package/composables/useVisitor.ts +29 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<v-toolbar>
|
|
4
4
|
<v-row no-gutters class="fill-height px-6 d-flex justify-space-between align-center" align="center">
|
|
5
5
|
<span class="font-weight-bold text-h5 text-capitalize">
|
|
6
|
-
{{
|
|
6
|
+
{{ formMode }} {{ formatVisitorType(type) }}
|
|
7
7
|
</span>
|
|
8
8
|
<ButtonClose @click="emit('close:all')" />
|
|
9
9
|
</v-row>
|
|
@@ -204,15 +204,20 @@
|
|
|
204
204
|
v-model:cards="passCards" :settings="entryPassSettings"
|
|
205
205
|
:loading="entryPassSettingsPending || siteDataPending" :site-id="prop.site"
|
|
206
206
|
:unit-id="visitor.unit || null" :visitor-type="prop.type" :hid-qr-code-enabled="hidQrCodePassAllowed"
|
|
207
|
-
:hid-qr-printer-configured="hasHidQrPrinterConfig"
|
|
207
|
+
:hid-qr-printer-configured="hasHidQrPrinterConfig"
|
|
208
|
+
@update:available-qr-count="(val) => availableQrCount = val" />
|
|
208
209
|
</v-col>
|
|
209
210
|
|
|
210
211
|
<v-col v-show="withStep3 && contractorStep === 3" cols="12">
|
|
211
212
|
<MemberInformation v-model="visitor.members" :type="prop.type" :contractor-type="visitor.contractorType"
|
|
212
|
-
:site="prop.site" :selected-visitor-pass="visitor.visitorPass" :clearable="true"
|
|
213
|
+
:site="prop.site" :selected-visitor-pass="visitor.visitorPass" :clearable="true"
|
|
214
|
+
:settings="entryPassSettings" :settings-loading="entryPassSettingsPending || siteDataPending"
|
|
215
|
+
:unit-id="visitor.unit || null"
|
|
216
|
+
:hid-qr-code-enabled="hidQrCodePassAllowed" :hid-qr-printer-configured="hasHidQrPrinterConfig"
|
|
217
|
+
:selected-nfc-cards="passType === 'NFC' ? passCards : []" />
|
|
213
218
|
</v-col>
|
|
214
219
|
|
|
215
|
-
<v-col v-if="
|
|
220
|
+
<v-col v-if="formMode === 'add'" cols="12" class="mt-2">
|
|
216
221
|
<v-checkbox v-model="createMore" density="comfortable" hide-details>
|
|
217
222
|
<template #label>
|
|
218
223
|
<span class="text-subtitle-2 font-weight-bold">
|
|
@@ -234,11 +239,11 @@
|
|
|
234
239
|
<v-row no-gutters>
|
|
235
240
|
<v-col cols="6">
|
|
236
241
|
<v-btn v-if="
|
|
237
|
-
|
|
242
|
+
formMode === 'add' &&
|
|
238
243
|
(withStep2 || withStep3) &&
|
|
239
244
|
contractorStep > 1
|
|
240
245
|
" tile block variant="text" class="text-none" size="48" @click="handleGoToPreviousPage" text="Back" />
|
|
241
|
-
<v-btn v-else-if="
|
|
246
|
+
<v-btn v-else-if="formMode === 'add' || formMode === 'register'" tile block variant="text" class="text-none"
|
|
242
247
|
size="48" @click="backToSelection" text="Back to Selection" />
|
|
243
248
|
<v-btn v-else tile block variant="text" class="text-none" size="48" @click="emit('close:all')" text="Close" />
|
|
244
249
|
</v-col>
|
|
@@ -247,7 +252,7 @@
|
|
|
247
252
|
:disabled="processing" @click="handleNextPage" :text="'Next'" />
|
|
248
253
|
<v-btn v-else tile block variant="flat" color="black" class="text-none" size="48"
|
|
249
254
|
:disabled="!validForm || processing || membersFieldIncomplete" @click="submit"
|
|
250
|
-
:text="
|
|
255
|
+
:text="formMode == 'add' ? 'Submit' : 'Update'" />
|
|
251
256
|
</v-col>
|
|
252
257
|
</v-row>
|
|
253
258
|
</v-toolbar>
|
|
@@ -292,6 +297,82 @@
|
|
|
292
297
|
</v-card-text>
|
|
293
298
|
</v-card>
|
|
294
299
|
</v-dialog>
|
|
300
|
+
|
|
301
|
+
<v-dialog
|
|
302
|
+
v-if="enableUnregistered"
|
|
303
|
+
v-model="dialog.showUnregisteredPlateDialog"
|
|
304
|
+
max-width="900"
|
|
305
|
+
persistent
|
|
306
|
+
>
|
|
307
|
+
<v-card color="background" class="pa-4">
|
|
308
|
+
<v-card-actions class="justify-end pa-0">
|
|
309
|
+
<v-btn
|
|
310
|
+
icon="mdi-close"
|
|
311
|
+
variant="text"
|
|
312
|
+
size="large"
|
|
313
|
+
@click="closeUnregisteredPlateDialog"
|
|
314
|
+
/>
|
|
315
|
+
</v-card-actions>
|
|
316
|
+
|
|
317
|
+
<v-card-text class="text-center pt-2">
|
|
318
|
+
<v-icon color="orange" size="96">mdi-alert-circle-outline</v-icon>
|
|
319
|
+
|
|
320
|
+
<div :class="`text-body-${$vuetify.display.xs ? 'mobile' : 'tablet'} mt-8`">
|
|
321
|
+
Vehicle Number {{ unregisteredPlateSearchText }} is similar to below
|
|
322
|
+
<br />
|
|
323
|
+
Unregistered visitors last 24 hours. Please select to
|
|
324
|
+
<br />
|
|
325
|
+
Update
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
<v-table class="mt-8 border rounded">
|
|
329
|
+
<thead>
|
|
330
|
+
<tr>
|
|
331
|
+
<th class="text-left">Plate Number</th>
|
|
332
|
+
<th class="text-left">Check In</th>
|
|
333
|
+
<th class="text-center">Action</th>
|
|
334
|
+
</tr>
|
|
335
|
+
</thead>
|
|
336
|
+
<tbody>
|
|
337
|
+
<tr
|
|
338
|
+
v-for="match in unregisteredPlateMatches"
|
|
339
|
+
:key="match._id || match.plateNumber"
|
|
340
|
+
>
|
|
341
|
+
<td class="text-left font-weight-bold text-uppercase">
|
|
342
|
+
{{ match.plateNumber || "N/A" }}
|
|
343
|
+
</td>
|
|
344
|
+
<td class="text-left">
|
|
345
|
+
{{ formatUnregisteredCheckIn(match.checkIn) }}
|
|
346
|
+
</td>
|
|
347
|
+
<td class="text-center">
|
|
348
|
+
<v-btn
|
|
349
|
+
color="red"
|
|
350
|
+
class="text-capitalize"
|
|
351
|
+
density="compact"
|
|
352
|
+
size="large"
|
|
353
|
+
@click="selectUnregisteredPlateMatch(match)"
|
|
354
|
+
>
|
|
355
|
+
Update
|
|
356
|
+
</v-btn>
|
|
357
|
+
</td>
|
|
358
|
+
</tr>
|
|
359
|
+
</tbody>
|
|
360
|
+
</v-table>
|
|
361
|
+
</v-card-text>
|
|
362
|
+
|
|
363
|
+
<v-card-actions>
|
|
364
|
+
<v-btn
|
|
365
|
+
block
|
|
366
|
+
color="red"
|
|
367
|
+
variant="flat"
|
|
368
|
+
size="x-large"
|
|
369
|
+
@click="closeUnregisteredPlateDialog"
|
|
370
|
+
>
|
|
371
|
+
Cancel & Add New
|
|
372
|
+
</v-btn>
|
|
373
|
+
</v-card-actions>
|
|
374
|
+
</v-card>
|
|
375
|
+
</v-dialog>
|
|
295
376
|
</v-card>
|
|
296
377
|
</template>
|
|
297
378
|
|
|
@@ -348,6 +429,7 @@ const {
|
|
|
348
429
|
typeFieldMap,
|
|
349
430
|
contractorTypes,
|
|
350
431
|
getVisitors,
|
|
432
|
+
checkSearchUncheckedOutUnregisteredVisitor,
|
|
351
433
|
updateVisitor,
|
|
352
434
|
} = useVisitor();
|
|
353
435
|
const { getBySiteId: getEntryPassSettingsBySiteId } =
|
|
@@ -394,6 +476,7 @@ const visitor = reactive<Partial<TVisitorPayload>>({
|
|
|
394
476
|
const passType = ref<string | null>(null);
|
|
395
477
|
const passQuantity = ref<number | null>(1);
|
|
396
478
|
const passCards = ref<{ _id: string; cardNo: string }[]>([]);
|
|
479
|
+
const availableQrCount = ref<number | null>(null);
|
|
397
480
|
const hidQrPrintPayload = ref<string | null>(null);
|
|
398
481
|
const hidQrPrinted = ref(false);
|
|
399
482
|
|
|
@@ -402,10 +485,12 @@ const registeredUnitCompanyName = ref("N/A");
|
|
|
402
485
|
const dialog = reactive({
|
|
403
486
|
vehicleNumberUsersList: false,
|
|
404
487
|
showNonCheckedOutDialog: false,
|
|
488
|
+
showUnregisteredPlateDialog: false,
|
|
405
489
|
});
|
|
406
490
|
|
|
407
491
|
const loading = reactive({
|
|
408
492
|
checkingOut: false,
|
|
493
|
+
checkingUnregisteredPlate: false,
|
|
409
494
|
});
|
|
410
495
|
|
|
411
496
|
const validForm = ref(false);
|
|
@@ -431,9 +516,18 @@ const deliveryCompanyInput = ref("");
|
|
|
431
516
|
const deliveryCompanyList = ref<string[]>([]);
|
|
432
517
|
|
|
433
518
|
const matchingPlateNumberNonCheckedOutArr = ref<TVisitor[]>([]);
|
|
519
|
+
const unregisteredPlateMatches = ref<TVisitor[]>([]);
|
|
520
|
+
const unregisteredPlateSearchText = ref("");
|
|
521
|
+
const selectedUnregisteredVisitor = ref<TVisitor | null>(null);
|
|
522
|
+
const skipUnregisteredPlateCheck = ref(false);
|
|
523
|
+
const pendingUnregisteredAction = ref<"next" | "submit" | null>(null);
|
|
434
524
|
|
|
435
525
|
const vehicleNumberUserItems = ref<TPeople[]>([]);
|
|
436
526
|
|
|
527
|
+
const formMode = computed<"add" | "edit" | "register">(() => {
|
|
528
|
+
return selectedUnregisteredVisitor.value ? "register" : prop.mode;
|
|
529
|
+
});
|
|
530
|
+
|
|
437
531
|
const shouldShowField = (
|
|
438
532
|
fieldKey: keyof TVisitorPayload | "delivery-company"
|
|
439
533
|
) => {
|
|
@@ -461,6 +555,10 @@ const showNextButton = computed(() => {
|
|
|
461
555
|
} else return false;
|
|
462
556
|
});
|
|
463
557
|
|
|
558
|
+
const enableUnregistered = computed(() => {
|
|
559
|
+
return prop.mode === "add" && shouldShowField("plateNumber");
|
|
560
|
+
});
|
|
561
|
+
|
|
464
562
|
const showShowKeysField = computed(() => {
|
|
465
563
|
return ["guest", "contractor", "walk-in"].includes(prop.type);
|
|
466
564
|
});
|
|
@@ -628,10 +726,10 @@ function selectNricSearchResult(item: Partial<TPeople>) {
|
|
|
628
726
|
if (!visitor.company) {
|
|
629
727
|
visitor.company = companyNames.value?.[0] || visitor.company;
|
|
630
728
|
}
|
|
631
|
-
visitor.block = (item.block as any) ?? (visitor.block as any) ?? "";
|
|
632
|
-
visitor.level = (item.level as any) ?? (visitor.level as any) ?? "";
|
|
633
|
-
visitor.unit = item.unit ?? visitor.unit ?? "";
|
|
634
|
-
visitor.unitName = item.unitName ?? visitor.unitName;
|
|
729
|
+
// visitor.block = (item.block as any) ?? (visitor.block as any) ?? "";
|
|
730
|
+
// visitor.level = (item.level as any) ?? (visitor.level as any) ?? "";
|
|
731
|
+
// visitor.unit = item.unit ?? visitor.unit ?? "";
|
|
732
|
+
// visitor.unitName = item.unitName ?? visitor.unitName;
|
|
635
733
|
|
|
636
734
|
setTimeout(() => {
|
|
637
735
|
currentAutofillSource.value = null;
|
|
@@ -690,12 +788,16 @@ const debounceSearchVisitorsByPlateNumbers = debounce(() => {
|
|
|
690
788
|
fetchVisitorListByVehicleNumberRefresh();
|
|
691
789
|
}, 300);
|
|
692
790
|
|
|
693
|
-
watch(
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
791
|
+
// watch(
|
|
792
|
+
// () => visitor.plateNumber,
|
|
793
|
+
// (newVal) => {
|
|
794
|
+
// skipUnregisteredPlateCheck.value = false;
|
|
795
|
+
// selectedUnregisteredVisitor.value = null;
|
|
796
|
+
// unregisteredPlateMatches.value = [];
|
|
797
|
+
// dialog.showUnregisteredPlateDialog = false;
|
|
798
|
+
// debounceSearchVisitorsByPlateNumbers();
|
|
799
|
+
// }
|
|
800
|
+
// );
|
|
699
801
|
|
|
700
802
|
async function handleCheckout(visitorId: string) {
|
|
701
803
|
if (!visitorId) {
|
|
@@ -982,6 +1084,95 @@ function formatVisitorType(type: TVisitorType): string {
|
|
|
982
1084
|
}
|
|
983
1085
|
}
|
|
984
1086
|
|
|
1087
|
+
async function checkUnregisteredPlateBeforeContinue(action: "next" | "submit") {
|
|
1088
|
+
if (
|
|
1089
|
+
!enableUnregistered.value ||
|
|
1090
|
+
skipUnregisteredPlateCheck.value ||
|
|
1091
|
+
selectedUnregisteredVisitor.value ||
|
|
1092
|
+
!visitor.plateNumber
|
|
1093
|
+
) {
|
|
1094
|
+
return true;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
try {
|
|
1098
|
+
loading.checkingUnregisteredPlate = true;
|
|
1099
|
+
unregisteredPlateSearchText.value = visitor.plateNumber;
|
|
1100
|
+
const res = await checkSearchUncheckedOutUnregisteredVisitor({
|
|
1101
|
+
site: prop.site,
|
|
1102
|
+
plateNumber: visitor.plateNumber,
|
|
1103
|
+
hourAgo: 24,
|
|
1104
|
+
page: 1,
|
|
1105
|
+
limit: 100,
|
|
1106
|
+
});
|
|
1107
|
+
const items = Array.isArray(res?.items)
|
|
1108
|
+
? res.items
|
|
1109
|
+
: Array.isArray(res?.data?.items)
|
|
1110
|
+
? res.data.items
|
|
1111
|
+
: Array.isArray(res?.data)
|
|
1112
|
+
? res.data
|
|
1113
|
+
: Array.isArray(res)
|
|
1114
|
+
? res
|
|
1115
|
+
: [];
|
|
1116
|
+
|
|
1117
|
+
unregisteredPlateMatches.value = items;
|
|
1118
|
+
if (items.length === 0) return true;
|
|
1119
|
+
|
|
1120
|
+
pendingUnregisteredAction.value = action;
|
|
1121
|
+
dialog.showUnregisteredPlateDialog = true;
|
|
1122
|
+
return false;
|
|
1123
|
+
} catch (error: any) {
|
|
1124
|
+
errorMessage.value =
|
|
1125
|
+
error?.data?.message ||
|
|
1126
|
+
error?.response?._data?.message ||
|
|
1127
|
+
"Unable to check unregistered visitors. Please try again.";
|
|
1128
|
+
return false;
|
|
1129
|
+
} finally {
|
|
1130
|
+
loading.checkingUnregisteredPlate = false;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
function formatUnregisteredCheckIn(checkIn?: string) {
|
|
1135
|
+
return checkIn ? UTCToLocalTIme(checkIn) : "N/A";
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
async function continuePendingUnregisteredAction() {
|
|
1139
|
+
const action = pendingUnregisteredAction.value;
|
|
1140
|
+
pendingUnregisteredAction.value = null;
|
|
1141
|
+
if (action === "next") {
|
|
1142
|
+
await handleNextPage();
|
|
1143
|
+
} else if (action === "submit") {
|
|
1144
|
+
await submit();
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
async function closeUnregisteredPlateDialog() {
|
|
1149
|
+
dialog.showUnregisteredPlateDialog = false;
|
|
1150
|
+
unregisteredPlateMatches.value = [];
|
|
1151
|
+
skipUnregisteredPlateCheck.value = true;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
async function selectUnregisteredPlateMatch(match: TVisitor) {
|
|
1155
|
+
selectedUnregisteredVisitor.value = match;
|
|
1156
|
+
skipUnregisteredPlateCheck.value = true;
|
|
1157
|
+
dialog.showUnregisteredPlateDialog = false;
|
|
1158
|
+
unregisteredPlateMatches.value = [];
|
|
1159
|
+
|
|
1160
|
+
visitor.plateNumber = match.plateNumber;
|
|
1161
|
+
visitor.attachments = match.attachments || visitor.attachments;
|
|
1162
|
+
visitor.block = match.block || visitor.block;
|
|
1163
|
+
visitor.level = match.level || visitor.level;
|
|
1164
|
+
visitor.unit = match.unit || visitor.unit;
|
|
1165
|
+
visitor.company = match.company || visitor.company;
|
|
1166
|
+
visitor.contractorType = match.contractorType || visitor.contractorType;
|
|
1167
|
+
visitor.name = match.name || visitor.name;
|
|
1168
|
+
visitor.contact = match.contact || visitor.contact;
|
|
1169
|
+
visitor.nric = match.nric || visitor.nric;
|
|
1170
|
+
visitor.company = match.company || visitor.company;
|
|
1171
|
+
visitor.remarks = match.remarks || visitor.remarks;
|
|
1172
|
+
|
|
1173
|
+
pendingUnregisteredAction.value = null;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
985
1176
|
async function handleNextPage() {
|
|
986
1177
|
errorMessage.value = "";
|
|
987
1178
|
formRef.value!.validate();
|
|
@@ -990,10 +1181,21 @@ async function handleNextPage() {
|
|
|
990
1181
|
return;
|
|
991
1182
|
}
|
|
992
1183
|
const step = contractorStep.value;
|
|
1184
|
+
if (step === 2 && passType.value === "QR") {
|
|
1185
|
+
if (availableQrCount.value === null) {
|
|
1186
|
+
errorMessage.value = "Please wait while QR passes are being generated...";
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
if (availableQrCount.value === 0) {
|
|
1190
|
+
errorMessage.value = "No QR passes available. Add a non-physical card to this unit in Access Management first.";
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
993
1194
|
if (step === 2 && passType.value === "NFC" && passCards.value.length === 0) {
|
|
994
1195
|
errorMessage.value = "Please select at least one NFC card before proceeding.";
|
|
995
1196
|
return;
|
|
996
1197
|
}
|
|
1198
|
+
if (!(await checkUnregisteredPlateBeforeContinue("next"))) return;
|
|
997
1199
|
if (step < 3) contractorStep.value++;
|
|
998
1200
|
else await submit();
|
|
999
1201
|
}
|
|
@@ -1007,6 +1209,7 @@ async function submit() {
|
|
|
1007
1209
|
}
|
|
1008
1210
|
|
|
1009
1211
|
if (passType.value === "HID_QR" && !validateHidQrPrinterConfig()) return;
|
|
1212
|
+
if (!(await checkUnregisteredPlateBeforeContinue("submit"))) return;
|
|
1010
1213
|
|
|
1011
1214
|
processing.value = true;
|
|
1012
1215
|
|
|
@@ -1017,7 +1220,7 @@ async function submit() {
|
|
|
1017
1220
|
createdBy: prop.currentUser,
|
|
1018
1221
|
};
|
|
1019
1222
|
|
|
1020
|
-
if (
|
|
1223
|
+
if (formMode.value === "add" || formMode.value === "register") {
|
|
1021
1224
|
const allowedFields = typeFieldMap[prop.type];
|
|
1022
1225
|
for (const key of allowedFields as (keyof TVisitorPayload)[]) {
|
|
1023
1226
|
if (visitor[key] !== undefined) {
|
|
@@ -1055,7 +1258,7 @@ async function submit() {
|
|
|
1055
1258
|
}
|
|
1056
1259
|
|
|
1057
1260
|
// add register status when registering unregistered visitor
|
|
1058
|
-
if (
|
|
1261
|
+
if (formMode.value === "register") {
|
|
1059
1262
|
payload.status = "registered";
|
|
1060
1263
|
const currentUserId = currentUser.value?._id;
|
|
1061
1264
|
if(currentUserId) {
|
|
@@ -1065,7 +1268,18 @@ async function submit() {
|
|
|
1065
1268
|
|
|
1066
1269
|
try {
|
|
1067
1270
|
let res;
|
|
1068
|
-
if (prop.mode === "add") {
|
|
1271
|
+
if (prop.mode === "add" && selectedUnregisteredVisitor.value?._id) {
|
|
1272
|
+
payload.status = "registered";
|
|
1273
|
+
const currentUserId = currentUser.value?._id;
|
|
1274
|
+
if (currentUserId) {
|
|
1275
|
+
payload.updatedBy = currentUserId;
|
|
1276
|
+
}
|
|
1277
|
+
const { unitName, ...rest } = payload;
|
|
1278
|
+
res = await updateVisitor(
|
|
1279
|
+
selectedUnregisteredVisitor.value._id,
|
|
1280
|
+
rest as TVisitorPayload
|
|
1281
|
+
);
|
|
1282
|
+
} else if (formMode.value === "add") {
|
|
1069
1283
|
res = await createVisitor(payload as TVisitorPayload);
|
|
1070
1284
|
} else if (
|
|
1071
1285
|
(prop.mode === "edit" || prop.mode === "register") &&
|
|
@@ -1208,7 +1422,7 @@ async function submit() {
|
|
|
1208
1422
|
const err = error?.data?.message;
|
|
1209
1423
|
errorMessage.value =
|
|
1210
1424
|
err ||
|
|
1211
|
-
`Failed to ${
|
|
1425
|
+
`Failed to ${formMode.value === "add" ? "add" : "update"
|
|
1212
1426
|
} visitor. Please try again.`;
|
|
1213
1427
|
} finally {
|
|
1214
1428
|
processing.value = false;
|
|
@@ -1352,7 +1566,22 @@ async function printHidQrCodePass(visitorId = "", manageProcessing = true) {
|
|
|
1352
1566
|
watch(
|
|
1353
1567
|
() => visitor.plateNumber,
|
|
1354
1568
|
(newVal) => {
|
|
1355
|
-
|
|
1569
|
+
const normalizedPlateNumber = newVal?.toUpperCase();
|
|
1570
|
+
if (newVal !== normalizedPlateNumber) {
|
|
1571
|
+
visitor.plateNumber = normalizedPlateNumber;
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
if (
|
|
1576
|
+
selectedUnregisteredVisitor.value &&
|
|
1577
|
+
normalizedPlateNumber !== selectedUnregisteredVisitor.value.plateNumber?.toUpperCase()
|
|
1578
|
+
) {
|
|
1579
|
+
selectedUnregisteredVisitor.value = null;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
skipUnregisteredPlateCheck.value = false;
|
|
1583
|
+
unregisteredPlateMatches.value = [];
|
|
1584
|
+
dialog.showUnregisteredPlateDialog = false;
|
|
1356
1585
|
}
|
|
1357
1586
|
);
|
|
1358
1587
|
|