@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
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
rounded="pill"
|
|
8
8
|
variant="tonal"
|
|
9
9
|
size="large"
|
|
10
|
+
@click="setCard()"
|
|
10
11
|
v-if="canCreate && canCreateAccessCard"
|
|
11
12
|
>
|
|
12
13
|
Add Access Card
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
|
|
15
16
|
<v-text-field
|
|
16
17
|
v-model="searchText"
|
|
17
|
-
placeholder="Search Unit..."
|
|
18
|
+
placeholder="Search Card, Unit..."
|
|
18
19
|
variant="outlined"
|
|
19
20
|
density="comfortable"
|
|
20
21
|
clearable
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
>
|
|
35
36
|
<v-toolbar density="compact" color="grey-lighten-4">
|
|
36
37
|
<template #prepend>
|
|
37
|
-
<v-btn fab icon density="comfortable">
|
|
38
|
+
<v-btn fab icon density="comfortable" @click="getCards">
|
|
38
39
|
<v-icon>mdi-refresh</v-icon>
|
|
39
40
|
</v-btn>
|
|
40
41
|
</template>
|
|
@@ -44,7 +45,11 @@
|
|
|
44
45
|
<span class="mr-2 text-caption text-fontgray">
|
|
45
46
|
{{ pageRange }}
|
|
46
47
|
</span>
|
|
47
|
-
<local-pagination
|
|
48
|
+
<local-pagination
|
|
49
|
+
v-model="page"
|
|
50
|
+
:length="pages"
|
|
51
|
+
@update:value="getCards"
|
|
52
|
+
/>
|
|
48
53
|
</v-row>
|
|
49
54
|
</template>
|
|
50
55
|
</v-toolbar>
|
|
@@ -55,13 +60,169 @@
|
|
|
55
60
|
items-per-page="10"
|
|
56
61
|
fixed-header
|
|
57
62
|
hide-default-footer
|
|
58
|
-
|
|
59
|
-
@click:row="(_: any, data: any) => $emit('row-click', data)"
|
|
63
|
+
@click:row="tableRowClickHandler"
|
|
60
64
|
style="max-height: calc(100vh - (200px))"
|
|
61
65
|
/>
|
|
62
66
|
</v-card>
|
|
63
67
|
</v-col>
|
|
64
68
|
|
|
69
|
+
<!-- Create Dialog -->
|
|
70
|
+
<v-dialog v-model="createDialog" width="650" persistent>
|
|
71
|
+
<AccessCardAddForm
|
|
72
|
+
@cancel="createDialog = false"
|
|
73
|
+
@success="successCreate()"
|
|
74
|
+
/>
|
|
75
|
+
</v-dialog>
|
|
76
|
+
|
|
77
|
+
<!-- Edit Dialog -->
|
|
78
|
+
<v-dialog v-model="editDialog" width="650" persistent>
|
|
79
|
+
<AccessCardAddForm
|
|
80
|
+
mode="edit"
|
|
81
|
+
@cancel="editDialog = false"
|
|
82
|
+
@success="successUpdate()"
|
|
83
|
+
:card="selectedCard"
|
|
84
|
+
/>
|
|
85
|
+
</v-dialog>
|
|
86
|
+
|
|
87
|
+
<!-- Preview Dialog -->
|
|
88
|
+
<v-dialog v-model="previewDialog" width="450" persistent>
|
|
89
|
+
<v-card width="100%">
|
|
90
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
|
|
91
|
+
<v-row no-gutters class="mb-4">
|
|
92
|
+
<v-col cols="12">
|
|
93
|
+
<strong>Card:</strong> {{ selectedCard?.cardNumber ?? "N/A" }}
|
|
94
|
+
</v-col>
|
|
95
|
+
<v-col cols="12">
|
|
96
|
+
<strong>Access Type:</strong>
|
|
97
|
+
{{ selectedCard?.accessCardType ?? "N/A" }}
|
|
98
|
+
</v-col>
|
|
99
|
+
<!-- <v-col cols="12">
|
|
100
|
+
<strong>Visitor Type:</strong>
|
|
101
|
+
{{ selectedCard?.visitorType ?? "N/A" }}
|
|
102
|
+
</v-col> -->
|
|
103
|
+
<v-col cols="12">
|
|
104
|
+
<strong>Unit:</strong>
|
|
105
|
+
{{ selectedCard?.unit || "N/A" }}
|
|
106
|
+
</v-col>
|
|
107
|
+
<v-col cols="12">
|
|
108
|
+
<strong>Assign:</strong> {{ selectedCard?.assign || "N/A" }}
|
|
109
|
+
</v-col>
|
|
110
|
+
<v-col cols="12">
|
|
111
|
+
<strong>Status:</strong> {{ selectedCard?.status ?? "N/A" }}
|
|
112
|
+
</v-col>
|
|
113
|
+
</v-row></v-card-text
|
|
114
|
+
>
|
|
115
|
+
<v-toolbar class="pa-0" density="compact">
|
|
116
|
+
<v-row no-gutters>
|
|
117
|
+
<v-col cols="6" class="pa-0">
|
|
118
|
+
<v-btn
|
|
119
|
+
block
|
|
120
|
+
variant="text"
|
|
121
|
+
class="text-none"
|
|
122
|
+
size="large"
|
|
123
|
+
@click="previewDialog = false"
|
|
124
|
+
height="48"
|
|
125
|
+
>
|
|
126
|
+
Close
|
|
127
|
+
</v-btn>
|
|
128
|
+
</v-col>
|
|
129
|
+
<v-col cols="6" class="pa-0" v-if="canUpdate">
|
|
130
|
+
<v-menu>
|
|
131
|
+
<template #activator="{ props }">
|
|
132
|
+
<v-btn
|
|
133
|
+
block
|
|
134
|
+
variant="flat"
|
|
135
|
+
color="black"
|
|
136
|
+
class="text-none"
|
|
137
|
+
height="48"
|
|
138
|
+
v-bind="props"
|
|
139
|
+
tile
|
|
140
|
+
:disabled="!canUpdateAccessCard && !canDeleteAccessCard"
|
|
141
|
+
>
|
|
142
|
+
More actions
|
|
143
|
+
</v-btn>
|
|
144
|
+
</template>
|
|
145
|
+
<v-list class="pa-0">
|
|
146
|
+
<v-list-item @click="openEditDialog()">
|
|
147
|
+
<v-list-item-title class="text-subtitle-2">
|
|
148
|
+
Edit Card
|
|
149
|
+
</v-list-item-title>
|
|
150
|
+
</v-list-item>
|
|
151
|
+
<v-list-item @click="openReplaceDialog()">
|
|
152
|
+
<v-list-item-title class="text-subtitle-2">
|
|
153
|
+
Replace Card
|
|
154
|
+
</v-list-item-title>
|
|
155
|
+
</v-list-item>
|
|
156
|
+
<v-list-item @click="openDeleteDialog()" class="text-red">
|
|
157
|
+
<v-list-item-title class="text-subtitle-2">
|
|
158
|
+
Delete Card
|
|
159
|
+
</v-list-item-title>
|
|
160
|
+
</v-list-item>
|
|
161
|
+
</v-list>
|
|
162
|
+
</v-menu>
|
|
163
|
+
</v-col>
|
|
164
|
+
</v-row>
|
|
165
|
+
</v-toolbar></v-card
|
|
166
|
+
>
|
|
167
|
+
</v-dialog>
|
|
168
|
+
|
|
169
|
+
<!-- Delete Dialog -->
|
|
170
|
+
<v-dialog
|
|
171
|
+
v-model="confirmDialog"
|
|
172
|
+
:loading="deleteLoading"
|
|
173
|
+
width="450"
|
|
174
|
+
persistent
|
|
175
|
+
>
|
|
176
|
+
<v-card width="100%">
|
|
177
|
+
<v-toolbar density="compact" class="pl-4">
|
|
178
|
+
<span class="font-weight-medium text-h5">Delete Card</span>
|
|
179
|
+
</v-toolbar>
|
|
180
|
+
<v-card-text>
|
|
181
|
+
<p class="text-subtitle-2 text-center">
|
|
182
|
+
Are you sure you want to delete this card? This action cannot be
|
|
183
|
+
undone.
|
|
184
|
+
</p>
|
|
185
|
+
|
|
186
|
+
<v-row v-if="message" no-gutters justify="center" class="mt-4">
|
|
187
|
+
<span class="text-caption text-error text-center">
|
|
188
|
+
{{ message }}
|
|
189
|
+
</span>
|
|
190
|
+
</v-row></v-card-text
|
|
191
|
+
>
|
|
192
|
+
<v-toolbar density="compact">
|
|
193
|
+
<v-row no-gutters>
|
|
194
|
+
<v-col cols="6">
|
|
195
|
+
<v-btn
|
|
196
|
+
tile
|
|
197
|
+
block
|
|
198
|
+
size="48"
|
|
199
|
+
variant="text"
|
|
200
|
+
class="text-none"
|
|
201
|
+
@click="confirmDialog = false"
|
|
202
|
+
:disabled="deleteLoading"
|
|
203
|
+
>
|
|
204
|
+
Close
|
|
205
|
+
</v-btn>
|
|
206
|
+
</v-col>
|
|
207
|
+
<v-col cols="6">
|
|
208
|
+
<v-btn
|
|
209
|
+
tile
|
|
210
|
+
block
|
|
211
|
+
size="48"
|
|
212
|
+
color="black"
|
|
213
|
+
variant="flat"
|
|
214
|
+
class="text-none"
|
|
215
|
+
@click="handleDeleteCard"
|
|
216
|
+
:loading="deleteLoading"
|
|
217
|
+
>
|
|
218
|
+
Delete Card
|
|
219
|
+
</v-btn>
|
|
220
|
+
</v-col>
|
|
221
|
+
</v-row></v-toolbar
|
|
222
|
+
>
|
|
223
|
+
</v-card>
|
|
224
|
+
</v-dialog>
|
|
225
|
+
|
|
65
226
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
66
227
|
</v-row>
|
|
67
228
|
</template>
|
|
@@ -76,7 +237,7 @@ const props = defineProps({
|
|
|
76
237
|
default: () => [
|
|
77
238
|
{
|
|
78
239
|
title: "Card",
|
|
79
|
-
value: "
|
|
240
|
+
value: "cardNumber",
|
|
80
241
|
},
|
|
81
242
|
{
|
|
82
243
|
title: "Unit",
|
|
@@ -115,7 +276,7 @@ const props = defineProps({
|
|
|
115
276
|
},
|
|
116
277
|
});
|
|
117
278
|
|
|
118
|
-
const { headerSearch } = useLocal();
|
|
279
|
+
// const { headerSearch } = useLocal();
|
|
119
280
|
const page = ref(1);
|
|
120
281
|
const pages = ref(0);
|
|
121
282
|
const pageRange = ref("-- - -- of --");
|
|
@@ -131,6 +292,123 @@ const previewDialog = ref(false);
|
|
|
131
292
|
const deleteLoading = ref(false);
|
|
132
293
|
const confirmDialog = ref(false);
|
|
133
294
|
const searchText = ref("");
|
|
295
|
+
const replaceDialog = ref(false);
|
|
296
|
+
|
|
297
|
+
const selectedCard = ref<TCard>({
|
|
298
|
+
_id: "",
|
|
299
|
+
name: "",
|
|
300
|
+
accessCardType: "",
|
|
301
|
+
// visitorType: "",
|
|
302
|
+
type: "",
|
|
303
|
+
cardNumber: "",
|
|
304
|
+
startDate: "",
|
|
305
|
+
endDate: "",
|
|
306
|
+
door: "",
|
|
307
|
+
accessGroup: [],
|
|
308
|
+
cardType: "",
|
|
309
|
+
pinNo: "",
|
|
310
|
+
useAsLiftCard: false,
|
|
311
|
+
liftAccessLevel: "",
|
|
312
|
+
isActivate: true,
|
|
313
|
+
isAntiPassBack: false,
|
|
314
|
+
status: "",
|
|
315
|
+
org: "",
|
|
316
|
+
site: "",
|
|
317
|
+
unit: "",
|
|
318
|
+
assign: "",
|
|
319
|
+
});
|
|
320
|
+
const selectedCardId = ref<string | null>(null);
|
|
321
|
+
|
|
322
|
+
const { getAll: _getAllCards, deleteById: _deleteCard } = useCard();
|
|
323
|
+
|
|
324
|
+
const {
|
|
325
|
+
data: getCardReq,
|
|
326
|
+
refresh: getCards,
|
|
327
|
+
status: getAllReqStatus,
|
|
328
|
+
} = useLazyAsyncData(
|
|
329
|
+
"get-all-cards",
|
|
330
|
+
() =>
|
|
331
|
+
_getAllCards({
|
|
332
|
+
page: page.value,
|
|
333
|
+
search: searchText.value,
|
|
334
|
+
// search: headerSearch.value,
|
|
335
|
+
}),
|
|
336
|
+
{
|
|
337
|
+
watch: [page, searchText],
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const loading = computed(() => getAllReqStatus.value === "pending");
|
|
342
|
+
|
|
343
|
+
watchEffect(() => {
|
|
344
|
+
if (getCardReq.value) {
|
|
345
|
+
items.value = getCardReq.value.items;
|
|
346
|
+
pages.value = getCardReq.value.pages;
|
|
347
|
+
pageRange.value = getCardReq.value.pageRange;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
function setCard({ mode = "create", dialog = true, data = {} as TCard } = {}) {
|
|
352
|
+
if (mode === "create") {
|
|
353
|
+
createDialog.value = dialog;
|
|
354
|
+
} else if (mode === "edit") {
|
|
355
|
+
editDialog.value = dialog;
|
|
356
|
+
selectedCard.value = data;
|
|
357
|
+
} else if (mode === "preview") {
|
|
358
|
+
previewDialog.value = dialog;
|
|
359
|
+
selectedCard.value = data;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function successCreate() {
|
|
364
|
+
createDialog.value = false;
|
|
365
|
+
getCards();
|
|
366
|
+
showMessage("Card created successfully!", "success");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function successUpdate() {
|
|
370
|
+
editDialog.value = false;
|
|
371
|
+
previewDialog.value = false;
|
|
372
|
+
getCards();
|
|
373
|
+
showMessage("Card updated successfully!", "success");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function showMessage(msg: string, color: string) {
|
|
377
|
+
message.value = msg;
|
|
378
|
+
messageColor.value = color;
|
|
379
|
+
messageSnackbar.value = true;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function tableRowClickHandler(_: any, data: any) {
|
|
383
|
+
selectedCard.value = data.item as TCard;
|
|
384
|
+
previewDialog.value = true;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function openEditDialog() {
|
|
388
|
+
editDialog.value = true;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function openDeleteDialog() {
|
|
392
|
+
confirmDialog.value = true;
|
|
393
|
+
message.value = "";
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function openReplaceDialog() {
|
|
397
|
+
replaceDialog.value = true;
|
|
398
|
+
}
|
|
134
399
|
|
|
135
|
-
|
|
400
|
+
async function handleDeleteCard() {
|
|
401
|
+
deleteLoading.value = true;
|
|
402
|
+
try {
|
|
403
|
+
await _deleteCard(selectedCard.value._id ?? "");
|
|
404
|
+
await getCards();
|
|
405
|
+
selectedCardId.value = null;
|
|
406
|
+
confirmDialog.value = false;
|
|
407
|
+
previewDialog.value = false;
|
|
408
|
+
} catch (error: any) {
|
|
409
|
+
message.value = error?.response?._data?.message || "Failed to delete card";
|
|
410
|
+
} finally {
|
|
411
|
+
deleteLoading.value = false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
136
414
|
</script>
|
|
@@ -60,6 +60,28 @@
|
|
|
60
60
|
</v-row>
|
|
61
61
|
</v-col>
|
|
62
62
|
|
|
63
|
+
<v-col cols="12">
|
|
64
|
+
<v-row>
|
|
65
|
+
<v-col cols="12" class="mt-2">
|
|
66
|
+
<v-row no-gutters>
|
|
67
|
+
<InputLabel
|
|
68
|
+
class="text-capitalize font-weight-bold"
|
|
69
|
+
title="Owner"
|
|
70
|
+
/>
|
|
71
|
+
<v-col cols="12">
|
|
72
|
+
<v-autocomplete
|
|
73
|
+
v-model="buildingUnit.ownerName"
|
|
74
|
+
:items="peopleItems"
|
|
75
|
+
item-title="name"
|
|
76
|
+
return-object
|
|
77
|
+
density="comfortable">
|
|
78
|
+
</v-autocomplete>
|
|
79
|
+
</v-col>
|
|
80
|
+
</v-row>
|
|
81
|
+
</v-col>
|
|
82
|
+
</v-row>
|
|
83
|
+
</v-col>
|
|
84
|
+
|
|
63
85
|
<v-col cols="12">
|
|
64
86
|
<v-row>
|
|
65
87
|
<v-col cols="12" class="mt-2">
|
|
@@ -258,6 +280,8 @@ const prop = defineProps({
|
|
|
258
280
|
_id: "",
|
|
259
281
|
site: "",
|
|
260
282
|
name: "",
|
|
283
|
+
owner: "",
|
|
284
|
+
ownerName: "",
|
|
261
285
|
building: "",
|
|
262
286
|
buildingName: "",
|
|
263
287
|
category: "",
|
|
@@ -277,6 +301,8 @@ const buildingUnit = ref({
|
|
|
277
301
|
_id: "",
|
|
278
302
|
site: "",
|
|
279
303
|
name: "",
|
|
304
|
+
owner: "",
|
|
305
|
+
ownerName: "",
|
|
280
306
|
building: "",
|
|
281
307
|
buildingName: "",
|
|
282
308
|
level: 0,
|
|
@@ -297,8 +323,10 @@ const emit = defineEmits(["cancel", "success", "success:create-more"]);
|
|
|
297
323
|
const validForm = ref(false);
|
|
298
324
|
|
|
299
325
|
const { getAll } = useBuilding();
|
|
326
|
+
const { getPeopleByUnit } = usePeople();
|
|
300
327
|
|
|
301
328
|
const buildings = ref<Record<string, any>[]>([]);
|
|
329
|
+
const peopleItems = ref<Array<Record<string, any>>>([]);
|
|
302
330
|
|
|
303
331
|
const { data: getBuildingReq } = useLazyAsyncData(
|
|
304
332
|
"get-all-buildings",
|
|
@@ -315,6 +343,17 @@ watchEffect(() => {
|
|
|
315
343
|
}
|
|
316
344
|
});
|
|
317
345
|
|
|
346
|
+
const { data: getUnitPeople } = useLazyAsyncData(
|
|
347
|
+
"get-unit-people",
|
|
348
|
+
async () => getPeopleByUnit(prop.roomFacility._id as string)
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
watch(getUnitPeople, (newData: any) => {
|
|
352
|
+
if (newData) {
|
|
353
|
+
peopleItems.value = newData ?? [];
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
318
357
|
buildingUnit.value.site = prop.site;
|
|
319
358
|
|
|
320
359
|
const selectedBuilding = computed(() => {
|
|
@@ -355,6 +394,12 @@ const hasChanges = computed(() => {
|
|
|
355
394
|
async function submit() {
|
|
356
395
|
disable.value = true;
|
|
357
396
|
try {
|
|
397
|
+
|
|
398
|
+
if (buildingUnit.value.ownerName) {
|
|
399
|
+
buildingUnit.value.owner = (buildingUnit.value.ownerName as any)._id
|
|
400
|
+
buildingUnit.value.ownerName = (buildingUnit.value.ownerName as any).name
|
|
401
|
+
}
|
|
402
|
+
|
|
358
403
|
await updateById(buildingUnit.value._id ?? "", {
|
|
359
404
|
name: buildingUnit.value.name,
|
|
360
405
|
level: buildingUnit.value.level,
|
|
@@ -364,6 +409,8 @@ async function submit() {
|
|
|
364
409
|
companyRegistrationNumber: buildingUnit.value.companyRegistrationNumber || "",
|
|
365
410
|
leaseStart: buildingUnit.value.leaseStart,
|
|
366
411
|
leaseEnd: buildingUnit.value.leaseEnd,
|
|
412
|
+
owner: buildingUnit.value.owner || "",
|
|
413
|
+
ownerName: buildingUnit.value.ownerName || ""
|
|
367
414
|
});
|
|
368
415
|
|
|
369
416
|
emit("success");
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters class="">
|
|
3
|
+
<v-col cols="12" elevation="3" class="border">
|
|
4
|
+
<v-row no-gutters class="px-6 pt-4">
|
|
5
|
+
<div class="d-flex mt-7 pb-5">
|
|
6
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
7
|
+
Physical / Key Pass
|
|
8
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
9
|
+
A Physical Pass Card is a tangible identification or access card
|
|
10
|
+
used for entry and verification purposes at a specific site or
|
|
11
|
+
property. Its primary functions include granting authorized
|
|
12
|
+
access, enhancing security, and tracking attendance or movement.
|
|
13
|
+
</span>
|
|
14
|
+
</p>
|
|
15
|
+
<v-switch color="success" hide-details></v-switch>
|
|
16
|
+
</div>
|
|
17
|
+
<v-divider thickness="1"></v-divider>
|
|
18
|
+
<div class="d-flex mt-7 pb-5">
|
|
19
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
20
|
+
NFC / QR Code Pass
|
|
21
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
22
|
+
NFC Card Pass is a type of access card that uses Near Field
|
|
23
|
+
Communication (NFC) technology to enable secure and convenient
|
|
24
|
+
entry to a site or property. This technology facilitates wireless
|
|
25
|
+
communication between the card and an NFC reader when they are
|
|
26
|
+
placed in close proximity (typically within 4 cm).
|
|
27
|
+
</span>
|
|
28
|
+
</p>
|
|
29
|
+
<v-switch color="success" hide-details></v-switch>
|
|
30
|
+
</div>
|
|
31
|
+
<v-divider thickness="1"></v-divider>
|
|
32
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
33
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
34
|
+
Upload Access Cards Template
|
|
35
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
36
|
+
<a
|
|
37
|
+
target="_blank"
|
|
38
|
+
class="text-truncate d-flex items-center text-decoration-none"
|
|
39
|
+
href=""
|
|
40
|
+
>
|
|
41
|
+
<v-icon class="mr-2" size="24px"> mdi-paperclip </v-icon>
|
|
42
|
+
template
|
|
43
|
+
</a>
|
|
44
|
+
</span>
|
|
45
|
+
</p>
|
|
46
|
+
<v-btn
|
|
47
|
+
variant="flat"
|
|
48
|
+
color="error"
|
|
49
|
+
size="small"
|
|
50
|
+
style="height: 40px; margin-left: auto"
|
|
51
|
+
prepend-icon="mdi-file-document-remove-outline"
|
|
52
|
+
>
|
|
53
|
+
Remove
|
|
54
|
+
</v-btn>
|
|
55
|
+
</div>
|
|
56
|
+
<v-divider thickness="1"></v-divider>
|
|
57
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
58
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
59
|
+
Printer Setup
|
|
60
|
+
<v-col cols="12">
|
|
61
|
+
<v-row>
|
|
62
|
+
<v-col cols="3">
|
|
63
|
+
<v-text-field
|
|
64
|
+
label="Vendor ID"
|
|
65
|
+
hide-details
|
|
66
|
+
clearable
|
|
67
|
+
></v-text-field>
|
|
68
|
+
</v-col>
|
|
69
|
+
<v-col cols="3">
|
|
70
|
+
<v-text-field
|
|
71
|
+
label="Product ID"
|
|
72
|
+
hide-details
|
|
73
|
+
clearable
|
|
74
|
+
></v-text-field>
|
|
75
|
+
</v-col>
|
|
76
|
+
<v-col cols="3">
|
|
77
|
+
<v-btn
|
|
78
|
+
color="primary"
|
|
79
|
+
variant="outlined"
|
|
80
|
+
prepend-icon="mdi-magnify"
|
|
81
|
+
block
|
|
82
|
+
>
|
|
83
|
+
Scan Printer
|
|
84
|
+
</v-btn>
|
|
85
|
+
</v-col>
|
|
86
|
+
<v-col cols="3">
|
|
87
|
+
<v-btn
|
|
88
|
+
color="success"
|
|
89
|
+
variant="outlined"
|
|
90
|
+
prepend-icon="mdi-printer-check"
|
|
91
|
+
block
|
|
92
|
+
>
|
|
93
|
+
Test & Print
|
|
94
|
+
</v-btn>
|
|
95
|
+
</v-col>
|
|
96
|
+
</v-row>
|
|
97
|
+
<v-row class="mt-4">
|
|
98
|
+
<v-col cols="12" sm="6" md="4">
|
|
99
|
+
<v-btn
|
|
100
|
+
color="primary"
|
|
101
|
+
variant="flat"
|
|
102
|
+
prepend-icon="mdi-content-save"
|
|
103
|
+
block
|
|
104
|
+
>
|
|
105
|
+
Save Printer Settings
|
|
106
|
+
</v-btn>
|
|
107
|
+
</v-col>
|
|
108
|
+
</v-row>
|
|
109
|
+
</v-col>
|
|
110
|
+
</p>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<v-divider thickness="1"></v-divider>
|
|
114
|
+
|
|
115
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
116
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
117
|
+
QR Code Template
|
|
118
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
119
|
+
<v-col cols="12">
|
|
120
|
+
<v-row>
|
|
121
|
+
<v-col cols="12">
|
|
122
|
+
<v-text-field
|
|
123
|
+
label="Header"
|
|
124
|
+
placeholder="Enter qr code header eg. Welcome to Company Name"
|
|
125
|
+
hide-details
|
|
126
|
+
density="comfortable"
|
|
127
|
+
clearable
|
|
128
|
+
></v-text-field>
|
|
129
|
+
</v-col>
|
|
130
|
+
<v-col cols="12">
|
|
131
|
+
<v-text-field
|
|
132
|
+
label="Subtext"
|
|
133
|
+
placeholder="Enter qr code sub header"
|
|
134
|
+
hide-details
|
|
135
|
+
density="comfortable"
|
|
136
|
+
clearable
|
|
137
|
+
class="mb-2"
|
|
138
|
+
></v-text-field>
|
|
139
|
+
</v-col>
|
|
140
|
+
<v-row class="mt-3">
|
|
141
|
+
<v-col cols="12" md="2">
|
|
142
|
+
<v-btn color="primary" variant="flat" block>
|
|
143
|
+
Preview
|
|
144
|
+
</v-btn>
|
|
145
|
+
</v-col>
|
|
146
|
+
<v-col cols="12" md="2">
|
|
147
|
+
<v-btn color="primary" variant="flat" block> Save </v-btn>
|
|
148
|
+
</v-col>
|
|
149
|
+
</v-row>
|
|
150
|
+
</v-row>
|
|
151
|
+
</v-col>
|
|
152
|
+
</span>
|
|
153
|
+
</p>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<v-divider thickness="1"></v-divider>
|
|
157
|
+
|
|
158
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
159
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
160
|
+
Resident-app Disclaimer Message
|
|
161
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
162
|
+
<v-col cols="12">
|
|
163
|
+
<v-row no-gutters>
|
|
164
|
+
<v-col cols="12" class="mb-5">
|
|
165
|
+
<v-textarea
|
|
166
|
+
label="Disclaimer Message"
|
|
167
|
+
placeholder="Enter disclaimer message for resident app"
|
|
168
|
+
hide-details
|
|
169
|
+
density="comfortable"
|
|
170
|
+
clearable
|
|
171
|
+
rows="5"
|
|
172
|
+
auto-grow
|
|
173
|
+
></v-textarea>
|
|
174
|
+
</v-col>
|
|
175
|
+
<v-row class="mt-3">
|
|
176
|
+
<v-col cols="12" md="2">
|
|
177
|
+
<v-btn color="primary" variant="flat" block> Save </v-btn>
|
|
178
|
+
</v-col>
|
|
179
|
+
</v-row>
|
|
180
|
+
</v-row>
|
|
181
|
+
</v-col>
|
|
182
|
+
</span>
|
|
183
|
+
</p>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<v-divider thickness="1"></v-divider>
|
|
187
|
+
|
|
188
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
189
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
190
|
+
Entrypass URL
|
|
191
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
192
|
+
<v-col>
|
|
193
|
+
<v-text-field
|
|
194
|
+
label="Enter entrypass URL"
|
|
195
|
+
placeholder="https://example.com"
|
|
196
|
+
outlined
|
|
197
|
+
clearable
|
|
198
|
+
hide-details
|
|
199
|
+
/>
|
|
200
|
+
</v-col>
|
|
201
|
+
<v-col>
|
|
202
|
+
<v-btn color="primary">Save</v-btn>
|
|
203
|
+
</v-col>
|
|
204
|
+
</span>
|
|
205
|
+
</p>
|
|
206
|
+
</div>
|
|
207
|
+
</v-row>
|
|
208
|
+
</v-col></v-row
|
|
209
|
+
>
|
|
210
|
+
</template>
|
|
211
|
+
<script lang="ts" setup>
|
|
212
|
+
definePageMeta({
|
|
213
|
+
middleware: ["01-auth", "02-org"],
|
|
214
|
+
memberOnly: true,
|
|
215
|
+
});
|
|
216
|
+
const prop = defineProps({
|
|
217
|
+
site: {
|
|
218
|
+
type: String,
|
|
219
|
+
required: true,
|
|
220
|
+
},
|
|
221
|
+
siteName: {
|
|
222
|
+
type: String,
|
|
223
|
+
required: true,
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
orgId: {
|
|
227
|
+
type: String,
|
|
228
|
+
required: true,
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
</script>
|