@7365admin1/layer-common 3.0.25 → 3.0.27
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 +14 -0
- package/components/AccessCardDetailsDialog.vue +129 -3
- package/components/AccessCardPreviewDialog.vue +31 -3
- package/components/AccessManagement.vue +10 -1
- package/components/AddPassKeyToVisitor.vue +346 -225
- package/components/DashboardMain.vue +95 -59
- package/components/DocumentManagement.vue +71 -5
- package/components/EntryPassInformation.vue +55 -17
- package/components/HidIntercomManagement.vue +186 -0
- package/components/HidReaderForm.vue +10 -16
- package/components/HidReaderManagement.vue +21 -1
- package/components/MemberInformation.vue +59 -1
- package/components/RolePermissionMain.vue +14 -8
- package/components/SiteSettings.vue +3 -1
- package/components/VisitorForm.vue +35 -7
- package/components/VisitorManagement.vue +233 -39
- package/components/VisitorSocketPopUp.vue +29 -1
- package/composables/useANPRSettings.ts +57 -8
- package/composables/useAccessManagement.ts +17 -1
- package/composables/useCleaningPermission.ts +2 -2
- package/composables/useCommonPermission.ts +2 -39
- package/composables/useDocument.ts +21 -0
- package/composables/useLocalAuth.ts +3 -1
- package/package.json +1 -1
- package/pages/[org]/[site]/access-mgmt/administrator/index.vue +2 -0
- package/pages/[org]/[site]/access-mgmt/hid-readers/index.vue +2 -0
- package/pages/[org]/[site]/access-mgmt/hid-users/index.vue +2 -0
- package/pages/[org]/[site]/access-mgmt/identity-mapping/index.vue +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 3.0.27
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c76ac10: Update Package Version
|
|
8
|
+
- 3d5034d: Update Version Package
|
|
9
|
+
|
|
10
|
+
## 3.0.26
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 4c4e01d: Update Package Version
|
|
15
|
+
- 165fd5a: Update Layer Common Version
|
|
16
|
+
|
|
3
17
|
## 3.0.25
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<div class="text-body-2 font-weight-medium">{{ details.type ?? "N/A" }}</div>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
|
-
<div>
|
|
33
|
+
<div v-if="details.status">
|
|
34
34
|
<div class="text-caption text-grey">Status</div>
|
|
35
35
|
<v-chip
|
|
36
36
|
:color="statusColor(details.status)"
|
|
@@ -47,16 +47,46 @@
|
|
|
47
47
|
<div class="text-body-2 font-weight-medium">{{ details.isActivated ? "Yes" : "No" }}</div>
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
|
-
<div>
|
|
50
|
+
<div v-if="details.site?.name">
|
|
51
51
|
<div class="text-caption text-grey">Site</div>
|
|
52
52
|
<div class="text-body-2 font-weight-medium">{{ details.site?.name ?? "N/A" }}</div>
|
|
53
53
|
</div>
|
|
54
54
|
|
|
55
55
|
<div>
|
|
56
56
|
<div class="text-caption text-grey">User</div>
|
|
57
|
-
<div class="text-body-2 font-weight-medium">
|
|
57
|
+
<div class="text-body-2 font-weight-medium">
|
|
58
|
+
{{ details.userCred?.name ?? details.user?.name ?? "N/A" }}
|
|
59
|
+
<template v-if="details.user?.email">({{ details.user.email }})</template>
|
|
60
|
+
</div>
|
|
58
61
|
</div>
|
|
59
62
|
|
|
63
|
+
<!-- Visitor Credentials -->
|
|
64
|
+
<template v-if="details.userCred">
|
|
65
|
+
<v-divider />
|
|
66
|
+
<div class="text-caption font-weight-bold text-grey-darken-2 text-uppercase">Visitor Information</div>
|
|
67
|
+
|
|
68
|
+
<div>
|
|
69
|
+
<div class="text-caption text-grey">NRIC</div>
|
|
70
|
+
<div class="text-body-2 font-weight-medium">{{ details.userCred.nric ?? "N/A" }}</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div>
|
|
74
|
+
<div class="text-caption text-grey">Contact</div>
|
|
75
|
+
<div class="text-body-2 font-weight-medium">{{ details.userCred.contact ?? "N/A" }}</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div v-if="details.userCred.company">
|
|
79
|
+
<div class="text-caption text-grey">Company</div>
|
|
80
|
+
<div class="text-body-2 font-weight-medium">{{ details.userCred.company }}</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div v-if="details.userCred.plateNumber">
|
|
84
|
+
<div class="text-caption text-grey">Plate Number</div>
|
|
85
|
+
<div class="text-body-2 font-weight-medium">{{ details.userCred.plateNumber }}</div>
|
|
86
|
+
</div>
|
|
87
|
+
<v-divider />
|
|
88
|
+
</template>
|
|
89
|
+
|
|
60
90
|
<div>
|
|
61
91
|
<div class="text-caption text-grey">Created At</div>
|
|
62
92
|
<div class="text-body-2 font-weight-medium">{{ formatDate(details.createdAt) }}</div>
|
|
@@ -71,6 +101,81 @@
|
|
|
71
101
|
<div class="text-caption text-grey">Remarks</div>
|
|
72
102
|
<div class="text-body-2 font-weight-medium">{{ details.remarks }}</div>
|
|
73
103
|
</div>
|
|
104
|
+
|
|
105
|
+
<!-- History -->
|
|
106
|
+
<template v-if="details.history?.length > 0">
|
|
107
|
+
<v-divider />
|
|
108
|
+
<div
|
|
109
|
+
class="d-flex align-center justify-space-between cursor-pointer"
|
|
110
|
+
@click="historyOpen = !historyOpen"
|
|
111
|
+
>
|
|
112
|
+
<div class="text-caption font-weight-bold text-grey-darken-2 text-uppercase">
|
|
113
|
+
History ({{ details.history.length }})
|
|
114
|
+
</div>
|
|
115
|
+
<v-icon size="16" :icon="historyOpen ? 'mdi-chevron-up' : 'mdi-chevron-down'" />
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<template v-if="historyOpen">
|
|
119
|
+
<div
|
|
120
|
+
v-for="(entry, idx) in sortedHistory"
|
|
121
|
+
:key="entry._id ?? idx"
|
|
122
|
+
class="d-flex ga-2"
|
|
123
|
+
>
|
|
124
|
+
<!-- Timeline spine -->
|
|
125
|
+
<div class="d-flex flex-column align-center" style="width: 20px; flex-shrink: 0;">
|
|
126
|
+
<div
|
|
127
|
+
class="timeline-dot rounded-circle mt-1"
|
|
128
|
+
:class="entry.visitorId ? 'bg-blue' : 'bg-orange'"
|
|
129
|
+
/>
|
|
130
|
+
<div
|
|
131
|
+
v-if="idx < sortedHistory.length - 1"
|
|
132
|
+
class="timeline-line bg-grey-lighten-2 mt-1"
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<!-- Entry content -->
|
|
137
|
+
<div class="d-flex flex-column ga-1 pb-4 flex-grow-1">
|
|
138
|
+
<div class="d-flex align-center justify-space-between">
|
|
139
|
+
<v-chip
|
|
140
|
+
size="x-small"
|
|
141
|
+
variant="tonal"
|
|
142
|
+
:color="entry.visitorId ? 'blue' : 'orange'"
|
|
143
|
+
:prepend-icon="entry.visitorId ? 'mdi-account-arrow-right' : 'mdi-arrow-u-left-top'"
|
|
144
|
+
>
|
|
145
|
+
{{ entry.visitorId ? "Assigned" : "Returned" }}
|
|
146
|
+
</v-chip>
|
|
147
|
+
<span class="text-caption text-grey">{{ formatDate(entry.createdAt) }}</span>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<!-- Assignment entry -->
|
|
151
|
+
<template v-if="entry.visitorId">
|
|
152
|
+
<div class="text-body-2 font-weight-medium">{{ entry.name ?? "N/A" }}</div>
|
|
153
|
+
<div class="text-caption text-grey-darken-1">
|
|
154
|
+
<span v-if="entry.nric">NRIC: {{ entry.nric }}</span>
|
|
155
|
+
<span v-if="entry.contact" class="ml-2">· {{ entry.contact }}</span>
|
|
156
|
+
</div>
|
|
157
|
+
<div class="text-caption text-grey-darken-1">
|
|
158
|
+
<span v-if="entry.company">{{ entry.company }}</span>
|
|
159
|
+
<span v-if="entry.plateNumber" class="ml-2">· {{ entry.plateNumber }}</span>
|
|
160
|
+
</div>
|
|
161
|
+
</template>
|
|
162
|
+
|
|
163
|
+
<!-- Return/checkout entry -->
|
|
164
|
+
<template v-else>
|
|
165
|
+
<div class="d-flex align-center ga-2">
|
|
166
|
+
<v-chip size="x-small" variant="flat" :color="statusColor(entry.status?.toLowerCase())">
|
|
167
|
+
{{ entry.status ?? "N/A" }}
|
|
168
|
+
</v-chip>
|
|
169
|
+
<span v-if="entry.damage" class="text-caption text-error">Damaged</span>
|
|
170
|
+
</div>
|
|
171
|
+
<div v-if="entry.remarks" class="text-caption text-grey-darken-1">
|
|
172
|
+
Remarks: {{ entry.remarks }}
|
|
173
|
+
</div>
|
|
174
|
+
</template>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</template>
|
|
178
|
+
</template>
|
|
74
179
|
</div>
|
|
75
180
|
</v-card-text>
|
|
76
181
|
</v-card>
|
|
@@ -101,6 +206,13 @@ const { getCardDetails } = useAccessManagement();
|
|
|
101
206
|
|
|
102
207
|
const details = ref<Record<string, any> | null>(null);
|
|
103
208
|
const pending = ref(false);
|
|
209
|
+
const historyOpen = ref(false);
|
|
210
|
+
|
|
211
|
+
const sortedHistory = computed(() =>
|
|
212
|
+
[...(details.value?.history ?? [])].sort(
|
|
213
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
214
|
+
)
|
|
215
|
+
);
|
|
104
216
|
|
|
105
217
|
watch(
|
|
106
218
|
() => props.modelValue,
|
|
@@ -115,6 +227,7 @@ watch(
|
|
|
115
227
|
}
|
|
116
228
|
} else {
|
|
117
229
|
details.value = null;
|
|
230
|
+
historyOpen.value = false;
|
|
118
231
|
}
|
|
119
232
|
}
|
|
120
233
|
);
|
|
@@ -142,3 +255,16 @@ function formatDate(date: string) {
|
|
|
142
255
|
}).format(new Date(date));
|
|
143
256
|
}
|
|
144
257
|
</script>
|
|
258
|
+
|
|
259
|
+
<style scoped>
|
|
260
|
+
.timeline-dot {
|
|
261
|
+
width: 10px;
|
|
262
|
+
height: 10px;
|
|
263
|
+
flex-shrink: 0;
|
|
264
|
+
}
|
|
265
|
+
.timeline-line {
|
|
266
|
+
width: 2px;
|
|
267
|
+
flex-grow: 1;
|
|
268
|
+
min-height: 16px;
|
|
269
|
+
}
|
|
270
|
+
</style>
|
|
@@ -116,9 +116,9 @@
|
|
|
116
116
|
<!-- Available Physical -->
|
|
117
117
|
<v-col cols="12" class="mt-3">
|
|
118
118
|
<strong>Available Physical</strong>
|
|
119
|
-
<div v-if="
|
|
119
|
+
<div v-if="availablePhysical.length" class="mt-1">
|
|
120
120
|
<v-chip
|
|
121
|
-
v-for="card in
|
|
121
|
+
v-for="card in availablePhysical"
|
|
122
122
|
:key="card._id"
|
|
123
123
|
size="small"
|
|
124
124
|
class="mr-1 mb-1"
|
|
@@ -133,6 +133,26 @@
|
|
|
133
133
|
<span v-else class="text-caption text-grey ml-1">None</span>
|
|
134
134
|
</v-col>
|
|
135
135
|
|
|
136
|
+
<!-- Damage Physical -->
|
|
137
|
+
<v-col cols="12" class="mt-2">
|
|
138
|
+
<strong>Damage</strong>
|
|
139
|
+
<div v-if="damagedPhysical.length" class="mt-1">
|
|
140
|
+
<v-chip
|
|
141
|
+
v-for="card in damagedPhysical"
|
|
142
|
+
:key="card._id"
|
|
143
|
+
size="small"
|
|
144
|
+
class="mr-1 mb-1"
|
|
145
|
+
color="deep-orange"
|
|
146
|
+
:variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
|
|
147
|
+
style="cursor: pointer"
|
|
148
|
+
@click="toggleCard(card)"
|
|
149
|
+
>
|
|
150
|
+
{{ card.cardNo }}
|
|
151
|
+
</v-chip>
|
|
152
|
+
</div>
|
|
153
|
+
<span v-else class="text-caption text-grey ml-1">None</span>
|
|
154
|
+
</v-col>
|
|
155
|
+
|
|
136
156
|
<!-- Available Non-Physical -->
|
|
137
157
|
<v-col cols="12" class="mt-2">
|
|
138
158
|
<strong>Available Non-Physical</strong>
|
|
@@ -424,11 +444,19 @@ function showToast(message: string, color: "success" | "error") {
|
|
|
424
444
|
snackbar.value = true;
|
|
425
445
|
}
|
|
426
446
|
|
|
447
|
+
const availablePhysical = computed(() =>
|
|
448
|
+
(props.unit?.available?.physical ?? []).filter((c: any) => !c.damage)
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
const damagedPhysical = computed(() =>
|
|
452
|
+
(props.unit?.available?.physical ?? []).filter((c: any) => c.damage === true)
|
|
453
|
+
);
|
|
454
|
+
|
|
427
455
|
const isSelectedCardAvailable = computed(() => {
|
|
428
456
|
if (!props.selectedCardInUnit?._id) return false;
|
|
429
457
|
const id = props.selectedCardInUnit._id;
|
|
430
458
|
return [
|
|
431
|
-
...
|
|
459
|
+
...availablePhysical.value,
|
|
432
460
|
...(props.unit?.available?.non_physical ?? []),
|
|
433
461
|
].some((c) => c._id === id);
|
|
434
462
|
});
|
|
@@ -301,7 +301,16 @@ const loading = computed(() => getAllReqStatus.value === "pending");
|
|
|
301
301
|
|
|
302
302
|
watchEffect(() => {
|
|
303
303
|
if (getCardReq.value?.data) {
|
|
304
|
-
items.value = getCardReq.value.data.items
|
|
304
|
+
items.value = getCardReq.value.data.items.map((item: any) => ({
|
|
305
|
+
...item,
|
|
306
|
+
cardCounts: {
|
|
307
|
+
...item.cardCounts,
|
|
308
|
+
available: {
|
|
309
|
+
...item.cardCounts?.available,
|
|
310
|
+
physical: (item.available?.physical ?? []).filter((c: any) => !c.damage).length,
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
}));
|
|
305
314
|
pages.value = getCardReq.value.data.pages;
|
|
306
315
|
pageRange.value = getCardReq.value.data.pageRange;
|
|
307
316
|
}
|