@7365admin1/layer-common 3.0.22 → 3.0.23

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.
@@ -181,7 +181,6 @@
181
181
  <v-card-text v-else class="text-body-2 text-medium-emphasis">
182
182
  You do not have permission to view service providers.
183
183
  </v-card-text>
184
-
185
184
  </v-card>
186
185
  </v-col>
187
186
  </v-row>
@@ -415,151 +414,151 @@
415
414
  </v-card>
416
415
  </v-dialog>
417
416
 
418
- <v-dialog v-model="createInviteDialog" width="580" persistent>
419
- <v-card width="100%" rounded="lg" class="sp-invite-card">
420
- <v-toolbar flat color="grey-lighten-4" height="76">
421
- <v-row no-gutters class="fill-height px-6" align="center">
422
- <span class="font-weight-bold text-h5">
423
- Invite Service Provider
424
- </span>
425
- </v-row>
426
- </v-toolbar>
427
-
428
- <v-card-text class="sp-invite-body">
429
- <v-form
430
- v-model="validServiceProvider"
431
- :disabled="disableServiceProvider"
432
- >
433
- <v-row no-gutters>
434
- <!-- Email -->
435
- <v-col cols="12">
436
- <v-row no-gutters>
437
- <InputLabel class="text-capitalize" title="Email" required />
438
- <v-col cols="12">
439
- <v-text-field
440
- v-model="serviceProviderInvite.email"
441
- variant="outlined"
442
- density="comfortable"
443
- :rules="[requiredRule, emailRule]"
444
- ></v-text-field>
445
- </v-col>
446
- </v-row>
447
- </v-col>
448
-
449
- <!-- Existing account block -->
450
- <v-col cols="12" v-if="existingAccount">
451
- <v-divider class="mb-6" />
452
-
453
- <div class="sp-existing-title">Existing Account Verified</div>
454
-
455
- <div class="sp-existing-copy">
456
- {{ serviceProviderInvite.email }} is already onboarded.
457
- Sending this invite will add this site to the list of
458
- locations this company manages.
459
- </div>
460
-
461
- <v-row no-gutters>
462
- <InputLabel title="Organization" />
463
- <v-col cols="12">
464
- <v-text-field
465
- :model-value="existingAccount.text"
466
- readonly
467
- variant="outlined"
468
- density="comfortable"
469
- />
470
- </v-col>
471
- </v-row>
472
- </v-col>
473
-
474
- <v-col cols="12">
475
- <v-divider class="mb-6" />
476
- </v-col>
417
+ <v-dialog v-model="createInviteDialog" width="580" persistent>
418
+ <v-card width="100%" rounded="lg" class="sp-invite-card">
419
+ <v-toolbar flat color="grey-lighten-4" height="76">
420
+ <v-row no-gutters class="fill-height px-6" align="center">
421
+ <span class="font-weight-bold text-h5">
422
+ Invite Service Provider
423
+ </span>
424
+ </v-row>
425
+ </v-toolbar>
477
426
 
478
- <!-- App & Site: only shown when no existing account is verified -->
479
- <template v-if="!existingAccount">
427
+ <v-card-text class="sp-invite-body">
428
+ <v-form
429
+ v-model="validServiceProvider"
430
+ :disabled="disableServiceProvider"
431
+ >
432
+ <v-row no-gutters>
433
+ <!-- Email -->
480
434
  <v-col cols="12">
481
435
  <v-row no-gutters>
482
- <InputLabel class="text-capitalize" title="App" required />
436
+ <InputLabel class="text-capitalize" title="Email" required />
483
437
  <v-col cols="12">
484
- <v-select
485
- v-model="serviceProviderInvite.app"
486
- :items="serviceProviderInviteApps"
487
- item-title="title"
488
- item-value="value"
438
+ <v-text-field
439
+ v-model="serviceProviderInvite.email"
489
440
  variant="outlined"
490
441
  density="comfortable"
491
- :rules="[requiredRule]"
492
- ></v-select>
442
+ :rules="[requiredRule, emailRule]"
443
+ ></v-text-field>
493
444
  </v-col>
494
445
  </v-row>
495
446
  </v-col>
496
447
 
