@7365admin1/layer-common 4.144.0 → 4.147.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 +65 -4
- package/components/AddPassKeyToVisitor.vue +332 -54
- package/components/AreaChecklistHistoryLogs.vue +2 -2
- package/components/CleaningScheduleMain.vue +2 -2
- package/components/FileInput.vue +4 -0
- package/components/MemberInformation.vue +580 -281
- package/components/NricScanDialog.vue +512 -0
- package/components/PassInformation.vue +11 -2
- package/components/RolePermissionMain.vue +3 -1
- package/components/ScheduleTaskForm.vue +16 -17
- package/components/ScheduleTaskMain.vue +43 -39
- package/components/SubscriptionPlanTable.vue +45 -1
- package/components/TableHygiene.vue +4 -1
- package/components/VisitorForm.vue +1796 -642
- package/components/VisitorFormSelection.vue +51 -18
- package/components/VisitorManagement.vue +1641 -640
- package/components/VisitorPassKeyQRScanner.vue +1 -1
- package/components/VisitorSocketPopUp.vue +72 -23
- package/composables/usePeople.ts +54 -0
- package/composables/useVisitor.ts +4 -2
- package/composables/useVisitorSocket.ts +19 -0
- package/package.json +2 -1
- package/utils/breadcrumb.ts +2 -1
- package/utils/nav-sections.ts +1 -0
- package/utils/nric-card.ts +278 -0
- package/utils/permission-labels.ts +17 -6
- package/utils/role.ts +24 -0
- package/utils/schedule-task.ts +51 -9
- package/utils/visitor-people.ts +262 -0
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
:org-id="orgId"
|
|
6
6
|
:site="site"
|
|
7
7
|
:service-type="serviceType"
|
|
8
|
-
text="
|
|
9
|
-
how-title="How extra
|
|
8
|
+
:text="FEATURE_SUBTITLE"
|
|
9
|
+
how-title="How extra checks work"
|
|
10
10
|
how-key="extra-visits"
|
|
11
11
|
>
|
|
12
12
|
<ol class="sg-steps">
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
that.
|
|
17
17
|
</li>
|
|
18
18
|
<li>
|
|
19
|
-
An <strong>extra
|
|
20
|
-
checklist, in the areas you pick, at the time you set - once,
|
|
21
|
-
repeating (every day, weekdays, chosen days, or monthly).
|
|
19
|
+
An <strong>extra check</strong> adds one more round of ticks to
|
|
20
|
+
that checklist, in the areas you pick, at the time you set - once,
|
|
21
|
+
or repeating (every day, weekdays, chosen days, or monthly).
|
|
22
22
|
</li>
|
|
23
23
|
<li>
|
|
24
|
-
At that time, staff
|
|
25
|
-
|
|
26
|
-
they finish it.
|
|
24
|
+
At that time, staff get a phone notification and see the extra
|
|
25
|
+
check in their app's Daily Checklist, marked "Extra check" with its
|
|
26
|
+
name. They tick each unit as they finish it.
|
|
27
27
|
</li>
|
|
28
28
|
<li>
|
|
29
29
|
Here and in the Daily Checklist you see how it went:
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
</ol>
|
|
34
34
|
<div class="sg-example">
|
|
35
35
|
<strong>Example:</strong> the lobby toilets get busy at lunch. Add
|
|
36
|
-
an extra
|
|
37
|
-
Toilets", set 2:00 pm, every weekday.
|
|
38
|
-
get one more toilet
|
|
36
|
+
an extra check called "Lunch toilet check", pick the area "Lobby
|
|
37
|
+
Toilets", set 2:00 pm, every weekday. Every weekday at 2:00 pm staff
|
|
38
|
+
get one more toilet check, on top of their normal rounds.
|
|
39
39
|
</div>
|
|
40
40
|
<div class="sg-h">What the words mean</div>
|
|
41
41
|
<dl class="sg-legend">
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
</template>
|
|
46
46
|
<template v-for="h in RESULT_HELP" :key="'r' + h.word">
|
|
47
47
|
<dt><StatusChip :status="h.word" :label="h.word" /></dt>
|
|
48
|
-
<dd>Last
|
|
48
|
+
<dd>Last check: {{ h.meaning }}</dd>
|
|
49
49
|
</template>
|
|
50
50
|
</dl>
|
|
51
51
|
</ScheduleGuide>
|
|
52
52
|
<TableMain
|
|
53
|
-
:title="
|
|
53
|
+
:title="FEATURE_NAME"
|
|
54
54
|
:items="items"
|
|
55
55
|
:headers="headers"
|
|
56
56
|
:loading="loading"
|
|
@@ -60,21 +60,21 @@
|
|
|
60
60
|
:pageRange="pageRange"
|
|
61
61
|
@refresh="getTaskRefresh"
|
|
62
62
|
:canCreate="canCreateScheduleTask"
|
|
63
|
-
createLabel="Add Extra
|
|
63
|
+
createLabel="Add Extra Check"
|
|
64
64
|
@create="openFormDialog"
|
|
65
65
|
@row-click="onRowClick"
|
|
66
66
|
>
|
|
67
67
|
<template #no-data>
|
|
68
68
|
<div class="st-empty">
|
|
69
|
-
<strong>No extra
|
|
69
|
+
<strong>No extra checks yet.</strong>
|
|
70
70
|
<span>
|
|
71
71
|
Your Daily Checklist already covers the normal rounds. Add an
|
|
72
|
-
extra
|
|
72
|
+
extra check when an area needs one more check at a set time -
|
|
73
73
|
for example "Lunch toilet check, Lobby Toilets, 2:00 pm every
|
|
74
74
|
weekday".
|
|
75
75
|
</span>
|
|
76
76
|
<span v-if="canCreateScheduleTask">
|
|
77
|
-
Press <strong>Add Extra
|
|
77
|
+
Press <strong>Add Extra Check</strong> above to start. Your
|
|
78
78
|
Areas and Units must be set up first.
|
|
79
79
|
</span>
|
|
80
80
|
</div>
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
variant="flat"
|
|
89
89
|
@click="openFormDialog"
|
|
90
90
|
>
|
|
91
|
-
Add Extra
|
|
91
|
+
Add Extra Check
|
|
92
92
|
</v-btn>
|
|
93
93
|
</v-col>
|
|
94
94
|
|
|
@@ -210,14 +210,14 @@
|
|
|
210
210
|
|
|
211
211
|
<v-dialog v-model="dialogShowMoreActions" width="400" persistent>
|
|
212
212
|
<HygieneUpdateMoreAction
|
|
213
|
-
:title="selectedTask?.title || 'Extra
|
|
213
|
+
:title="selectedTask?.title || 'Extra Check'"
|
|
214
214
|
:canUpdate="canUpdateScheduleTask"
|
|
215
215
|
@close="dialogShowMoreActions = false"
|
|
216
216
|
:canDelete="canDeleteScheduleTask"
|
|
217
|
-
:deleteButtonLabel="'Delete Extra
|
|
217
|
+
:deleteButtonLabel="'Delete Extra Check'"
|
|
218
218
|
@edit="onEditFromMoreAction"
|
|
219
219
|
@delete="onDeleteFromMoreAction"
|
|
220
|
-
:editButtonLabel="'Edit Extra
|
|
220
|
+
:editButtonLabel="'Edit Extra Check'"
|
|
221
221
|
>
|
|
222
222
|
<template #content>
|
|
223
223
|
<v-row no-gutters>
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
|
|
243
243
|
<v-row no-gutters class="mb-2">
|
|
244
244
|
<v-col cols="5" class="text-subtitle-2 font-weight-bold">
|
|
245
|
-
Next
|
|
245
|
+
Next check:
|
|
246
246
|
</v-col>
|
|
247
247
|
<v-col cols="7" class="text-subtitle-2">
|
|
248
248
|
{{ selectedNext || "-" }}
|
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
|
|
252
252
|
<v-row no-gutters class="mb-2">
|
|
253
253
|
<v-col cols="5" class="text-subtitle-2 font-weight-bold">
|
|
254
|
-
Last
|
|
254
|
+
Last check:
|
|
255
255
|
</v-col>
|
|
256
256
|
<v-col cols="7" class="text-subtitle-2">
|
|
257
257
|
{{ lastRunLabel(selectedTask) }}
|
|
@@ -375,7 +375,7 @@
|
|
|
375
375
|
</div>
|
|
376
376
|
<span v-else class="text-caption text-disabled"
|
|
377
377
|
>No units in this area, so it is skipped when
|
|
378
|
-
this
|
|
378
|
+
this check is added.</span
|
|
379
379
|
>
|
|
380
380
|
</v-card-text>
|
|
381
381
|
</div>
|
|
@@ -388,7 +388,7 @@
|
|
|
388
388
|
|
|
389
389
|
<v-row v-if="selectedTask.description" no-gutters class="mb-2">
|
|
390
390
|
<v-col cols="5" class="text-subtitle-2 font-weight-bold">
|
|
391
|
-
|
|
391
|
+
Instructions:
|
|
392
392
|
</v-col>
|
|
393
393
|
<v-col cols="7" class="text-subtitle-2">
|
|
394
394
|
{{ selectedTask.description || "N/A" }}
|
|
@@ -441,11 +441,11 @@
|
|
|
441
441
|
<v-dialog v-model="dialogDeleteTask" max-width="520">
|
|
442
442
|
<v-card class="screen-modal">
|
|
443
443
|
<v-card-title class="text-capitalize">
|
|
444
|
-
Delete {{ selectedTask?.title || "Extra
|
|
444
|
+
Delete {{ selectedTask?.title || "Extra Check" }}
|
|
445
445
|
</v-card-title>
|
|
446
446
|
|
|
447
447
|
<v-card-text class="screen-modal__body">
|
|
448
|
-
This stops all future extra
|
|
448
|
+
This stops all future extra checks from it. Checks that already
|
|
449
449
|
happened stay on their Daily Checklists. Delete it?
|
|
450
450
|
</v-card-text>
|
|
451
451
|
|
|
@@ -487,6 +487,8 @@ import {
|
|
|
487
487
|
RESULT_HELP,
|
|
488
488
|
STATUS_HELP,
|
|
489
489
|
STATUS_LABELS,
|
|
490
|
+
FEATURE_NAME,
|
|
491
|
+
FEATURE_SUBTITLE,
|
|
490
492
|
describeRow,
|
|
491
493
|
describeWhen,
|
|
492
494
|
finishedReason,
|
|
@@ -526,7 +528,7 @@ const canViewScheduleTaskDetails = computed(
|
|
|
526
528
|
|
|
527
529
|
const checklistRoute = scheduleNameFor(props.serviceType).route;
|
|
528
530
|
|
|
529
|
-
/** Opens the Daily Checklist filtered to the day this extra
|
|
531
|
+
/** Opens the Daily Checklist filtered to the day this extra check was last added. */
|
|
530
532
|
function openChecklist(row: Record<string, any>) {
|
|
531
533
|
const day = String(row?.lastRun || "").slice(0, 10);
|
|
532
534
|
navigateTo({
|
|
@@ -593,10 +595,10 @@ watch(dialogShowMoreActions, async (isOpen) => {
|
|
|
593
595
|
const items = ref<any[]>([]);
|
|
594
596
|
|
|
595
597
|
const headers = [
|
|
596
|
-
{ title: "Extra
|
|
597
|
-
{ title: "
|
|
598
|
-
{ title: "Next
|
|
599
|
-
{ title: "Last
|
|
598
|
+
{ title: "Extra check", value: "title" },
|
|
599
|
+
{ title: "When and where", value: "when", sortable: false },
|
|
600
|
+
{ title: "Next check", value: "nextRun", sortable: false },
|
|
601
|
+
{ title: "Last check", value: "lastRun", sortable: false },
|
|
600
602
|
{ title: "Status", value: "status", sortable: false },
|
|
601
603
|
{ title: "", value: "actions", sortable: false, align: "end" as const },
|
|
602
604
|
];
|
|
@@ -660,7 +662,9 @@ const debounceSearch = debounce(getTaskRefresh, 500);
|
|
|
660
662
|
watch(
|
|
661
663
|
[searchInput],
|
|
662
664
|
() => {
|
|
663
|
-
|
|
665
|
+
// A search on page 2 must not land on an empty page: start from page 1.
|
|
666
|
+
if (page.value !== 1) page.value = 1;
|
|
667
|
+
else debounceSearch();
|
|
664
668
|
},
|
|
665
669
|
{ immediate: false, deep: true }
|
|
666
670
|
);
|
|
@@ -679,7 +683,7 @@ function onEditRow(item: Record<string, any>) {
|
|
|
679
683
|
showForm.value = true;
|
|
680
684
|
}
|
|
681
685
|
|
|
682
|
-
// A finished extra
|
|
686
|
+
// A finished extra check: open its "When" step so a new end date or repeat is one change away.
|
|
683
687
|
function onExtendRow(item: Record<string, any>) {
|
|
684
688
|
selectedTask.value = item;
|
|
685
689
|
formMode.value = "edit";
|
|
@@ -699,14 +703,14 @@ async function togglePause(item: Record<string, any>) {
|
|
|
699
703
|
await setScheduleTaskPaused(item._id, !resuming);
|
|
700
704
|
showMessage(
|
|
701
705
|
resuming
|
|
702
|
-
? "Resumed.
|
|
703
|
-
: "Paused.
|
|
706
|
+
? "Resumed. It is added again from its next date."
|
|
707
|
+
: "Paused. Nothing is added to staff's checklist until you resume it.",
|
|
704
708
|
"success",
|
|
705
709
|
);
|
|
706
710
|
await getTaskRefresh();
|
|
707
711
|
} catch (error: any) {
|
|
708
712
|
showMessage(
|
|
709
|
-
error?.data?.message || "Could not change this extra
|
|
713
|
+
error?.data?.message || "Could not change this extra check.",
|
|
710
714
|
"error",
|
|
711
715
|
);
|
|
712
716
|
} finally {
|
|
@@ -756,12 +760,12 @@ async function _deleteScheduleTask() {
|
|
|
756
760
|
|
|
757
761
|
const response = await deleteScheduleTask(id);
|
|
758
762
|
dialogDeleteTask.value = false;
|
|
759
|
-
showMessage("Extra
|
|
763
|
+
showMessage("Extra check deleted. Past checks are kept.", "success");
|
|
760
764
|
|
|
761
765
|
await getTaskRefresh();
|
|
762
766
|
} catch (error: any) {
|
|
763
767
|
showMessage(
|
|
764
|
-
error?.data?.message || "Could not delete this extra
|
|
768
|
+
error?.data?.message || "Could not delete this extra check.",
|
|
765
769
|
"error",
|
|
766
770
|
);
|
|
767
771
|
} finally {
|
|
@@ -163,7 +163,11 @@
|
|
|
163
163
|
"
|
|
164
164
|
value="toggle-status"
|
|
165
165
|
class="text-body-2"
|
|
166
|
-
@click="
|
|
166
|
+
@click="
|
|
167
|
+
item.status === 'active'
|
|
168
|
+
? (planToDeactivate = item)
|
|
169
|
+
: togglePlanStatus(item)
|
|
170
|
+
"
|
|
167
171
|
/>
|
|
168
172
|
</v-list>
|
|
169
173
|
</v-card>
|
|
@@ -197,6 +201,32 @@
|
|
|
197
201
|
/>
|
|
198
202
|
</v-dialog>
|
|
199
203
|
|
|
204
|
+
<ConfirmDialog
|
|
205
|
+
:model-value="!!planToDeactivate"
|
|
206
|
+
@update:model-value="(v: boolean) => { if (!v) planToDeactivate = null; }"
|
|
207
|
+
>
|
|
208
|
+
<template #title>Deactivate plan</template>
|
|
209
|
+
<template #description>
|
|
210
|
+
Deactivate {{ planToDeactivate?.name || "this plan" }}? You can activate
|
|
211
|
+
it again from the Deactivated tab.
|
|
212
|
+
</template>
|
|
213
|
+
<template #footer>
|
|
214
|
+
<v-spacer />
|
|
215
|
+
<v-btn
|
|
216
|
+
variant="outlined"
|
|
217
|
+
:disabled="isDeactivating"
|
|
218
|
+
@click="planToDeactivate = null"
|
|
219
|
+
>Cancel</v-btn
|
|
220
|
+
>
|
|
221
|
+
<v-btn
|
|
222
|
+
color="error"
|
|
223
|
+
variant="flat"
|
|
224
|
+
:loading="isDeactivating"
|
|
225
|
+
@click="confirmDeactivate"
|
|
226
|
+
>Deactivate</v-btn
|
|
227
|
+
>
|
|
228
|
+
</template>
|
|
229
|
+
</ConfirmDialog>
|
|
200
230
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
201
231
|
</v-container>
|
|
202
232
|
</template>
|
|
@@ -417,6 +447,20 @@ async function handleSubmit(payload: PlanFormState) {
|
|
|
417
447
|
}
|
|
418
448
|
}
|
|
419
449
|
|
|
450
|
+
// Deactivate asks first; Activate stays one tap.
|
|
451
|
+
const planToDeactivate = ref<SubscriptionPlan | null>(null);
|
|
452
|
+
const isDeactivating = ref(false);
|
|
453
|
+
async function confirmDeactivate() {
|
|
454
|
+
if (!planToDeactivate.value) return;
|
|
455
|
+
isDeactivating.value = true;
|
|
456
|
+
try {
|
|
457
|
+
await togglePlanStatus(planToDeactivate.value);
|
|
458
|
+
} finally {
|
|
459
|
+
isDeactivating.value = false;
|
|
460
|
+
planToDeactivate.value = null;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
420
464
|
async function togglePlanStatus(plan: SubscriptionPlan) {
|
|
421
465
|
const nextStatus = plan.status === "active" ? "deactive" : "active";
|
|
422
466
|
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
class="text-none"
|
|
93
93
|
>
|
|
94
94
|
<v-icon size="12">mdi-calendar-clock</v-icon>
|
|
95
|
-
|
|
95
|
+
{{ extraCheckLabel(group) }}
|
|
96
96
|
</StatusChip>
|
|
97
97
|
<slot name="group-header-chips" :group="group">
|
|
98
98
|
<StatusChip
|
|
@@ -206,6 +206,7 @@
|
|
|
206
206
|
</template>
|
|
207
207
|
|
|
208
208
|
<script lang="ts" setup>
|
|
209
|
+
import { extraCheckLabel } from "../utils/schedule-task";
|
|
209
210
|
defineOptions({ inheritAttrs: false });
|
|
210
211
|
|
|
211
212
|
const props = defineProps({
|
|
@@ -296,6 +297,8 @@ const groupedItems = computed(() => {
|
|
|
296
297
|
return {
|
|
297
298
|
set: item.set,
|
|
298
299
|
isScheduleTask: item.isScheduleTask ?? false,
|
|
300
|
+
scheduleTaskTitle: item.scheduleTaskTitle ?? null,
|
|
301
|
+
scheduleTaskTime: item.scheduleTaskTime ?? null,
|
|
299
302
|
completedByName: item.completedByName ?? null,
|
|
300
303
|
attachments:
|
|
301
304
|
(item.attachment as string[] | undefined) ??
|