@7365admin1/layer-common 3.0.31-staging.23 → 3.1.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/AddEqupmentForm.vue +1 -52
- package/components/AddPassKeyToVisitor.vue +53 -115
- package/components/DashboardMain.vue +87 -231
- package/components/EquipmentManagementMain.vue +0 -56
- package/components/InvitationMain.vue +3 -4
- package/components/ManageChecklistMain.vue +25 -32
- package/components/Nfc/NFCPatrolReportMain.vue +38 -128
- package/components/Nfc/PatrolReport/DailyReportTab.vue +6 -10
- package/components/Nfc/PatrolReport/MonthlyReportTab.vue +9 -19
- package/components/Nfc/PatrolReport/PatrolReportTab.vue +3 -5
- package/components/Nfc/PatrolReport/ReportFilters.vue +18 -50
- package/components/PhotoUpload.vue +4 -19
- package/components/ServiceProviderMain.vue +29 -46
- package/components/VisitorForm.vue +182 -19
- package/components/VisitorManagement.vue +30 -109
- package/composables/useCleaningSchedulePermission.ts +51 -16
- package/composables/useEquipment.ts +0 -2
- package/composables/useLocalAuth.ts +1 -1
- package/composables/useNFCPatrolDailyReport.ts +4 -1
- package/composables/useNFCPatrolMonthlyReport.ts +30 -62
- 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 -15
- package/components/Nfc/PatrolReport/MonthlyReportTable.vue +0 -69
package/CHANGELOG.md
CHANGED
|
@@ -12,24 +12,6 @@
|
|
|
12
12
|
<v-card-text class="pa-4">
|
|
13
13
|
<v-form ref="formRef" v-model="valid">
|
|
14
14
|
<v-row no-gutters class="pa-0">
|
|
15
|
-
<v-col cols="12" class="pa-0 mb-2">
|
|
16
|
-
<PhotoUpload
|
|
17
|
-
v-model="attachmentPhotos"
|
|
18
|
-
v-model:photo-ids="attachmentIds"
|
|
19
|
-
title="Photo"
|
|
20
|
-
@error="photoUploadError = $event"
|
|
21
|
-
/>
|
|
22
|
-
|
|
23
|
-
<v-alert
|
|
24
|
-
v-if="photoUploadError"
|
|
25
|
-
type="error"
|
|
26
|
-
density="compact"
|
|
27
|
-
variant="tonal"
|
|
28
|
-
class="mt-2"
|
|
29
|
-
>
|
|
30
|
-
{{ photoUploadError }}
|
|
31
|
-
</v-alert>
|
|
32
|
-
</v-col>
|
|
33
15
|
<v-col cols="12" class="pa-0 mb-2">
|
|
34
16
|
<InputLabel for="name" title="Name" required class="mb-1" />
|
|
35
17
|
<v-text-field
|
|
@@ -105,10 +87,6 @@ const unitOfMeasurementModel = defineModel("unitOfMeasurement", {
|
|
|
105
87
|
type: String,
|
|
106
88
|
default: "",
|
|
107
89
|
});
|
|
108
|
-
const attachmentModel = defineModel("attachment", {
|
|
109
|
-
type: String,
|
|
110
|
-
default: "",
|
|
111
|
-
});
|
|
112
90
|
const showDialog = defineModel({ type: Boolean, default: false });
|
|
113
91
|
|
|
114
92
|
const prop = defineProps({
|
|
@@ -127,9 +105,6 @@ const emit = defineEmits(["saved", "close"]);
|
|
|
127
105
|
const formRef = ref<any>(null);
|
|
128
106
|
const valid = ref(false);
|
|
129
107
|
const submitting = ref(false);
|
|
130
|
-
const attachmentPhotos = ref<string[]>([]);
|
|
131
|
-
const attachmentIds = ref<string[]>([]);
|
|
132
|
-
const photoUploadError = ref("");
|
|
133
108
|
|
|
134
109
|
const { requiredRule } = useUtils();
|
|
135
110
|
|
|
@@ -149,29 +124,6 @@ const unitOfMeasurementOptions = [
|
|
|
149
124
|
watchEffect(() => {
|
|
150
125
|
nameModel.value = prop.equipmentData?.name || "";
|
|
151
126
|
unitOfMeasurementModel.value = prop.equipmentData?.unitOfMeasurement || "";
|
|
152
|
-
attachmentModel.value = prop.equipmentData?.attachment || "";
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
watch(
|
|
156
|
-
attachmentIds,
|
|
157
|
-
(photoIds) => {
|
|
158
|
-
const [attachmentId] = photoIds;
|
|
159
|
-
attachmentModel.value = attachmentId || "";
|
|
160
|
-
|
|
161
|
-
if (photoIds.length > 1) {
|
|
162
|
-
attachmentIds.value = attachmentId ? [attachmentId] : [];
|
|
163
|
-
attachmentPhotos.value = attachmentPhotos.value.slice(0, 1);
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
{ deep: true }
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
watch(showDialog, (isOpen) => {
|
|
170
|
-
if (!isOpen) {
|
|
171
|
-
attachmentPhotos.value = [];
|
|
172
|
-
attachmentIds.value = [];
|
|
173
|
-
photoUploadError.value = "";
|
|
174
|
-
}
|
|
175
127
|
});
|
|
176
128
|
|
|
177
129
|
function close() {
|
|
@@ -195,15 +147,12 @@ async function submit() {
|
|
|
195
147
|
|
|
196
148
|
emit("saved", {
|
|
197
149
|
name: nameModel.value,
|
|
150
|
+
|
|
198
151
|
unitOfMeasurement: unitOfMeasurementModel.value,
|
|
199
|
-
attachment: attachmentModel.value,
|
|
200
152
|
});
|
|
201
153
|
|
|
202
154
|
nameModel.value = "";
|
|
203
155
|
unitOfMeasurementModel.value = "";
|
|
204
|
-
attachmentModel.value = "";
|
|
205
|
-
attachmentPhotos.value = [];
|
|
206
|
-
attachmentIds.value = [];
|
|
207
156
|
|
|
208
157
|
showDialog.value = false;
|
|
209
158
|
emit("close");
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
color="blue"
|
|
33
33
|
variant="tonal"
|
|
34
34
|
size="small"
|
|
35
|
+
closable
|
|
36
|
+
@click:close="
|
|
37
|
+
existingPassToBeReplaced = existingPass;
|
|
38
|
+
existingPass = null;
|
|
39
|
+
"
|
|
35
40
|
>
|
|
36
41
|
{{ existingPass.prefixAndName }}
|
|
37
42
|
</v-chip>
|
|
@@ -40,9 +45,9 @@
|
|
|
40
45
|
|
|
41
46
|
<!-- New pass selector -->
|
|
42
47
|
<v-autocomplete
|
|
48
|
+
v-if="!existingPass"
|
|
43
49
|
v-model="selectedPass"
|
|
44
50
|
v-model:search="passInput"
|
|
45
|
-
:label="existingPass?.keyId ? 'Change pass' : undefined"
|
|
46
51
|
:hide-no-data="false"
|
|
47
52
|
:items="passItems"
|
|
48
53
|
item-title="prefixAndName"
|
|
@@ -80,20 +85,20 @@
|
|
|
80
85
|
class="d-flex flex-wrap ga-1 mb-2"
|
|
81
86
|
>
|
|
82
87
|
<v-chip
|
|
83
|
-
v-for="key in existingKeys
|
|
88
|
+
v-for="key in existingKeys"
|
|
84
89
|
:key="key.keyId"
|
|
85
90
|
prepend-icon="mdi-key"
|
|
86
91
|
color="orange"
|
|
87
92
|
variant="tonal"
|
|
88
93
|
size="small"
|
|
89
94
|
closable
|
|
90
|
-
@click:close="removeExistingKey(key)"
|
|
95
|
+
@click:close="removeExistingKey(key.keyId)"
|
|
91
96
|
>
|
|
92
97
|
{{ key.prefixAndName }}
|
|
93
98
|
</v-chip>
|
|
94
|
-
<span class="text-caption text-medium-emphasis align-self-center"
|
|
95
|
-
(current)
|
|
96
|
-
|
|
99
|
+
<span class="text-caption text-medium-emphasis align-self-center"
|
|
100
|
+
>(current)</span
|
|
101
|
+
>
|
|
97
102
|
</div>
|
|
98
103
|
|
|
99
104
|
<!-- New keys selector -->
|
|
@@ -111,8 +116,6 @@
|
|
|
111
116
|
density="compact"
|
|
112
117
|
small-chips
|
|
113
118
|
:loading="fetchKeysPending"
|
|
114
|
-
clearable
|
|
115
|
-
@update:model-value="selectKeys"
|
|
116
119
|
>
|
|
117
120
|
<template v-slot:chip="{ props: chipProps, item }">
|
|
118
121
|
<v-chip
|
|
@@ -202,7 +205,7 @@ const processing = ref(false);
|
|
|
202
205
|
const errorMessage = ref("");
|
|
203
206
|
|
|
204
207
|
// New selections
|
|
205
|
-
const selectedPass = ref<string
|
|
208
|
+
const selectedPass = ref<string>("");
|
|
206
209
|
const selectedKeys = ref<string[]>([]);
|
|
207
210
|
const passInput = ref("");
|
|
208
211
|
const keyInput = ref("");
|
|
@@ -210,15 +213,12 @@ const passItems = ref<TPassKey[]>([]);
|
|
|
210
213
|
const keyItems = ref<TPassKey[]>([]);
|
|
211
214
|
|
|
212
215
|
// Existing pass/keys (editable)
|
|
213
|
-
const existingPass = ref<{
|
|
216
|
+
const existingPass = ref<{ keyId: string; prefixAndName: string } | null>(null);
|
|
217
|
+
const existingPassToBeReplaced = ref<{
|
|
214
218
|
keyId: string;
|
|
215
219
|
prefixAndName: string;
|
|
216
|
-
status?: string;
|
|
217
220
|
} | null>(null);
|
|
218
|
-
|
|
219
|
-
const existingKeys = ref<
|
|
220
|
-
{ keyId: string; prefixAndName: string; status?: string }[]
|
|
221
|
-
>([]);
|
|
221
|
+
const existingKeys = ref<{ keyId: string; prefixAndName: string }[]>([]);
|
|
222
222
|
|
|
223
223
|
const isEditMode = computed(() => prop.mode === "edit");
|
|
224
224
|
const showKeys = computed(() => prop.visitor.type === "contractor");
|
|
@@ -237,82 +237,28 @@ const passTypesComputed = computed(() => {
|
|
|
237
237
|
// Initialise existing values in edit mode
|
|
238
238
|
onMounted(() => {
|
|
239
239
|
if (isEditMode.value) {
|
|
240
|
-
const vPass = prop.visitor.visitorPass
|
|
241
|
-
(i) => i.status != "Removed"
|
|
242
|
-
);
|
|
240
|
+
const vPass = prop.visitor.visitorPass;
|
|
243
241
|
if (Array.isArray(vPass) && vPass.length > 0) {
|
|
244
242
|
const p = vPass[0] as any;
|
|
245
|
-
existingPass.value = {
|
|
246
|
-
keyId: p.keyId,
|
|
247
|
-
prefixAndName: p.prefixAndName,
|
|
248
|
-
status: p.status,
|
|
249
|
-
};
|
|
243
|
+
existingPass.value = { keyId: p.keyId, prefixAndName: p.prefixAndName };
|
|
250
244
|
}
|
|
251
|
-
const vKeys = prop.visitor.passKeys
|
|
245
|
+
const vKeys = prop.visitor.passKeys;
|
|
252
246
|
if (Array.isArray(vKeys) && vKeys.length > 0) {
|
|
253
247
|
existingKeys.value = (vKeys as any[]).map((k) => ({
|
|
254
248
|
keyId: k.keyId,
|
|
255
249
|
prefixAndName: k.prefixAndName,
|
|
256
|
-
status: k.status,
|
|
257
250
|
}));
|
|
258
251
|
}
|
|
259
252
|
}
|
|
260
253
|
});
|
|
261
254
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
function removeExistingKey(key: Record<string, any>) {
|
|
265
|
-
const originalKey = existingKeys.value.find((k) => k.keyId === key.keyId);
|
|
266
|
-
|
|
267
|
-
if (
|
|
268
|
-
originalKey &&
|
|
269
|
-
!previouslyRemovedKeys.value.some((k: any) => k.keyId === key.keyId)
|
|
270
|
-
) {
|
|
271
|
-
previouslyRemovedKeys.value.push({ ...originalKey });
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
existingKeys.value = existingKeys.value.map((i) => {
|
|
275
|
-
if (i.keyId === key.keyId) {
|
|
276
|
-
return {
|
|
277
|
-
...i,
|
|
278
|
-
status: "Removed",
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
return i;
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function selectKeys() {
|
|
286
|
-
const currentSelections = [...selectedKeys.value];
|
|
287
|
-
|
|
288
|
-
currentSelections.forEach((selectedId) => {
|
|
289
|
-
const removedMatch = previouslyRemovedKeys.value.find(
|
|
290
|
-
(k: any) => k.keyId === selectedId
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
if (removedMatch) {
|
|
294
|
-
existingKeys.value = existingKeys.value.map((i) => {
|
|
295
|
-
if (i.keyId === selectedId) {
|
|
296
|
-
return {
|
|
297
|
-
...i,
|
|
298
|
-
status: removedMatch.status,
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
return i;
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
previouslyRemovedKeys.value = previouslyRemovedKeys.value.filter(
|
|
305
|
-
(k: any) => k.keyId !== selectedId
|
|
306
|
-
);
|
|
307
|
-
|
|
308
|
-
selectedKeys.value = selectedKeys.value.filter((id) => id !== selectedId);
|
|
309
|
-
}
|
|
310
|
-
});
|
|
255
|
+
function removeExistingKey(keyId: string) {
|
|
256
|
+
existingKeys.value = existingKeys.value.filter((k) => k.keyId !== keyId);
|
|
311
257
|
}
|
|
312
258
|
|
|
313
259
|
// Exclude already-held pass/keys from selectable lists
|
|
314
260
|
const existingPassId = computed(() => existingPass.value?.keyId);
|
|
315
|
-
|
|
261
|
+
const existingKeyIds = computed(() => existingKeys.value.map((k) => k.keyId));
|
|
316
262
|
|
|
317
263
|
const {
|
|
318
264
|
data: passesData,
|
|
@@ -348,50 +294,43 @@ const {
|
|
|
348
294
|
})
|
|
349
295
|
);
|
|
350
296
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
297
|
+
watch(passesData, (data: any) => {
|
|
298
|
+
const all: TPassKey[] = Array.isArray(data?.items) ? data.items : [];
|
|
299
|
+
passItems.value = all.filter((p) => p._id !== existingPassId.value);
|
|
300
|
+
});
|
|
355
301
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
302
|
+
watch(keysData, (data: any) => {
|
|
303
|
+
const all: TPassKey[] = Array.isArray(data?.items) ? data.items : [];
|
|
304
|
+
keyItems.value = all.filter((k) => !existingKeyIds.value.includes(k._id!));
|
|
305
|
+
});
|
|
360
306
|
|
|
361
307
|
// Re-filter when existing items change
|
|
362
308
|
watch(
|
|
363
|
-
[existingPassId,
|
|
309
|
+
[existingPassId, existingKeyIds],
|
|
364
310
|
() => {
|
|
365
311
|
const rawPasses = (passesData.value as any)?.items ?? [];
|
|
366
312
|
passItems.value = rawPasses.filter(
|
|
367
313
|
(p: TPassKey) => p._id !== existingPassId.value
|
|
368
314
|
);
|
|
369
|
-
|
|
370
315
|
const rawKeys = (keysData.value as any)?.items ?? [];
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
.map((k) => ({
|
|
374
|
-
_id: k.keyId,
|
|
375
|
-
prefixAndName: k.prefixAndName,
|
|
376
|
-
}));
|
|
377
|
-
|
|
378
|
-
const allExistingKeyIds = existingKeys.value.map((k) => k.keyId);
|
|
379
|
-
|
|
380
|
-
const filteredRawKeys = rawKeys.filter(
|
|
381
|
-
(k: TPassKey) => !allExistingKeyIds.includes(k._id!)
|
|
316
|
+
keyItems.value = rawKeys.filter(
|
|
317
|
+
(k: TPassKey) => !existingKeyIds.value.includes(k._id!)
|
|
382
318
|
);
|
|
383
|
-
|
|
384
|
-
keyItems.value = [...filteredRawKeys, ...manuallyRemovedKeys];
|
|
385
|
-
console.log("keyItems: ", keyItems.value);
|
|
386
319
|
},
|
|
387
|
-
{ deep: true
|
|
320
|
+
{ deep: true }
|
|
388
321
|
);
|
|
389
322
|
|
|
390
323
|
const canSubmit = computed(() => {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
324
|
+
if (isEditMode.value) {
|
|
325
|
+
// allow save if anything changed: existing items modified OR new items selected
|
|
326
|
+
return (
|
|
327
|
+
existingPass.value !== null ||
|
|
328
|
+
selectedPass.value ||
|
|
329
|
+
existingKeys.value.length > 0 ||
|
|
330
|
+
selectedKeys.value.length > 0
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
return !!selectedPass.value || selectedKeys.value.length > 0;
|
|
395
334
|
});
|
|
396
335
|
|
|
397
336
|
async function handleSubmit() {
|
|
@@ -404,13 +343,16 @@ async function handleSubmit() {
|
|
|
404
343
|
|
|
405
344
|
// Build final pass list: kept existing + newly selected
|
|
406
345
|
const finalPasses: { keyId: string; status?: string; add?: boolean }[] = [];
|
|
346
|
+
if (existingPass.value) {
|
|
347
|
+
finalPasses.push({ keyId: existingPass.value.keyId, status: "Removed" });
|
|
348
|
+
}
|
|
349
|
+
if (existingPassToBeReplaced.value) {
|
|
350
|
+
finalPasses.push({
|
|
351
|
+
keyId: existingPassToBeReplaced.value.keyId,
|
|
352
|
+
status: "Removed",
|
|
353
|
+
});
|
|
354
|
+
}
|
|
407
355
|
if (selectedPass.value) {
|
|
408
|
-
if (existingPass.value) {
|
|
409
|
-
finalPasses.push({
|
|
410
|
-
keyId: existingPass.value.keyId,
|
|
411
|
-
status: "Removed",
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
356
|
finalPasses.push({
|
|
415
357
|
keyId: selectedPass.value,
|
|
416
358
|
status: "Not Returned",
|
|
@@ -422,17 +364,13 @@ async function handleSubmit() {
|
|
|
422
364
|
// Build final keys list: kept existing + newly selected
|
|
423
365
|
if (showKeys.value) {
|
|
424
366
|
const finalKeys: { keyId: string; status?: string; add?: boolean }[] = [
|
|
425
|
-
...existingKeys.value.map((k) => ({
|
|
426
|
-
keyId: k.keyId,
|
|
427
|
-
status: k.status,
|
|
428
|
-
})),
|
|
367
|
+
...existingKeys.value.map((k) => ({ keyId: k.keyId })),
|
|
429
368
|
...selectedKeys.value.map((keyId) => ({
|
|
430
369
|
keyId,
|
|
431
370
|
status: "Not Returned",
|
|
432
371
|
add: true,
|
|
433
372
|
})),
|
|
434
373
|
];
|
|
435
|
-
|
|
436
374
|
payload.passKeys = finalKeys;
|
|
437
375
|
}
|
|
438
376
|
|