@iservice365/layer-common 1.6.0 → 1.7.0
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 +6 -0
- package/components/AccessCardAddForm.vue +363 -0
- package/components/AccessManagement.vue +286 -8
- package/components/BuildingUnitFormEdit.vue +47 -0
- package/components/EntryPassMain.vue +231 -0
- package/components/ImageCarousel.vue +74 -34
- package/components/Input/FileV2.vue +1 -1
- package/components/Input/NRICNumber.vue +2 -2
- package/components/Input/VehicleNumber.vue +1 -1
- package/components/Nfc/NFCTagForm.vue +210 -0
- package/components/Nfc/NFCTagMain.vue +342 -0
- package/components/VideoPlayer.vue +125 -0
- package/components/VisitorForm.vue +143 -62
- package/components/VisitorManagement.vue +1 -14
- package/composables/useCard.ts +46 -0
- package/composables/useNFCPatrolTag.ts +51 -0
- package/composables/usePeople.ts +19 -1
- package/composables/useVisitor.ts +1 -1
- package/package.json +1 -1
- package/types/building.d.ts +2 -0
- package/types/card.d.ts +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card width="100%">
|
|
3
|
+
<v-toolbar>
|
|
4
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
|
+
<span class="font-weight-bold text-h5 text-capitalize">
|
|
6
|
+
{{ prop.mode }} Access Card
|
|
7
|
+
</span>
|
|
8
|
+
</v-row>
|
|
9
|
+
</v-toolbar>
|
|
10
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-0">
|
|
11
|
+
<v-form v-model="validForm" :disabled="disable">
|
|
12
|
+
<v-row no-gutters class="px-6 pt-4">
|
|
13
|
+
<v-col cols="12" class="px-1">
|
|
14
|
+
<InputLabel
|
|
15
|
+
class="text-capitalize font-weight-bold"
|
|
16
|
+
title="Types of Access Card"
|
|
17
|
+
required
|
|
18
|
+
/>
|
|
19
|
+
<v-select
|
|
20
|
+
v-model.number="card.accessCardType"
|
|
21
|
+
:items="accessCardTypes"
|
|
22
|
+
density="comfortable"
|
|
23
|
+
:rules="[requiredRule]"
|
|
24
|
+
type="text"
|
|
25
|
+
></v-select>
|
|
26
|
+
</v-col>
|
|
27
|
+
<v-col cols="12" class="px-1 pb-5">
|
|
28
|
+
<InputLabel
|
|
29
|
+
class="text-capitalize font-weight-bold"
|
|
30
|
+
:title="`Card No (${cardNoMaxLength} digits)`"
|
|
31
|
+
required
|
|
32
|
+
/>
|
|
33
|
+
<v-text-field
|
|
34
|
+
v-model="card.cardNumber"
|
|
35
|
+
density="compact"
|
|
36
|
+
hide-details
|
|
37
|
+
:rules="[requiredRule]"
|
|
38
|
+
maxlength="10"
|
|
39
|
+
type="number"
|
|
40
|
+
hide-spin-buttons
|
|
41
|
+
>
|
|
42
|
+
</v-text-field>
|
|
43
|
+
</v-col>
|
|
44
|
+
<v-col cols="12" class="px-1">
|
|
45
|
+
<InputLabel
|
|
46
|
+
class="text-capitalize font-weight-bold"
|
|
47
|
+
title="Start Date"
|
|
48
|
+
required
|
|
49
|
+
/>
|
|
50
|
+
<InputDateTimePicker
|
|
51
|
+
ref="startDateRef"
|
|
52
|
+
v-model="card.startDate"
|
|
53
|
+
placeholder="Start Date"
|
|
54
|
+
:rules="[requiredRule]"
|
|
55
|
+
/>
|
|
56
|
+
</v-col>
|
|
57
|
+
<v-col cols="12" class="px-1 pb-4">
|
|
58
|
+
<InputLabel
|
|
59
|
+
class="text-capitalize font-weight-bold"
|
|
60
|
+
title="End Date"
|
|
61
|
+
required
|
|
62
|
+
/>
|
|
63
|
+
<InputDateTimePicker
|
|
64
|
+
ref="endDateRef"
|
|
65
|
+
v-model="card.endDate"
|
|
66
|
+
placeholder="End Date"
|
|
67
|
+
:rules="[requiredRule]"
|
|
68
|
+
/>
|
|
69
|
+
</v-col>
|
|
70
|
+
<v-divider />
|
|
71
|
+
<v-row class="py-8 px-0">
|
|
72
|
+
<v-col cols="12">
|
|
73
|
+
<InputLabel
|
|
74
|
+
class="text-capitalize font-weight-bold"
|
|
75
|
+
title="Doors Location"
|
|
76
|
+
required
|
|
77
|
+
/>
|
|
78
|
+
<v-select
|
|
79
|
+
v-model="card.door"
|
|
80
|
+
density="compact"
|
|
81
|
+
:items="accessLevelItems"
|
|
82
|
+
item-title="name"
|
|
83
|
+
item-value="no"
|
|
84
|
+
hide-details
|
|
85
|
+
:rules="[requiredRule]"
|
|
86
|
+
>
|
|
87
|
+
</v-select>
|
|
88
|
+
</v-col>
|
|
89
|
+
<v-col cols="12">
|
|
90
|
+
<InputLabel
|
|
91
|
+
class="text-capitalize font-weight-bold"
|
|
92
|
+
title="Access Group"
|
|
93
|
+
required
|
|
94
|
+
/>
|
|
95
|
+
<v-select
|
|
96
|
+
v-model="card.accessGroup"
|
|
97
|
+
density="compact"
|
|
98
|
+
:items="accessGroupItems"
|
|
99
|
+
hide-details
|
|
100
|
+
:rules="[requiredRule]"
|
|
101
|
+
multiple
|
|
102
|
+
>
|
|
103
|
+
</v-select>
|
|
104
|
+
</v-col>
|
|
105
|
+
<v-col cols="12">
|
|
106
|
+
<InputLabel
|
|
107
|
+
class="text-capitalize font-weight-bold"
|
|
108
|
+
title="Card Type"
|
|
109
|
+
required
|
|
110
|
+
/>
|
|
111
|
+
<v-select
|
|
112
|
+
v-model="card.cardType"
|
|
113
|
+
density="compact"
|
|
114
|
+
:items="cardTypeItems"
|
|
115
|
+
hide-details
|
|
116
|
+
:rules="[requiredRule]"
|
|
117
|
+
item-title="name"
|
|
118
|
+
item-value="value"
|
|
119
|
+
>
|
|
120
|
+
</v-select>
|
|
121
|
+
</v-col>
|
|
122
|
+
<v-col cols="12">
|
|
123
|
+
<InputLabel
|
|
124
|
+
class="text-capitalize font-weight-bold"
|
|
125
|
+
:title="`Pin No (${cardPinMaxLength} digits)`"
|
|
126
|
+
required
|
|
127
|
+
/>
|
|
128
|
+
<v-text-field
|
|
129
|
+
v-model="card.pinNo"
|
|
130
|
+
density="compact"
|
|
131
|
+
hide-details
|
|
132
|
+
:rules="[requiredRule]"
|
|
133
|
+
maxlength="10"
|
|
134
|
+
type="number"
|
|
135
|
+
hide-spin-buttons
|
|
136
|
+
>
|
|
137
|
+
</v-text-field>
|
|
138
|
+
</v-col>
|
|
139
|
+
<v-col cols="12" class="pt-5">
|
|
140
|
+
<v-btn
|
|
141
|
+
block
|
|
142
|
+
color="primary"
|
|
143
|
+
variant="text"
|
|
144
|
+
class="text-none font-weight-bold"
|
|
145
|
+
text="Use as lift Card"
|
|
146
|
+
@click="card.useAsLiftCard = !card.useAsLiftCard"
|
|
147
|
+
></v-btn>
|
|
148
|
+
</v-col>
|
|
149
|
+
<v-col cols="12" v-if="card.useAsLiftCard">
|
|
150
|
+
<InputLabel
|
|
151
|
+
class="text-capitalize font-weight-bold"
|
|
152
|
+
title="Lift Access Label"
|
|
153
|
+
:required="card.useAsLiftCard"
|
|
154
|
+
/>
|
|
155
|
+
<v-select
|
|
156
|
+
v-model="card.liftAccessLevel"
|
|
157
|
+
density="compact"
|
|
158
|
+
:items="liftAccessLevelItems"
|
|
159
|
+
hide-details
|
|
160
|
+
:rules="card.useAsLiftCard ? [requiredRule] : []"
|
|
161
|
+
item-title="name"
|
|
162
|
+
item-value="value"
|
|
163
|
+
/>
|
|
164
|
+
</v-col>
|
|
165
|
+
<v-col cols="12">
|
|
166
|
+
<div
|
|
167
|
+
class="d-flex justify-space-between align-center rounded px-0"
|
|
168
|
+
>
|
|
169
|
+
<span class="d-flex align-center"
|
|
170
|
+
>Activate
|
|
171
|
+
<v-checkbox
|
|
172
|
+
v-model="card.isActivate"
|
|
173
|
+
label="Yes"
|
|
174
|
+
class="d-flex align-center"
|
|
175
|
+
></v-checkbox
|
|
176
|
+
></span>
|
|
177
|
+
<span class="d-flex align-center">
|
|
178
|
+
Anti Pass Back
|
|
179
|
+
<v-icon class="ml-1" color="grey" size="small"
|
|
180
|
+
>mdi-help-circle</v-icon
|
|
181
|
+
>
|
|
182
|
+
<v-checkbox
|
|
183
|
+
v-model="card.isAntiPassBack"
|
|
184
|
+
label="Yes"
|
|
185
|
+
class="d-flex align-center"
|
|
186
|
+
></v-checkbox>
|
|
187
|
+
</span>
|
|
188
|
+
</div>
|
|
189
|
+
</v-col>
|
|
190
|
+
</v-row>
|
|
191
|
+
</v-row>
|
|
192
|
+
</v-form>
|
|
193
|
+
</v-card-text>
|
|
194
|
+
<v-toolbar density="compact">
|
|
195
|
+
<v-row no-gutters>
|
|
196
|
+
<v-col cols="6">
|
|
197
|
+
<v-btn
|
|
198
|
+
tile
|
|
199
|
+
block
|
|
200
|
+
variant="text"
|
|
201
|
+
class="text-none"
|
|
202
|
+
size="48"
|
|
203
|
+
@click="cancel"
|
|
204
|
+
:disabled="disable"
|
|
205
|
+
>
|
|
206
|
+
Cancel
|
|
207
|
+
</v-btn>
|
|
208
|
+
</v-col>
|
|
209
|
+
|
|
210
|
+
<v-col cols="6">
|
|
211
|
+
<v-btn
|
|
212
|
+
tile
|
|
213
|
+
block
|
|
214
|
+
variant="flat"
|
|
215
|
+
color="black"
|
|
216
|
+
class="text-none"
|
|
217
|
+
size="48"
|
|
218
|
+
:disabled="!validForm || disable"
|
|
219
|
+
@click="submit"
|
|
220
|
+
:loading="disable"
|
|
221
|
+
>
|
|
222
|
+
Submit
|
|
223
|
+
</v-btn>
|
|
224
|
+
</v-col>
|
|
225
|
+
</v-row>
|
|
226
|
+
</v-toolbar>
|
|
227
|
+
</v-card>
|
|
228
|
+
</template>
|
|
229
|
+
<script setup lang="ts">
|
|
230
|
+
const prop = defineProps({
|
|
231
|
+
mode: {
|
|
232
|
+
type: String,
|
|
233
|
+
default: "add",
|
|
234
|
+
},
|
|
235
|
+
card: {
|
|
236
|
+
type: Object as PropType<TCard>,
|
|
237
|
+
default: () => ({
|
|
238
|
+
name: "",
|
|
239
|
+
accessCardType: "",
|
|
240
|
+
// visitorType: "",
|
|
241
|
+
status: "active",
|
|
242
|
+
}),
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const { add: _addCard, updateById: _updateCardById } = useCard();
|
|
247
|
+
const emit = defineEmits(["cancel", "success"]);
|
|
248
|
+
|
|
249
|
+
const validForm = ref(false);
|
|
250
|
+
const disable = ref(false);
|
|
251
|
+
const message = ref("");
|
|
252
|
+
|
|
253
|
+
const { requiredRule } = useUtils();
|
|
254
|
+
|
|
255
|
+
const card = ref<Record<string, any>>({
|
|
256
|
+
accessCardType: "",
|
|
257
|
+
type: "door-setup",
|
|
258
|
+
cardNumber: "",
|
|
259
|
+
startDate: "",
|
|
260
|
+
endDate: "",
|
|
261
|
+
door: "",
|
|
262
|
+
accessGroup: [],
|
|
263
|
+
cardType: "",
|
|
264
|
+
pinNo: "",
|
|
265
|
+
isActivate: true,
|
|
266
|
+
isAntiPassBack: false,
|
|
267
|
+
useAsLiftCard: false,
|
|
268
|
+
status: "active",
|
|
269
|
+
liftAccessLevel: "",
|
|
270
|
+
org: "",
|
|
271
|
+
site: "",
|
|
272
|
+
unit: "",
|
|
273
|
+
assign: "",
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (prop.mode === "edit") {
|
|
277
|
+
card.value.accessCardType = prop.card.accessCardType;
|
|
278
|
+
card.value.type = prop.card.type;
|
|
279
|
+
card.value.cardNumber = prop.card.cardNumber;
|
|
280
|
+
card.value.startDate = prop.card.startDate;
|
|
281
|
+
card.value.endDate = prop.card.endDate;
|
|
282
|
+
card.value.door = prop.card.door;
|
|
283
|
+
card.value.accessGroup = prop.card.accessGroup;
|
|
284
|
+
card.value.cardType = prop.card.cardType;
|
|
285
|
+
card.value.pinNo = prop.card.pinNo;
|
|
286
|
+
card.value.isActivate = prop.card.isActivate;
|
|
287
|
+
card.value.isAntiPassBack = prop.card.isAntiPassBack;
|
|
288
|
+
card.value.useAsLiftCard = prop.card.useAsLiftCard;
|
|
289
|
+
card.value.status = prop.card.status;
|
|
290
|
+
card.value.liftAccessLevel = prop.card.liftAccessLevel;
|
|
291
|
+
card.value.org = prop.card.org;
|
|
292
|
+
card.value.site = prop.card.site;
|
|
293
|
+
card.value.unit = prop.card.unit;
|
|
294
|
+
card.value.assign = prop.card.assign;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const accessCardTypes = ["Physical Access Card", "Non Physical Access Card"];
|
|
298
|
+
const typeOfVisitors = ["Contractor", "Visitor"];
|
|
299
|
+
|
|
300
|
+
const accessLevelItems = ref<{ name: string; no: string }[]>([
|
|
301
|
+
{ name: "All access", no: "1" },
|
|
302
|
+
]);
|
|
303
|
+
const accessGroupItems = ref(["All Access", "Glass Door 1"]);
|
|
304
|
+
const cardTypeItems = ref([
|
|
305
|
+
{
|
|
306
|
+
name: "Normal - Access Card",
|
|
307
|
+
value: "Normal",
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
name: "Special - Arm/Disarm Card",
|
|
311
|
+
value: "Special",
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: "Master - Master Card",
|
|
315
|
+
value: "Master",
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: "Maintenance - Maintenance Card",
|
|
319
|
+
value: "Maintenance",
|
|
320
|
+
},
|
|
321
|
+
]);
|
|
322
|
+
const cardNoMaxLength = ref(10);
|
|
323
|
+
const cardPinMaxLength = ref(6);
|
|
324
|
+
const startDateRef = ref<HTMLInputElement | null>(null);
|
|
325
|
+
const endDateRef = ref<HTMLInputElement | null>(null);
|
|
326
|
+
const liftAccessLevelItems = ref<{ name: string; no: string }[]>([]);
|
|
327
|
+
|
|
328
|
+
const route = useRoute();
|
|
329
|
+
const siteId = route.params.site as string;
|
|
330
|
+
const orgId = route.params.org as string;
|
|
331
|
+
|
|
332
|
+
function cancel() {
|
|
333
|
+
// createMore.value = false;
|
|
334
|
+
message.value = "";
|
|
335
|
+
emit("cancel");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function submit() {
|
|
339
|
+
disable.value = true;
|
|
340
|
+
try {
|
|
341
|
+
if (prop.mode === "add") {
|
|
342
|
+
const payload = {
|
|
343
|
+
...card.value,
|
|
344
|
+
site: siteId,
|
|
345
|
+
org: orgId,
|
|
346
|
+
};
|
|
347
|
+
await _addCard(payload);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (prop.mode === "edit") {
|
|
351
|
+
const payload = {
|
|
352
|
+
...card.value,
|
|
353
|
+
};
|
|
354
|
+
await _updateCardById(prop.card._id ?? "", payload);
|
|
355
|
+
}
|
|
356
|
+
emit("success");
|
|
357
|
+
} catch (error: any) {
|
|
358
|
+
message.value = error.response?._data?.message || "Failed to create card";
|
|
359
|
+
} finally {
|
|
360
|
+
disable.value = false;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
</script>
|