@7365admin1/layer-common 1.10.0 → 1.10.1
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/AcceptDialog.vue +44 -0
- package/components/AccessCardAddForm.vue +101 -13
- package/components/AccessManagement.vue +130 -47
- package/components/AddSupplyForm.vue +165 -0
- package/components/AreaChecklistHistoryLogs.vue +235 -0
- package/components/AreaChecklistHistoryMain.vue +176 -0
- package/components/AreaFormDialog.vue +266 -0
- package/components/AreaMain.vue +841 -0
- package/components/AttendanceCheckInOutDialog.vue +416 -0
- package/components/AttendanceDetailsDialog.vue +184 -0
- package/components/AttendanceMain.vue +155 -0
- package/components/AttendanceMapSearchDialog.vue +393 -0
- package/components/AttendanceSettingsDialog.vue +398 -0
- package/components/BuildingManagement/buildings.vue +5 -5
- package/components/BuildingManagement/units.vue +5 -5
- package/components/ChecklistItemRow.vue +54 -0
- package/components/CheckoutItemMain.vue +705 -0
- package/components/CleaningScheduleMain.vue +271 -0
- package/components/DocumentManagement.vue +4 -0
- package/components/EntryPass/QrTemplatePreview.vue +104 -0
- package/components/EntryPassMain.vue +252 -200
- package/components/HygieneUpdateMoreAction.vue +238 -0
- package/components/ManageChecklistMain.vue +384 -0
- package/components/MemberMain.vue +48 -20
- package/components/MyAttendanceMain.vue +224 -0
- package/components/OnlineFormsConfiguration.vue +9 -2
- package/components/PhotoUpload.vue +410 -0
- package/components/ScheduleAreaMain.vue +313 -0
- package/components/ScheduleTaskAreaFormDialog.vue +144 -0
- package/components/ScheduleTaskAreaUpdateMoreAction.vue +109 -0
- package/components/ScheduleTaskForm.vue +471 -0
- package/components/ScheduleTaskMain.vue +345 -0
- package/components/ScheduleTastTicketMain.vue +182 -0
- package/components/StockCard.vue +191 -0
- package/components/SupplyManagementMain.vue +557 -0
- package/components/TableHygiene.vue +617 -0
- package/components/UnitMain.vue +451 -0
- package/components/VisitorManagement.vue +28 -15
- package/composables/useAccessManagement.ts +90 -0
- package/composables/useAreaPermission.ts +51 -0
- package/composables/useAreas.ts +99 -0
- package/composables/useAttendance.ts +89 -0
- package/composables/useAttendancePermission.ts +68 -0
- package/composables/useBuilding.ts +2 -2
- package/composables/useBuildingUnit.ts +2 -2
- package/composables/useCard.ts +2 -0
- package/composables/useCheckout.ts +61 -0
- package/composables/useCheckoutPermission.ts +80 -0
- package/composables/useCleaningPermission.ts +229 -0
- package/composables/useCleaningSchedulePermission.ts +58 -0
- package/composables/useCleaningSchedules.ts +233 -0
- package/composables/useCountry.ts +8 -0
- package/composables/useDashboardData.ts +2 -2
- package/composables/useFeedback.ts +1 -1
- package/composables/useLocation.ts +78 -0
- package/composables/useOnlineForm.ts +16 -9
- package/composables/usePeople.ts +87 -72
- package/composables/useQR.ts +29 -0
- package/composables/useScheduleTask.ts +89 -0
- package/composables/useScheduleTaskArea.ts +85 -0
- package/composables/useScheduleTaskPermission.ts +68 -0
- package/composables/useSiteEntryPassSettings.ts +4 -15
- package/composables/useStock.ts +45 -0
- package/composables/useSupply.ts +63 -0
- package/composables/useSupplyPermission.ts +92 -0
- package/composables/useUnitPermission.ts +51 -0
- package/composables/useUnits.ts +82 -0
- package/composables/useWebUsb.ts +389 -0
- package/composables/useWorkOrder.ts +1 -1
- package/nuxt.config.ts +3 -0
- package/package.json +4 -1
- package/types/area.d.ts +22 -0
- package/types/attendance.d.ts +38 -0
- package/types/checkout-item.d.ts +27 -0
- package/types/cleaner-schedule.d.ts +54 -0
- package/types/location.d.ts +42 -0
- package/types/schedule-task.d.ts +18 -0
- package/types/stock.d.ts +16 -0
- package/types/supply.d.ts +11 -0
- package/utils/acm-crypto.ts +30 -0
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-dialog
|
|
3
|
+
:model-value="modelValue"
|
|
4
|
+
@update:model-value="val => $emit('update:modelValue', val)"
|
|
5
|
+
max-width="420"
|
|
6
|
+
persistent
|
|
7
|
+
>
|
|
8
|
+
<v-card class="pa-4" style="border-radius:12px;">
|
|
9
|
+
<v-card-title class="headline" style="font-size:1.3rem; font-weight:500;">
|
|
10
|
+
{{ title }}
|
|
11
|
+
</v-card-title>
|
|
12
|
+
<v-card-text style="font-size:1.05rem; margin-bottom:24px;">
|
|
13
|
+
{{ message }}
|
|
14
|
+
</v-card-text>
|
|
15
|
+
<v-card-actions class="justify-end" style="gap:12px;">
|
|
16
|
+
<v-btn
|
|
17
|
+
color="primary"
|
|
18
|
+
variant="outlined"
|
|
19
|
+
style="min-width:70px; background:#e3f2fd; color:#1976d2; font-weight:500;"
|
|
20
|
+
@click="$emit('confirm')"
|
|
21
|
+
>
|
|
22
|
+
Yes
|
|
23
|
+
</v-btn>
|
|
24
|
+
<v-btn
|
|
25
|
+
color="error"
|
|
26
|
+
variant="outlined"
|
|
27
|
+
style="min-width:70px; background:#ffebee; color:#d32f2f; font-weight:500;"
|
|
28
|
+
@click="$emit('cancel')"
|
|
29
|
+
>
|
|
30
|
+
No
|
|
31
|
+
</v-btn>
|
|
32
|
+
</v-card-actions>
|
|
33
|
+
</v-card>
|
|
34
|
+
</v-dialog>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
defineProps<{
|
|
39
|
+
modelValue: boolean,
|
|
40
|
+
title?: string,
|
|
41
|
+
message?: string
|
|
42
|
+
}>();
|
|
43
|
+
defineEmits(['confirm', 'cancel', 'update:modelValue']);
|
|
44
|
+
</script>
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
<v-col cols="12">
|
|
92
92
|
<InputLabel
|
|
93
93
|
class="text-capitalize font-weight-bold"
|
|
94
|
-
title="
|
|
94
|
+
title="Door Location"
|
|
95
95
|
required
|
|
96
96
|
/>
|
|
97
97
|
<v-select
|
|
@@ -115,6 +115,8 @@
|
|
|
115
115
|
v-model="card.accessGroup"
|
|
116
116
|
density="compact"
|
|
117
117
|
:items="accessGroupItems"
|
|
118
|
+
item-title="name"
|
|
119
|
+
item-value="no"
|
|
118
120
|
hide-details
|
|
119
121
|
:rules="[requiredRule]"
|
|
120
122
|
multiple
|
|
@@ -179,7 +181,7 @@
|
|
|
179
181
|
hide-details
|
|
180
182
|
:rules="card.useAsLiftCard ? [requiredRule] : []"
|
|
181
183
|
item-title="name"
|
|
182
|
-
item-value="
|
|
184
|
+
item-value="no"
|
|
183
185
|
/>
|
|
184
186
|
</v-col>
|
|
185
187
|
<v-col cols="12">
|
|
@@ -327,6 +329,15 @@ const prop = defineProps({
|
|
|
327
329
|
const { add: _addCard, updateById: _updateCardById } = useCard();
|
|
328
330
|
const { getAll: _getBuildings } = useBuilding();
|
|
329
331
|
const { getAllUnits: _getUnits } = useBuildingUnit();
|
|
332
|
+
const {
|
|
333
|
+
getDoorAccessLevels: _getDoorAccessLevels,
|
|
334
|
+
getLiftAccessLevels: _getLiftAccessLevels,
|
|
335
|
+
getAccessGroups: _getAccessGroups,
|
|
336
|
+
addPhysicalCard: _addPhysicalCard,
|
|
337
|
+
addNonPhysicalCard: _addNonPhysicalCard,
|
|
338
|
+
} = useAccessManagement();
|
|
339
|
+
|
|
340
|
+
const config = useRuntimeConfig();
|
|
330
341
|
const emit = defineEmits(["cancel", "success"]);
|
|
331
342
|
|
|
332
343
|
const validForm = ref(false);
|
|
@@ -429,11 +440,32 @@ const buildingItems = ref<{ name: string; value: string }[]>([]);
|
|
|
429
440
|
const levelItems = ref<{ name: string; value: string }[]>([]);
|
|
430
441
|
const unitItems = ref<{ name: string; value: string }[]>([]);
|
|
431
442
|
const buildingsData = ref<Record<string, any>[]>([]);
|
|
443
|
+
const encryptedAcmUrl = ref("");
|
|
432
444
|
|
|
433
445
|
const route = useRoute();
|
|
434
|
-
const siteId =
|
|
446
|
+
const siteId = '66ab2f1381856008f1887971' as string;
|
|
447
|
+
// const siteId = route.params.site as string; @TODO
|
|
435
448
|
const orgId = route.params.org as string;
|
|
436
449
|
|
|
450
|
+
onMounted(async () => {
|
|
451
|
+
try {
|
|
452
|
+
const { encrypted: acmUrl } = await $fetch<{ encrypted: string }>(
|
|
453
|
+
"/api/encrypt-acm-url"
|
|
454
|
+
);
|
|
455
|
+
encryptedAcmUrl.value = acmUrl;
|
|
456
|
+
const [doorLevels, liftLevels, groups] = await Promise.all([
|
|
457
|
+
_getDoorAccessLevels(acmUrl),
|
|
458
|
+
_getLiftAccessLevels(acmUrl),
|
|
459
|
+
_getAccessGroups(acmUrl),
|
|
460
|
+
]);
|
|
461
|
+
accessLevelItems.value = doorLevels.data ?? [];
|
|
462
|
+
liftAccessLevelItems.value = liftLevels.data ?? [];
|
|
463
|
+
accessGroupItems.value = groups.data ?? [];
|
|
464
|
+
} catch (error) {
|
|
465
|
+
console.error("Failed to fetch access management data:", error);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
|
|
437
469
|
function limitCardNumber() {
|
|
438
470
|
if (card.value.cardNumber && card.value.cardNumber.toString().length > cardNoMaxLength.value) {
|
|
439
471
|
card.value.cardNumber = card.value.cardNumber.toString().slice(0, cardNoMaxLength.value);
|
|
@@ -543,23 +575,79 @@ function cancel() {
|
|
|
543
575
|
emit("cancel");
|
|
544
576
|
}
|
|
545
577
|
|
|
578
|
+
function buildPhysicalCardPayload() {
|
|
579
|
+
const now = new Date().toISOString();
|
|
580
|
+
const doorItem = accessLevelItems.value.find((i: any) => i.no === card.value.door);
|
|
581
|
+
const liftItem = liftAccessLevelItems.value.find((i: any) => i.no === card.value.liftAccessLevel);
|
|
582
|
+
|
|
583
|
+
return {
|
|
584
|
+
site: siteId,
|
|
585
|
+
cardNo: card.value.cardNumber,
|
|
586
|
+
isActivated: card.value.isActivate,
|
|
587
|
+
isAntiPassBack: card.value.isAntiPassBack,
|
|
588
|
+
isLiftCard: card.value.useAsLiftCard,
|
|
589
|
+
userType: "Visitor/Resident",
|
|
590
|
+
accessLevel: card.value.door,
|
|
591
|
+
accessGroup: card.value.accessGroup,
|
|
592
|
+
accessType: card.value.cardType,
|
|
593
|
+
startDate: card.value.startDate,
|
|
594
|
+
endDate: card.value.endDate,
|
|
595
|
+
doorName: doorItem?.name ?? "",
|
|
596
|
+
createdAt: now,
|
|
597
|
+
updatedAt: now,
|
|
598
|
+
...(card.value.pinNo ? { pin: card.value.pinNo } : {}),
|
|
599
|
+
...(card.value.useAsLiftCard
|
|
600
|
+
? {
|
|
601
|
+
liftAccessLevel: card.value.liftAccessLevel,
|
|
602
|
+
liftName: liftItem?.name ?? "",
|
|
603
|
+
}
|
|
604
|
+
: {}),
|
|
605
|
+
...(card.value.assignUnit ? { unit: [card.value.assignUnit] } : {}),
|
|
606
|
+
...(card.value.isWinsland !== undefined ? { isWinsland: card.value.isWinsland } : {}),
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function buildNonPhysicalCardPayload() {
|
|
611
|
+
const now = new Date().toISOString();
|
|
612
|
+
const doorItem = accessLevelItems.value.find((i: any) => i.no === card.value.door);
|
|
613
|
+
const liftItem = liftAccessLevelItems.value.find((i: any) => i.no === card.value.liftAccessLevel);
|
|
614
|
+
|
|
615
|
+
return {
|
|
616
|
+
site: siteId,
|
|
617
|
+
quantity: card.value.quantity,
|
|
618
|
+
accessLevel: card.value.door,
|
|
619
|
+
isLiftCard: card.value.useAsLiftCard,
|
|
620
|
+
accessGroup: card.value.accessGroup,
|
|
621
|
+
userType: "Visitor/Resident",
|
|
622
|
+
doorName: doorItem?.name ?? "",
|
|
623
|
+
startDate: card.value.startDate,
|
|
624
|
+
endDate: card.value.endDate,
|
|
625
|
+
createdAt: now,
|
|
626
|
+
updatedAt: now,
|
|
627
|
+
...(card.value.useAsLiftCard
|
|
628
|
+
? {
|
|
629
|
+
liftAccessLevel: card.value.liftAccessLevel,
|
|
630
|
+
liftName: liftItem?.name ?? "",
|
|
631
|
+
}
|
|
632
|
+
: {}),
|
|
633
|
+
...(card.value.assignUnit ? { unit: [card.value.assignUnit] } : {}),
|
|
634
|
+
...(card.value.isWinsland !== undefined ? { isWinsland: card.value.isWinsland } : {}),
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
|
|
546
638
|
async function submit() {
|
|
547
639
|
disable.value = true;
|
|
548
640
|
try {
|
|
549
641
|
if (prop.mode === "add") {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
555
|
-
await _addCard(payload);
|
|
642
|
+
if (isNonPhysicalCard.value) {
|
|
643
|
+
await _addNonPhysicalCard(buildNonPhysicalCardPayload());
|
|
644
|
+
} else {
|
|
645
|
+
await _addPhysicalCard(buildPhysicalCardPayload());
|
|
646
|
+
}
|
|
556
647
|
}
|
|
557
648
|
|
|
558
649
|
if (prop.mode === "edit") {
|
|
559
|
-
|
|
560
|
-
...card.value,
|
|
561
|
-
};
|
|
562
|
-
await _updateCardById(prop.card._id ?? "", payload);
|
|
650
|
+
await _updateCardById(prop.card._id ?? "", { ...card.value });
|
|
563
651
|
}
|
|
564
652
|
emit("success");
|
|
565
653
|
} catch (error: any) {
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
mode="edit"
|
|
81
81
|
@cancel="editDialog = false"
|
|
82
82
|
@success="successUpdate()"
|
|
83
|
-
:card="selectedCard"
|
|
83
|
+
:card="selectedCard as TCard"
|
|
84
84
|
/>
|
|
85
85
|
</v-dialog>
|
|
86
86
|
|
|
@@ -90,21 +90,93 @@
|
|
|
90
90
|
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
|
|
91
91
|
<v-row no-gutters class="mb-4">
|
|
92
92
|
<v-col cols="12">
|
|
93
|
-
<strong>
|
|
93
|
+
<strong>Unit:</strong> {{ selectedCard?.name ?? "N/A" }}
|
|
94
94
|
</v-col>
|
|
95
95
|
<v-col cols="12">
|
|
96
|
-
<strong>
|
|
97
|
-
{{ selectedCard?.accessCardType ?? "N/A" }}
|
|
96
|
+
<strong>Block:</strong> {{ selectedCard?.block?.name ?? "N/A" }}
|
|
98
97
|
</v-col>
|
|
99
98
|
<v-col cols="12">
|
|
100
|
-
<strong>
|
|
101
|
-
{{ selectedCard?.unit || "N/A" }}
|
|
99
|
+
<strong>Level:</strong> {{ selectedCard?.level?.level ?? "N/A" }}
|
|
102
100
|
</v-col>
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
|
|
102
|
+
<!-- Available Physical -->
|
|
103
|
+
<v-col cols="12" class="mt-3">
|
|
104
|
+
<strong>Available Physical</strong>
|
|
105
|
+
<div v-if="selectedCard?.available?.physical?.length" class="mt-1">
|
|
106
|
+
<v-chip
|
|
107
|
+
v-for="card in selectedCard.available.physical"
|
|
108
|
+
:key="card._id"
|
|
109
|
+
size="small"
|
|
110
|
+
class="mr-1 mb-1"
|
|
111
|
+
:color="selectedCardInUnit?._id === card._id ? 'primary' : undefined"
|
|
112
|
+
:variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
|
|
113
|
+
style="cursor: pointer"
|
|
114
|
+
@click="selectedCardInUnit = selectedCardInUnit?._id === card._id ? null : card"
|
|
115
|
+
>
|
|
116
|
+
{{ card.cardNo }}
|
|
117
|
+
</v-chip>
|
|
118
|
+
</div>
|
|
119
|
+
<span v-else class="text-caption text-grey ml-1">None</span>
|
|
105
120
|
</v-col>
|
|
106
|
-
|
|
107
|
-
|
|
121
|
+
|
|
122
|
+
<!-- Available Non-Physical -->
|
|
123
|
+
<v-col cols="12" class="mt-2">
|
|
124
|
+
<strong>Available Non-Physical</strong>
|
|
125
|
+
<div v-if="selectedCard?.available?.non_physical?.length" class="mt-1">
|
|
126
|
+
<v-chip
|
|
127
|
+
v-for="card in selectedCard.available.non_physical"
|
|
128
|
+
:key="card._id"
|
|
129
|
+
size="small"
|
|
130
|
+
class="mr-1 mb-1"
|
|
131
|
+
:color="selectedCardInUnit?._id === card._id ? 'primary' : undefined"
|
|
132
|
+
:variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
|
|
133
|
+
style="cursor: pointer"
|
|
134
|
+
@click="selectedCardInUnit = selectedCardInUnit?._id === card._id ? null : card"
|
|
135
|
+
>
|
|
136
|
+
{{ card.cardNo }}
|
|
137
|
+
</v-chip>
|
|
138
|
+
</div>
|
|
139
|
+
<span v-else class="text-caption text-grey ml-1">None</span>
|
|
140
|
+
</v-col>
|
|
141
|
+
|
|
142
|
+
<!-- Assigned Physical -->
|
|
143
|
+
<v-col cols="12" class="mt-2">
|
|
144
|
+
<strong>Assigned Physical</strong>
|
|
145
|
+
<div v-if="selectedCard?.assigned?.physical?.length" class="mt-1">
|
|
146
|
+
<v-chip
|
|
147
|
+
v-for="card in selectedCard.assigned.physical"
|
|
148
|
+
:key="card._id"
|
|
149
|
+
size="small"
|
|
150
|
+
class="mr-1 mb-1"
|
|
151
|
+
:color="selectedCardInUnit?._id === card._id ? 'primary' : undefined"
|
|
152
|
+
:variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
|
|
153
|
+
style="cursor: pointer"
|
|
154
|
+
@click="selectedCardInUnit = selectedCardInUnit?._id === card._id ? null : card"
|
|
155
|
+
>
|
|
156
|
+
{{ card.cardNo }}
|
|
157
|
+
</v-chip>
|
|
158
|
+
</div>
|
|
159
|
+
<span v-else class="text-caption text-grey ml-1">None</span>
|
|
160
|
+
</v-col>
|
|
161
|
+
|
|
162
|
+
<!-- Assigned Non-Physical -->
|
|
163
|
+
<v-col cols="12" class="mt-2">
|
|
164
|
+
<strong>Assigned Non-Physical</strong>
|
|
165
|
+
<div v-if="selectedCard?.assigned?.non_physical?.length" class="mt-1">
|
|
166
|
+
<v-chip
|
|
167
|
+
v-for="card in selectedCard.assigned.non_physical"
|
|
168
|
+
:key="card._id"
|
|
169
|
+
size="small"
|
|
170
|
+
class="mr-1 mb-1"
|
|
171
|
+
:color="selectedCardInUnit?._id === card._id ? 'primary' : undefined"
|
|
172
|
+
:variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
|
|
173
|
+
style="cursor: pointer"
|
|
174
|
+
@click="selectedCardInUnit = selectedCardInUnit?._id === card._id ? null : card"
|
|
175
|
+
>
|
|
176
|
+
{{ card.cardNo }}
|
|
177
|
+
</v-chip>
|
|
178
|
+
</div>
|
|
179
|
+
<span v-else class="text-caption text-grey ml-1">None</span>
|
|
108
180
|
</v-col>
|
|
109
181
|
</v-row></v-card-text
|
|
110
182
|
>
|
|
@@ -238,18 +310,38 @@ const props = defineProps({
|
|
|
238
310
|
type: Array as PropType<Array<Record<string, any>>>,
|
|
239
311
|
default: () => [
|
|
240
312
|
{
|
|
241
|
-
title: "
|
|
242
|
-
value: "
|
|
313
|
+
title: "Unit",
|
|
314
|
+
value: "name",
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
title: "Block",
|
|
318
|
+
value: "block.name",
|
|
243
319
|
},
|
|
244
320
|
{
|
|
245
|
-
title: "
|
|
246
|
-
value: "
|
|
321
|
+
title: "Level",
|
|
322
|
+
value: "level.level",
|
|
247
323
|
},
|
|
248
324
|
{
|
|
249
|
-
title: "
|
|
250
|
-
value: "
|
|
325
|
+
title: "Avail. (P)",
|
|
326
|
+
value: "cardCounts.available.physical",
|
|
251
327
|
},
|
|
252
|
-
{
|
|
328
|
+
{
|
|
329
|
+
title: "Avail. (NP)",
|
|
330
|
+
value: "cardCounts.available.non_physical",
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
title: "Asgn. (P)",
|
|
334
|
+
value: "cardCounts.assigned.physical",
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
title: "Asgn. (NP)",
|
|
338
|
+
value: "cardCounts.assigned.non_physical",
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
title: "Total",
|
|
342
|
+
value: "totalCardCount",
|
|
343
|
+
},
|
|
344
|
+
// { title: "Action", value: "action-table" },
|
|
253
345
|
],
|
|
254
346
|
},
|
|
255
347
|
canCreate: {
|
|
@@ -300,32 +392,21 @@ const confirmDialog = ref(false);
|
|
|
300
392
|
const searchText = ref("");
|
|
301
393
|
const replaceDialog = ref(false);
|
|
302
394
|
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
startDate: "",
|
|
311
|
-
endDate: "",
|
|
312
|
-
door: "",
|
|
313
|
-
accessGroup: [],
|
|
314
|
-
cardType: "",
|
|
315
|
-
pinNo: "",
|
|
316
|
-
useAsLiftCard: false,
|
|
317
|
-
liftAccessLevel: "",
|
|
318
|
-
isActivate: true,
|
|
319
|
-
isAntiPassBack: false,
|
|
320
|
-
status: "",
|
|
321
|
-
org: "",
|
|
322
|
-
site: "",
|
|
323
|
-
unit: "",
|
|
324
|
-
assign: "",
|
|
325
|
-
});
|
|
395
|
+
const route = useRoute();
|
|
396
|
+
// const siteId = computed(() => route.params.site as string); @TODO
|
|
397
|
+
const siteId = computed(() => '66ab2f1381856008f1887971' as string);
|
|
398
|
+
const orgId = computed(() => route.params.org as string);
|
|
399
|
+
|
|
400
|
+
const selectedCard = ref<Record<string, any>>({});
|
|
401
|
+
const selectedCardInUnit = ref<Record<string, any> | null>(null);
|
|
326
402
|
const selectedCardId = ref<string | null>(null);
|
|
327
403
|
|
|
328
|
-
|
|
404
|
+
watch(previewDialog, (val) => {
|
|
405
|
+
if (!val) selectedCardInUnit.value = null;
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const { deleteById: _deleteCard } = useCard();
|
|
409
|
+
const { getUserTypeAccessCards } = useAccessManagement();
|
|
329
410
|
|
|
330
411
|
const {
|
|
331
412
|
data: getCardReq,
|
|
@@ -334,10 +415,12 @@ const {
|
|
|
334
415
|
} = useLazyAsyncData(
|
|
335
416
|
"get-all-cards",
|
|
336
417
|
() =>
|
|
337
|
-
|
|
418
|
+
getUserTypeAccessCards({
|
|
338
419
|
page: page.value,
|
|
339
420
|
search: searchText.value,
|
|
340
|
-
|
|
421
|
+
organization: orgId.value,
|
|
422
|
+
site: siteId.value,
|
|
423
|
+
userType: "Visitor/Resident",
|
|
341
424
|
}),
|
|
342
425
|
{
|
|
343
426
|
watch: [page, searchText],
|
|
@@ -347,10 +430,10 @@ const {
|
|
|
347
430
|
const loading = computed(() => getAllReqStatus.value === "pending");
|
|
348
431
|
|
|
349
432
|
watchEffect(() => {
|
|
350
|
-
if (getCardReq.value) {
|
|
351
|
-
items.value = getCardReq.value.items;
|
|
352
|
-
pages.value = getCardReq.value.pages;
|
|
353
|
-
pageRange.value = getCardReq.value.pageRange;
|
|
433
|
+
if (getCardReq.value?.data) {
|
|
434
|
+
items.value = getCardReq.value.data.items;
|
|
435
|
+
pages.value = getCardReq.value.data.pages;
|
|
436
|
+
pageRange.value = getCardReq.value.data.pageRange;
|
|
354
437
|
}
|
|
355
438
|
});
|
|
356
439
|
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-dialog v-model="showDialog" max-width="450">
|
|
3
|
+
<v-card>
|
|
4
|
+
<v-toolbar>
|
|
5
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
6
|
+
<span class="font-weight-bold text-h6 text-capitalize">
|
|
7
|
+
{{ prop.mode === "edit" ? "Edit Supply" : "Add New Supply" }}
|
|
8
|
+
</span>
|
|
9
|
+
</v-row>
|
|
10
|
+
</v-toolbar>
|
|
11
|
+
|
|
12
|
+
<v-card-text class="pa-4">
|
|
13
|
+
<v-form ref="formRef" v-model="valid">
|
|
14
|
+
<v-row no-gutters class="pa-0">
|
|
15
|
+
<v-col cols="12" class="pa-0 mb-2">
|
|
16
|
+
<InputLabel for="name" title="Name" required class="mb-1" />
|
|
17
|
+
<v-text-field
|
|
18
|
+
v-model="nameModel"
|
|
19
|
+
:rules="[requiredRule]"
|
|
20
|
+
density="comfortable"
|
|
21
|
+
variant="outlined"
|
|
22
|
+
placeholder="Enter supply name"
|
|
23
|
+
hide-details="auto"
|
|
24
|
+
class="mb-0"
|
|
25
|
+
/>
|
|
26
|
+
</v-col>
|
|
27
|
+
|
|
28
|
+
<v-col cols="12" class="pa-0 mb-0">
|
|
29
|
+
<InputLabel
|
|
30
|
+
for="unitOfMeasurement"
|
|
31
|
+
title="Unit of Measurement"
|
|
32
|
+
required
|
|
33
|
+
class="mb-1"
|
|
34
|
+
/>
|
|
35
|
+
<v-select
|
|
36
|
+
v-model="unitOfMeasurementModel"
|
|
37
|
+
:items="unitOfMeasurementOptions"
|
|
38
|
+
:rules="[requiredRule]"
|
|
39
|
+
density="comfortable"
|
|
40
|
+
variant="outlined"
|
|
41
|
+
placeholder="Select unitOfMeasurement"
|
|
42
|
+
hide-details="auto"
|
|
43
|
+
class="mb-0"
|
|
44
|
+
/>
|
|
45
|
+
</v-col>
|
|
46
|
+
</v-row>
|
|
47
|
+
</v-form>
|
|
48
|
+
</v-card-text>
|
|
49
|
+
|
|
50
|
+
<v-toolbar class="pa-0" density="compact">
|
|
51
|
+
<v-row no-gutters>
|
|
52
|
+
<v-col cols="6" class="pa-0">
|
|
53
|
+
<v-btn
|
|
54
|
+
block
|
|
55
|
+
variant="text"
|
|
56
|
+
class="text-none"
|
|
57
|
+
size="large"
|
|
58
|
+
@click="close"
|
|
59
|
+
height="48"
|
|
60
|
+
>
|
|
61
|
+
Cancel
|
|
62
|
+
</v-btn>
|
|
63
|
+
</v-col>
|
|
64
|
+
|
|
65
|
+
<v-col cols="6" class="pa-0">
|
|
66
|
+
<v-btn
|
|
67
|
+
block
|
|
68
|
+
variant="flat"
|
|
69
|
+
color="black"
|
|
70
|
+
class="text-none font-weight-bold rounded-0"
|
|
71
|
+
height="48"
|
|
72
|
+
:loading="submitting"
|
|
73
|
+
@click="submit"
|
|
74
|
+
>
|
|
75
|
+
{{ prop.mode === "edit" ? "Save" : "Create" }}
|
|
76
|
+
</v-btn>
|
|
77
|
+
</v-col>
|
|
78
|
+
</v-row>
|
|
79
|
+
</v-toolbar>
|
|
80
|
+
</v-card>
|
|
81
|
+
</v-dialog>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<script setup lang="ts">
|
|
85
|
+
const nameModel = defineModel("name", { type: String, default: "" });
|
|
86
|
+
const unitOfMeasurementModel = defineModel("unitOfMeasurement", {
|
|
87
|
+
type: String,
|
|
88
|
+
default: "",
|
|
89
|
+
});
|
|
90
|
+
const showDialog = defineModel({ type: Boolean, default: false });
|
|
91
|
+
|
|
92
|
+
const prop = defineProps({
|
|
93
|
+
mode: {
|
|
94
|
+
type: String,
|
|
95
|
+
default: "add",
|
|
96
|
+
},
|
|
97
|
+
supplyData: {
|
|
98
|
+
type: Object,
|
|
99
|
+
default: null,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const emit = defineEmits(["saved", "close"]);
|
|
104
|
+
|
|
105
|
+
const formRef = ref<any>(null);
|
|
106
|
+
const valid = ref(false);
|
|
107
|
+
const submitting = ref(false);
|
|
108
|
+
|
|
109
|
+
const { requiredRule } = useUtils();
|
|
110
|
+
|
|
111
|
+
const unitOfMeasurementOptions = [
|
|
112
|
+
"Pieces",
|
|
113
|
+
"Boxes",
|
|
114
|
+
"Bottles",
|
|
115
|
+
"Liters",
|
|
116
|
+
"Kilograms",
|
|
117
|
+
"Grams",
|
|
118
|
+
"Rolls",
|
|
119
|
+
"Packs",
|
|
120
|
+
"Sets",
|
|
121
|
+
"Units",
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
watchEffect(() => {
|
|
125
|
+
nameModel.value = prop.supplyData?.name || "";
|
|
126
|
+
unitOfMeasurementModel.value = prop.supplyData?.unitOfMeasurement || "";
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
function close() {
|
|
130
|
+
showDialog.value = false;
|
|
131
|
+
emit("close");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function submit() {
|
|
135
|
+
const form = formRef.value as any;
|
|
136
|
+
let ok = valid.value;
|
|
137
|
+
if (form && typeof form.validate === "function") {
|
|
138
|
+
const result = await form.validate();
|
|
139
|
+
ok = result.valid;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!ok) return;
|
|
143
|
+
|
|
144
|
+
submitting.value = true;
|
|
145
|
+
try {
|
|
146
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
147
|
+
|
|
148
|
+
emit("saved", {
|
|
149
|
+
name: nameModel.value,
|
|
150
|
+
|
|
151
|
+
unitOfMeasurement: unitOfMeasurementModel.value,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
nameModel.value = "";
|
|
155
|
+
unitOfMeasurementModel.value = "";
|
|
156
|
+
|
|
157
|
+
showDialog.value = false;
|
|
158
|
+
emit("close");
|
|
159
|
+
} catch (e) {
|
|
160
|
+
console.error("Error submitting form:", e);
|
|
161
|
+
} finally {
|
|
162
|
+
submitting.value = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
</script>
|