497
- <v-col cols="12">
448
+ <!-- Existing account block -->
449
+ <v-col cols="12" v-if="existingAccount">
450
+ <v-divider class="mb-6" />
451
+
452
+ <div class="sp-existing-title">Existing Account Verified</div>
453
+
454
+ <div class="sp-existing-copy">
455
+ {{ serviceProviderInvite.email }} is already onboarded. Sending
456
+ this invite will add this site to the list of locations this
457
+ company manages.
458
+ </div>
459
+
498
460
  <v-row no-gutters>
499
- <InputLabel class="text-capitalize" title="Site" required />
461
+ <InputLabel title="Organization" />
500
462
  <v-col cols="12">
501
- <v-select
502
- v-model="serviceProviderInvite.siteId"
503
- :items="serviceProviderInviteSites"
504
- item-title="title"
505
- item-value="value"
463
+ <v-text-field
464
+ :model-value="existingAccount.text"
465
+ readonly
506
466
  variant="outlined"
507
467
  density="comfortable"
508
- :rules="[requiredRule]"
509
- @update:model-value="setInviteSiteName"
510
- ></v-select>
468
+ />
511
469
  </v-col>
512
470
  </v-row>
513
471
  </v-col>
514
- </template>
515
472
 
516
- <!-- Error message -->
517
- <v-col cols="12" class="my-2">
518
- <v-row no-gutters>
519
- <v-col cols="12" class="text-center">
520
- <span
521
- class="text-none text-subtitle-2 font-weight-medium text-error"
522
- >
523
- {{ messageServiceProvider }}
524
- </span>
473
+ <v-col cols="12">
474
+ <v-divider class="mb-6" />
475
+ </v-col>
476
+
477
+ <!-- App & Site: only shown when no existing account is verified -->
478
+ <template v-if="!existingAccount">
479
+ <v-col cols="12">
480
+ <v-row no-gutters>
481
+ <InputLabel class="text-capitalize" title="App" required />
482
+ <v-col cols="12">
483
+ <v-select
484
+ v-model="serviceProviderInvite.app"
485
+ :items="serviceProviderInviteApps"
486
+ item-title="title"
487
+ item-value="value"
488
+ variant="outlined"
489
+ density="comfortable"
490
+ :rules="[requiredRule]"
491
+ ></v-select>
492
+ </v-col>
493
+ </v-row>
525
494
  </v-col>
526
- </v-row>
527
- </v-col>
528
- </v-row>
529
- </v-form>
530
- </v-card-text>
531
495
 
532
- <v-toolbar flat height="76" class="sp-invite-footer">
533
- <v-row no-gutters class="fill-height">
534
- <v-col cols="6" class="fill-height">
535
- <v-btn
536
- block
537
- variant="flat"
538
- class="text-none sp-invite-footer-btn"
539
- height="76"
540
- @click="setServiceProvider({ mode: 'invite', dialog: false })"
541
- >
542
- Back
543
- </v-btn>
544
- </v-col>
496
+ <v-col cols="12">
497
+ <v-row no-gutters>
498
+ <InputLabel class="text-capitalize" title="Site" required />
499
+ <v-col cols="12">
500
+ <v-select
501
+ v-model="serviceProviderInvite.siteId"
502
+ :items="serviceProviderInviteSites"
503
+ item-title="title"
504
+ item-value="value"
505
+ variant="outlined"
506
+ density="comfortable"
507
+ :rules="[requiredRule]"
508
+ @update:model-value="setInviteSiteName"
509
+ ></v-select>
510
+ </v-col>
511
+ </v-row>
512
+ </v-col>
513
+ </template>
545
514
 
