@7365admin1/layer-common 1.11.2 → 1.11.4
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 +12 -0
- package/components/AccessCardAddForm.vue +2 -2
- package/components/AreaMain.vue +4 -0
- package/components/DashboardMain.vue +2 -2
- package/components/{SupplyManagementMain.vue → EquipmentManagementMain.vue} +107 -115
- package/components/ManageChecklistMain.vue +68 -13
- package/components/OvernightParkingAvailability.vue +267 -0
- package/components/OvernightParkingManagement.vue +130 -0
- package/components/Signature.vue +36 -28
- package/components/UnitMain.vue +4 -1
- package/components/VisitorForm.vue +44 -14
- package/composables/useAccessManagement.ts +11 -0
- package/composables/useAreas.ts +3 -0
- package/composables/useComment.ts +1 -1
- package/composables/useFacilityUtils.ts +140 -0
- package/composables/useFeedback.ts +1 -1
- package/composables/useLocalAuth.ts +1 -0
- package/composables/useSiteSettings.ts +21 -0
- package/composables/useUnits.ts +9 -6
- package/composables/useWorkOrder.ts +50 -18
- package/nuxt.config.ts +2 -1
- package/package.json +1 -1
- package/pages/require-organization-membership.vue +3 -3
- package/types/area.d.ts +1 -0
- package/types/dashboard.d.ts +4 -3
- package/types/overnight-parking.d.ts +35 -0
- package/types/user.d.ts +1 -1
- package/types/work-order.d.ts +1 -0
- package/utils/data.ts +17 -0
- package/components/EquipmentManagement.vue +0 -292
package/CHANGELOG.md
CHANGED
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
type="number"
|
|
147
147
|
:min="1"
|
|
148
148
|
hide-spin-buttons
|
|
149
|
-
@
|
|
149
|
+
@blur="enforceMinQuantity"
|
|
150
150
|
/>
|
|
151
151
|
</v-col>
|
|
152
152
|
<v-col cols="12" class="px-1 pb-5" v-if="!isNonPhysicalCard">
|
|
@@ -224,7 +224,7 @@
|
|
|
224
224
|
density="compact"
|
|
225
225
|
:items="accessGroupItems"
|
|
226
226
|
item-title="name"
|
|
227
|
-
item-value="
|
|
227
|
+
item-value="name"
|
|
228
228
|
hide-details
|
|
229
229
|
:rules="[requiredRule]"
|
|
230
230
|
multiple
|
package/components/AreaMain.vue
CHANGED
|
@@ -358,11 +358,13 @@ import useAreas from "../composables/useAreas";
|
|
|
358
358
|
import useUnits from "../composables/useUnits";
|
|
359
359
|
import { useAreaPermission } from "../composables/useAreaPermission";
|
|
360
360
|
import useSiteSettings from "../composables/useSiteSettings";
|
|
361
|
+
import useUtils from "../composables/useUtils";
|
|
361
362
|
|
|
362
363
|
const props = defineProps({
|
|
363
364
|
orgId: { type: String, default: "" },
|
|
364
365
|
site: { type: String, default: "" },
|
|
365
366
|
type: { type: String, default: "" },
|
|
367
|
+
serviceType: { type: String, default: "" },
|
|
366
368
|
});
|
|
367
369
|
|
|
368
370
|
const isCleanerArea = computed(() => {
|
|
@@ -458,6 +460,7 @@ const {
|
|
|
458
460
|
site: props.site,
|
|
459
461
|
search: searchInput.value,
|
|
460
462
|
type: areaTypeFilter.value === "all" ? undefined : areaTypeFilter.value,
|
|
463
|
+
serviceType: props.serviceType,
|
|
461
464
|
}),
|
|
462
465
|
{
|
|
463
466
|
watch: [page, () => props.site, () => props.type, areaTypeFilter],
|
|
@@ -646,6 +649,7 @@ async function _createArea() {
|
|
|
646
649
|
set: itemSet.value,
|
|
647
650
|
type: (itemType.value || "common").toLowerCase(),
|
|
648
651
|
units: units.value,
|
|
652
|
+
serviceType: props.serviceType,
|
|
649
653
|
};
|
|
650
654
|
|
|
651
655
|
let response;
|
|
@@ -91,7 +91,7 @@ const props = defineProps({
|
|
|
91
91
|
default: false,
|
|
92
92
|
},
|
|
93
93
|
cardPeriods: {
|
|
94
|
-
type: Object as () =>
|
|
94
|
+
type: Object as () => Record<string, TDashboardValues>,
|
|
95
95
|
required: true,
|
|
96
96
|
},
|
|
97
97
|
currentSiteName: {
|
|
@@ -134,7 +134,7 @@ const countCardList = computed(() => {
|
|
|
134
134
|
: [];
|
|
135
135
|
|
|
136
136
|
return sourceCards.map((card: any, idx: number) => {
|
|
137
|
-
const periodKey = card.periodKey as keyof
|
|
137
|
+
const periodKey = card.periodKey as keyof Record<string, TDashboardValues>;
|
|
138
138
|
const apiPeriod = props.cardPeriods[periodKey] || "today";
|
|
139
139
|
const displayPeriod = datePeriod[apiPeriod] || "Today";
|
|
140
140
|
|
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
v-model:page="page"
|
|
11
11
|
:pages="pages"
|
|
12
12
|
:pageRange="pageRange"
|
|
13
|
-
:no-data-text="`No
|
|
14
|
-
@refresh="
|
|
15
|
-
:canCreate="
|
|
16
|
-
createLabel="Add
|
|
13
|
+
:no-data-text="`No equipment found for ${siteName}.`"
|
|
14
|
+
@refresh="getEquipmentsRefresh"
|
|
15
|
+
:canCreate="canAddEquipment"
|
|
16
|
+
createLabel="Add Equipment"
|
|
17
17
|
@row-click="handleRowClick"
|
|
18
18
|
>
|
|
19
19
|
<template #actions>
|
|
20
20
|
<v-row no-gutters align="center" class="w-100">
|
|
21
|
-
<v-col cols="auto" v-if="
|
|
21
|
+
<v-col cols="auto" v-if="canAddEquipment">
|
|
22
22
|
<v-btn
|
|
23
23
|
class="text-none"
|
|
24
24
|
rounded="pill"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
size="large"
|
|
27
27
|
@click="onCreateUnit()"
|
|
28
28
|
>
|
|
29
|
-
Add
|
|
29
|
+
Add Equipment
|
|
30
30
|
</v-btn>
|
|
31
31
|
</v-col>
|
|
32
32
|
|
|
@@ -57,28 +57,27 @@
|
|
|
57
57
|
</v-col>
|
|
58
58
|
</v-row>
|
|
59
59
|
|
|
60
|
-
<
|
|
60
|
+
<AddEqupmentForm
|
|
61
61
|
v-model="dialogShowForm"
|
|
62
|
-
v-model:name="
|
|
63
|
-
v-model:
|
|
64
|
-
v-model:unitOfMeasurement="supplyUnit"
|
|
62
|
+
v-model:name="equipmentName"
|
|
63
|
+
v-model:unitOfMeasurement="equipmentUnit"
|
|
65
64
|
:mode="dialogMode"
|
|
66
|
-
:
|
|
65
|
+
:equipmentData="editingEquipment"
|
|
67
66
|
:site="props.site"
|
|
68
|
-
@saved="
|
|
67
|
+
@saved="_createEquipment"
|
|
69
68
|
/>
|
|
70
69
|
|
|
71
70
|
<v-dialog v-model="dialogShowMoreActions" width="400" persistent>
|
|
72
71
|
<HygieneUpdateMoreAction
|
|
73
|
-
:title="
|
|
74
|
-
:canUpdate="
|
|
75
|
-
:canDelete="
|
|
72
|
+
:title="selectedEquipment?.name || 'Unit Actions'"
|
|
73
|
+
:canUpdate="canUpdateEquipment"
|
|
74
|
+
:canDelete="canDeleteEquipment"
|
|
76
75
|
:showAddStock="canAddStock"
|
|
77
76
|
:showViewStock="canViewStock"
|
|
78
77
|
:showRequestItem="canRequestItem"
|
|
79
78
|
:manageButtonLabel="''"
|
|
80
|
-
:editButtonLabel="'Edit
|
|
81
|
-
:deleteButtonLabel="'Delete
|
|
79
|
+
:editButtonLabel="'Edit Equipment'"
|
|
80
|
+
:deleteButtonLabel="'Delete Equipment'"
|
|
82
81
|
:addStockButtonLabel="'Add Stock'"
|
|
83
82
|
:viewButtonLabel="'View Stock'"
|
|
84
83
|
:requestItemButtonLabel="'Checkout Item'"
|
|
@@ -91,13 +90,13 @@
|
|
|
91
90
|
>
|
|
92
91
|
<template #content>
|
|
93
92
|
<v-row no-gutters>
|
|
94
|
-
<v-col v-if="
|
|
93
|
+
<v-col v-if="selectedEquipment" cols="12" class="mb-2">
|
|
95
94
|
<v-row no-gutters class="mb-2">
|
|
96
95
|
<v-col cols="5" class="text-subtitle-2 font-weight-bold">
|
|
97
96
|
Name:
|
|
98
97
|
</v-col>
|
|
99
98
|
<v-col cols="7" class="text-subtitle-2">
|
|
100
|
-
{{
|
|
99
|
+
{{ selectedEquipment.name || "N/A" }}
|
|
101
100
|
</v-col>
|
|
102
101
|
</v-row>
|
|
103
102
|
|
|
@@ -106,7 +105,7 @@
|
|
|
106
105
|
Quantity:
|
|
107
106
|
</v-col>
|
|
108
107
|
<v-col cols="7" class="text-subtitle-2">
|
|
109
|
-
{{
|
|
108
|
+
{{ selectedEquipment.qty || "N/A" }}
|
|
110
109
|
</v-col>
|
|
111
110
|
</v-row>
|
|
112
111
|
|
|
@@ -115,7 +114,7 @@
|
|
|
115
114
|
Unit of Measurement:
|
|
116
115
|
</v-col>
|
|
117
116
|
<v-col cols="7" class="text-subtitle-2">
|
|
118
|
-
{{
|
|
117
|
+
{{ selectedEquipment.unitOfMeasurement || "N/A" }}
|
|
119
118
|
</v-col>
|
|
120
119
|
</v-row>
|
|
121
120
|
|
|
@@ -128,18 +127,18 @@
|
|
|
128
127
|
</HygieneUpdateMoreAction>
|
|
129
128
|
</v-dialog>
|
|
130
129
|
|
|
131
|
-
<v-dialog v-model="
|
|
130
|
+
<v-dialog v-model="dialogDeleteEquipment" max-width="450">
|
|
132
131
|
<v-card>
|
|
133
132
|
<v-toolbar>
|
|
134
133
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
135
134
|
<span class="font-weight-bold text-h6 text-capitalize">
|
|
136
|
-
Delete {{
|
|
135
|
+
Delete {{ selectedEquipment?.name || "Unit" }}
|
|
137
136
|
</span>
|
|
138
137
|
</v-row>
|
|
139
138
|
</v-toolbar>
|
|
140
139
|
<v-card-text>
|
|
141
140
|
<span class="text-subtitle-2"
|
|
142
|
-
>Are you sure you want to delete this
|
|
141
|
+
>Are you sure you want to delete this equipment?</span
|
|
143
142
|
>
|
|
144
143
|
</v-card-text>
|
|
145
144
|
|
|
@@ -151,7 +150,7 @@
|
|
|
151
150
|
variant="text"
|
|
152
151
|
class="text-none"
|
|
153
152
|
size="large"
|
|
154
|
-
@click="
|
|
153
|
+
@click="dialogDeleteEquipment = false"
|
|
155
154
|
height="48"
|
|
156
155
|
>
|
|
157
156
|
Cancel
|
|
@@ -166,7 +165,7 @@
|
|
|
166
165
|
class="text-none font-weight-bold"
|
|
167
166
|
height="48"
|
|
168
167
|
:loading="submitting"
|
|
169
|
-
@click="
|
|
168
|
+
@click="_deleteEquipment"
|
|
170
169
|
>
|
|
171
170
|
Delete
|
|
172
171
|
</v-btn>
|
|
@@ -245,11 +244,11 @@
|
|
|
245
244
|
|
|
246
245
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
247
246
|
</template>
|
|
248
|
-
|
|
249
247
|
<script setup lang="ts">
|
|
250
|
-
import
|
|
248
|
+
import useEquipment from "../composables/useEquipment";
|
|
251
249
|
import useStock from "../composables/useStock";
|
|
252
|
-
import {
|
|
250
|
+
import { useEquipmentPermission } from "../composables/useEquipmentPermission";
|
|
251
|
+
import useUtils from "../composables/useUtils";
|
|
253
252
|
|
|
254
253
|
const props = defineProps({
|
|
255
254
|
orgId: { type: String, default: "" },
|
|
@@ -257,14 +256,14 @@ const props = defineProps({
|
|
|
257
256
|
});
|
|
258
257
|
|
|
259
258
|
const {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
259
|
+
canViewEquipments,
|
|
260
|
+
canAddEquipment,
|
|
261
|
+
canUpdateEquipment,
|
|
262
|
+
canDeleteEquipment,
|
|
264
263
|
canAddStock,
|
|
265
264
|
canViewStock,
|
|
266
265
|
canRequestItem,
|
|
267
|
-
} =
|
|
266
|
+
} = useEquipmentPermission();
|
|
268
267
|
|
|
269
268
|
const items = ref<Array<Record<string, any>>>([]);
|
|
270
269
|
const siteName = ref<string>("");
|
|
@@ -276,8 +275,13 @@ const headers = [
|
|
|
276
275
|
{ title: "Status", value: "status" },
|
|
277
276
|
];
|
|
278
277
|
|
|
279
|
-
const {
|
|
280
|
-
|
|
278
|
+
const {
|
|
279
|
+
getEquipments,
|
|
280
|
+
getEquipmentById,
|
|
281
|
+
createEquipment,
|
|
282
|
+
updateEquipment,
|
|
283
|
+
deleteEquipment,
|
|
284
|
+
} = useEquipment();
|
|
281
285
|
const { debounce, requiredRule } = useUtils();
|
|
282
286
|
|
|
283
287
|
const searchInput = ref("");
|
|
@@ -288,13 +292,13 @@ const pages = ref(0);
|
|
|
288
292
|
const pageRange = ref("-- - -- of --");
|
|
289
293
|
|
|
290
294
|
const {
|
|
291
|
-
data:
|
|
292
|
-
refresh:
|
|
295
|
+
data: getEquipmentsReq,
|
|
296
|
+
refresh: getEquipmentsRefresh,
|
|
293
297
|
pending: loading,
|
|
294
|
-
} = await useLazyAsyncData(
|
|
295
|
-
"get-all-
|
|
298
|
+
} = await useLazyAsyncData<any>(
|
|
299
|
+
"get-all-equipments",
|
|
296
300
|
() =>
|
|
297
|
-
|
|
301
|
+
getEquipments({
|
|
298
302
|
page: page.value,
|
|
299
303
|
search: searchInput.value,
|
|
300
304
|
site: props.site,
|
|
@@ -305,14 +309,14 @@ const {
|
|
|
305
309
|
);
|
|
306
310
|
|
|
307
311
|
watchEffect(() => {
|
|
308
|
-
if (
|
|
309
|
-
items.value =
|
|
310
|
-
pages.value =
|
|
311
|
-
pageRange.value =
|
|
312
|
+
if (getEquipmentsReq.value) {
|
|
313
|
+
items.value = getEquipmentsReq.value.items;
|
|
314
|
+
pages.value = getEquipmentsReq.value.pages;
|
|
315
|
+
pageRange.value = getEquipmentsReq.value.pageRange;
|
|
312
316
|
}
|
|
313
317
|
});
|
|
314
318
|
|
|
315
|
-
const debounceSearch = debounce(
|
|
319
|
+
const debounceSearch = debounce(getEquipmentsRefresh, 500);
|
|
316
320
|
watch(
|
|
317
321
|
[searchInput, endDate, startDate],
|
|
318
322
|
([]) => {
|
|
@@ -321,23 +325,21 @@ watch(
|
|
|
321
325
|
{ immediate: false, deep: true }
|
|
322
326
|
);
|
|
323
327
|
|
|
324
|
-
const
|
|
328
|
+
const selectedEquipment = ref<Record<string, any>>({});
|
|
325
329
|
const message = ref("");
|
|
326
330
|
const messageSnackbar = ref(false);
|
|
327
331
|
const messageColor = ref("");
|
|
328
|
-
const fileInput = ref<HTMLInputElement | null>(null);
|
|
329
332
|
|
|
330
333
|
const dialogShowMoreActions = ref(false);
|
|
331
334
|
const dialogShowForm = ref(false);
|
|
332
|
-
const
|
|
335
|
+
const dialogDeleteEquipment = ref(false);
|
|
333
336
|
const dialogStockAction = ref(false);
|
|
334
337
|
const stockActionMode = ref<"add" | "request">("add");
|
|
335
338
|
const dialogMode = ref<"add" | "edit">("add");
|
|
336
339
|
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
const supplyUnit = ref("");
|
|
340
|
+
const editingEquipment = ref<Record<string, any>>({});
|
|
341
|
+
const equipmentName = ref("");
|
|
342
|
+
const equipmentUnit = ref("");
|
|
341
343
|
|
|
342
344
|
const stockActionFormRef = ref<any>(null);
|
|
343
345
|
const stockActionValid = ref(false);
|
|
@@ -350,49 +352,39 @@ function showMessage(msg: string, color: string = "error") {
|
|
|
350
352
|
|
|
351
353
|
function onCreateUnit() {
|
|
352
354
|
dialogMode.value = "add";
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
supplyUnit.value = "";
|
|
355
|
+
editingEquipment.value = {};
|
|
356
|
+
equipmentName.value = "";
|
|
357
|
+
equipmentUnit.value = "";
|
|
357
358
|
dialogShowForm.value = true;
|
|
358
359
|
}
|
|
359
360
|
|
|
360
|
-
function
|
|
361
|
-
name: string;
|
|
362
|
-
qty: number;
|
|
363
|
-
unitOfMeasurement: string;
|
|
364
|
-
}) {
|
|
365
|
-
showMessage("Supply saved successfully", "success");
|
|
366
|
-
getSuppliesRefresh();
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
async function _createSupply() {
|
|
361
|
+
async function _createEquipment() {
|
|
370
362
|
submitting.value = true;
|
|
371
363
|
try {
|
|
372
|
-
const payload:
|
|
373
|
-
name:
|
|
374
|
-
unitOfMeasurement:
|
|
364
|
+
const payload: TEquipmentCreate = {
|
|
365
|
+
name: equipmentName.value,
|
|
366
|
+
unitOfMeasurement: equipmentUnit.value,
|
|
375
367
|
};
|
|
376
368
|
|
|
377
369
|
let response;
|
|
378
370
|
|
|
379
|
-
if (dialogMode.value === "edit" &&
|
|
371
|
+
if (dialogMode.value === "edit" && editingEquipment.value) {
|
|
380
372
|
const id =
|
|
381
|
-
(
|
|
382
|
-
|
|
383
|
-
|
|
373
|
+
(editingEquipment.value as any)._id ||
|
|
374
|
+
(editingEquipment.value as any).id;
|
|
375
|
+
if (!id) throw new Error("Invalid equipment id for update");
|
|
376
|
+
response = await updateEquipment(id, payload);
|
|
384
377
|
} else {
|
|
385
|
-
response = await
|
|
378
|
+
response = await createEquipment(payload, props.site);
|
|
386
379
|
}
|
|
387
380
|
|
|
388
381
|
showMessage(response?.message, "success");
|
|
389
382
|
dialogShowForm.value = false;
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
supplyUnit.value = "";
|
|
383
|
+
editingEquipment.value = {};
|
|
384
|
+
equipmentName.value = "";
|
|
385
|
+
equipmentUnit.value = "";
|
|
394
386
|
|
|
395
|
-
await
|
|
387
|
+
await getEquipmentsRefresh();
|
|
396
388
|
} catch (error: any) {
|
|
397
389
|
console.error(error);
|
|
398
390
|
showMessage(error?.data?.message, "error");
|
|
@@ -401,60 +393,59 @@ async function _createSupply() {
|
|
|
401
393
|
}
|
|
402
394
|
}
|
|
403
395
|
|
|
404
|
-
const
|
|
396
|
+
const selectedEquipmentId = ref("");
|
|
405
397
|
|
|
406
398
|
const {
|
|
407
|
-
data:
|
|
408
|
-
refresh:
|
|
409
|
-
status:
|
|
410
|
-
} = await useLazyAsyncData(
|
|
411
|
-
"get-
|
|
412
|
-
() =>
|
|
399
|
+
data: getEquipmentByIdReq,
|
|
400
|
+
refresh: getEquipmentByIdRefresh,
|
|
401
|
+
status: getEquipmentByIdStatus,
|
|
402
|
+
} = await useLazyAsyncData<any>(
|
|
403
|
+
"get-equipment-by-id",
|
|
404
|
+
() => getEquipmentById(selectedEquipmentId.value),
|
|
413
405
|
{
|
|
414
|
-
watch: [
|
|
406
|
+
watch: [selectedEquipmentId],
|
|
415
407
|
immediate: false,
|
|
416
408
|
}
|
|
417
409
|
);
|
|
418
410
|
|
|
419
411
|
watchEffect(() => {
|
|
420
|
-
if (
|
|
421
|
-
|
|
412
|
+
if (getEquipmentByIdReq.value && getEquipmentByIdStatus.value === "success") {
|
|
413
|
+
selectedEquipment.value = getEquipmentByIdReq.value;
|
|
422
414
|
}
|
|
423
415
|
});
|
|
424
416
|
|
|
425
417
|
async function handleRowClick(data: any) {
|
|
426
|
-
|
|
418
|
+
selectedEquipment.value = data?.item;
|
|
427
419
|
message.value = "";
|
|
428
420
|
|
|
429
|
-
|
|
430
|
-
await
|
|
421
|
+
selectedEquipmentId.value = selectedEquipment.value._id;
|
|
422
|
+
await getEquipmentByIdRefresh();
|
|
431
423
|
|
|
432
424
|
dialogShowMoreActions.value = true;
|
|
433
425
|
}
|
|
434
426
|
|
|
435
427
|
const onEditFromMoreAction = async () => {
|
|
436
428
|
dialogShowMoreActions.value = false;
|
|
437
|
-
if (!
|
|
429
|
+
if (!selectedEquipment.value) return;
|
|
438
430
|
|
|
439
431
|
submitting.value = true;
|
|
440
|
-
|
|
441
|
-
await
|
|
432
|
+
selectedEquipmentId.value = selectedEquipment.value._id;
|
|
433
|
+
await getEquipmentByIdRefresh();
|
|
442
434
|
submitting.value = false;
|
|
443
435
|
|
|
444
|
-
const response =
|
|
436
|
+
const response = getEquipmentByIdReq.value;
|
|
445
437
|
if (!response) return;
|
|
446
438
|
|
|
447
439
|
dialogMode.value = "edit";
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
supplyUnit.value = response.unitOfMeasurement || "";
|
|
440
|
+
editingEquipment.value = response;
|
|
441
|
+
equipmentName.value = response.name || "";
|
|
442
|
+
equipmentUnit.value = response.unitOfMeasurement || "";
|
|
452
443
|
dialogShowForm.value = true;
|
|
453
444
|
};
|
|
454
445
|
|
|
455
446
|
const onDeleteFromMoreAction = () => {
|
|
456
447
|
dialogShowMoreActions.value = false;
|
|
457
|
-
|
|
448
|
+
dialogDeleteEquipment.value = true;
|
|
458
449
|
};
|
|
459
450
|
|
|
460
451
|
const onAddStockFromMoreAction = () => {
|
|
@@ -469,8 +460,8 @@ const onViewStockFromMoreAction = () => {
|
|
|
469
460
|
dialogShowMoreActions.value = false;
|
|
470
461
|
const org = props.orgId;
|
|
471
462
|
const site = props.site;
|
|
472
|
-
const id =
|
|
473
|
-
useRouter().push(`/${org}/${site}/
|
|
463
|
+
const id = selectedEquipment.value._id;
|
|
464
|
+
useRouter().push(`/${org}/${site}/equipment-management/stock/${id}`);
|
|
474
465
|
};
|
|
475
466
|
|
|
476
467
|
const onRequestItemFromMoreAction = () => {
|
|
@@ -481,20 +472,21 @@ const onRequestItemFromMoreAction = () => {
|
|
|
481
472
|
dialogStockAction.value = true;
|
|
482
473
|
};
|
|
483
474
|
|
|
484
|
-
async function
|
|
485
|
-
if (!
|
|
475
|
+
async function _deleteEquipment() {
|
|
476
|
+
if (!selectedEquipment.value) return;
|
|
486
477
|
|
|
487
478
|
try {
|
|
488
479
|
submitting.value = true;
|
|
489
480
|
const id =
|
|
490
|
-
(
|
|
491
|
-
|
|
481
|
+
(selectedEquipment.value as any)._id ||
|
|
482
|
+
(selectedEquipment.value as any).id;
|
|
483
|
+
if (!id) throw new Error("Invalid equipment id");
|
|
492
484
|
|
|
493
|
-
const response = await
|
|
494
|
-
|
|
485
|
+
const response = await deleteEquipment(id);
|
|
486
|
+
dialogDeleteEquipment.value = false;
|
|
495
487
|
showMessage(response?.message, "success");
|
|
496
488
|
|
|
497
|
-
await
|
|
489
|
+
await getEquipmentsRefresh();
|
|
498
490
|
} catch (error: any) {
|
|
499
491
|
showMessage(error?.data?.message, "error");
|
|
500
492
|
} finally {
|
|
@@ -510,7 +502,7 @@ const stockActionRemarks = ref("");
|
|
|
510
502
|
async function _addStock() {
|
|
511
503
|
submitting.value = true;
|
|
512
504
|
try {
|
|
513
|
-
const id =
|
|
505
|
+
const id = selectedEquipment.value._id || selectedEquipment.value.id;
|
|
514
506
|
|
|
515
507
|
const payload: TStockCreate = {
|
|
516
508
|
qty: stockActionQuantity.value,
|
|
@@ -523,7 +515,7 @@ async function _addStock() {
|
|
|
523
515
|
stockActionQuantity.value = 0;
|
|
524
516
|
stockActionRemarks.value = "";
|
|
525
517
|
|
|
526
|
-
await
|
|
518
|
+
await getEquipmentsRefresh();
|
|
527
519
|
} catch (error: any) {
|
|
528
520
|
console.error(error);
|
|
529
521
|
showMessage(error?.data?.message, "error");
|
|
@@ -535,7 +527,7 @@ async function _addStock() {
|
|
|
535
527
|
async function _requestItem() {
|
|
536
528
|
submitting.value = true;
|
|
537
529
|
try {
|
|
538
|
-
const id =
|
|
530
|
+
const id = selectedEquipment.value._id || selectedEquipment.value.id;
|
|
539
531
|
|
|
540
532
|
const payload: TStockCreate = {
|
|
541
533
|
qty: stockActionQuantity.value,
|
|
@@ -546,7 +538,7 @@ async function _requestItem() {
|
|
|
546
538
|
dialogStockAction.value = false;
|
|
547
539
|
stockActionQuantity.value = 0;
|
|
548
540
|
|
|
549
|
-
await
|
|
541
|
+
await getEquipmentsRefresh();
|
|
550
542
|
} catch (error: any) {
|
|
551
543
|
console.error(error);
|
|
552
544
|
showMessage(error?.data?.message, "error");
|
|
@@ -117,20 +117,45 @@
|
|
|
117
117
|
</v-col>
|
|
118
118
|
</v-row>
|
|
119
119
|
</template>
|
|
120
|
+
<template #group-header-chips> </template>
|
|
120
121
|
<template #group-header-append="{ group }">
|
|
121
|
-
<v-
|
|
122
|
-
v-if="group
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
122
|
+
<v-row no-gutters align="center" class="ga-2">
|
|
123
|
+
<v-col v-if="isGroupAnyApproved(group)" cols="auto">
|
|
124
|
+
<v-chip
|
|
125
|
+
size="x-small"
|
|
126
|
+
:color="isGroupComplete(group) ? 'success' : 'warning'"
|
|
127
|
+
variant="tonal"
|
|
128
|
+
:prepend-icon="
|
|
129
|
+
isGroupComplete(group)
|
|
130
|
+
? 'mdi-check-circle-outline'
|
|
131
|
+
: 'mdi-progress-clock'
|
|
132
|
+
"
|
|
133
|
+
class="text-none"
|
|
134
|
+
>
|
|
135
|
+
{{ isGroupComplete(group) ? "Completed" : "Ongoing" }}
|
|
136
|
+
<template v-if="getGroupCompletedByName(group)">
|
|
137
|
+
· {{ getGroupCompletedByName(group) }}
|
|
138
|
+
</template>
|
|
139
|
+
</v-chip>
|
|
140
|
+
</v-col>
|
|
141
|
+
<v-col
|
|
142
|
+
v-if="group.attachments && group.attachments.length > 0"
|
|
143
|
+
cols="auto"
|
|
144
|
+
>
|
|
145
|
+
<v-btn
|
|
146
|
+
size="x-small"
|
|
147
|
+
variant="tonal"
|
|
148
|
+
color="primary"
|
|
149
|
+
class="text-none"
|
|
150
|
+
prepend-icon="mdi-paperclip"
|
|
151
|
+
@click.stop="openAttachmentDialog(group.set, group.attachments)"
|
|
152
|
+
>
|
|
153
|
+
{{ group.attachments.length }} attachment{{
|
|
154
|
+
group.attachments.length > 1 ? "s" : ""
|
|
155
|
+
}}
|
|
156
|
+
</v-btn>
|
|
157
|
+
</v-col>
|
|
158
|
+
</v-row>
|
|
134
159
|
</template>
|
|
135
160
|
</TableHygiene>
|
|
136
161
|
</v-col>
|
|
@@ -328,6 +353,36 @@ function getKey(item: any, set?: number): string {
|
|
|
328
353
|
return `${item.unit}_${set ?? ""}`;
|
|
329
354
|
}
|
|
330
355
|
|
|
356
|
+
function isGroupComplete(group: { set: number; items: any[] }): boolean {
|
|
357
|
+
return (
|
|
358
|
+
group.items.length > 0 &&
|
|
359
|
+
group.items.every(
|
|
360
|
+
(item: any) =>
|
|
361
|
+
item.approve === true ||
|
|
362
|
+
activeActions[getKey(item, group.set)] === "approve"
|
|
363
|
+
)
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function isGroupAnyApproved(group: { set: number; items: any[] }): boolean {
|
|
368
|
+
return group.items.some(
|
|
369
|
+
(item: any) =>
|
|
370
|
+
item.approve === true ||
|
|
371
|
+
activeActions[getKey(item, group.set)] === "approve"
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function getGroupCompletedByName(group: {
|
|
376
|
+
completedByName: string | null;
|
|
377
|
+
items: any[];
|
|
378
|
+
}): string | null {
|
|
379
|
+
return (
|
|
380
|
+
group.completedByName ??
|
|
381
|
+
group.items.find((item: any) => item.completedByName)?.completedByName ??
|
|
382
|
+
null
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
331
386
|
function isSetFullyApproved(setNumber: number): boolean {
|
|
332
387
|
const group = items.value.find((g: any) => g.set === setNumber);
|
|
333
388
|
if (!group) return false;
|