@7365admin1/layer-common 1.10.7 → 1.10.8
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/{AddSupplyForm.vue → AddEqupmentForm.vue} +5 -5
- package/components/BuildingManagement/units.vue +2 -2
- package/components/BuildingUnitFormAdd.vue +4 -4
- package/components/BuildingUnitFormEdit.vue +114 -68
- package/components/EntryPassInformation.vue +251 -23
- package/components/{CheckoutItemMain.vue → EquipmentItemMain.vue} +88 -85
- package/components/{SupplyManagement.vue → EquipmentManagement.vue} +3 -3
- package/components/Input/DateTimePicker.vue +17 -11
- package/components/ManageChecklistMain.vue +379 -41
- package/components/TableHygiene.vue +42 -452
- package/components/UnitPersonCard.vue +74 -14
- package/components/VisitorForm.vue +77 -21
- package/components/VisitorFormSelection.vue +13 -2
- package/components/VisitorManagement.vue +83 -55
- package/composables/useCleaningPermission.ts +7 -7
- package/composables/useDashboardData.ts +2 -2
- package/composables/{useSupply.ts → useEquipment.ts} +11 -11
- package/composables/{useCheckout.ts → useEquipmentItem.ts} +7 -7
- package/composables/{useCheckoutPermission.ts → useEquipmentItemPermission.ts} +13 -13
- package/composables/useEquipmentManagementPermission.ts +96 -0
- package/composables/{useSupplyPermission.ts → useEquipmentPermission.ts} +9 -9
- package/composables/useVehicle.ts +21 -2
- package/composables/useVisitor.ts +3 -3
- package/composables/useWorkOrder.ts +25 -3
- package/package.json +1 -1
- package/types/building.d.ts +1 -1
- package/types/{checkout-item.d.ts → equipment-item.d.ts} +3 -3
- package/types/{supply.d.ts → equipment.d.ts} +2 -2
- package/types/people.d.ts +3 -1
- package/types/vehicle.d.ts +2 -0
- package/types/visitor.d.ts +2 -1
|
@@ -104,46 +104,34 @@
|
|
|
104
104
|
>
|
|
105
105
|
Schedule Task
|
|
106
106
|
</v-chip>
|
|
107
|
-
<
|
|
108
|
-
v-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
v-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
107
|
+
<slot name="group-header-chips" :group="group">
|
|
108
|
+
<v-chip
|
|
109
|
+
v-if="group.completedByName && isGroupComplete(group)"
|
|
110
|
+
size="x-small"
|
|
111
|
+
color="success"
|
|
112
|
+
variant="tonal"
|
|
113
|
+
prepend-icon="mdi-check-circle-outline"
|
|
114
|
+
class="text-none"
|
|
115
|
+
>
|
|
116
|
+
Completed · {{ group.completedByName }}
|
|
117
|
+
</v-chip>
|
|
118
|
+
<v-chip
|
|
119
|
+
v-else-if="
|
|
120
|
+
group.completedByName && isGroupInProgress(group)
|
|
121
|
+
"
|
|
122
|
+
size="x-small"
|
|
123
|
+
color="warning"
|
|
124
|
+
variant="tonal"
|
|
125
|
+
prepend-icon="mdi-progress-clock"
|
|
126
|
+
class="text-none"
|
|
127
|
+
>
|
|
128
|
+
Ongoing · {{ group.completedByName }}
|
|
129
|
+
</v-chip>
|
|
130
|
+
</slot>
|
|
129
131
|
</v-col>
|
|
130
132
|
<v-spacer />
|
|
131
133
|
<v-col cols="auto">
|
|
132
|
-
<
|
|
133
|
-
v-if="group.attachments && group.attachments.length > 0"
|
|
134
|
-
size="x-small"
|
|
135
|
-
variant="tonal"
|
|
136
|
-
color="primary"
|
|
137
|
-
class="text-none"
|
|
138
|
-
prepend-icon="mdi-paperclip"
|
|
139
|
-
@click.stop="
|
|
140
|
-
openAttachmentDialog(group.set, group.attachments)
|
|
141
|
-
"
|
|
142
|
-
>
|
|
143
|
-
{{ group.attachments.length }} attachment{{
|
|
144
|
-
group.attachments.length > 1 ? "s" : ""
|
|
145
|
-
}}
|
|
146
|
-
</v-btn>
|
|
134
|
+
<slot name="group-header-append" :group="group" />
|
|
147
135
|
</v-col>
|
|
148
136
|
</v-row>
|
|
149
137
|
</v-sheet>
|
|
@@ -151,45 +139,20 @@
|
|
|
151
139
|
<v-sheet
|
|
152
140
|
v-for="item in group.items"
|
|
153
141
|
:key="item[itemValue]"
|
|
154
|
-
|
|
155
|
-
isItemSelected(item, group.set) ? 'grey-lighten-4' : 'white'
|
|
156
|
-
"
|
|
142
|
+
color="white"
|
|
157
143
|
border="b"
|
|
158
144
|
>
|
|
159
145
|
<v-row no-gutters align="center" class="px-4 py-2">
|
|
160
146
|
<v-col cols="auto" class="mr-3">
|
|
161
|
-
<
|
|
162
|
-
size="20"
|
|
163
|
-
:color="
|
|
164
|
-
activeActions[getKey(item, group.set)] === 'approve'
|
|
165
|
-
? 'success'
|
|
166
|
-
: activeActions[getKey(item, group.set)] === 'reject'
|
|
167
|
-
? 'error'
|
|
168
|
-
: 'grey-lighten-2'
|
|
169
|
-
"
|
|
170
|
-
>
|
|
171
|
-
{{
|
|
172
|
-
activeActions[getKey(item, group.set)] === "approve"
|
|
173
|
-
? "mdi-check-circle"
|
|
174
|
-
: activeActions[getKey(item, group.set)] === "reject"
|
|
175
|
-
? "mdi-close-circle"
|
|
176
|
-
: "mdi-circle-outline"
|
|
177
|
-
}}
|
|
178
|
-
</v-icon>
|
|
147
|
+
<slot name="item-prepend" :item="item" :group="group" />
|
|
179
148
|
</v-col>
|
|
149
|
+
|
|
180
150
|
<v-col>
|
|
181
|
-
<slot name="
|
|
182
|
-
<v-row no-gutters
|
|
151
|
+
<slot name="item-content" :item="item" :group="group">
|
|
152
|
+
<v-row no-gutters>
|
|
183
153
|
<v-col cols="12">
|
|
184
|
-
<span
|
|
185
|
-
|
|
186
|
-
:class="
|
|
187
|
-
activeActions[getKey(item, group.set)] === 'approve'
|
|
188
|
-
? 'text-decoration-line-through text-medium-emphasis'
|
|
189
|
-
: ''
|
|
190
|
-
"
|
|
191
|
-
>
|
|
192
|
-
{{ getItemValue(item, headers[0].value) }}
|
|
154
|
+
<span class="text-body-2 font-weight-medium">
|
|
155
|
+
{{ getItemValue(item, headers[0]?.value) }}
|
|
193
156
|
</span>
|
|
194
157
|
</v-col>
|
|
195
158
|
<v-col
|
|
@@ -239,50 +202,7 @@
|
|
|
239
202
|
</v-col>
|
|
240
203
|
|
|
241
204
|
<v-col cols="auto">
|
|
242
|
-
<slot
|
|
243
|
-
name="list-item-append"
|
|
244
|
-
:item="item"
|
|
245
|
-
:isSelected="isItemSelected(item, group.set)"
|
|
246
|
-
>
|
|
247
|
-
<v-row
|
|
248
|
-
v-if="canManageScheduleTasks"
|
|
249
|
-
no-gutters
|
|
250
|
-
align="center"
|
|
251
|
-
>
|
|
252
|
-
<v-col cols="auto">
|
|
253
|
-
<v-btn
|
|
254
|
-
icon="mdi-close"
|
|
255
|
-
size="small"
|
|
256
|
-
:variant="
|
|
257
|
-
activeActions[getKey(item, group.set)] === 'reject'
|
|
258
|
-
? 'flat'
|
|
259
|
-
: 'text'
|
|
260
|
-
"
|
|
261
|
-
color="error"
|
|
262
|
-
@click.stop="
|
|
263
|
-
handleActionClick(item, group.set, 'reject')
|
|
264
|
-
"
|
|
265
|
-
/>
|
|
266
|
-
</v-col>
|
|
267
|
-
<v-col cols="auto">
|
|
268
|
-
<v-btn
|
|
269
|
-
icon="mdi-check"
|
|
270
|
-
size="small"
|
|
271
|
-
:variant="
|
|
272
|
-
activeActions[getKey(item, group.set)] === 'approve'
|
|
273
|
-
? 'flat'
|
|
274
|
-
: 'text'
|
|
275
|
-
"
|
|
276
|
-
color="success"
|
|
277
|
-
:loading="!!loadingActions[getKey(item, group.set)]"
|
|
278
|
-
:disabled="!!loadingActions[getKey(item, group.set)]"
|
|
279
|
-
@click.stop="
|
|
280
|
-
handleActionClick(item, group.set, 'approve')
|
|
281
|
-
"
|
|
282
|
-
/>
|
|
283
|
-
</v-col>
|
|
284
|
-
</v-row>
|
|
285
|
-
</slot>
|
|
205
|
+
<slot name="item-append" :item="item" :group="group" />
|
|
286
206
|
</v-col>
|
|
287
207
|
</v-row>
|
|
288
208
|
</v-sheet>
|
|
@@ -293,81 +213,6 @@
|
|
|
293
213
|
</v-card>
|
|
294
214
|
</v-col>
|
|
295
215
|
</v-row>
|
|
296
|
-
|
|
297
|
-
<v-dialog v-model="showAttachmentDialog" max-width="700" scrollable>
|
|
298
|
-
<v-card>
|
|
299
|
-
<v-card-title class="d-flex align-center pa-4">
|
|
300
|
-
<span class="text-h6 font-weight-bold">
|
|
301
|
-
Set {{ attachmentDialogSet }} — Attachments
|
|
302
|
-
</span>
|
|
303
|
-
<v-spacer />
|
|
304
|
-
<v-btn
|
|
305
|
-
icon="mdi-close"
|
|
306
|
-
variant="text"
|
|
307
|
-
size="small"
|
|
308
|
-
@click="showAttachmentDialog = false"
|
|
309
|
-
/>
|
|
310
|
-
</v-card-title>
|
|
311
|
-
|
|
312
|
-
<v-divider />
|
|
313
|
-
|
|
314
|
-
<v-card-text class="pa-4">
|
|
315
|
-
<v-row>
|
|
316
|
-
<v-col
|
|
317
|
-
v-for="(id, index) in attachmentDialogIds"
|
|
318
|
-
:key="index"
|
|
319
|
-
cols="6"
|
|
320
|
-
sm="4"
|
|
321
|
-
>
|
|
322
|
-
<v-sheet
|
|
323
|
-
rounded="lg"
|
|
324
|
-
class="overflow-hidden"
|
|
325
|
-
style="aspect-ratio: 1"
|
|
326
|
-
>
|
|
327
|
-
<v-img
|
|
328
|
-
:src="getFileUrl(id)"
|
|
329
|
-
aspect-ratio="1"
|
|
330
|
-
cover
|
|
331
|
-
class="rounded-lg"
|
|
332
|
-
@click="openFullImage(getFileUrl(id))"
|
|
333
|
-
style="cursor: zoom-in"
|
|
334
|
-
>
|
|
335
|
-
<template v-slot:placeholder>
|
|
336
|
-
<v-row
|
|
337
|
-
class="fill-height ma-0"
|
|
338
|
-
align="center"
|
|
339
|
-
justify="center"
|
|
340
|
-
>
|
|
341
|
-
<v-progress-circular indeterminate color="grey-lighten-4" />
|
|
342
|
-
</v-row>
|
|
343
|
-
</template>
|
|
344
|
-
<template v-slot:error>
|
|
345
|
-
<v-row
|
|
346
|
-
class="fill-height ma-0"
|
|
347
|
-
align="center"
|
|
348
|
-
justify="center"
|
|
349
|
-
>
|
|
350
|
-
<v-icon icon="mdi-image-broken" size="40" color="grey" />
|
|
351
|
-
</v-row>
|
|
352
|
-
</template>
|
|
353
|
-
</v-img>
|
|
354
|
-
</v-sheet>
|
|
355
|
-
</v-col>
|
|
356
|
-
</v-row>
|
|
357
|
-
</v-card-text>
|
|
358
|
-
</v-card>
|
|
359
|
-
</v-dialog>
|
|
360
|
-
|
|
361
|
-
<v-dialog v-model="showLightbox" max-width="900">
|
|
362
|
-
<v-card>
|
|
363
|
-
<v-card-actions class="pa-2 justify-end">
|
|
364
|
-
<v-btn icon="mdi-close" variant="text" @click="showLightbox = false" />
|
|
365
|
-
</v-card-actions>
|
|
366
|
-
<v-card-text class="pa-2 pt-0">
|
|
367
|
-
<v-img :src="lightboxSrc" contain max-height="80vh" />
|
|
368
|
-
</v-card-text>
|
|
369
|
-
</v-card>
|
|
370
|
-
</v-dialog>
|
|
371
216
|
</template>
|
|
372
217
|
|
|
373
218
|
<script lang="ts" setup>
|
|
@@ -426,14 +271,6 @@ const props = defineProps({
|
|
|
426
271
|
type: Boolean,
|
|
427
272
|
default: false,
|
|
428
273
|
},
|
|
429
|
-
canManageScheduleTasks: {
|
|
430
|
-
type: Boolean,
|
|
431
|
-
default: true,
|
|
432
|
-
},
|
|
433
|
-
canAddRemarks: {
|
|
434
|
-
type: Boolean,
|
|
435
|
-
default: true,
|
|
436
|
-
},
|
|
437
274
|
extensionHeight: {
|
|
438
275
|
type: Number,
|
|
439
276
|
default: 50,
|
|
@@ -442,71 +279,28 @@ const props = defineProps({
|
|
|
442
279
|
type: Number,
|
|
443
280
|
default: 200,
|
|
444
281
|
},
|
|
445
|
-
selected: {
|
|
446
|
-
type: Array as PropType<any[]>,
|
|
447
|
-
default: () => [],
|
|
448
|
-
},
|
|
449
282
|
});
|
|
450
283
|
|
|
451
|
-
const emits = defineEmits([
|
|
452
|
-
"create",
|
|
453
|
-
"refresh",
|
|
454
|
-
"update:page",
|
|
455
|
-
"row-click",
|
|
456
|
-
"update:selected",
|
|
457
|
-
"action-click",
|
|
458
|
-
"request-completion-dialog",
|
|
459
|
-
]);
|
|
460
|
-
|
|
461
|
-
defineExpose({
|
|
462
|
-
revertSetApprovals,
|
|
463
|
-
stopLoadingAction,
|
|
464
|
-
});
|
|
284
|
+
const emits = defineEmits(["create", "refresh", "update:page"]);
|
|
465
285
|
|
|
466
286
|
const internalPage = ref(props.page);
|
|
467
|
-
const selected = shallowRef<any[]>(props.selected);
|
|
468
|
-
const activeActions = reactive<Record<string, "approve" | "reject">>({});
|
|
469
|
-
const persistedActions = reactive<Record<string, "approve" | "reject">>({});
|
|
470
|
-
const loadingActions = reactive<Record<string, boolean>>({});
|
|
471
|
-
const completedSets = ref<Set<number>>(new Set());
|
|
472
287
|
const itemOrderMap = new Map<string, number>();
|
|
473
288
|
|
|
474
|
-
const showAttachmentDialog = ref(false);
|
|
475
|
-
const attachmentDialogSet = ref<number | undefined>(undefined);
|
|
476
|
-
const attachmentDialogIds = ref<string[]>([]);
|
|
477
|
-
const showLightbox = ref(false);
|
|
478
|
-
const lightboxSrc = ref("");
|
|
479
|
-
|
|
480
|
-
const { getFileUrl } = useFile();
|
|
481
|
-
|
|
482
|
-
function openAttachmentDialog(setNumber: number, attachments: string[]) {
|
|
483
|
-
attachmentDialogSet.value = setNumber;
|
|
484
|
-
attachmentDialogIds.value = attachments;
|
|
485
|
-
showAttachmentDialog.value = true;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
function openFullImage(src: string) {
|
|
489
|
-
lightboxSrc.value = src;
|
|
490
|
-
showLightbox.value = true;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
289
|
const groupedItems = computed(() => {
|
|
494
290
|
return props.items.map((item: any) => {
|
|
495
291
|
const units = item.units || [item];
|
|
496
292
|
|
|
497
|
-
units.forEach((unit: any
|
|
498
|
-
const key =
|
|
293
|
+
units.forEach((unit: any) => {
|
|
294
|
+
const key = `${unit[props.itemValue]}_${item.set}`;
|
|
499
295
|
if (!itemOrderMap.has(key)) {
|
|
500
296
|
itemOrderMap.set(key, itemOrderMap.size);
|
|
501
297
|
}
|
|
502
298
|
});
|
|
503
299
|
|
|
504
300
|
const sortedUnits = [...units].sort((a: any, b: any) => {
|
|
505
|
-
const keyA =
|
|
506
|
-
const keyB =
|
|
507
|
-
|
|
508
|
-
const orderB = itemOrderMap.get(keyB) ?? 0;
|
|
509
|
-
return orderA - orderB;
|
|
301
|
+
const keyA = `${a[props.itemValue]}_${item.set}`;
|
|
302
|
+
const keyB = `${b[props.itemValue]}_${item.set}`;
|
|
303
|
+
return (itemOrderMap.get(keyA) ?? 0) - (itemOrderMap.get(keyB) ?? 0);
|
|
510
304
|
});
|
|
511
305
|
|
|
512
306
|
return {
|
|
@@ -522,27 +316,6 @@ const groupedItems = computed(() => {
|
|
|
522
316
|
});
|
|
523
317
|
});
|
|
524
318
|
|
|
525
|
-
const totalItemsCount = computed(() => {
|
|
526
|
-
return groupedItems.value.reduce((acc, group) => acc + group.items.length, 0);
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
const approvedItemsCount = computed(() => {
|
|
530
|
-
return Object.values(activeActions).filter((action) => action === "approve")
|
|
531
|
-
.length;
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
const hasRejectedItems = computed(() => {
|
|
535
|
-
return Object.values(activeActions).some((action) => action === "reject");
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
const allItemsApproved = computed(() => {
|
|
539
|
-
return (
|
|
540
|
-
totalItemsCount.value > 0 &&
|
|
541
|
-
approvedItemsCount.value === totalItemsCount.value &&
|
|
542
|
-
!hasRejectedItems.value
|
|
543
|
-
);
|
|
544
|
-
});
|
|
545
|
-
|
|
546
319
|
function formatTimestamp(ts: string): string {
|
|
547
320
|
if (!ts) return "";
|
|
548
321
|
const date = new Date(ts);
|
|
@@ -571,199 +344,16 @@ function isGroupInProgress(group: { items: any[] }): boolean {
|
|
|
571
344
|
);
|
|
572
345
|
}
|
|
573
346
|
|
|
574
|
-
function
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
return group.items.every((item: any) => {
|
|
579
|
-
const key = getKey(item, setNumber);
|
|
580
|
-
return activeActions[key] === "approve";
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function getNewApprovedItemsForSet(
|
|
585
|
-
setNumber: number
|
|
586
|
-
): Array<{ key: string; item: any; action: "approve" }> {
|
|
587
|
-
const group = groupedItems.value.find((g) => g.set === setNumber);
|
|
588
|
-
if (!group) return [];
|
|
589
|
-
|
|
590
|
-
const approvedItems: Array<{ key: string; item: any; action: "approve" }> =
|
|
591
|
-
[];
|
|
592
|
-
|
|
593
|
-
group.items.forEach((item: any) => {
|
|
594
|
-
const key = getKey(item, setNumber);
|
|
595
|
-
if (activeActions[key] === "approve" && !(key in persistedActions)) {
|
|
596
|
-
approvedItems.push({
|
|
597
|
-
key,
|
|
598
|
-
item: { ...item, set: setNumber },
|
|
599
|
-
action: "approve",
|
|
600
|
-
});
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
return approvedItems;
|
|
347
|
+
function getItemValue(item: any, key: string): string {
|
|
348
|
+
if (!key) return "";
|
|
349
|
+
return key.split(".").reduce((obj: any, k: string) => obj?.[k], item) ?? "";
|
|
605
350
|
}
|
|
606
351
|
|
|
607
|
-
const lastApprovedKey = ref<string | null>(null);
|
|
608
|
-
|
|
609
352
|
watch(
|
|
610
353
|
() => props.page,
|
|
611
354
|
(val) => {
|
|
612
355
|
internalPage.value = val;
|
|
613
|
-
|
|
614
356
|
itemOrderMap.clear();
|
|
615
357
|
}
|
|
616
358
|
);
|
|
617
|
-
|
|
618
|
-
watch(
|
|
619
|
-
() => props.selected,
|
|
620
|
-
(val) => {
|
|
621
|
-
selected.value = val;
|
|
622
|
-
}
|
|
623
|
-
);
|
|
624
|
-
|
|
625
|
-
watch(selected, (val) => {
|
|
626
|
-
emits("update:selected", val);
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
watch(
|
|
630
|
-
() => props.items,
|
|
631
|
-
(items) => {
|
|
632
|
-
if (!items || !Array.isArray(items)) return;
|
|
633
|
-
|
|
634
|
-
Object.keys(persistedActions).forEach(
|
|
635
|
-
(key) => delete persistedActions[key]
|
|
636
|
-
);
|
|
637
|
-
|
|
638
|
-
items.forEach((group: any) => {
|
|
639
|
-
const set = group.set;
|
|
640
|
-
const units = group.units || [];
|
|
641
|
-
|
|
642
|
-
units.forEach((unit: any) => {
|
|
643
|
-
const key = getKey(unit, set);
|
|
644
|
-
if (unit.approve === true) {
|
|
645
|
-
activeActions[key] = "approve";
|
|
646
|
-
persistedActions[key] = "approve";
|
|
647
|
-
} else if (unit.reject === true) {
|
|
648
|
-
activeActions[key] = "reject";
|
|
649
|
-
persistedActions[key] = "reject";
|
|
650
|
-
}
|
|
651
|
-
});
|
|
652
|
-
});
|
|
653
|
-
},
|
|
654
|
-
{ immediate: true }
|
|
655
|
-
);
|
|
656
|
-
|
|
657
|
-
function getKey(item: any, set?: number): string {
|
|
658
|
-
return `${item[props.itemValue]}_${set ?? ""}`;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
function getItemValue(item: any, key: string): string {
|
|
662
|
-
if (!key) return "";
|
|
663
|
-
return key.split(".").reduce((obj, k) => obj?.[k], item) ?? "";
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
function isItemSelected(item: any, set?: number): boolean {
|
|
667
|
-
if (!Array.isArray(selected.value) || selected.value.length === 0) {
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
if (typeof selected.value[0] === "object" && "unit" in selected.value[0]) {
|
|
672
|
-
return selected.value.some(
|
|
673
|
-
(s: any) => s.unit === item[props.itemValue] && s.set === set
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
return selected.value.includes(item[props.itemValue]);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
function handleActionClick(
|
|
681
|
-
item: any,
|
|
682
|
-
set: number | undefined,
|
|
683
|
-
action: "approve" | "reject"
|
|
684
|
-
): void {
|
|
685
|
-
const key = getKey(item, set);
|
|
686
|
-
|
|
687
|
-
const isPersisted = key in persistedActions;
|
|
688
|
-
|
|
689
|
-
if (activeActions[key] === action && !isPersisted) {
|
|
690
|
-
delete activeActions[key];
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
activeActions[key] = action;
|
|
695
|
-
|
|
696
|
-
if (action === "reject") {
|
|
697
|
-
console.debug("TableHygiene: emitting action-click", {
|
|
698
|
-
item: { ...item, set },
|
|
699
|
-
action,
|
|
700
|
-
});
|
|
701
|
-
emits("action-click", { item: { ...item, set }, action });
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
if (action === "approve") {
|
|
705
|
-
lastApprovedKey.value = key;
|
|
706
|
-
|
|
707
|
-
if (
|
|
708
|
-
set !== undefined &&
|
|
709
|
-
isSetFullyApproved(set) &&
|
|
710
|
-
!completedSets.value.has(set)
|
|
711
|
-
) {
|
|
712
|
-
const newApprovedItems = getNewApprovedItemsForSet(set);
|
|
713
|
-
|
|
714
|
-
if (newApprovedItems.length > 0) {
|
|
715
|
-
// Mark this set as completed
|
|
716
|
-
completedSets.value.add(set);
|
|
717
|
-
|
|
718
|
-
// Emit request to open completion dialog
|
|
719
|
-
emits("request-completion-dialog", {
|
|
720
|
-
setNumber: set,
|
|
721
|
-
approvedItems: newApprovedItems,
|
|
722
|
-
lastApprovedKey: lastApprovedKey.value,
|
|
723
|
-
});
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// Non-completing approve: undo optimistic check and show loading instead
|
|
729
|
-
if (!isPersisted) {
|
|
730
|
-
delete activeActions[key];
|
|
731
|
-
loadingActions[key] = true;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
console.debug("TableHygiene: emitting action-click (approve immediate)", {
|
|
735
|
-
item: { ...item, set },
|
|
736
|
-
action,
|
|
737
|
-
});
|
|
738
|
-
emits("action-click", { item: { ...item, set }, action });
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
function stopLoadingAction(key: string): void {
|
|
743
|
-
delete loadingActions[key];
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
function revertSetApprovals(setNumber: number): void {
|
|
747
|
-
const group = groupedItems.value.find((g) => g.set === setNumber);
|
|
748
|
-
if (group) {
|
|
749
|
-
group.items.forEach((item: any) => {
|
|
750
|
-
const key = getKey(item, setNumber);
|
|
751
|
-
|
|
752
|
-
if (!(key in persistedActions)) {
|
|
753
|
-
delete activeActions[key];
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
completedSets.value.delete(setNumber);
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
watch(
|
|
762
|
-
() => props.items,
|
|
763
|
-
() => {
|
|
764
|
-
completedSets.value.clear();
|
|
765
|
-
Object.keys(loadingActions).forEach((k) => delete loadingActions[k]);
|
|
766
|
-
},
|
|
767
|
-
{ deep: true }
|
|
768
|
-
);
|
|
769
359
|
</script>
|