@7365admin1/layer-common 3.1.2-staging.37 → 3.1.2
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/.github/workflows/publish-staging.yml +0 -11
- package/CHANGELOG.md +6 -0
- package/components/AddEqupmentForm.vue +1 -52
- package/components/CameraMain.vue +6 -5
- package/components/DashboardMain.vue +87 -231
- package/components/EquipmentManagementMain.vue +0 -56
- package/components/InvitationMain.vue +3 -4
- package/components/ManageChecklistMain.vue +38 -44
- package/components/Nfc/NFCPatrolReportMain.vue +38 -146
- package/components/Nfc/PatrolReport/DailyReportTab.vue +6 -10
- package/components/Nfc/PatrolReport/MonthlyReportTab.vue +9 -19
- package/components/Nfc/PatrolReport/PatrolActivityTable.vue +0 -20
- package/components/Nfc/PatrolReport/PatrolReportTab.vue +3 -5
- package/components/Nfc/PatrolReport/ReportFilters.vue +20 -52
- package/components/Nfc/PatrolReport/SummaryReportTable.vue +0 -22
- package/components/PhotoUpload.vue +4 -19
- package/components/ServiceProviderMain.vue +29 -46
- package/components/VisitorForm.vue +18 -78
- package/components/VisitorManagement.vue +16 -12
- package/composables/useCleaningSchedulePermission.ts +51 -16
- package/composables/useEquipment.ts +0 -2
- package/composables/useLocalAuth.ts +1 -1
- package/composables/useNFCPatrolDailyReport.ts +4 -3
- package/composables/useNFCPatrolMonthlyReport.ts +30 -62
- package/composables/useNFCPatrolReport.ts +0 -2
- package/package.json +1 -1
- package/types/customer.d.ts +1 -2
- package/types/equipment.d.ts +1 -5
- package/types/nfc-patrol-report.ts +1 -19
- package/components/Nfc/PatrolReport/MonthlyReportTable.vue +0 -69
- package/components/Nfc/PatrolReport/ReportDatePicker.vue +0 -61
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
:model-value="filters"
|
|
5
5
|
:options="options"
|
|
6
6
|
@update:model-value="$emit('update:filters', $event)"
|
|
7
|
-
@export="
|
|
7
|
+
@export="$emit('export')"
|
|
8
8
|
/>
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
<v-divider :thickness="1" class="border-opacity-100" />
|
|
11
11
|
|
|
12
12
|
<template v-if="report">
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
<ReportEmptyState v-else-if="!loading" />
|
|
31
31
|
|
|
32
32
|
<RemarksDialog v-model="dialogRemarks" :remarks="selectedActivityRemarks" />
|
|
33
|
-
</div>
|
|
34
33
|
</div>
|
|
35
34
|
</template>
|
|
36
35
|
|
|
@@ -56,7 +55,7 @@ const props = defineProps<{
|
|
|
56
55
|
|
|
57
56
|
defineEmits<{
|
|
58
57
|
"update:filters": [value: NFCPatrolReportFilters];
|
|
59
|
-
export: [
|
|
58
|
+
export: [];
|
|
60
59
|
}>();
|
|
61
60
|
|
|
62
61
|
const {
|
|
@@ -78,5 +77,4 @@ watch(
|
|
|
78
77
|
},
|
|
79
78
|
{ immediate: true },
|
|
80
79
|
);
|
|
81
|
-
|
|
82
80
|
</script>
|
|
@@ -16,12 +16,7 @@
|
|
|
16
16
|
/>
|
|
17
17
|
</v-col>
|
|
18
18
|
|
|
19
|
-
<v-col
|
|
20
|
-
v-if="showTimeFilter"
|
|
21
|
-
cols="12"
|
|
22
|
-
md="2"
|
|
23
|
-
class="px-md-2 mb-2 mb-md-0"
|
|
24
|
-
>
|
|
19
|
+
<v-col cols="12" md="2" class="px-md-2 mb-2 mb-md-0">
|
|
25
20
|
<v-select
|
|
26
21
|
:model-value="modelValue.timeRange"
|
|
27
22
|
:items="options.timeRanges"
|
|
@@ -35,14 +30,10 @@
|
|
|
35
30
|
/>
|
|
36
31
|
</v-col>
|
|
37
32
|
|
|
38
|
-
<v-col
|
|
39
|
-
v-
|
|
40
|
-
cols="12"
|
|
41
|
-
md="2"
|
|
42
|
-
class="px-md-2 mb-2 mb-md-0"
|
|
43
|
-
>
|
|
44
|
-
<ReportDatePicker
|
|
33
|
+
<v-col cols="12" md="2" class="px-md-2 mb-2 mb-md-0">
|
|
34
|
+
<v-text-field
|
|
45
35
|
:model-value="modelValue.date"
|
|
36
|
+
type="date"
|
|
46
37
|
variant="outlined"
|
|
47
38
|
density="comfortable"
|
|
48
39
|
rounded="lg"
|
|
@@ -55,31 +46,17 @@
|
|
|
55
46
|
<v-spacer />
|
|
56
47
|
|
|
57
48
|
<v-col cols="12" md="2" class="pl-md-2">
|
|
58
|
-
<v-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Export
|
|
70
|
-
</v-btn>
|
|
71
|
-
</template>
|
|
72
|
-
|
|
73
|
-
<v-list density="compact">
|
|
74
|
-
<v-list-item @click="$emit('export', 'pdf')">
|
|
75
|
-
<v-list-item-title>PDF</v-list-item-title>
|
|
76
|
-
</v-list-item>
|
|
77
|
-
|
|
78
|
-
<v-list-item @click="$emit('export', 'csv')">
|
|
79
|
-
<v-list-item-title>CSV</v-list-item-title>
|
|
80
|
-
</v-list-item>
|
|
81
|
-
</v-list>
|
|
82
|
-
</v-menu>
|
|
49
|
+
<v-btn
|
|
50
|
+
variant="outlined"
|
|
51
|
+
block
|
|
52
|
+
size="large"
|
|
53
|
+
rounded="lg"
|
|
54
|
+
class="text-none"
|
|
55
|
+
prepend-icon="mdi-export"
|
|
56
|
+
@click="$emit('export')"
|
|
57
|
+
>
|
|
58
|
+
Export
|
|
59
|
+
</v-btn>
|
|
83
60
|
</v-col>
|
|
84
61
|
</v-row>
|
|
85
62
|
</template>
|
|
@@ -89,24 +66,15 @@ import type {
|
|
|
89
66
|
NFCPatrolReportFilterOptions,
|
|
90
67
|
NFCPatrolReportFilters,
|
|
91
68
|
} from "../../../types/nfc-patrol-report";
|
|
92
|
-
import ReportDatePicker from "./ReportDatePicker.vue";
|
|
93
69
|
|
|
94
|
-
const props =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
showTimeFilter?: boolean;
|
|
99
|
-
showDateFilter?: boolean;
|
|
100
|
-
}>(),
|
|
101
|
-
{
|
|
102
|
-
showTimeFilter: true,
|
|
103
|
-
showDateFilter: true,
|
|
104
|
-
},
|
|
105
|
-
);;
|
|
70
|
+
const props = defineProps<{
|
|
71
|
+
modelValue: NFCPatrolReportFilters;
|
|
72
|
+
options: NFCPatrolReportFilterOptions;
|
|
73
|
+
}>();
|
|
106
74
|
|
|
107
75
|
const emit = defineEmits<{
|
|
108
76
|
"update:modelValue": [value: NFCPatrolReportFilters];
|
|
109
|
-
export: [
|
|
77
|
+
export: [];
|
|
110
78
|
}>();
|
|
111
79
|
|
|
112
80
|
function updateFilter(key: keyof NFCPatrolReportFilters, value: unknown) {
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
<tr>
|
|
9
9
|
<th>Patrol Route Name</th>
|
|
10
10
|
<th>Security Check Schedule</th>
|
|
11
|
-
<th>Security Personnel</th>
|
|
12
|
-
<th>Signature</th>
|
|
13
11
|
<th>Checked</th>
|
|
14
12
|
<th>Missed</th>
|
|
15
13
|
<th>Status</th>
|
|
@@ -22,17 +20,6 @@
|
|
|
22
20
|
<v-icon size="small" class="mr-1">mdi-clock-outline</v-icon>
|
|
23
21
|
{{ row.securityCheckSchedule }}
|
|
24
22
|
</td>
|
|
25
|
-
<td>{{ row.guardName || "-" }}</td>
|
|
26
|
-
<td>
|
|
27
|
-
<v-img
|
|
28
|
-
v-if="row.guardSignatureFileId"
|
|
29
|
-
:src="getFileUrl(row.guardSignatureFileId)"
|
|
30
|
-
:alt="`${row.guardName || 'Guard'} signature`"
|
|
31
|
-
class="guard-signature"
|
|
32
|
-
contain
|
|
33
|
-
/>
|
|
34
|
-
<span v-else>-</span>
|
|
35
|
-
</td>
|
|
36
23
|
<td>{{ row.checked }}</td>
|
|
37
24
|
<td>{{ row.missed }}</td>
|
|
38
25
|
<td>
|
|
@@ -58,16 +45,7 @@ defineProps<{
|
|
|
58
45
|
rows: NFCPatrolReportSummaryRow[];
|
|
59
46
|
}>();
|
|
60
47
|
|
|
61
|
-
const { getFileUrl } = useFile();
|
|
62
|
-
|
|
63
48
|
function statusClass(status: NFCPatrolReportSummaryStatus) {
|
|
64
49
|
return status === "Completed" ? "text-success" : "text-error";
|
|
65
50
|
}
|
|
66
51
|
</script>
|
|
67
|
-
|
|
68
|
-
<style scoped>
|
|
69
|
-
.guard-signature {
|
|
70
|
-
width: 80px;
|
|
71
|
-
height: 40px;
|
|
72
|
-
}
|
|
73
|
-
</style>
|
|
@@ -59,21 +59,6 @@
|
|
|
59
59
|
</v-col>
|
|
60
60
|
</v-row>
|
|
61
61
|
|
|
62
|
-
<v-dialog v-model="showPhotoPreview" max-width="900">
|
|
63
|
-
<v-card>
|
|
64
|
-
<v-card-actions class="pa-2 justify-end">
|
|
65
|
-
<v-btn
|
|
66
|
-
icon="mdi-close"
|
|
67
|
-
variant="text"
|
|
68
|
-
@click="showPhotoPreview = false"
|
|
69
|
-
/>
|
|
70
|
-
</v-card-actions>
|
|
71
|
-
<v-card-text class="pa-2 pt-0">
|
|
72
|
-
<v-img :src="selectedPhoto" contain max-height="80vh" />
|
|
73
|
-
</v-card-text>
|
|
74
|
-
</v-card>
|
|
75
|
-
</v-dialog>
|
|
76
|
-
|
|
77
62
|
<v-dialog v-model="photoOptionsDialog" max-width="420">
|
|
78
63
|
<v-card>
|
|
79
64
|
<v-card-title class="d-flex align-center pa-4">
|
|
@@ -211,8 +196,6 @@ const photos = ref<string[]>([...props.modelValue]);
|
|
|
211
196
|
const photosIds = ref<string[]>([...props.photoIds]);
|
|
212
197
|
const photoOptionsDialog = ref(false);
|
|
213
198
|
const showCameraDialog = ref(false);
|
|
214
|
-
const showPhotoPreview = ref(false);
|
|
215
|
-
const selectedPhoto = ref("");
|
|
216
199
|
const videoRef = ref<HTMLVideoElement | null>(null);
|
|
217
200
|
const canvasRef = ref<HTMLCanvasElement | null>(null);
|
|
218
201
|
const fileInputRef = ref<HTMLInputElement | null>(null);
|
|
@@ -222,8 +205,10 @@ const uploading = ref(false);
|
|
|
222
205
|
const { addFile } = useFile();
|
|
223
206
|
|
|
224
207
|
function viewPhoto(photoData: string) {
|
|
225
|
-
|
|
226
|
-
|
|
208
|
+
const link = document.createElement("a");
|
|
209
|
+
link.href = photoData;
|
|
210
|
+
link.target = "_blank";
|
|
211
|
+
link.click();
|
|
227
212
|
}
|
|
228
213
|
|
|
229
214
|
watch(
|
|
@@ -548,7 +548,7 @@
|
|
|
548
548
|
variant="flat"
|
|
549
549
|
class="text-none sp-invite-submit-btn"
|
|
550
550
|
height="76"
|
|
551
|
-
:disabled="!
|
|
551
|
+
:disabled="!validServiceProvider"
|
|
552
552
|
:loading="disableServiceProvider"
|
|
553
553
|
@click="submitServiceProviderInvite()"
|
|
554
554
|
>
|
|
@@ -574,7 +574,6 @@ type ListTab = "active" | "pending" | "inactive";
|
|
|
574
574
|
|
|
575
575
|
type TableRow = {
|
|
576
576
|
_id: string;
|
|
577
|
-
userId: string;
|
|
578
577
|
serviceProviderOrgId: string;
|
|
579
578
|
companyName: string;
|
|
580
579
|
email: string;
|
|
@@ -734,10 +733,11 @@ const {
|
|
|
734
733
|
updateStatus: updateServiceProviderStatus,
|
|
735
734
|
invite,
|
|
736
735
|
} = useServiceProvider();
|
|
737
|
-
const {
|
|
736
|
+
const { getAll: getAllMembers } = useMember();
|
|
738
737
|
|
|
739
738
|
const { getVerifications, cancelUserInvitation, getVerificationByEmail } =
|
|
740
739
|
useVerification();
|
|
740
|
+
const { getOrgsByMembership } = useMember();
|
|
741
741
|
|
|
742
742
|
const existingAccount = ref<any>(null);
|
|
743
743
|
const checkingExistingAccount = ref(false);
|
|
@@ -757,10 +757,11 @@ const createInviteDialog = ref(false);
|
|
|
757
757
|
// const loadingInviteRoles = ref(false);
|
|
758
758
|
// const serviceProviderInviteRoles = ref<Array<Record<string, any>>>([]);
|
|
759
759
|
|
|
760
|
+
const { getByUserType } = useMember();
|
|
761
|
+
const { getOrgs } = useOrg();
|
|
760
762
|
|
|
761
763
|
async function checkExistingAccount(email: string) {
|
|
762
764
|
existingAccount.value = null;
|
|
763
|
-
messageServiceProvider.value = "";
|
|
764
765
|
|
|
765
766
|
if (!email.trim() || emailRule(email) !== true) return;
|
|
766
767
|
|
|
@@ -769,50 +770,30 @@ async function checkExistingAccount(email: string) {
|
|
|
769
770
|
try {
|
|
770
771
|
const user = await getUserByEmail(email);
|
|
771
772
|
|
|
772
|
-
if (!user?._id) return;
|
|
773
|
-
|
|
774
|
-
const members = await getAllByUserId(user._id);
|
|
775
|
-
|
|
776
|
-
const appMember = (members.items ?? []).find(
|
|
777
|
-
(member: any) => member.type === serviceProviderInvite.value.app
|
|
778
|
-
);
|
|
779
|
-
|
|
780
|
-
if (!appMember) {
|
|
781
|
-
existingAccount.value = null;
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
773
|
+
if (!user?._id) return;
|
|
784
774
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
) {
|
|
789
|
-
existingAccount.value = null;
|
|
790
|
-
messageServiceProvider.value =
|
|
791
|
-
"This user is already a member of this service provider.";
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
775
|
+
const orgs = await getOrgs({
|
|
776
|
+
user: user._id,
|
|
777
|
+
});
|
|
794
778
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
org: appMember.org,
|
|
799
|
-
orgName: appMember.orgName,
|
|
800
|
-
siteId: appMember.siteId,
|
|
801
|
-
siteName: appMember.siteName,
|
|
802
|
-
};
|
|
779
|
+
const matchedOrg = orgs.items?.find(
|
|
780
|
+
(org: any) => org.type === serviceProviderInvite.value.app
|
|
781
|
+
);
|
|
803
782
|
|
|
783
|
+
if (matchedOrg) {
|
|
784
|
+
existingAccount.value = {
|
|
785
|
+
_id: matchedOrg.value,
|
|
786
|
+
text: matchedOrg.text,
|
|
787
|
+
...matchedOrg,
|
|
788
|
+
};
|
|
789
|
+
}
|
|
804
790
|
} catch (error) {
|
|
805
791
|
existingAccount.value = null;
|
|
806
792
|
} finally {
|
|
807
793
|
checkingExistingAccount.value = false;
|
|
808
794
|
}
|
|
809
795
|
}
|
|
810
|
-
|
|
811
|
-
return (
|
|
812
|
-
validServiceProvider.value &&
|
|
813
|
-
!messageServiceProvider.value
|
|
814
|
-
);
|
|
815
|
-
});
|
|
796
|
+
|
|
816
797
|
watch(
|
|
817
798
|
() => serviceProviderInvite.value.email,
|
|
818
799
|
async (value) => {
|
|
@@ -958,7 +939,6 @@ function formatEmailCell(value: unknown): string {
|
|
|
958
939
|
function mapProviderRows(raw: Record<string, any>[]): TableRow[] {
|
|
959
940
|
return raw.map((row) => ({
|
|
960
941
|
_id: String(row._id ?? ""),
|
|
961
|
-
userId: String(row.user ?? ""),
|
|
962
942
|
serviceProviderOrgId: String(row.serviceProviderOrgId ?? ""),
|
|
963
943
|
companyName: row.name ?? "-",
|
|
964
944
|
email: formatEmailCell(row.email),
|
|
@@ -981,7 +961,6 @@ function inviteTypeLabel(t: string) {
|
|
|
981
961
|
function mapInviteRows(raw: Record<string, any>[]): TableRow[] {
|
|
982
962
|
return raw.map((row) => ({
|
|
983
963
|
_id: String(row._id ?? ""),
|
|
984
|
-
userId: String(row.user ?? ""),
|
|
985
964
|
serviceProviderOrgId: String(row.metadata?.serviceProviderOrgId ?? ""),
|
|
986
965
|
companyName: row.metadata?.name || "-",
|
|
987
966
|
email: formatEmailCell(row.email),
|
|
@@ -1050,12 +1029,16 @@ async function openView(row: TableRow) {
|
|
|
1050
1029
|
|
|
1051
1030
|
loadingMembers.value = true;
|
|
1052
1031
|
try {
|
|
1053
|
-
const data = await
|
|
1054
|
-
|
|
1032
|
+
const data = await getAllMembers({
|
|
1033
|
+
page: 1,
|
|
1034
|
+
limit: 1000,
|
|
1035
|
+
org: row.serviceProviderOrgId,
|
|
1036
|
+
status: "active",
|
|
1037
|
+
});
|
|
1055
1038
|
serviceProviderMembers.value = (data.items ?? []).map((member: any) => ({
|
|
1056
|
-
_id: member._id,
|
|
1057
|
-
name: member.name || "-",
|
|
1058
|
-
role: member.role || "-",
|
|
1039
|
+
_id: String(member._id ?? ""),
|
|
1040
|
+
name: member.name || member.fullName || member.email || "-",
|
|
1041
|
+
role: member.roleName || member.role?.name || "-",
|
|
1059
1042
|
}));
|
|
1060
1043
|
} catch (error: any) {
|
|
1061
1044
|
showMessage(errorConverter(error), "error");
|
|
@@ -36,17 +36,10 @@
|
|
|
36
36
|
</template>
|
|
37
37
|
|
|
38
38
|
<v-list v-if="nricSearchResults.length" class="pa-1 phone-search-results">
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
</v-list-item>
|
|
44
|
-
</div>
|
|
45
|
-
<div class="search-results-close pa-1">
|
|
46
|
-
<v-btn block variant="flat" color="red" @click.stop="closeAutofillSearchResults('nric')">
|
|
47
|
-
Close
|
|
48
|
-
</v-btn>
|
|
49
|
-
</div>
|
|
39
|
+
<v-list-item v-for="(item, index) in nricSearchResults" :key="item._id || index"
|
|
40
|
+
@click="selectNricSearchResult(item)" class="cursor-pointer nric-search-item">
|
|
41
|
+
<VisitorSearchResultSummary :item="item" />
|
|
42
|
+
</v-list-item>
|
|
50
43
|
</v-list>
|
|
51
44
|
</v-menu>
|
|
52
45
|
</v-col>
|
|
@@ -65,17 +58,10 @@
|
|
|
65
58
|
</template>
|
|
66
59
|
|
|
67
60
|
<v-list v-if="phoneSearchResults.length" class="pa-1 phone-search-results">
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</v-list-item>
|
|
73
|
-
</div>
|
|
74
|
-
<div class="search-results-close pa-1">
|
|
75
|
-
<v-btn block variant="flat" color="red" @click.stop="closeAutofillSearchResults('contact')">
|
|
76
|
-
Close
|
|
77
|
-
</v-btn>
|
|
78
|
-
</div>
|
|
61
|
+
<v-list-item v-for="(item, index) in phoneSearchResults" :key="item._id || index"
|
|
62
|
+
@click="selectPhoneNumberSearchResult(item)" class="cursor-pointer nric-search-item">
|
|
63
|
+
<VisitorSearchResultSummary :item="item" />
|
|
64
|
+
</v-list-item>
|
|
79
65
|
</v-list>
|
|
80
66
|
</v-menu>
|
|
81
67
|
</v-col>
|
|
@@ -91,23 +77,15 @@
|
|
|
91
77
|
<v-menu v-model="vehicleSearchMenu" location="bottom" offset-y :close-on-content-click="false">
|
|
92
78
|
<template #activator="{ props }">
|
|
93
79
|
<InputVehicleNumber v-bind="props" v-model="visitor.plateNumber" density="comfortable"
|
|
94
|
-
@update:model-value="handleUpdateVehicleNumber" @focus="
|
|
80
|
+
@update:model-value="handleUpdateVehicleNumber" @focus="isPlateNumberFieldFocused = true"
|
|
95
81
|
@blur="isPlateNumberFieldFocused = false" />
|
|
96
82
|
</template>
|
|
97
83
|
|
|
98
84
|
<v-list v-if="vehicleSearchResults.length" class="pa-1 phone-search-results">
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
</v-list-item>
|
|
104
|
-
</div>
|
|
105
|
-
<div class="search-results-close pa-1">
|
|
106
|
-
<v-btn block variant="flat" color="red"
|
|
107
|
-
@click.stop="closeAutofillSearchResults('vehicleNumber')">
|
|
108
|
-
Close
|
|
109
|
-
</v-btn>
|
|
110
|
-
</div>
|
|
85
|
+
<v-list-item v-for="(item, index) in vehicleSearchResults" :key="item._id || index"
|
|
86
|
+
@click="selectPlateNumberSearchResult(item)" class="cursor-pointer nric-search-item">
|
|
87
|
+
<VisitorSearchResultSummary :item="item" />
|
|
88
|
+
</v-list-item>
|
|
111
89
|
</v-list>
|
|
112
90
|
</v-menu>
|
|
113
91
|
</v-col>
|
|
@@ -330,10 +308,10 @@
|
|
|
330
308
|
|
|
331
309
|
<div class="nric-selected-person d-flex align-center justify-space-between ga-3 mb-5">
|
|
332
310
|
<span>{{ selectedNricSearchResult.name || "Unknown" }}</span>
|
|
333
|
-
<span
|
|
311
|
+
<span class="text-no-wrap">NRIC: {{ selectedNricSearchResult.nric || "N/A" }}</span>
|
|
334
312
|
</div>
|
|
335
313
|
|
|
336
|
-
<template v-if="
|
|
314
|
+
<template v-if="!visitor.contact && selectedNricContactOptions.length >= 1">
|
|
337
315
|
<h3 class="nric-options-section-title font-weight-bold mb-2">Contact</h3>
|
|
338
316
|
<v-radio-group v-model="selectedNricContact" hide-details color="success" class="nric-option-group">
|
|
339
317
|
<v-radio v-for="contact in selectedNricContactOptions" :key="contact" :label="contact" :value="contact"
|
|
@@ -341,7 +319,7 @@
|
|
|
341
319
|
</v-radio-group>
|
|
342
320
|
</template>
|
|
343
321
|
|
|
344
|
-
<template v-if="
|
|
322
|
+
<template v-if="!visitor.plateNumber && selectedNricPlateOptions.length >= 1">
|
|
345
323
|
<h3 class="nric-options-section-title font-weight-bold mb-2 mt-5">Vehicle</h3>
|
|
346
324
|
<v-radio-group v-model="selectedNricPlate" hide-details color="success" class="nric-option-group">
|
|
347
325
|
<v-radio v-for="plate in selectedNricPlateOptions" :key="plate" :label="plate" :value="plate"
|
|
@@ -1066,8 +1044,8 @@ function selectAutofillSearchResult(item: Partial<TPeople>, source: Exclude<Auto
|
|
|
1066
1044
|
const selectedPlate =
|
|
1067
1045
|
findMatchingPlateOption(plateOptions, visitor.plateNumber) || plateOptions[0] || "";
|
|
1068
1046
|
|
|
1069
|
-
const needsContactChoice =
|
|
1070
|
-
const needsPlateChoice =
|
|
1047
|
+
const needsContactChoice = !visitor.contact?.trim() && contactOptions.length > 1;
|
|
1048
|
+
const needsPlateChoice = !visitor.plateNumber?.trim() && plateOptions.length > 1;
|
|
1071
1049
|
|
|
1072
1050
|
if (needsContactChoice || needsPlateChoice) {
|
|
1073
1051
|
nricSearchMenu.value = false;
|
|
@@ -1088,23 +1066,6 @@ function selectAutofillSearchResult(item: Partial<TPeople>, source: Exclude<Auto
|
|
|
1088
1066
|
});
|
|
1089
1067
|
}
|
|
1090
1068
|
|
|
1091
|
-
function closeAutofillSearchResults(source: Exclude<AutofillSource, null>) {
|
|
1092
|
-
if (source === "nric") {
|
|
1093
|
-
nricSearchMenu.value = false;
|
|
1094
|
-
nricSearchResults.value = [];
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
if (source === "contact") {
|
|
1098
|
-
phoneSearchMenu.value = false;
|
|
1099
|
-
phoneSearchResults.value = [];
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
if (source === "vehicleNumber") {
|
|
1103
|
-
vehicleSearchMenu.value = false;
|
|
1104
|
-
vehicleSearchResults.value = [];
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
1069
|
function closeNricAutofillOptions() {
|
|
1109
1070
|
dialog.nricAutofillOptions = false;
|
|
1110
1071
|
selectedNricSearchResult.value = null;
|
|
@@ -1542,15 +1503,6 @@ function handleUpdateVehicleNumber() {
|
|
|
1542
1503
|
debounceFetchPlateNumber();
|
|
1543
1504
|
}
|
|
1544
1505
|
|
|
1545
|
-
const handleFocusPlateNumber = () => {
|
|
1546
|
-
isPlateNumberFieldFocused.value = true;
|
|
1547
|
-
if (prop.mode === 'register') {
|
|
1548
|
-
|
|
1549
|
-
handleUpdateVehicleNumber();
|
|
1550
|
-
}
|
|
1551
|
-
};
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
1506
|
function backToSelection() {
|
|
1555
1507
|
emit("back");
|
|
1556
1508
|
message.value = "";
|
|
@@ -2156,22 +2108,10 @@ onMounted(() => {
|
|
|
2156
2108
|
}
|
|
2157
2109
|
|
|
2158
2110
|
.phone-search-results {
|
|
2159
|
-
display: flex;
|
|
2160
|
-
flex-direction: column;
|
|
2161
2111
|
max-height: 400px;
|
|
2162
|
-
overflow: hidden;
|
|
2163
|
-
}
|
|
2164
|
-
|
|
2165
|
-
.search-results-scroll {
|
|
2166
|
-
flex: 1 1 auto;
|
|
2167
|
-
min-height: 0;
|
|
2168
2112
|
overflow-y: auto;
|
|
2169
2113
|
}
|
|
2170
2114
|
|
|
2171
|
-
.search-results-close {
|
|
2172
|
-
flex: 0 0 auto;
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
2115
|
.nric-options-card {
|
|
2176
2116
|
border-radius: 16px !important;
|
|
2177
2117
|
}
|
|
@@ -825,8 +825,10 @@
|
|
|
825
825
|
item-title="label"
|
|
826
826
|
item-value="value"
|
|
827
827
|
v-model="pass.status"
|
|
828
|
-
:disabled="
|
|
829
|
-
|
|
828
|
+
:disabled="
|
|
829
|
+
selectedVisitorObject.checkOut || pass.status == 'Removed'
|
|
830
|
+
"
|
|
831
|
+
></v-select>
|
|
830
832
|
<v-textarea
|
|
831
833
|
v-if="pass.status === 'Lost' || pass.status === 'Damaged'"
|
|
832
834
|
no-resize
|
|
@@ -834,7 +836,8 @@
|
|
|
834
836
|
class="w-100"
|
|
835
837
|
density="compact"
|
|
836
838
|
v-model="pass.remarks"
|
|
837
|
-
|
|
839
|
+
:disabled="selectedVisitorObject.checkOut"
|
|
840
|
+
></v-textarea>
|
|
838
841
|
</v-row>
|
|
839
842
|
</div>
|
|
840
843
|
<div v-if="keyReturnStatuses.length > 0" class="mb-2">
|
|
@@ -861,8 +864,10 @@
|
|
|
861
864
|
item-title="label"
|
|
862
865
|
item-value="value"
|
|
863
866
|
v-model="key.status"
|
|
864
|
-
:disabled="
|
|
865
|
-
|
|
867
|
+
:disabled="
|
|
868
|
+
selectedVisitorObject.checkOut || key.status == 'Removed'
|
|
869
|
+
"
|
|
870
|
+
></v-select>
|
|
866
871
|
<v-textarea
|
|
867
872
|
v-if="key.status === 'Lost' || key.status === 'Damaged'"
|
|
868
873
|
no-resize
|
|
@@ -870,7 +875,8 @@
|
|
|
870
875
|
class="w-100"
|
|
871
876
|
density="compact"
|
|
872
877
|
v-model="key.remarks"
|
|
873
|
-
|
|
878
|
+
:disabled="selectedVisitorObject.checkOut"
|
|
879
|
+
></v-textarea>
|
|
874
880
|
</v-row>
|
|
875
881
|
</div>
|
|
876
882
|
|
|
@@ -880,11 +886,11 @@
|
|
|
880
886
|
color="blue"
|
|
881
887
|
density="comfortable"
|
|
882
888
|
class="text-capitalize"
|
|
889
|
+
:disabled="selectedVisitorObject.checkOut"
|
|
883
890
|
:loading="loading.updatingPassKeys"
|
|
884
891
|
@click.stop="handleUpdatePassKeys"
|
|
892
|
+
>Update Pass/Keys</v-btn
|
|
885
893
|
>
|
|
886
|
-
Update Pass/Keys
|
|
887
|
-
</v-btn>
|
|
888
894
|
</v-row>
|
|
889
895
|
</v-card-text>
|
|
890
896
|
<v-toolbar class="pa-0" density="compact">
|
|
@@ -894,9 +900,8 @@
|
|
|
894
900
|
variant="text"
|
|
895
901
|
block
|
|
896
902
|
@click="dialog.returnPassesKeys = false"
|
|
903
|
+
>Close</v-btn
|
|
897
904
|
>
|
|
898
|
-
Close
|
|
899
|
-
</v-btn>
|
|
900
905
|
</v-col>
|
|
901
906
|
<v-col cols="6">
|
|
902
907
|
<v-btn
|
|
@@ -910,9 +915,8 @@
|
|
|
910
915
|
!canConfirmCheckout || selectedVisitorObject.checkOut
|
|
911
916
|
"
|
|
912
917
|
@click="proceedCheckout"
|
|
918
|
+
>Confirm Checkout</v-btn
|
|
913
919
|
>
|
|
914
|
-
Confirm Checkout
|
|
915
|
-
</v-btn>
|
|
916
920
|
</v-col>
|
|
917
921
|
</v-row>
|
|
918
922
|
</v-toolbar>
|