@7365admin1/layer-common 3.2.8-staging.204 → 3.2.8-staging.206

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.
@@ -108,6 +108,7 @@
108
108
 
109
109
  <HidReaderForm
110
110
  v-model="formDialog"
111
+ :site="props.site"
111
112
  :mode="selectedReader ? 'edit' : 'add'"
112
113
  :reader="selectedReader"
113
114
  :loading="saving"
@@ -125,6 +126,8 @@
125
126
  <span>Location</span><strong>{{ selectedReader?.location || "N/A" }}</strong>
126
127
  <span>HID Portal</span><strong>{{ selectedReader?.portalName || selectedReader?.portalId || "N/A" }}</strong>
127
128
  <span>Monitor Path</span><strong>{{ selectedReader?.monitorPath || "N/A" }}</strong>
129
+ <span>Monitor Callback</span><strong>{{ formatMonitorStatus(selectedReader?.monitorStatus) }}</strong>
130
+ <span>Last Callback</span><strong>{{ formatCallback(selectedReader) }}</strong>
128
131
  <span>Status</span><strong>{{ formatReaderStatus(resolveReaderStatus(selectedReader)) }}</strong>
129
132
  <span>Username</span><strong>{{ selectedReader?.username || "N/A" }}</strong>
130
133
  </div>
@@ -242,6 +245,80 @@
242
245
  </template>
243
246
 
244
247
  <script setup lang="ts">
