@7365admin1/layer-common 3.0.31-staging.19 → 3.0.31-staging.21
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.
|
@@ -12,6 +12,24 @@
|
|
|
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>
|
|
15
33
|
<v-col cols="12" class="pa-0 mb-2">
|
|
16
34
|
<InputLabel for="name" title="Name" required class="mb-1" />
|
|
17
35
|
<v-text-field
|
|
@@ -87,6 +105,10 @@ const unitOfMeasurementModel = defineModel("unitOfMeasurement", {
|
|
|
87
105
|
type: String,
|
|
88
106
|
default: "",
|
|
89
107
|
});
|
|
108
|
+
const attachmentModel = defineModel("attachment", {
|
|
109
|
+
type: String,
|
|
110
|
+
default: "",
|
|
111
|
+
});
|
|
90
112
|
const showDialog = defineModel({ type: Boolean, default: false });
|
|
91
113
|
|
|
92
114
|
const prop = defineProps({
|
|
@@ -105,6 +127,9 @@ const emit = defineEmits(["saved", "close"]);
|
|
|
105
127
|
const formRef = ref<any>(null);
|
|
106
128
|
const valid = ref(false);
|
|
107
129
|
const submitting = ref(false);
|
|
130
|
+
const attachmentPhotos = ref<string[]>([]);
|
|
131
|
+
const attachmentIds = ref<string[]>([]);
|
|
132
|
+
const photoUploadError = ref("");
|
|
108
133
|
|
|
109
134
|
const { requiredRule } = useUtils();
|
|
110
135
|
|
|
@@ -124,6 +149,29 @@ const unitOfMeasurementOptions = [
|
|
|
124
149
|
watchEffect(() => {
|
|
125
150
|
nameModel.value = prop.equipmentData?.name || "";
|
|
126
151
|
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
|
+
}
|
|
127
175
|
});
|
|
128
176
|
|
|
129
177
|
function close() {
|
|
@@ -147,12 +195,15 @@ async function submit() {
|
|
|
147
195
|
|
|
148
196
|
emit("saved", {
|
|
149
197
|
name: nameModel.value,
|
|
150
|
-
|
|
151
198
|
unitOfMeasurement: unitOfMeasurementModel.value,
|
|
199
|
+
attachment: attachmentModel.value,
|
|
152
200
|
});
|
|
153
201
|
|
|
154
202
|
nameModel.value = "";
|
|
155
203
|
unitOfMeasurementModel.value = "";
|
|
204
|
+
attachmentModel.value = "";
|
|
205
|
+
attachmentPhotos.value = [];
|
|
206
|
+
attachmentIds.value = [];
|
|
156
207
|
|
|
157
208
|
showDialog.value = false;
|
|
158
209
|
emit("close");
|
|
@@ -46,6 +46,19 @@
|
|
|
46
46
|
</v-row>
|
|
47
47
|
</template>
|
|
48
48
|
|
|
49
|
+
<template #item.attachment="{ value }">
|
|
50
|
+
<v-btn
|
|
51
|
+
v-if="value"
|
|
52
|
+
size="small"
|
|
53
|
+
variant="tonal"
|
|
54
|
+
class="text-none"
|
|
55
|
+
@click.stop="viewAttachment(value)"
|
|
56
|
+
>
|
|
57
|
+
View Image
|
|
58
|
+
</v-btn>
|
|
59
|
+
<span v-else>—</span>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
49
62
|
<template #item.status="{ value }">
|
|
50
63
|
<v-chip class="text-capitalize">{{ value || "N/A" }}</v-chip>
|
|
51
64
|
</template>
|
|
@@ -61,6 +74,7 @@
|
|
|
61
74
|
v-model="dialogShowForm"
|
|
62
75
|
v-model:name="equipmentName"
|
|
63
76
|
v-model:unitOfMeasurement="equipmentUnit"
|
|
77
|
+
v-model:attachment="equipmentAttachment"
|
|
64
78
|
:mode="dialogMode"
|
|
65
79
|
:equipmentData="editingEquipment"
|
|
66
80
|
:site="props.site"
|
|
@@ -242,6 +256,29 @@
|
|
|
242
256
|
</v-card>
|
|
243
257
|
</v-dialog>
|
|
244
258
|
|
|
259
|
+
<v-dialog v-model="showAttachmentDialog" max-width="720" persistent>
|
|
260
|
+
<v-card rounded="lg">
|
|
261
|
+
<v-card-title class="d-flex align-center pa-4">
|
|
262
|
+
<span class="text-h6 font-weight-bold">Attachment</span>
|
|
263
|
+
|
|
264
|
+
<v-spacer />
|
|
265
|
+
|
|
266
|
+
<v-btn
|
|
267
|
+
icon="mdi-close"
|
|
268
|
+
variant="text"
|
|
269
|
+
size="small"
|
|
270
|
+
@click="(showAttachmentDialog = false), (attachmentUrl = '')"
|
|
271
|
+
/>
|
|
272
|
+
</v-card-title>
|
|
273
|
+
|
|
274
|
+
<v-divider />
|
|
275
|
+
|
|
276
|
+
<v-card-text class="pa-6">
|
|
277
|
+
<v-img :src="attachmentUrl" contain />
|
|
278
|
+
</v-card-text>
|
|
279
|
+
</v-card>
|
|
280
|
+
</v-dialog>
|
|
281
|
+
|
|
245
282
|
<Snackbar
|
|
246
283
|
v-model="messageSnackbar"
|
|
247
284
|
:text="snackbarMessage"
|
|
@@ -253,6 +290,7 @@ import useEquipment from "../composables/useEquipment";
|
|
|
253
290
|
import useStock from "../composables/useStock";
|
|
254
291
|
import useUtils from "../composables/useUtils";
|
|
255
292
|
import useEquipmentManagement from "../composables/useEquipmentManagement";
|
|
293
|
+
import useFile from "../composables/useFile";
|
|
256
294
|
|
|
257
295
|
const props = defineProps({
|
|
258
296
|
orgId: { type: String, default: "" },
|
|
@@ -280,6 +318,7 @@ const siteName = ref<string>("");
|
|
|
280
318
|
const submitting = ref(false);
|
|
281
319
|
|
|
282
320
|
const headers = [
|
|
321
|
+
{ title: "Image", value: "attachment" },
|
|
283
322
|
{ title: "Name", value: "name" },
|
|
284
323
|
{ title: "Available Stock Qty", value: "qty" },
|
|
285
324
|
{ title: "Status", value: "status" },
|
|
@@ -293,6 +332,7 @@ const {
|
|
|
293
332
|
deleteEquipment,
|
|
294
333
|
} = useEquipment();
|
|
295
334
|
const { debounce, requiredRule } = useUtils();
|
|
335
|
+
const { getFileUrl } = useFile();
|
|
296
336
|
|
|
297
337
|
const searchInput = ref("");
|
|
298
338
|
const startDate = ref("");
|
|
@@ -352,11 +392,21 @@ const dialogMode = ref<"add" | "edit">("add");
|
|
|
352
392
|
const editingEquipment = ref<Record<string, any>>({});
|
|
353
393
|
const equipmentName = ref("");
|
|
354
394
|
const equipmentUnit = ref("");
|
|
395
|
+
const equipmentAttachment = ref("");
|
|
355
396
|
|
|
356
397
|
const stockActionFormRef = ref<any>(null);
|
|
357
398
|
const stockActionValid = ref(false);
|
|
358
399
|
|
|
359
400
|
const snackbarMessage = ref("");
|
|
401
|
+
const showAttachmentDialog = ref(false);
|
|
402
|
+
const attachmentUrl = ref("");
|
|
403
|
+
|
|
404
|
+
function viewAttachment(attachmentId: string) {
|
|
405
|
+
if (!attachmentId) return;
|
|
406
|
+
|
|
407
|
+
attachmentUrl.value = getFileUrl(attachmentId);
|
|
408
|
+
showAttachmentDialog.value = true;
|
|
409
|
+
}
|
|
360
410
|
|
|
361
411
|
function showMessage(msg: string, color: string = "error") {
|
|
362
412
|
message.value = msg;
|
|
@@ -370,6 +420,7 @@ function onCreateUnit() {
|
|
|
370
420
|
editingEquipment.value = {};
|
|
371
421
|
equipmentName.value = "";
|
|
372
422
|
equipmentUnit.value = "";
|
|
423
|
+
equipmentAttachment.value = "";
|
|
373
424
|
dialogShowForm.value = true;
|
|
374
425
|
}
|
|
375
426
|
|
|
@@ -379,6 +430,9 @@ async function _createEquipment() {
|
|
|
379
430
|
const payload: TEquipmentCreate = {
|
|
380
431
|
name: equipmentName.value,
|
|
381
432
|
unitOfMeasurement: equipmentUnit.value,
|
|
433
|
+
...(equipmentAttachment.value
|
|
434
|
+
? { attachment: equipmentAttachment.value }
|
|
435
|
+
: {}),
|
|
382
436
|
};
|
|
383
437
|
|
|
384
438
|
let response;
|
|
@@ -398,6 +452,7 @@ async function _createEquipment() {
|
|
|
398
452
|
editingEquipment.value = {};
|
|
399
453
|
equipmentName.value = "";
|
|
400
454
|
equipmentUnit.value = "";
|
|
455
|
+
equipmentAttachment.value = "";
|
|
401
456
|
|
|
402
457
|
await getEquipmentsRefresh();
|
|
403
458
|
} catch (error: any) {
|
|
@@ -455,6 +510,7 @@ const onEditFromMoreAction = async () => {
|
|
|
455
510
|
editingEquipment.value = response;
|
|
456
511
|
equipmentName.value = response.name || "";
|
|
457
512
|
equipmentUnit.value = response.unitOfMeasurement || "";
|
|
513
|
+
equipmentAttachment.value = response.attachment || "";
|
|
458
514
|
dialogShowForm.value = true;
|
|
459
515
|
};
|
|
460
516
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<div class="w-100 d-flex justify-space-between ga-2">
|
|
13
13
|
<span class="text-subtitle-1 w-100 font-weight-bold mb-3">{{
|
|
14
14
|
formTitle
|
|
15
|
-
|
|
15
|
+
}}</span>
|
|
16
16
|
<span v-if="withStep2 || withStep3" class="text-subtitle-2 font-weight-bold" style="text-wrap: nowrap">Step
|
|
17
17
|
<span class="text-primary-button">{{ contractorStep }}</span>/{{ withStep3 ? 3 : withStep2 ? 2 : 1 }}</span>
|
|
18
18
|
</div>
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
</v-row>
|
|
93
93
|
</v-col>
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
<v-col v-if="shouldShowField('contractorType')" cols="12">
|
|
96
96
|
<InputLabel class="text-capitalize" title="Contractor Type" required />
|
|
97
97
|
<v-combobox v-model="contractorTypeObj" v-model:search="contractorTypeInput" ref="contractorTypeCombo"
|
|
98
98
|
autocomplete="off" :hide-no-data="false" @update:focused="handleFocusedContractorType"
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
<v-list-item-title @click.stop="handleAddNewContractorType" class="d-flex align-center ga-1">
|
|
105
105
|
<span><v-icon icon="mdi-plus" /></span> Add "<strong>{{
|
|
106
106
|
contractorTypeInput
|
|
107
|
-
|
|
107
|
+
}}</strong>" as custom contractor type.
|
|
108
108
|
</v-list-item-title>
|
|
109
109
|
</v-list-item>
|
|
110
110
|
</template>
|
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
<InputLabel class="text-capitalize" title="Company Name" />
|
|
138
138
|
<v-combobox v-model="visitor.company" v-model:search="companyNameInput" ref="companyCombo"
|
|
139
139
|
autocomplete="off" :hide-no-data="false" :items="companyNames" item-value="value"
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
@update:model-value="handleSelectCompanyName" variant="outlined" density="comfortable" persistent-hint
|
|
141
|
+
small-chips>
|
|
142
142
|
<!-- <template v-slot:no-data>
|
|
143
143
|
<v-list-item>
|
|
144
144
|
<v-list-item-title v-if="companyNameInput" @click.stop="handleAddNewCompany"
|
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
class="d-flex align-center ga-1">
|
|
176
176
|
<span><v-icon icon="mdi-plus" /></span>Add "<strong>{{
|
|
177
177
|
companyNameInput
|
|
178
|
-
|
|
178
|
+
}}</strong>" as new company.
|
|
179
179
|
</v-list-item-title>
|
|
180
180
|
<v-list-item-title v-else-if="!companyNameInput && companyNames.length === 0">
|
|
181
181
|
Start typing to search for companies.
|
|
@@ -929,23 +929,34 @@ function getPersonPlateOptions(item: Partial<TPeople>) {
|
|
|
929
929
|
function findMatchingContactOption(options: string[], value?: string | null) {
|
|
930
930
|
const normalizedValue = value?.trim();
|
|
931
931
|
if (!normalizedValue) return "";
|
|
932
|
+
const compactValue = normalizedValue.replace(/\s/g, "");
|
|
932
933
|
|
|
933
934
|
return (
|
|
934
935
|
options.find((option) => option.trim() === normalizedValue) ||
|
|
935
|
-
options.find((option) => option.replace(/\s/g, "") ===
|
|
936
|
+
options.find((option) => option.replace(/\s/g, "") === compactValue) ||
|
|
937
|
+
options.find((option) => option.trim().includes(normalizedValue)) ||
|
|
938
|
+
options.find((option) => option.replace(/\s/g, "").includes(compactValue)) ||
|
|
936
939
|
""
|
|
937
940
|
);
|
|
938
941
|
}
|
|
939
942
|
|
|
943
|
+
function normalizePlateNumber(value?: string | null) {
|
|
944
|
+
return (value ?? "").replace(/[^A-Z0-9]/gi, "").toUpperCase();
|
|
945
|
+
}
|
|
946
|
+
|
|
940
947
|
function normalizePlateOption(value?: string | null) {
|
|
941
948
|
return (value || "").replace(/[^A-Z0-9]/gi, "").toUpperCase();
|
|
942
949
|
}
|
|
943
950
|
|
|
944
951
|
function findMatchingPlateOption(options: string[], value?: string | null) {
|
|
945
|
-
const normalizedValue =
|
|
952
|
+
const normalizedValue = normalizePlateNumber(value);
|
|
946
953
|
if (!normalizedValue) return "";
|
|
947
954
|
|
|
948
|
-
return
|
|
955
|
+
return (
|
|
956
|
+
options.find((option) => normalizePlateNumber(option) === normalizedValue) ||
|
|
957
|
+
options.find((option) => normalizePlateNumber(option).includes(normalizedValue)) ||
|
|
958
|
+
""
|
|
959
|
+
);
|
|
949
960
|
}
|
|
950
961
|
|
|
951
962
|
function applyNricSearchResult(
|
|
@@ -969,11 +980,11 @@ function applyNricSearchResult(
|
|
|
969
980
|
|
|
970
981
|
companyNames.value = Array.isArray(item.companyName) ? item.companyName : [];
|
|
971
982
|
|
|
972
|
-
if(item.companyName && item.companyName.length === 1) {
|
|
983
|
+
if (item.companyName && item.companyName.length === 1) {
|
|
973
984
|
visitor.company = item.companyName?.[0] || visitor.company;
|
|
974
985
|
}
|
|
975
986
|
|
|
976
|
-
if(item.companyName && item.companyName.length > 1){
|
|
987
|
+
if (item.companyName && item.companyName.length > 1) {
|
|
977
988
|
visitor.company = ""
|
|
978
989
|
}
|
|
979
990
|
|
|
@@ -27,6 +27,7 @@ export default function useEquipment() {
|
|
|
27
27
|
name: payload.name,
|
|
28
28
|
unitOfMeasurement: payload.unitOfMeasurement,
|
|
29
29
|
serviceType,
|
|
30
|
+
...(payload.attachment ? { attachment: payload.attachment } : {}),
|
|
30
31
|
},
|
|
31
32
|
}
|
|
32
33
|
);
|
|
@@ -40,6 +41,7 @@ export default function useEquipment() {
|
|
|
40
41
|
body: {
|
|
41
42
|
name: payload.name,
|
|
42
43
|
unitOfMeasurement: payload.unitOfMeasurement,
|
|
44
|
+
...(payload.attachment ? { attachment: payload.attachment } : {}),
|
|
43
45
|
},
|
|
44
46
|
}
|
|
45
47
|
);
|
package/package.json
CHANGED
package/types/equipment.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ declare type TEquipment = {
|
|
|
6
6
|
unitOfMeasurement: string;
|
|
7
7
|
createdAt: string;
|
|
8
8
|
updatedAt: string;
|
|
9
|
+
attachment?: string;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
|
-
declare type TEquipmentCreate = Pick<
|
|
12
|
+
declare type TEquipmentCreate = Pick<
|
|
13
|
+
TEquipment,
|
|
14
|
+
"name" | "unitOfMeasurement" | "attachment"
|
|
15
|
+
>;
|