546
- <v-col cols="6" class="fill-height">
547
- <v-btn
548
- block
549
- variant="flat"
550
- class="text-none sp-invite-submit-btn"
551
- height="76"
552
- :disabled="!validServiceProvider"
553
- :loading="disableServiceProvider"
554
- @click="submitServiceProviderInvite()"
555
- >
556
- Submit
557
- </v-btn>
558
- </v-col>
559
- </v-row>
560
- </v-toolbar>
561
- </v-card>
562
- </v-dialog>
515
+ <!-- Error message -->
516
+ <v-col cols="12" class="my-2">
517
+ <v-row no-gutters>
518
+ <v-col cols="12" class="text-center">
519
+ <span
520
+ class="text-none text-subtitle-2 font-weight-medium text-error"
521
+ >
522
+ {{ messageServiceProvider }}
523
+ </span>
524
+ </v-col>
525
+ </v-row>
526
+ </v-col>
527
+ </v-row>
528
+ </v-form>
529
+ </v-card-text>
530
+
531
+ <v-toolbar flat height="76" class="sp-invite-footer">
532
+ <v-row no-gutters class="fill-height">
533
+ <v-col cols="6" class="fill-height">
534
+ <v-btn
535
+ block
536
+ variant="flat"
537
+ class="text-none sp-invite-footer-btn"
538
+ height="76"
539
+ @click="setServiceProvider({ mode: 'invite', dialog: false })"
540
+ >
541
+ Back
542
+ </v-btn>
543
+ </v-col>
544
+
545
+ <v-col cols="6" class="fill-height">
546
+ <v-btn
547
+ block
548
+ variant="flat"
549
+ class="text-none sp-invite-submit-btn"
550
+ height="76"
551
+ :disabled="!validServiceProvider"
552
+ :loading="disableServiceProvider"
553
+ @click="submitServiceProviderInvite()"
554
+ >
555
+ Submit
556
+ </v-btn>
557
+ </v-col>
558
+ </v-row>
559
+ </v-toolbar>
560
+ </v-card>
561
+ </v-dialog>
563
562
 
564
563
  <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
565
564
  </template>
