@7365admin1/layer-common 1.11.39 → 1.11.41
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
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 1.11.41
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- bc096ed: Fix navigation not get children item
|
|
8
|
+
- 5031c18: Update Vehicle Management
|
|
9
|
+
|
|
10
|
+
## 1.11.40
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 91ae5da: Update Verification Status
|
|
15
|
+
|
|
3
16
|
## 1.11.39
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
|
@@ -5,6 +5,96 @@
|
|
|
5
5
|
:site-id="siteId"
|
|
6
6
|
/>
|
|
7
7
|
|
|
8
|
+
<!-- Assign to Person Dialog -->
|
|
9
|
+
<v-dialog :model-value="showAssignForm" width="420" persistent>
|
|
10
|
+
<v-card width="100%">
|
|
11
|
+
<v-toolbar density="compact" color="surface">
|
|
12
|
+
<v-row no-gutters class="fill-height px-4" align="center">
|
|
13
|
+
<span class="font-weight-bold">Assign Card to Person</span>
|
|
14
|
+
</v-row>
|
|
15
|
+
</v-toolbar>
|
|
16
|
+
|
|
17
|
+
<v-card-text class="pa-4">
|
|
18
|
+
<div class="text-caption text-grey mb-4">
|
|
19
|
+
Card: <strong class="text-body-2 text-black">{{ selectedCardInUnit?.cardNo }}</strong>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Person Type Filter -->
|
|
23
|
+
<div class="text-caption font-weight-bold mb-1 text-uppercase text-grey-darken-1">Person Type</div>
|
|
24
|
+
<v-btn-toggle
|
|
25
|
+
v-model="assignPersonType"
|
|
26
|
+
color="primary"
|
|
27
|
+
density="compact"
|
|
28
|
+
variant="outlined"
|
|
29
|
+
rounded="pill"
|
|
30
|
+
class="mb-4"
|
|
31
|
+
>
|
|
32
|
+
<v-btn value="" size="small" class="text-none px-3">All</v-btn>
|
|
33
|
+
<v-btn value="owner" size="small" class="text-none px-3">Unit Owner</v-btn>
|
|
34
|
+
<v-btn value="resident" size="small" class="text-none px-3">Resident</v-btn>
|
|
35
|
+
<v-btn value="tenant" size="small" class="text-none px-3">Tenant</v-btn>
|
|
36
|
+
</v-btn-toggle>
|
|
37
|
+
|
|
38
|
+
<!-- Person Selector -->
|
|
39
|
+
<div class="text-caption font-weight-bold mb-1 text-uppercase text-grey-darken-1">
|
|
40
|
+
Person <span class="text-error">*</span>
|
|
41
|
+
</div>
|
|
42
|
+
<v-autocomplete
|
|
43
|
+
v-model="assignPerson"
|
|
44
|
+
:items="filteredPeopleItems"
|
|
45
|
+
density="compact"
|
|
46
|
+
item-title="name"
|
|
47
|
+
item-value="_id"
|
|
48
|
+
hide-details="auto"
|
|
49
|
+
placeholder="Select person..."
|
|
50
|
+
persistent-placeholder
|
|
51
|
+
:loading="peopleLoading"
|
|
52
|
+
return-object
|
|
53
|
+
no-data-text="No residents or tenants found for this unit"
|
|
54
|
+
>
|
|
55
|
+
<template #item="{ props: itemProps, item }">
|
|
56
|
+
<v-list-item v-bind="itemProps" :subtitle="personTypeLabel(item.raw)" />
|
|
57
|
+
</template>
|
|
58
|
+
<template #selection="{ item }">
|
|
59
|
+
<span>{{ item.raw.name }}</span>
|
|
60
|
+
<v-chip size="x-small" class="ml-2" color="grey" variant="tonal">
|
|
61
|
+
{{ personTypeLabel(item.raw) }}
|
|
62
|
+
</v-chip>
|
|
63
|
+
</template>
|
|
64
|
+
</v-autocomplete>
|
|
65
|
+
</v-card-text>
|
|
66
|
+
|
|
67
|
+
<v-toolbar density="compact">
|
|
68
|
+
<v-row no-gutters>
|
|
69
|
+
<v-col cols="6" class="pa-0">
|
|
70
|
+
<v-btn
|
|
71
|
+
block
|
|
72
|
+
variant="text"
|
|
73
|
+
class="text-none"
|
|
74
|
+
height="48"
|
|
75
|
+
@click="cancelAssign"
|
|
76
|
+
>
|
|
77
|
+
Cancel
|
|
78
|
+
</v-btn>
|
|
79
|
+
</v-col>
|
|
80
|
+
<v-col cols="6" class="pa-0">
|
|
81
|
+
<v-btn
|
|
82
|
+
block
|
|
83
|
+
variant="flat"
|
|
84
|
+
color="black"
|
|
85
|
+
class="text-none"
|
|
86
|
+
height="48"
|
|
87
|
+
:disabled="!assignPerson"
|
|
88
|
+
@click="confirmAssign"
|
|
89
|
+
>
|
|
90
|
+
Assign
|
|
91
|
+
</v-btn>
|
|
92
|
+
</v-col>
|
|
93
|
+
</v-row>
|
|
94
|
+
</v-toolbar>
|
|
95
|
+
</v-card>
|
|
96
|
+
</v-dialog>
|
|
97
|
+
|
|
8
98
|
<v-dialog :model-value="modelValue" width="450" persistent>
|
|
9
99
|
<v-card width="100%">
|
|
10
100
|
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
|
|
@@ -211,6 +301,14 @@
|
|
|
211
301
|
</v-btn>
|
|
212
302
|
</template>
|
|
213
303
|
<v-list class="pa-0">
|
|
304
|
+
<v-list-item
|
|
305
|
+
v-if="canAssignToPerson && isSelectedCardAvailable"
|
|
306
|
+
@click="openAssignForm"
|
|
307
|
+
>
|
|
308
|
+
<v-list-item-title class="text-subtitle-2">
|
|
309
|
+
Assign to Person
|
|
310
|
+
</v-list-item-title>
|
|
311
|
+
</v-list-item>
|
|
214
312
|
<v-list-item
|
|
215
313
|
:disabled="!isSelectedCardAssignedPhysical"
|
|
216
314
|
@click="emit('replace')"
|
|
@@ -270,6 +368,10 @@ const props = defineProps({
|
|
|
270
368
|
type: Boolean,
|
|
271
369
|
default: true,
|
|
272
370
|
},
|
|
371
|
+
canAssignToPerson: {
|
|
372
|
+
type: Boolean,
|
|
373
|
+
default: true,
|
|
374
|
+
},
|
|
273
375
|
isSelectedCardAssignedPhysical: {
|
|
274
376
|
type: Boolean,
|
|
275
377
|
default: false,
|
|
@@ -289,9 +391,26 @@ const emit = defineEmits<{
|
|
|
289
391
|
"update:selectedCardInUnit": [value: Record<string, any> | null];
|
|
290
392
|
replace: [];
|
|
291
393
|
delete: [];
|
|
394
|
+
"assign-to-person": [{ card: Record<string, any> | null; person: Record<string, any> | null }];
|
|
292
395
|
}>();
|
|
293
396
|
|
|
397
|
+
const { getPeopleByUnit: _getPeopleByUnit } = usePeople();
|
|
398
|
+
|
|
294
399
|
const historyDialog = ref(false);
|
|
400
|
+
const showAssignForm = ref(false);
|
|
401
|
+
const assignPersonType = ref<string>("");
|
|
402
|
+
const assignPerson = ref<Record<string, any> | null>(null);
|
|
403
|
+
const peopleItems = ref<Record<string, any>[]>([]);
|
|
404
|
+
const peopleLoading = ref(false);
|
|
405
|
+
|
|
406
|
+
const isSelectedCardAvailable = computed(() => {
|
|
407
|
+
if (!props.selectedCardInUnit?._id) return false;
|
|
408
|
+
const id = props.selectedCardInUnit._id;
|
|
409
|
+
return [
|
|
410
|
+
...(props.unit?.available?.physical ?? []),
|
|
411
|
+
...(props.unit?.available?.non_physical ?? []),
|
|
412
|
+
].some((c) => c._id === id);
|
|
413
|
+
});
|
|
295
414
|
|
|
296
415
|
const isSelectedCardDeletable = computed(() => {
|
|
297
416
|
if (!props.selectedCardInUnit?._id) return false;
|
|
@@ -304,6 +423,51 @@ const isSelectedCardDeletable = computed(() => {
|
|
|
304
423
|
].some((c) => c._id === id);
|
|
305
424
|
});
|
|
306
425
|
|
|
426
|
+
const filteredPeopleItems = computed(() => {
|
|
427
|
+
if (!assignPersonType.value) return peopleItems.value;
|
|
428
|
+
if (assignPersonType.value === "owner") return peopleItems.value.filter((p) => p.isOwner);
|
|
429
|
+
return peopleItems.value.filter((p) => p.type === assignPersonType.value && !p.isOwner);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const personTypeLabel = (person: Record<string, any>) => {
|
|
433
|
+
if (person.isOwner) return "Unit Owner";
|
|
434
|
+
if (person.type === "resident") return "Resident";
|
|
435
|
+
if (person.type === "tenant") return "Tenant";
|
|
436
|
+
return person.type ?? "";
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
async function openAssignForm() {
|
|
440
|
+
showAssignForm.value = true;
|
|
441
|
+
assignPerson.value = null;
|
|
442
|
+
assignPersonType.value = "";
|
|
443
|
+
peopleItems.value = [];
|
|
444
|
+
|
|
445
|
+
if (!props.unit?._id) return;
|
|
446
|
+
peopleLoading.value = true;
|
|
447
|
+
try {
|
|
448
|
+
const res = await _getPeopleByUnit(props.unit._id);
|
|
449
|
+
peopleItems.value = res?.data ?? [];
|
|
450
|
+
} catch {
|
|
451
|
+
peopleItems.value = [];
|
|
452
|
+
} finally {
|
|
453
|
+
peopleLoading.value = false;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function cancelAssign() {
|
|
458
|
+
showAssignForm.value = false;
|
|
459
|
+
assignPerson.value = null;
|
|
460
|
+
assignPersonType.value = "";
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function confirmAssign() {
|
|
464
|
+
emit("assign-to-person", {
|
|
465
|
+
card: props.selectedCardInUnit,
|
|
466
|
+
person: assignPerson.value,
|
|
467
|
+
});
|
|
468
|
+
cancelAssign();
|
|
469
|
+
}
|
|
470
|
+
|
|
307
471
|
function toggleCard(card: Record<string, any>) {
|
|
308
472
|
emit(
|
|
309
473
|
"update:selectedCardInUnit",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- LayoutNavigationDrawer.vue -->
|
|
1
2
|
<template>
|
|
2
3
|
<v-navigation-drawer
|
|
3
4
|
v-model="drawer"
|
|
@@ -19,26 +20,19 @@
|
|
|
19
20
|
v-for="(item, index) in props.navigationItems"
|
|
20
21
|
:key="`${item.title}-${index}`"
|
|
21
22
|
location="right"
|
|
23
|
+
:disabled="!item.disabled"
|
|
22
24
|
>
|
|
23
25
|
<template #activator="{ props: tooltipProps }">
|
|
24
26
|
<div v-bind="tooltipProps">
|
|
25
|
-
<NavigationItem
|
|
26
|
-
:
|
|
27
|
-
:icon="item.icon"
|
|
28
|
-
:route="item.route"
|
|
29
|
-
:link="item.link"
|
|
30
|
-
:class="{
|
|
27
|
+
<NavigationItem :title="item.title" :icon="item.icon" :route="item.route" :link="item.link"
|
|
28
|
+
:children="item.children" :class="{
|
|
31
29
|
'opacity-50 pointer-events-none': item.disabled
|
|
32
|
-
}"
|
|
33
|
-
|
|
34
|
-
/>
|
|
30
|
+
}" @click="() => handleClick(item)" />
|
|
31
|
+
|
|
35
32
|
</div>
|
|
36
33
|
</template>
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
<span v-if="item.disabled">
|
|
40
|
-
Please complete onboarding first
|
|
41
|
-
</span>
|
|
35
|
+
<span>Please complete onboarding first</span>
|
|
42
36
|
</v-tooltip>
|
|
43
37
|
|
|
44
38
|
<!-- SERVICES SLOT -->
|
|
@@ -58,9 +52,6 @@ const emit = defineEmits(['navigate'])
|
|
|
58
52
|
const { drawer } = useLocal()
|
|
59
53
|
const { APP_NAME } = useRuntimeConfig().public
|
|
60
54
|
|
|
61
|
-
/**
|
|
62
|
-
* GLOBAL CLICK CONTROL
|
|
63
|
-
*/
|
|
64
55
|
const handleClick = (item: any) => {
|
|
65
56
|
if (item.disabled) return
|
|
66
57
|
emit('navigate', item)
|
|
@@ -53,14 +53,15 @@
|
|
|
53
53
|
<v-col v-if="shouldShowField('nric')" cols="12">
|
|
54
54
|
<InputLabel class="text-capitalize" title="NRIC" required />
|
|
55
55
|
<InputNRICNumber v-model="vehicle.nric" density="comfortable" :rules="[requiredRule]"
|
|
56
|
-
:disabled="disablePrefilledInputs && type !== 'blocklist'" />
|
|
56
|
+
:disabled="disablePrefilledInputs && type !== 'blocklist' && prop.mode !== 'edit'" />
|
|
57
57
|
</v-col>
|
|
58
58
|
|
|
59
59
|
<v-col v-if="shouldShowField('name')" cols="12">
|
|
60
60
|
<v-row>
|
|
61
61
|
<v-col cols="12">
|
|
62
62
|
<InputLabel class="text-capitalize" title="Full Name" required />
|
|
63
|
-
<v-text-field v-model.trim="vehicle.name" density="comfortable" :rules="[requiredRule]"
|
|
63
|
+
<v-text-field v-model.trim="vehicle.name" density="comfortable" :rules="[requiredRule]"
|
|
64
|
+
:disabled="disablePrefilledInputs && type !== 'blocklist' && prop.mode !== 'edit'" />
|
|
64
65
|
</v-col>
|
|
65
66
|
</v-row>
|
|
66
67
|
</v-col>
|
|
@@ -777,6 +778,7 @@ onMounted(() => {
|
|
|
777
778
|
vehicle.start = prop.vehicleData.start || '';
|
|
778
779
|
vehicle.plateNumber = prop.vehicleData.plateNumber
|
|
779
780
|
vehicle.peopleId = prop.vehicleData.peopleId || '';
|
|
781
|
+
vehicle.block = prop.vehicleData.block === 0 ? null : prop.vehicleData.block || null;
|
|
780
782
|
|
|
781
783
|
if(prop.type === "seasonpass"){
|
|
782
784
|
showSubscriptionDateOptions.value = true;
|
|
@@ -141,6 +141,13 @@ export default function useLocalAuth() {
|
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
async function updateVerificationStatus(id: string, status: string) {
|
|
145
|
+
return useNuxtApp().$api<Record<string, any>>(`/api/auth/verification/status`, {
|
|
146
|
+
method: "PATCH",
|
|
147
|
+
body: { id, status },
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
144
151
|
function signUp(email: string, referral: string) {
|
|
145
152
|
return useNuxtApp().$api<Record<string, any>>("/api/auth/sign-up", {
|
|
146
153
|
method: "POST",
|
|
@@ -159,6 +166,7 @@ export default function useLocalAuth() {
|
|
|
159
166
|
resetPassword,
|
|
160
167
|
currentUser,
|
|
161
168
|
verify,
|
|
169
|
+
updateVerificationStatus,
|
|
162
170
|
signUp,
|
|
163
171
|
};
|
|
164
172
|
}
|