248
+ type HidRecord = {
249
+ [key: string]: unknown;
250
+ _id?: string;
251
+ data?: HidRecord;
252
+ items?: HidRecord[];
253
+ identities?: HidRecord[];
254
+ users?: HidRecord[];
255
+ user_roles?: HidRecord[];
256
+ result?: HidRecord;
257
+ metadata?: HidRecord;
258
+ id?: string | number;
259
+ name?: string;
260
+ registration?: string;
261
+ card_value?: string | number;
262
+ cardNo?: string | number;
263
+ person?: string;
264
+ user?: string;
265
+ member?: string;
266
+ serviceProvider?: string;
267
+ visitor?: string;
268
+ type?: string;
269
+ status?: string;
270
+ location?: string;
271
+ deviceId?: string;
272
+ portalId?: number;
273
+ portalName?: string;
274
+ monitorPath?: string;
275
+ monitorStatus?: string;
276
+ operatingMode?: "standalone" | "online";
277
+ lastSyncAt?: string;
278
+ lastSyncStatus?: "idle" | "running" | "completed" | "failed";
279
+ lastSyncMessage?: string;
280
+ lastCallbackAt?: string;
281
+ lastCallbackType?: string;
282
+ readerModel?: "VL35LF" | "VL70LF" | "unknown" | "";
283
+ firmwareVersion?: string;
284
+ cardReadingMode?: "unconfigured" | "pacs" | "csn" | "csn_for_mifare";
285
+ csnByteOrder?: "msb" | "lsb";
286
+ pacsFormat?: "raw" | "wiegand";
287
+ };
288
+
289
+ type HidReaderFormPayload = {
290
+ name: string;
291
+ baseUrl: string;
292
+ deviceId: string;
293
+ portalId: number | null;
294
+ portalName: string;
295
+ location: string;
296
+ username: string;
297
+ password: string;
298
+ readerModel: "VL35LF" | "VL70LF" | "unknown" | "";
299
+ firmwareVersion: string;
300
+ cardReadingMode: "unconfigured" | "pacs" | "csn" | "csn_for_mifare";
301
+ csnByteOrder: "msb" | "lsb";
302
+ pacsFormat: "raw" | "wiegand";
303
+ operatingMode: "standalone" | "online";
304
+ monitorEnabled: boolean;
305
+ };
306
+
307
+ type HidSyncUser = HidRecord & {
308
+ id: number;
309
+ name: string;
310
+ registration: string;
311
+ _identityType: string;
312
+ };
313
+
314
+ type HidSyncPayload = {
315
+ objects: Array<{ object: "users"; values: HidSyncUser[] }>;
316
+ users: HidSyncUser[];
317
+ unmappedCount: number;
318
+ stats: { newEnrolled: number; updatedInformation: number; facialData: number };
319
+ defaultMessage: string;
320
+ };
321
+
245
322
  const props = defineProps({
246
323
  site: {
247
324
  type: String,
@@ -255,12 +332,14 @@ const {
255
332
  updateReader,
256
333
  deleteReader,
257
334
  testReader,
335
+ configureReaderIntegration,
336
+ setReaderMonitor,
337
+ setReaderOperatingMode,
258
338
  getIdentities,
259
- createIdentity,
260
339
  runObjectOperation,
261
340
  } = useHidAmico();
262
341
 
263
- const readers = ref<Record<string, any>[]>([]);
342
+ const readers = ref<HidRecord[]>([]);
264
343
  const search = ref("");
265
344
  const status = ref("");
266
345
  const loading = ref(false);
@@ -270,7 +349,7 @@ const formDialog = ref(false);
270
349
  const viewDialog = ref(false);
271
350
  const confirmDialog = ref(false);
272
351
  const resultDialog = ref(false);
273
- const selectedReader = ref<Record<string, any> | null>(null);
352
+ const selectedReader = ref<HidRecord | null>(null);
274
353
  const pendingAction = ref<"test" | "sync" | "delete" | null>(null);
275
354
  const actionStage = ref<"confirm" | "review" | "loading">("confirm");
276
355
  const resultSuccess = ref(true);
@@ -278,7 +357,7 @@ const resultTitle = ref("");
278
357
  const resultMessage = ref("");
279
358
  const resultReaderName = ref("");
280
359
  const syncMessage = ref("");
281
- const syncPreviewPayload = ref<Record<string, any> | null>(null);
360
+ const syncPreviewPayload = ref<HidSyncPayload | null>(null);
282
361
  const syncPreviewStats = ref({
283
362
  newEnrolled: 0,
284
363
  updatedInformation: 0,
@@ -398,31 +477,31 @@ function openAdd() {
398
477
  formDialog.value = true;
399
478
  }
400
479
 
401
- function openEdit(reader: Record<string, any>) {
480
+ function openEdit(reader: HidRecord) {
402
481
  selectedReader.value = reader;
403
482
  formDialog.value = true;
404
483
  }
405
484
 
406
- function openView(reader: Record<string, any>) {
485
+ function openView(reader: HidRecord) {
407
486
  selectedReader.value = reader;
408
487
  viewDialog.value = true;
409
488
  }
410
489
 
411
- function openTestConfirm(reader?: Record<string, any> | null) {
490
+ function openTestConfirm(reader?: HidRecord | null) {
412
491
  if (reader) selectedReader.value = reader;
413
492
  pendingAction.value = "test";
414
493
  resetActionFlow();
415
494
  confirmDialog.value = true;
416
495
  }
417
496
 
418
- function openSyncConfirm(reader?: Record<string, any> | null) {
497
+ function openSyncConfirm(reader?: HidRecord | null) {
419
498
  if (reader) selectedReader.value = reader;
420
499
  pendingAction.value = "sync";
421
500
  resetActionFlow();
422
501
  confirmDialog.value = true;
423
502
  }
424
503
 
425
- function openDeleteConfirm(reader: Record<string, any>) {
504
+ function openDeleteConfirm(reader: HidRecord) {
426
505
  selectedReader.value = reader;
427
506
  pendingAction.value = "delete";
428
507
  resetActionFlow();
@@ -445,16 +524,46 @@ function closeConfirmDialog() {
445
524
  resetActionFlow();
446
525
  }
447
526
 
448
- async function saveReader(payload: Record<string, any>) {
527
+ async function saveReader(payload: HidReaderFormPayload) {
449
528
  saving.value = true;
450
529
  try {
530
+ let readerId = String(selectedReader.value?._id || "");
531
+ let monitorWarning = "";
451
532
  if (selectedReader.value?._id) {
452
533
  await updateReader(selectedReader.value._id, payload);
534
+ if (payload.monitorEnabled) {
535
+ await configureReaderIntegration(selectedReader.value._id);
536
+ await setReaderOperatingMode(selectedReader.value._id, payload.operatingMode || "standalone");
537
+ } else {
538
+ await setReaderMonitor(selectedReader.value._id, false);
539
+ }
453
540
  } else {
454
- await createReader({ ...payload, site: props.site });
541
+ const response = await createReader({ ...payload, site: props.site });
542
+ const createdReader = response?.data || response || {};
543
+ readerId = String(createdReader?._id || "");
544
+ monitorWarning = String(createdReader?.monitorWarning || "");
545
+ }
546
+ if (!selectedReader.value?._id && readerId && payload.monitorEnabled && !monitorWarning) {
547
+ await setReaderOperatingMode(readerId, payload.operatingMode || "standalone");
455
548
  }
456
549
  formDialog.value = false;
457
550
  await loadReaders();
551
+ if (monitorWarning) {
552
+ showResult(
553
+ false,
554
+ "Reader Requires Configuration",
555
+ monitorWarning,
556
+ { readerName: payload.name || "HID Reader" },
557
+ );
558
+ }
559
+ } catch (error: unknown) {
560
+ console.error("Unable to save HID reader:", error);
561
+ showResult(
562
+ false,
563
+ "Save HID Reader Failed",
564
+ getFriendlyHidError(error),
565
+ { readerName: payload.name || selectedReader.value?.name || "HID Reader" },
566
+ );
458
567
  } finally {
459
568
  saving.value = false;
460
569
  }
@@ -485,22 +594,16 @@ async function runConfirmedAction() {
485
594
 
486
595
  actionStage.value = "loading";
487
596
  const payload = syncPreviewPayload.value;
488
- const hidUsersToImport = payload.hidUsersToImport || [];
489
- const importedCount = hidUsersToImport.length
490
- ? await importHidUsers(selectedReader.value._id, hidUsersToImport)
491
- : 0;
597
+ const unmappedCount = Number(payload.unmappedCount || 0);
492
598
 
493
599
  if (!payload.objects.length) {
494
- if (importedCount) {
495
- const stats = {
496
- ...syncPreviewStats.value,
497
- newEnrolled: importedCount,
498
- };
499
- const message = syncMessage.value || `Synced ${importedCount} HID user(s) from reader.`;
600
+ if (unmappedCount) {
601
+ const message = syncMessage.value
602
+ || `Found ${unmappedCount} HID user(s) that must be linked from the HID Users screen.`;
500
603
  await applyReaderSyncState(selectedReader.value._id, "completed", message);
501
- showResult(true, "Sync Successful", message, {
604
+ showResult(true, "Sync Review Required", message, {
502
605
  readerName: selectedReader.value.name || "HID Reader",
503
- stats,
606
+ stats: syncPreviewStats.value,
504
607
  });
505
608
  confirmDialog.value = false;
506
609
  resetActionFlow();
@@ -517,8 +620,10 @@ async function runConfirmedAction() {
517
620
  return;
518
621
  }
519
622
  const result = await syncHidUsers(selectedReader.value._id, payload.users);
520
- const importMessage = importedCount ? `${importedCount} HID user(s) imported from reader.` : "";
521
- const message = syncMessage.value || [result.message, importMessage].filter(Boolean).join(" ");
623
+ const mappingMessage = unmappedCount
624
+ ? `${unmappedCount} HID user(s) still need to be linked from the HID Users screen.`
625
+ : "";
626
+ const message = syncMessage.value || [result.message, mappingMessage].filter(Boolean).join(" ");
522
627
  await applyReaderSyncState(selectedReader.value._id, "completed", message);
523
628
  showResult(true, "Sync Successful", message, {
524
629
  readerName: selectedReader.value.name || "HID Reader",
@@ -532,7 +637,7 @@ async function runConfirmedAction() {
532
637
  confirmDialog.value = false;
533
638
  resetActionFlow();
534
639
  await loadReaders();
535
- } catch (error: any) {
640
+ } catch (error: unknown) {
536
641
  console.error("HID reader action failed:", error);
537
642
  const friendlyMessage = getFriendlyHidError(error);
538
643
  if ((pendingAction.value === "sync" || pendingAction.value === "test") && selectedReader.value?._id) {
@@ -552,7 +657,7 @@ async function runConfirmedAction() {
552
657
 
553
658
  async function applyReaderSyncState(readerId: string, status: "completed" | "failed", message: string) {
554
659
  const lastSyncAt = new Date().toISOString();
555
- const patch: Record<string, any> = {
660
+ const patch: HidRecord = {
556
661
  lastSyncAt,
557
662
  lastSyncStatus: status,
558
663
  lastSyncMessage: message,
@@ -602,35 +707,40 @@ async function buildSyncPayload(readerId: string) {
602
707
  const hidUsers = normalizeHidUsers(hidResponse);
603
708
  return {
604
709
  objects: [],
605
- importedCount: 0,
606
710
  users: [],
607
- hidUsersToImport: hidUsers,
711
+ unmappedCount: hidUsers.length,
608
712
  stats: {
609
- newEnrolled: hidUsers.length,
713
+ newEnrolled: 0,
610
714
  updatedInformation: 0,
611
715
  facialData: countFacialData(hidUsers),
612
716
  },
613
- defaultMessage: hidUsers.length ? `Ready to import ${hidUsers.length} HID user(s) from reader.` : "",
717
+ defaultMessage: hidUsers.length
718
+ ? `Found ${hidUsers.length} HID user(s) that must be linked from the HID Users screen.`
719
+ : "",
614
720
  };
615
721
  }
616
722
 
723
+ const allLinkedIds = new Set(
724
+ identities
725
+ .map((identity) => Number(identity.hidUserId))
726
+ .filter((id: number) => Number.isInteger(id) && id > 0),
727
+ );
617
728
  const users = identities
729
+ .filter((identity) => (
730
+ identity.type !== "visitor"
731
+ && (identity.metadata as Record<string, unknown> | undefined)?.temporary !== true
732
+ ))
618
733
  .map(toHidUserObject)
619
- .filter((user: Record<string, any>) => user.id && user.name);
734
+ .filter((user): user is HidSyncUser => user !== null);
620
735
  const existingHidUsers = await getExistingHidUsers(readerId);
621
736
  const existingIds = new Set(existingHidUsers.map((user) => Number(user.hidUserId)));
622
- const localIds = new Set(
623
- users
624
- .map((user: Record<string, any>) => Number(user.id))
625
- .filter((id) => Number.isInteger(id) && id > 0),
626
- );
627
737
  const hidUsersToImport = existingHidUsers.filter((user) => {
628
738
  const hidUserId = Number(user.hidUserId);
629
- return Number.isInteger(hidUserId) && hidUserId > 0 && !localIds.has(hidUserId);
739
+ return Number.isInteger(hidUserId) && hidUserId > 0 && !allLinkedIds.has(hidUserId);
630
740
  });
631
- const newEnrolled = users.filter((user: Record<string, any>) => !existingIds.has(Number(user.id))).length;
632
- const updatedInformation = users.filter((user: Record<string, any>) => existingIds.has(Number(user.id))).length;
633
- const totalUsersToSync = users.length + hidUsersToImport.length;
741
+ const newEnrolled = users.filter((user) => !existingIds.has(Number(user.id))).length;
742
+ const updatedInformation = users.filter((user) => existingIds.has(Number(user.id))).length;
743
+ const totalUsersToSync = users.length;
634
744
 
635
745
  return {
636
746
  objects: users.length
@@ -642,22 +752,26 @@ async function buildSyncPayload(readerId: string) {
642
752
  ]
643
753
  : [],
644
754
  users,
645
- hidUsersToImport,
646
- importedCount: hidUsersToImport.length,
755
+ unmappedCount: hidUsersToImport.length,
647
756
  stats: {
648
- newEnrolled: newEnrolled + hidUsersToImport.length,
757
+ newEnrolled,
649
758
  updatedInformation,
650
759
  facialData: countFacialData([...users, ...hidUsersToImport]),
651
760
  },
652
- defaultMessage: totalUsersToSync ? `Ready to sync ${totalUsersToSync} HID user(s).` : "",
761
+ defaultMessage: [
762
+ totalUsersToSync ? `Ready to sync ${totalUsersToSync} linked HID user(s).` : "",
763
+ hidUsersToImport.length
764
+ ? `${hidUsersToImport.length} HID user(s) must be linked from the HID Users screen.`
765
+ : "",
766
+ ].filter(Boolean).join(" "),
653
767
  };
654
768
  }
655
769
 
656
- async function syncHidUsers(readerId: string, users: Record<string, any>[]) {
770
+ async function syncHidUsers(readerId: string, users: HidSyncUser[]) {
657
771
  const existingIds = await getExistingHidUserIds(readerId);
658
772
  const usersToCreate = users.filter((user) => !existingIds.has(Number(user.id)));
659
773
  const usersToModify = users.filter((user) => existingIds.has(Number(user.id)));
660
- const results: Record<string, any>[] = [];
774
+ const results: HidRecord[] = [];
661
775
 
662
776
  if (usersToModify.length) {
663
777
  const modifyResults = [];
@@ -711,7 +825,7 @@ async function getExistingHidUsers(readerId: string) {
711
825
  return normalizeHidUsers(hidResponse);
712
826
  }
713
827
 
714
- function normalizeHidUsers(response: Record<string, any>) {
828
+ function normalizeHidUsers(response: HidRecord) {
715
829
  const users =
716
830
  response?.data?.users ||
717
831
  response?.data?.data?.users ||
@@ -731,49 +845,29 @@ function normalizeHidUsers(response: Record<string, any>) {
731
845
  : [];
732
846
  }
733
847
 
734
- async function importHidUsers(readerId: string, hidUsers: Record<string, any>[]) {
735
- let importedCount = 0;
736
- for (const user of hidUsers) {
737
- if (!user.hidUserId) continue;
738
- try {
739
- await createIdentity(readerId, {
740
- site: props.site,
741
- hidUserId: user.hidUserId,
742
- registration: user.registration || "",
743
- cardNo: user.cardNo || "",
744
- type: "resident",
745
- status: "active",
746
- metadata: {
747
- name: user.metadata?.name || user.name || `HID User ${user.hidUserId}`,
748
- hidImported: true,
749
- importedAt: new Date().toISOString(),
750
- },
751
- });
752
- importedCount += 1;
753
- } catch {
754
- // Existing users may already be mapped; keep syncing the remaining HID users.
755
- }
756
- }
757
- return importedCount;
758
- }
848
+ function toHidUserObject(identity: HidRecord): HidSyncUser | null {
849
+ const id = toHidNumericId(identity.hidUserId);
850
+ const name = String(
851
+ identity.metadata?.name ?? identity.name ?? `User ${identity.hidUserId ?? ""}`,
852
+ ).trim();
853
+ if (!id || !name) return null;
759
854
 
760
- function toHidUserObject(identity: Record<string, any>) {
761
855
  return {
762
- id: toHidNumericId(identity.hidUserId),
763
- name: identity.metadata?.name || identity.name || `User ${identity.hidUserId || ""}`.trim(),
856
+ id,
857
+ name,
764
858
  registration: identity.registration || "",
765
859
  _identityType: identity.type || "resident",
766
860
  };
767
861
  }
768
862
 
769
- function toHidUserCreateValues(user: Record<string, any>) {
863
+ function toHidUserCreateValues(user: HidSyncUser) {
770
864
  return {
771
865
  id: user.id,
772
866
  ...toHidUserValues(user),
773
867
  };
774
868
  }
775
869
 
776
- function toHidUserValues(user: Record<string, any>) {
870
+ function toHidUserValues(user: HidSyncUser) {
777
871
  return {
778
872
  name: user.name,
779
873
  registration: user.registration || "",
@@ -873,11 +967,11 @@ function showResult(
873
967
  resultDialog.value = true;
874
968
  }
875
969
 
876
- function countFacialData(users: Record<string, any>[]) {
970
+ function countFacialData(users: HidRecord[]) {
877
971
  return users.filter((user) => user.face || user.photo || user.image || user.imageUrl || user.faceImage).length;
878
972
  }
879
973
 
880
- function getFriendlyHidError(error: any) {
974
+ function getFriendlyHidError(error: unknown) {
881
975
  const message = getHidErrorMessage(error);
882
976
  const lowerMessage = message.toLowerCase();
883
977
 
@@ -939,22 +1033,30 @@ function getFriendlyHidError(error: any) {
939
1033
  return message || "The HID device rejected the request. Please check the reader connection and try again.";
940
1034
  }
941
1035
 
942
- function getHidErrorMessage(error: any) {
943
- const data =
944
- error?.data ||
945
- error?.response?._data ||
946
- error?.response?.data ||
947
- error?.cause?.data ||
948
- error?.cause?.response?._data ||
949
- {};
1036
+ function asHidRecord(value: unknown): HidRecord {
1037
+ return typeof value === "object" && value !== null ? value as HidRecord : {};
1038
+ }
1039
+
1040
+ function getHidErrorMessage(error: unknown) {
1041
+ const record = asHidRecord(error);
1042
+ const response = asHidRecord(record.response);
1043
+ const cause = asHidRecord(record.cause);
1044
+ const causeResponse = asHidRecord(cause.response);
1045
+ const data = asHidRecord(
1046
+ record.data
1047
+ ?? response._data
1048
+ ?? response.data
1049
+ ?? cause.data
1050
+ ?? causeResponse._data,
1051
+ );
950
1052
 
951
1053
  return String(
952
- data?.message ||
953
- data?.error ||
954
- data?.statusMessage ||
955
- error?.statusMessage ||
956
- error?.message ||
957
- "Request failed.",
1054
+ data.message
1055
+ ?? data.error
1056
+ ?? data.statusMessage
1057
+ ?? record.statusMessage
1058
+ ?? record.message
1059
+ ?? "Request failed.",
958
1060
  );
959
1061
  }
960
1062
 
@@ -964,13 +1066,13 @@ function formatDate(value?: string) {
964
1066
  return Number.isNaN(date.getTime()) ? "N/A" : date.toLocaleString();
965
1067
  }
966
1068
 
967
- function resolveReaderStatus(reader?: Record<string, any> | null) {
1069
+ function resolveReaderStatus(reader?: HidRecord | null) {
968
1070
  if (!reader) return "";
969
1071
  if (reader.lastSyncStatus === "failed" && reader.status === "active") return "offline";
970
1072
  return reader.status || "offline";
971
1073
  }
972
1074
 
973
- function normalizeReaderStatus(reader: Record<string, any>) {
1075
+ function normalizeReaderStatus(reader: HidRecord) {
974
1076
  return {
975
1077
  ...reader,
976
1078
  status: resolveReaderStatus(reader),
@@ -982,6 +1084,19 @@ function formatReaderStatus(value?: string) {
982
1084
  if (value === "offline") return "Offline";
983
1085
  return value.charAt(0).toUpperCase() + value.slice(1);
984
1086
  }
1087
+
1088
+ function formatMonitorStatus(value?: string) {
1089
+ if (value === "configured") return "Enabled";
1090
+ if (value === "disabled") return "Disabled";
1091
+ if (value === "failed") return "Failed";
1092
+ return "Not configured";
1093
+ }
1094
+
1095
+ function formatCallback(reader?: HidRecord | null) {
1096
+ if (!reader?.lastCallbackAt) return "No callback received";
1097
+ const type = typeof reader.lastCallbackType === "string" ? reader.lastCallbackType : "event";
1098
+ return `${type} - ${formatDate(String(reader.lastCallbackAt))}`;
1099
+ }
985
1100
  </script>
986
1101
 
987
1102
 
@@ -60,10 +60,18 @@
60
60
  </template>
61
61
 
62
62
  <script setup lang="ts">
63
+ type HidServiceMetadata = Record<string, unknown> & {
64
+ services?: unknown[];
65
+ };
66
+
67
+ type HidServiceSite = Record<string, unknown> & {
68
+ metadata?: HidServiceMetadata;
69
+ };
70
+
63
71
  const props = defineProps<{
64
72
  site: string;
65
73
  org: string;
66
- siteData?: Record<string, any> | null;
74
+ siteData?: HidServiceSite | null;
67
75
  }>();
68
76
 
69
77
  const emit = defineEmits<{
@@ -112,13 +120,14 @@ function buildHidServices(enabled: boolean) {
112
120
  status: enabled ? "active" : "inactive",
113
121
  };
114
122
 
115
- const index = currentServices.findIndex((item: any) =>
116
- hidServiceKeys.includes(normalizeServiceKey(item?.key ?? item?.code ?? item?.name)),
117
- );
123
+ const index = currentServices.findIndex((item) => {
124
+ const record = toServiceRecord(item);
125
+ return hidServiceKeys.includes(normalizeServiceKey(record.key ?? record.code ?? record.name));
126
+ });
118
127
 
119
128
  if (index >= 0) {
120
129
  currentServices[index] = {
121
- ...currentServices[index],
130
+ ...toServiceRecord(currentServices[index]),
122
131
  ...service,
123
132
  };
124
133
  } else {
@@ -146,7 +155,7 @@ async function saveHidService(value: boolean) {
146
155
  emit("refresh");
147
156
  await refreshNuxtData(`layout-selected-site-details-${useRuntimeConfig().public.APP}`);
148
157
  showMessage(`HID Face Reader ${value ? "enabled" : "disabled"} successfully`, "success");
149
- } catch (error: any) {
158
+ } catch (error: unknown) {
150
159
  hidEnabled.value = previousValue;
151
160
  showMessage(errorConverter(error), "error");
152
161
  } finally {
@@ -154,6 +163,12 @@ async function saveHidService(value: boolean) {
154
163
  }
155
164
  }
156
165
 
166
+ function toServiceRecord(value: unknown): Record<string, unknown> {
167
+ return typeof value === "object" && value !== null && !Array.isArray(value)
168
+ ? value as Record<string, unknown>
169
+ : {};
170
+ }
171
+
157
172
  function goToHidReaders() {
158
173
  navigateTo({
159
174
  name: "org-site-access-mgmt-hid-readers",