@@ -689,7 +688,7 @@ const headers = [
689
688
 
690
689
  const { natureOfBusinessV3 } = useLocal();
691
690
  const { requiredRule, emailRule, debounce } = useUtils();
692
- const {getUserByEmail} = useUser()
691
+ const { getUserByEmail } = useUser();
693
692
 
694
693
  const listTab = ref<ListTab>("active");
695
694
  const page = ref(1);
@@ -732,14 +731,13 @@ const {
732
731
  add: addServiceProvider,
733
732
  createServiceProviderInvite,
734
733
  updateStatus: updateServiceProviderStatus,
735
- invite
734
+ invite,
736
735
  } = useServiceProvider();
737
736
  const { getAll: getAllMembers } = useMember();
738
737
 
739
- const { getVerifications, cancelUserInvitation, getVerificationByEmail } = useVerification();
740
- const {
741
- getOrgsByMembership,
742
- } = useMember();
738
+ const { getVerifications, cancelUserInvitation, getVerificationByEmail } =
739
+ useVerification();
740
+ const { getOrgsByMembership } = useMember();
743
741
 
744
742
  const existingAccount = ref<any>(null);
745
743
  const checkingExistingAccount = ref(false);
@@ -774,22 +772,21 @@ async function checkExistingAccount(email: string) {
774
772
 
775
773
  if (!user?._id) return;
776
774
 
777
- const orgs = await getOrgs({
778
- user: user._id,
779
- });
780
-
781
- const matchedOrg = orgs.items?.find(
782
- (org: any) => org.type === serviceProviderInvite.value.app
783
- );
775
+ const orgs = await getOrgs({
776
+ user: user._id,
777
+ });
784
778
 
785
- if (matchedOrg) {
786
- existingAccount.value = {
787
- _id: matchedOrg.value,
788
- text: matchedOrg.text,
789
- ...matchedOrg,
790
- };
791
- }
779
+ const matchedOrg = orgs.items?.find(
780
+ (org: any) => org.type === serviceProviderInvite.value.app
781
+ );
792
782
 
783
+ if (matchedOrg) {
784
+ existingAccount.value = {
785
+ _id: matchedOrg.value,
786
+ text: matchedOrg.text,
787
+ ...matchedOrg,
788
+ };
789
+ }
793
790
  } catch (error) {
794
791
  existingAccount.value = null;
795
792
  } finally {
@@ -797,7 +794,6 @@ if (matchedOrg) {
797
794
  }
798
795
  }
799
796
 
800
-
801
797
  watch(
802
798
  () => serviceProviderInvite.value.email,
803
799
  async (value) => {
@@ -876,7 +872,10 @@ function rowActionLabel(row: TableRow) {
876
872
 
877
873
  function typeDisplay(type: string, nature?: string) {
878
874
  if (nature && String(nature).trim()) return String(nature);
879
- const list = natureOfBusinessV3.value as Array<{ title?: string; value?: string }>;
875
+ const list = natureOfBusinessV3.value as Array<{
876
+ title?: string;
877
+ value?: string;
878
+ }>;
880
879
  const hit = list?.find((x) => x.value === type);
881
880
  return hit?.title ?? type ?? "-";
882
881
  }
@@ -975,12 +974,12 @@ function mapInviteRows(raw: Record<string, any>[]): TableRow[] {
975
974
  }
976
975
 
977
976
  async function loadList() {
978
- if (!props.siteId || !props.canViewServiceProviders) {
979
- items.value = [];
980
- pages.value = 0;
981
- pageRange.value = "-- - -- of --";
982
- return;
983
- }
977
+ // if (!props.siteId || !props.canViewServiceProviders) {
978
+ // items.value = [];
979
+ // pages.value = 0;
980
+ // pageRange.value = "-- - -- of --";
981
+ // return;
982
+ // }
984
983
 
985
984
  loading.value = true;
986
985
  try {
@@ -1077,7 +1076,8 @@ async function confirmStatusChange() {
1077
1076
  if (!statusActionRow.value) return;
1078
1077
 
1079
1078
  statusUpdating.value = true;
1080
- const nextStatus = statusAction.value === "reactivate" ? "active" : "inactive";
1079
+ const nextStatus =
1080
+ statusAction.value === "reactivate" ? "active" : "inactive";
1081
1081
  try {
1082
1082
  await updateServiceProviderStatus(statusActionRow.value._id, nextStatus);
1083
1083
  showMessage(
@@ -1142,38 +1142,38 @@ function setServiceProvider({
1142
1142
  createDialog.value = dialog;
1143
1143
  }
1144
1144
 
1145
- if (dialog) {
1146
- serviceProvider.value = {
1147
- name: "",
1148
- type: "",
1149
- email: "",
1150
- description: "",
1151
- orgId: props.orgId,
1152
- siteId: props.siteId,
1153
- siteName: site.value?.name ?? "",
1154
- orgName: "Org Name",
1155
- category: mode === "add" ? "internal" : "external",
1156
- };
1157
-
1158
- if (mode === "invite") {
1159
- existingAccount.value = null;
1160
-
1161
- serviceProviderInvite.value = {
1145
+ if (dialog) {
1146
+ serviceProvider.value = {
1147
+ name: "",
1148
+ type: "",
1162
1149
  email: "",
1163
- app: defaultInviteApp,
1150
+ description: "",
1151
+ orgId: props.orgId,
1164
1152
  siteId: props.siteId,
1165
- siteName: site.value?.name || props.siteName,
1153
+ siteName: site.value?.name ?? "",
1154
+ orgName: "Org Name",
1155
+ category: mode === "add" ? "internal" : "external",
1166
1156
  };
1167
- }
1168
1157
 
1169
- createMoreServiceProvider.value = false;
1170
- return;
1171
- }
1158
+ if (mode === "invite") {
1159
+ existingAccount.value = null;
1160
+
1161
+ serviceProviderInvite.value = {
1162
+ email: "",
1163
+ app: defaultInviteApp,
1164
+ siteId: props.siteId,
1165
+ siteName: site.value?.name || props.siteName,
1166
+ };
1167
+ }
1168
+
1169
+ createMoreServiceProvider.value = false;
1170
+ return;
1171
+ }
1172
1172
 
1173
- serviceProvider.value.description = data.description ?? "";
1174
- serviceProvider.value.email = data.email ?? "";
1175
- serviceProvider.value.name = data.name ?? "";
1176
- serviceProvider.value.type = data.type ?? "";
1173
+ serviceProvider.value.description = data.description ?? "";
1174
+ serviceProvider.value.email = data.email ?? "";
1175
+ serviceProvider.value.name = data.name ?? "";
1176
+ serviceProvider.value.type = data.type ?? "";
1177
1177
  }
1178
1178
 
1179
1179
  async function submitServiceProviderAdd() {
@@ -1211,9 +1211,7 @@ async function submitServiceProviderInvite() {
1211
1211
  site.value?.name ||
1212
1212
  props.siteName,
1213
1213
 
1214
- inviteType: existingAccount.value
1215
- ? "create-org"
1216
- : "organization-invite",
1214
+ inviteType: existingAccount.value ? "create-org" : "organization-invite",
1217
1215
  });
1218
1216
 
1219
1217
  showMessage("Invitation sent.", "success");
@@ -1604,6 +1604,10 @@ function handleRegistrationUnregisteredVisitor(item: Partial<TVisitor>) {
1604
1604
  selectedVisitorId.value = id;
1605
1605
  dialog.showSelection = true;
1606
1606
  mode.value = "register";
1607
+
1608
+ if(!selectedVisitorDataObject.value){
1609
+ getVisitorRefresh();
1610
+ }
1607
1611
  }
1608
1612
 
1609
1613
  function handleViewImage(imageId: string) {
@@ -2053,6 +2057,10 @@ const { socketUnregisteredVisitorTrigger, visitorSocketData } =
2053
2057
  const { _id } = visitorSocketData.value;
2054
2058
  await handleRegistrationUnregisteredVisitor({ _id });
2055
2059
  socketUnregisteredVisitorTrigger.value = false;
2060
+
2061
+ setTimeout(() => {
2062
+ visitorSocketData.value = null;
2063
+ }, 1000)
2056
2064
  }, 1000)
2057
2065
  }
2058
2066
  })
@@ -32,7 +32,7 @@
32
32
  </section> -->
33
33
 
34
34
  <v-snackbar
35
- v-if="!isVisitorRoute && !socketUnregisteredVisitorTrigger"
35
+ v-if="!isUnregisteredVisitorRoute"
36
36
  v-model="snackBarMessage.modal"
37
37
  :color="snackBarMessage.color"
38
38
  :timeout="snackBarMessage.timeout"
@@ -103,6 +103,8 @@ const { tab } = useVisitor();
103
103
  const { socketUnregisteredVisitorTrigger, visitorSocketData } =
104
104
  useVisitorSocket();
105
105
 
106
+ const APP_NAME = publicConfig.APP || "";
107
+
106
108
  const socket = shallowRef<Socket | null>(null);
107
109
  const status = ref("disconnected");
108
110
  const newVisitor = ref<TVisitorSocketData | null>(null);
@@ -125,6 +127,7 @@ const permanentMessageDialog = reactive({
125
127
  const path = computed(() => route.path);
126
128
  const isVisitorManagementPath = (path: string) =>
127
129
  path.includes("/visitor-management");
130
+
128
131
  const isVisitorRoute = computed(
129
132
  () =>
130
133
  path.value === "/visitors" ||
@@ -197,7 +200,7 @@ const connectSocket = () => {
197
200
  visitorSocketData.value = data;
198
201
  newVisitor.value = data;
199
202
 
200
- if (!isVisitorRoute.value && isCheckIn) {
203
+ if (isCheckIn) {
201
204
  showTransientMessage(
202
205
  `New plate detected: ${plateNumber}`,
203
206
  "info",
@@ -207,20 +210,6 @@ const connectSocket = () => {
207
210
  return;
208
211
  }
209
212
 
210
- if (isUnregisteredVisitorRoute.value && isCheckIn) {
211
- if (isPlateNumberChanging) {
212
- showTransientMessage(`New plate detected: ${plateNumber}`, "info", true);
213
- } else {
214
- snackBarMessage.modal = false;
215
- }
216
-
217
- lastPlateNumber.value = plateNumber;
218
- return;
219
- }
220
-
221
- if (isCheckIn) {
222
- lastPlateNumber.value = plateNumber;
223
- }
224
213
 
225
214
  if (data?.message) {
226
215
  showTransientMessage(data.message, "error");
@@ -254,8 +243,10 @@ const goToUnregistered = async () => {
254
243
  if (route.params.org && route.params.site) {
255
244
  const defaultDateQuery = getDefaultDateQuery();
256
245
 
246
+ if(!APP_NAME) return;
247
+
257
248
  await navigateTo({
258
- path: `/${route.params.org}/${route.params.site}/visitor-management`,
249
+ path: `/${route.params.org}/${route.params.site}/${APP_NAME === "security_agency" ? "visitor-management" : APP_NAME === "property_management_agency" ? "visitor-mgmt" : "visitor-management"}`,
259
250
  query: {
260
251
  tab: "unregistered",
261
252
  dateFrom: route.query.dateFrom || defaultDateQuery.dateFrom,
@@ -279,7 +270,7 @@ watch(
279
270
  disconnectSocket();
280
271
  connectSocket();
281
272
  },
282
- { immediate: true }
273
+ { immediate: true, deep: true }
283
274
  );
284
275
 
285
276
  watch(
@@ -296,17 +287,6 @@ onUnmounted(() => {
296
287
  disconnectSocket();
297
288
  });
298
289
 
299
- watch(
300
- () => route.path,
301
- (currentPath, previousPath) => {
302
- if (
303
- previousPath &&
304
- isVisitorManagementPath(previousPath) &&
305
- !isVisitorManagementPath(currentPath)
306
- ) {
307
- handleCloseSnackbar();
308
- }
309
- }
310
- );
290
+
311
291
 
312
292
  </script>
@@ -0,0 +1,27 @@
1
+ import type {
2
+ NFCPatrolReportFilters,
3
+ NFCPatrolSummaryReport,
4
+ } from "../types/nfc-patrol-report";
5
+ import { useNFCPatrolReportService } from "../services/nfcPatrolReport";
6
+
7
+ export function useNFCPatrolDailyReport(filters: NFCPatrolReportFilters) {
8
+ const reportService = useNFCPatrolReportService();
9
+ const report = ref<NFCPatrolSummaryReport | null>(null);
10
+ const loading = ref(false);
11
+
12
+ async function fetchReport() {
13
+ loading.value = true;
14
+
15
+ try {
16
+ report.value = await reportService.getDailyReport(filters);
17
+ } finally {
18
+ loading.value = false;
19
+ }
20
+ }
21
+
22
+ return {
23
+ report,
24
+ loading,
25
+ fetchReport,
26
+ };
27
+ }
@@ -0,0 +1,27 @@
1
+ import type {
2
+ NFCPatrolReportFilters,
3
+ NFCPatrolSummaryReport,
4
+ } from "../types/nfc-patrol-report";
5
+ import { useNFCPatrolReportService } from "../services/nfcPatrolReport";
6
+
7
+ export function useNFCPatrolMonthlyReport(filters: NFCPatrolReportFilters) {
8
+ const reportService = useNFCPatrolReportService();
9
+ const report = ref<NFCPatrolSummaryReport | null>(null);
10
+ const loading = ref(false);
11
+
12
+ async function fetchReport() {
13
+ loading.value = true;
14
+
15
+ try {
16
+ report.value = await reportService.getMonthlyReport(filters);
17
+ } finally {
18
+ loading.value = false;
19
+ }
20
+ }
21
+
22
+ return {
23
+ report,
24
+ loading,
25
+ fetchReport,
26
+ };
27
+ }
@@ -0,0 +1,38 @@
1
+ import type {
2
+ NFCPatrolActivity,
3
+ NFCPatrolReport,
4
+ NFCPatrolReportFilters,
5
+ } from "../types/nfc-patrol-report";
6
+ import { useNFCPatrolReportService } from "../services/nfcPatrolReport";
7
+
8
+ export function useNFCPatrolReport(filters: NFCPatrolReportFilters) {
9
+ const reportService = useNFCPatrolReportService();
10
+ const report = ref<NFCPatrolReport | null>(null);
11
+ const loading = ref(false);
12
+ const selectedActivityRemarks = ref("");
13
+ const dialogRemarks = ref(false);
14
+
15
+ async function fetchReport() {
16
+ loading.value = true;
17
+
18
+ try {
19
+ report.value = await reportService.getPatrolReport(filters);
20
+ } finally {
21
+ loading.value = false;
22
+ }
23
+ }
24
+
25
+ function openRemarksDialog(activity: NFCPatrolActivity) {
26
+ selectedActivityRemarks.value = activity.remarks || "No remarks provided";
27
+ dialogRemarks.value = true;
28
+ }
29
+
30
+ return {
31
+ report,
32
+ loading,
33
+ selectedActivityRemarks,
34
+ dialogRemarks,
35
+ fetchReport,
36
+ openRemarksDialog,
37
+ };
38
+ }