@7365admin1/layer-common 1.11.54 → 3.0.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 +16 -0
- package/components/BuildingForm.vue +203 -21
- package/components/BuildingManagement/buildings.vue +2 -2
- package/components/BuildingManagement/units.vue +5 -5
- package/components/BuildingUnitFormAdd.vue +4 -4
- package/components/BuildingUnitFormEdit.vue +17 -13
- package/components/DocumentManagement.vue +9 -1
- package/components/Facility/BookingSetup.vue +9 -9
- package/components/OnlineFormConfigurationForm.vue +1 -1
- package/components/OnlineFormsConfiguration.vue +24 -2
- package/components/VehicleForm.vue +89 -50
- package/components/VehicleManagement.vue +10 -4
- package/components/VisitorForm.vue +67 -43
- package/components/VisitorManagement.vue +10 -6
- package/composables/useBuilding.ts +32 -3
- package/composables/useBuildingLevel.ts +31 -0
- package/composables/useSecurityUtils.ts +3 -3
- package/package.json +1 -1
- package/types/building.d.ts +14 -2
- package/types/vehicle.d.ts +9 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- f4ee57d: Refactor Building Management Module
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 34bd7cf: Update on Building Unit Page
|
|
12
|
+
|
|
13
|
+
## 2.0.0
|
|
14
|
+
|
|
15
|
+
### Major Changes
|
|
16
|
+
|
|
17
|
+
- f4ee57d: Refactor Building Management Module
|
|
18
|
+
|
|
3
19
|
## 1.11.54
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<v-toolbar>
|
|
4
4
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
5
|
<span class="font-weight-bold text-h5 text-capitalize">
|
|
6
|
-
{{ prop.mode }} Block
|
|
6
|
+
{{ prop.mode }} Block {{ (prop.mode === "edit" && building.block) ? `- ${building.block}` : "" }}
|
|
7
7
|
</span>
|
|
8
8
|
</v-row>
|
|
9
9
|
</v-toolbar>
|
|
@@ -12,21 +12,21 @@
|
|
|
12
12
|
<v-row no-gutters class="px-6 pt-4">
|
|
13
13
|
<v-col cols="12" class="mt-2">
|
|
14
14
|
<v-row no-gutters>
|
|
15
|
-
<InputLabel class="text-capitalize font-weight-bold" title="Name" required />
|
|
15
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Block Name" required />
|
|
16
16
|
<v-col cols="12">
|
|
17
17
|
<v-text-field v-model="building.name" density="comfortable" :rules="[requiredRule]"></v-text-field>
|
|
18
18
|
</v-col>
|
|
19
19
|
</v-row>
|
|
20
20
|
</v-col>
|
|
21
21
|
|
|
22
|
-
<v-col cols="12">
|
|
22
|
+
<v-col v-if="prop.mode === 'add'" cols="12">
|
|
23
23
|
<v-row>
|
|
24
24
|
<v-col cols="6" class="mt-2">
|
|
25
25
|
<v-row no-gutters>
|
|
26
|
-
<InputLabel class="text-capitalize font-weight-bold" title="Block" required />
|
|
26
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Block No." required />
|
|
27
27
|
<v-col cols="12">
|
|
28
28
|
<v-select v-model.number="building.block" :items="blocks" item-title="label" item-value="value"
|
|
29
|
-
density="comfortable" :
|
|
29
|
+
density="comfortable" :rules="[
|
|
30
30
|
requiredRule,
|
|
31
31
|
() =>
|
|
32
32
|
(building.block && building.block > 0) ||
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
<v-col cols="6" class="mt-2">
|
|
45
45
|
<v-row no-gutters>
|
|
46
|
-
<InputLabel class="text-capitalize font-weight-bold" title="Levels" required />
|
|
46
|
+
<InputLabel class="text-capitalize font-weight-bold" title="No. of Levels" required />
|
|
47
47
|
<v-col cols="12">
|
|
48
48
|
<v-text-field v-model.number="buildingLevels" density="comfortable" :rules="[requiredRule]"
|
|
49
49
|
type="number" @update:model-value="setBuildingLevels()"></v-text-field>
|
|
@@ -53,24 +53,33 @@
|
|
|
53
53
|
</v-row>
|
|
54
54
|
</v-col>
|
|
55
55
|
|
|
56
|
-
<v-col v-if="buildingLevels" cols="12">
|
|
56
|
+
<!-- <v-col v-if="buildingLevels &&" cols="12">
|
|
57
57
|
<v-row justify="center">
|
|
58
58
|
<v-col cols="6">
|
|
59
59
|
<v-btn block color="primary" variant="text" class="text-none font-weight-bold" text="Set level labels"
|
|
60
60
|
@click="show = !show"></v-btn>
|
|
61
61
|
</v-col>
|
|
62
62
|
</v-row>
|
|
63
|
-
</v-col>
|
|
63
|
+
</v-col> -->
|
|
64
|
+
</v-row>
|
|
65
|
+
|
|
66
|
+
<v-row no-gutters v-if="building.levels.length > 0 || newLevelsArray.length > 0" class="mt-2">
|
|
67
|
+
<InputLabel class="text-capitalize font-weight-bold px-6 mb-2" title="Levels" />
|
|
64
68
|
</v-row>
|
|
65
69
|
|
|
66
70
|
<v-expand-transition>
|
|
67
|
-
<v-row v-
|
|
71
|
+
<v-row v-if="prop.mode === 'edit'" no-gutters class="px-6">
|
|
68
72
|
<template v-for="(level, levelIndex) in building.levels" :key="levelIndex">
|
|
69
73
|
<v-col cols="12">
|
|
70
74
|
<v-row no-gutters>
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
<v-col :cols="prop.mode === 'edit' ? 10 : 12">
|
|
76
|
+
<v-text-field v-model.trim="building.levels[levelIndex].name" density="comfortable"></v-text-field>
|
|
77
|
+
</v-col>
|
|
78
|
+
<v-col v-if="prop.mode === 'edit'" cols="2" class="d-flex align-center pb-5 justify-end">
|
|
79
|
+
<v-btn icon variant="text" color="error" :disabled="disable"
|
|
80
|
+
@click="openDeleteLevelPrompt(levelIndex)">
|
|
81
|
+
<v-icon icon="mdi-trash-can-outline"></v-icon>
|
|
82
|
+
</v-btn>
|
|
74
83
|
</v-col>
|
|
75
84
|
</v-row>
|
|
76
85
|
</v-col>
|
|
@@ -78,9 +87,43 @@
|
|
|
78
87
|
</v-row>
|
|
79
88
|
</v-expand-transition>
|
|
80
89
|
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
<v-row no-gutters class="px-6 w-100">
|
|
93
|
+
<v-row no-gutters v-for="(newLevelsItem, index) in newLevelsArray" :key="index" :cols="12" class="w-100">
|
|
94
|
+
<v-text-field v-model.trim="newLevelsArray[index]" density="comfortable"></v-text-field>
|
|
95
|
+
<v-col cols="2" class="d-flex align-center pb-5 justify-end">
|
|
96
|
+
<v-btn icon variant="text" color="error" @click="newLevelsArray.splice(index, 1)">
|
|
97
|
+
<v-icon icon="mdi-trash-can-outline"></v-icon>
|
|
98
|
+
</v-btn>
|
|
99
|
+
</v-col>
|
|
100
|
+
</v-row>
|
|
101
|
+
</v-row>
|
|
102
|
+
|
|
103
|
+
<v-row v-if="prop.mode === 'edit'" no-gutters class="px-6 w-100">
|
|
104
|
+
<v-col cols="10">
|
|
105
|
+
<v-text-field v-model.trim="activeNewLevelInput" density="comfortable" class="w-100"
|
|
106
|
+
placeholder="Add new level" @click="addNewLevelErrorMessage = ''"></v-text-field>
|
|
107
|
+
</v-col>
|
|
108
|
+
<v-col cols="2" class="d-flex align-center pb-5 justify-end">
|
|
109
|
+
<v-btn icon variant="text" @click="addNewLevel()">
|
|
110
|
+
<v-icon icon="mdi-plus"></v-icon>
|
|
111
|
+
</v-btn>
|
|
112
|
+
</v-col>
|
|
113
|
+
</v-row>
|
|
114
|
+
<v-row v-if="prop.mode === 'edit'" no-gutters class="px-6 mb-2">
|
|
115
|
+
<span class="text-caption text-error">
|
|
116
|
+
{{ addNewLevelErrorMessage }}
|
|
117
|
+
</span>
|
|
118
|
+
</v-row>
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
81
123
|
<v-col cols="12" class="px-6">
|
|
82
|
-
<InputLabel class="text-capitalize" title="Building Floor plan" />
|
|
83
|
-
<InputFileV2 v-model="building.buildingFiles" :multiple="true" accept="*"
|
|
124
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Building Floor plan" />
|
|
125
|
+
<InputFileV2 v-model="building.buildingFiles" :multiple="true" accept="*" :max-length="10"
|
|
126
|
+
title="Upload Files" />
|
|
84
127
|
</v-col>
|
|
85
128
|
|
|
86
129
|
<v-col cols="12" class="mt-2">
|
|
@@ -121,10 +164,40 @@
|
|
|
121
164
|
</v-col>
|
|
122
165
|
</v-row>
|
|
123
166
|
</v-toolbar>
|
|
167
|
+
|
|
168
|
+
<ConfirmDialog v-model="confirmDeleteLevelDialog" :loading="loading.deletingLevel" width="450" persistent>
|
|
169
|
+
<template #title>
|
|
170
|
+
Delete Level
|
|
171
|
+
</template>
|
|
172
|
+
|
|
173
|
+
<template #description>
|
|
174
|
+
Are you sure you want to delete {{ levelPendingDeleteName || "this level" }}?
|
|
175
|
+
</template>
|
|
176
|
+
|
|
177
|
+
<template #footer>
|
|
178
|
+
<v-row no-gutters class="w-100">
|
|
179
|
+
<v-col cols="6">
|
|
180
|
+
<v-btn tile block size="48" variant="text" class="text-none" :disabled="loading.deletingLevel"
|
|
181
|
+
@click="closeDeleteLevelPrompt">
|
|
182
|
+
Cancel
|
|
183
|
+
</v-btn>
|
|
184
|
+
</v-col>
|
|
185
|
+
|
|
186
|
+
<v-col cols="6">
|
|
187
|
+
<v-btn tile block size="48" variant="flat" color="error" class="text-none" :loading="loading.deletingLevel"
|
|
188
|
+
:disabled="loading.deletingLevel" @click="confirmDeleteLevel">
|
|
189
|
+
Delete
|
|
190
|
+
</v-btn>
|
|
191
|
+
</v-col>
|
|
192
|
+
</v-row>
|
|
193
|
+
</template>
|
|
194
|
+
</ConfirmDialog>
|
|
124
195
|
</v-card>
|
|
125
196
|
</template>
|
|
126
197
|
|
|
127
198
|
<script setup lang="ts">
|
|
199
|
+
import InputLabel from './InputLabel.vue';
|
|
200
|
+
|
|
128
201
|
const prop = defineProps({
|
|
129
202
|
site: {
|
|
130
203
|
type: String,
|
|
@@ -152,6 +225,7 @@ const prop = defineProps({
|
|
|
152
225
|
|
|
153
226
|
const { getSiteById } = useSite();
|
|
154
227
|
const { getFileById } = useFile();
|
|
228
|
+
const { deleteById, batchUpdateLevels } = useBuildingLevel();
|
|
155
229
|
|
|
156
230
|
const site = ref<TSite | null>(null);
|
|
157
231
|
|
|
@@ -184,21 +258,64 @@ const blocks = computed(() => {
|
|
|
184
258
|
return formattedArray;
|
|
185
259
|
});
|
|
186
260
|
|
|
187
|
-
const emit = defineEmits(["cancel", "success", "success:create-more"]);
|
|
261
|
+
const emit = defineEmits(["cancel", "success", "success:create-more", "refresh"]);
|
|
188
262
|
|
|
189
263
|
const validForm = ref(false);
|
|
190
264
|
|
|
191
265
|
const buildingLevels = ref(0);
|
|
266
|
+
const newLevelsArray = ref<string[]>([])
|
|
267
|
+
const activeNewLevelInput = ref<string>("")
|
|
268
|
+
const addNewLevelErrorMessage = ref("");
|
|
269
|
+
|
|
270
|
+
const loading = reactive({
|
|
271
|
+
deletingLevel: false,
|
|
272
|
+
});
|
|
192
273
|
|
|
193
274
|
const show = ref(false);
|
|
275
|
+
const confirmDeleteLevelDialog = ref(false);
|
|
276
|
+
const levelPendingDeleteIndex = ref<number | null>(null);
|
|
277
|
+
const levelActionLoading = ref(false);
|
|
278
|
+
|
|
279
|
+
const levelPendingDeleteName = computed(() => {
|
|
280
|
+
if (levelPendingDeleteIndex.value === null) return "";
|
|
281
|
+
return building.value.levels[levelPendingDeleteIndex.value]?.name ?? "";
|
|
282
|
+
});
|
|
194
283
|
|
|
195
284
|
function setBuildingLevels() {
|
|
196
|
-
|
|
285
|
+
newLevelsArray.value = [];
|
|
197
286
|
for (let index = 0; index < buildingLevels.value; index++) {
|
|
198
|
-
|
|
287
|
+
newLevelsArray.value.push(`Lvl${index + 1}`);
|
|
199
288
|
}
|
|
200
289
|
}
|
|
201
290
|
|
|
291
|
+
// function addNewLevels() {
|
|
292
|
+
// const levelsToAdd = newLevelsInput.value
|
|
293
|
+
// .split(/\r?\n|,/)
|
|
294
|
+
// .map((item) => item.trim())
|
|
295
|
+
// .filter(Boolean);
|
|
296
|
+
|
|
297
|
+
// if (!levelsToAdd.length) return;
|
|
298
|
+
// buildingLevels.value = building.value.levels.length;
|
|
299
|
+
// newLevelsInput.value = "";
|
|
300
|
+
// }
|
|
301
|
+
|
|
302
|
+
function openDeleteLevelPrompt(levelIndex: number) {
|
|
303
|
+
levelPendingDeleteIndex.value = levelIndex;
|
|
304
|
+
confirmDeleteLevelDialog.value = true;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function closeDeleteLevelPrompt() {
|
|
308
|
+
confirmDeleteLevelDialog.value = false;
|
|
309
|
+
levelPendingDeleteIndex.value = null;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async function deleteLevelPlaceholder(levelName: string, levelIndex: number) {
|
|
313
|
+
// Placeholder integration for future delete-level API call.
|
|
314
|
+
return { success: true, levelName, levelIndex };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
202
319
|
const building = ref<TBuilding>({
|
|
203
320
|
site: "",
|
|
204
321
|
name: "",
|
|
@@ -207,13 +324,17 @@ const building = ref<TBuilding>({
|
|
|
207
324
|
buildingFiles: []
|
|
208
325
|
});
|
|
209
326
|
|
|
327
|
+
const initialBuildingLevels = ref([])
|
|
328
|
+
|
|
210
329
|
// Normalize buildingFiles: extract IDs for InputFileV2, keep names in a separate map
|
|
211
330
|
const buildingFilesNames = ref<Record<string, string>>({});
|
|
212
331
|
|
|
213
332
|
building.value.site = prop.site;
|
|
214
333
|
if (prop.mode === "edit") {
|
|
215
334
|
building.value = JSON.parse(JSON.stringify(prop.building));
|
|
335
|
+
building.value.levels = building.value.levels.map((level: any) => ({ _id: level._id, name: level.name })); //temporary
|
|
216
336
|
buildingLevels.value = building.value.levels.length;
|
|
337
|
+
initialBuildingLevels.value = JSON.parse(JSON.stringify(building.value.levels));
|
|
217
338
|
|
|
218
339
|
const rawFiles = building.value.buildingFiles as any[];
|
|
219
340
|
if (rawFiles?.length && typeof rawFiles[0] === 'object') {
|
|
@@ -256,16 +377,34 @@ async function submit() {
|
|
|
256
377
|
try {
|
|
257
378
|
if (prop.mode === "add") {
|
|
258
379
|
const buildingPayload = { ...building.value };
|
|
259
|
-
|
|
260
|
-
|
|
380
|
+
|
|
381
|
+
let payload: TBuildingPayload = {
|
|
382
|
+
site: buildingPayload.site,
|
|
383
|
+
name: buildingPayload.name,
|
|
384
|
+
block: buildingPayload.block,
|
|
385
|
+
levels: [...newLevelsArray.value],
|
|
386
|
+
buildingFiles: (building.value.buildingFiles as string[] || []).map((id) => ({ id, name: buildingFilesNames.value[id] ?? "" }))
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
await createBuilding(payload);
|
|
261
390
|
}
|
|
262
391
|
|
|
263
392
|
if (prop.mode === "edit") {
|
|
393
|
+
|
|
394
|
+
console.log('Updating building with levels:', building.value.levels);
|
|
395
|
+
|
|
396
|
+
if(JSON.stringify(initialBuildingLevels.value) !== JSON.stringify(building.value.levels)) {
|
|
397
|
+
await batchUpdateLevels(building.value.levels as { _id: string; name: string }[]);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const newLevels = [...newLevelsArray.value, ...(activeNewLevelInput.value.trim() ? [activeNewLevelInput.value.trim()] : [])];
|
|
401
|
+
|
|
264
402
|
await updateById(building.value._id ?? "", {
|
|
265
403
|
name: building.value.name,
|
|
266
404
|
block: building.value.block,
|
|
267
|
-
levels: building.value.levels,
|
|
268
|
-
buildingFiles: (building.value.buildingFiles as string[] || []).map((id) => ({ id, name: buildingFilesNames.value[id] ?? "" }))
|
|
405
|
+
// levels: building.value.levels,
|
|
406
|
+
buildingFiles: (building.value.buildingFiles as string[] || []).map((id) => ({ id, name: buildingFilesNames.value[id] ?? "" })),
|
|
407
|
+
...(newLevels.length > 0 ? { levels: newLevels } : {})
|
|
269
408
|
});
|
|
270
409
|
}
|
|
271
410
|
|
|
@@ -288,6 +427,49 @@ async function submit() {
|
|
|
288
427
|
}
|
|
289
428
|
}
|
|
290
429
|
|
|
430
|
+
|
|
431
|
+
const addNewLevel = () => {
|
|
432
|
+
if (!activeNewLevelInput.value.trim()) {
|
|
433
|
+
addNewLevelErrorMessage.value = "Please fill in the current new level before adding another.";
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
newLevelsArray.value.push(activeNewLevelInput.value);
|
|
437
|
+
activeNewLevelInput.value = "";
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const confirmDeleteLevel = async () => {
|
|
441
|
+
const levelIndex = levelPendingDeleteIndex.value;
|
|
442
|
+
if (levelIndex === null) {
|
|
443
|
+
console.error("No level selected for deletion.");
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const levelId = building.value.levels[levelIndex]._id;
|
|
447
|
+
if (!levelId) {
|
|
448
|
+
console.error("Level ID is missing. Cannot delete level.");
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
try {
|
|
453
|
+
loading.deletingLevel = true;
|
|
454
|
+
await deleteById(levelId);
|
|
455
|
+
const index = building.value.levels.findIndex(level => level._id === levelId);
|
|
456
|
+
closeDeleteLevelPrompt();
|
|
457
|
+
if (index !== -1) {
|
|
458
|
+
building.value.levels.splice(index, 1);
|
|
459
|
+
buildingLevels.value = building.value.levels.length;
|
|
460
|
+
}
|
|
461
|
+
emit('refresh')
|
|
462
|
+
} catch (error: any) {
|
|
463
|
+
console.error("Failed to delete level:", error);
|
|
464
|
+
const message = error.response?._data?.message || "Failed to delete level";
|
|
465
|
+
message.value = message;
|
|
466
|
+
} finally {
|
|
467
|
+
loading.deletingLevel = false;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
}
|
|
472
|
+
|
|
291
473
|
watch(buildingLevels, (newVal) => {
|
|
292
474
|
setTimeout(() => {
|
|
293
475
|
show.value = newVal > 0 && !!newVal;
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
<v-dialog v-model="createDialog" width="450" persistent>
|
|
44
44
|
<BuildingForm :site="site" :blocks="items" @cancel="createDialog = false" @success="successCreate()"
|
|
45
45
|
@success:create-more="getBuildings()" />
|
|
46
|
-
</v-dialog>
|
|
46
|
+
</v-dialog>
|
|
47
47
|
|
|
48
48
|
<!-- Edit Dialog -->
|
|
49
49
|
<v-dialog v-model="editDialog" width="450" persistent>
|
|
50
50
|
<BuildingForm :site="site" :blocks="items" mode="edit" @cancel="editDialog = false" @success="successUpdate()"
|
|
51
|
-
:building="selectedBuilding" />
|
|
51
|
+
:building="selectedBuilding" @refresh="getBuildings()" />
|
|
52
52
|
</v-dialog>
|
|
53
53
|
|
|
54
54
|
<!-- Preview Dialog -->
|
|
@@ -103,12 +103,12 @@ const props = defineProps({
|
|
|
103
103
|
},
|
|
104
104
|
{
|
|
105
105
|
title: "Level",
|
|
106
|
-
value: "level",
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
title: "Block",
|
|
110
|
-
value: "block",
|
|
106
|
+
value: "level.name",
|
|
111
107
|
},
|
|
108
|
+
// {
|
|
109
|
+
// title: "Block",
|
|
110
|
+
// value: "block",
|
|
111
|
+
// },
|
|
112
112
|
{
|
|
113
113
|
title: "Block Name",
|
|
114
114
|
value: "buildingName",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
item-value="_id" v-model:search="searchBuilding" :hide-no-data="false" density="comfortable"
|
|
32
32
|
:rules="[requiredRule]" variant="outlined">
|
|
33
33
|
<template v-slot:item="{ props: itemProps, item }">
|
|
34
|
-
<v-list-item v-bind="itemProps" :title="
|
|
34
|
+
<v-list-item v-bind="itemProps" :title="item?.raw?.name">
|
|
35
35
|
|
|
36
36
|
</v-list-item>
|
|
37
37
|
</template>
|
|
38
38
|
<template v-slot:selection="{ item }">
|
|
39
|
-
{{ buildingUnit.building &&
|
|
39
|
+
{{ buildingUnit.building && `${item?.raw?.name}` }}
|
|
40
40
|
</template>
|
|
41
41
|
</v-autocomplete>
|
|
42
42
|
</v-col>
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
<v-row no-gutters>
|
|
48
48
|
<InputLabel class="text-capitalize" title="Level" required />
|
|
49
49
|
<v-col cols="12">
|
|
50
|
-
<v-select v-model="buildingUnit.level" :items="buildingLevels" density="comfortable"
|
|
50
|
+
<v-select v-model="buildingUnit.level" :items="buildingLevels" item-title="name" item-value="_id" density="comfortable"
|
|
51
51
|
:rules="[requiredRule]"></v-select>
|
|
52
52
|
</v-col>
|
|
53
53
|
</v-row>
|
|
@@ -275,7 +275,7 @@ watchEffect(() => {
|
|
|
275
275
|
|
|
276
276
|
const buildingUnitQty = ref(1);
|
|
277
277
|
|
|
278
|
-
const buildingUnit = ref<
|
|
278
|
+
const buildingUnit = ref<TBuildingUnitPayload>({
|
|
279
279
|
site: "",
|
|
280
280
|
name: "Unit",
|
|
281
281
|
building: "",
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
|
|
30
30
|
<v-col cols="12" md="6" lg="4" class="mt-2">
|
|
31
31
|
<v-row no-gutters>
|
|
32
|
-
<InputLabel class="text-capitalize font-weight-bold" title="Level"
|
|
32
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Level"/>
|
|
33
33
|
<v-col cols="12">
|
|
34
|
-
<v-select v-model="buildingUnit.level" :items="buildingLevels" density="comfortable"
|
|
35
|
-
:rules="[requiredRule]"></v-select>
|
|
34
|
+
<!-- <v-select v-model="buildingUnit.level" :items="buildingLevels" readonly item-title="name" class="no-pointer" item-value="_id" density="comfortable"
|
|
35
|
+
:rules="[requiredRule]"></v-select> -->
|
|
36
|
+
<v-text-field :model-value="buildingUnit.level.name" density="comfortable" readonly class="no-pointer" />
|
|
36
37
|
</v-col>
|
|
37
38
|
</v-row>
|
|
38
39
|
</v-col>
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
<v-row no-gutters>
|
|
44
45
|
<InputLabel class="text-capitalize font-weight-bold" title="Block Name" />
|
|
45
46
|
<v-col cols="12">
|
|
46
|
-
<v-text-field :model-value="
|
|
47
|
+
<v-text-field :model-value="buildingUnit.buildingName"
|
|
47
48
|
density="comfortable" readonly class="no-pointer"></v-text-field>
|
|
48
49
|
</v-col>
|
|
49
50
|
</v-row>
|
|
@@ -328,7 +329,10 @@ const buildingUnit = ref({
|
|
|
328
329
|
ownerName: "",
|
|
329
330
|
building: "",
|
|
330
331
|
buildingName: "",
|
|
331
|
-
level:
|
|
332
|
+
level: {
|
|
333
|
+
_id: "",
|
|
334
|
+
name: "",
|
|
335
|
+
},
|
|
332
336
|
// category: "",
|
|
333
337
|
block: null,
|
|
334
338
|
status: "active",
|
|
@@ -457,13 +461,13 @@ const selectedBuilding = computed(() => {
|
|
|
457
461
|
return buildings.value.find((b) => b.value === buildingUnit.value.building);
|
|
458
462
|
});
|
|
459
463
|
|
|
460
|
-
const buildingLevels = computed(() => {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
});
|
|
464
|
+
// const buildingLevels = computed(() => {
|
|
465
|
+
// const levels = selectedBuilding.value?.levels ?? [];
|
|
466
|
+
// return levels.map((level: { name: string; _id: string }) => ({
|
|
467
|
+
// name: level.name,
|
|
468
|
+
// value: level._id,
|
|
469
|
+
// }))
|
|
470
|
+
// });
|
|
467
471
|
|
|
468
472
|
const disable = ref(false);
|
|
469
473
|
|
|
@@ -500,7 +504,7 @@ async function submit() {
|
|
|
500
504
|
|
|
501
505
|
await updateById(buildingUnit.value._id ?? "", {
|
|
502
506
|
name: buildingUnit.value.name,
|
|
503
|
-
level: buildingUnit.value.level,
|
|
507
|
+
level: buildingUnit.value.level._id,
|
|
504
508
|
// category: buildingUnit.value.category,
|
|
505
509
|
buildingUnitFiles: (buildingUnit.value.buildingUnitFiles as string[] || []).map((id) => ({ id, name: buildingUnitFilesNames.value[id] ?? "" })),
|
|
506
510
|
companyName: buildingUnit.value.companyName,
|
|
@@ -276,13 +276,16 @@
|
|
|
276
276
|
<v-col cols="6" class="text-body-1">Document</v-col>
|
|
277
277
|
<v-col cols="6" class="text-right text-body-1">
|
|
278
278
|
<NuxtLink
|
|
279
|
-
v-if="selectedDocument?.attachment"
|
|
279
|
+
v-if="selectedDocument?.attachment && isViewable"
|
|
280
280
|
:to="getFileUrl(selectedDocument.attachment)"
|
|
281
281
|
external
|
|
282
282
|
target="_blank"
|
|
283
283
|
>
|
|
284
284
|
View Document
|
|
285
285
|
</NuxtLink>
|
|
286
|
+
<span v-else-if="selectedDocument?.attachment" class="text-grey" style="opacity: 0.6; cursor: not-allowed;">
|
|
287
|
+
View Document
|
|
288
|
+
</span>
|
|
286
289
|
<span v-else>N/A</span>
|
|
287
290
|
</v-col>
|
|
288
291
|
</v-row>
|
|
@@ -660,6 +663,11 @@ const selectedDocument = ref<TDocument>({
|
|
|
660
663
|
type: "",
|
|
661
664
|
});
|
|
662
665
|
|
|
666
|
+
const isViewable = computed(() => {
|
|
667
|
+
const lowerType = String(selectedDocument.value?.type || "").trim().toLowerCase();
|
|
668
|
+
return ["pdf", "doc", "csv"].includes(lowerType);
|
|
669
|
+
});
|
|
670
|
+
|
|
663
671
|
const previewDetails = computed(() => {
|
|
664
672
|
const document = selectedDocument.value as Record<string, any>;
|
|
665
673
|
const fileType =
|
|
@@ -548,7 +548,7 @@
|
|
|
548
548
|
</v-col>
|
|
549
549
|
<v-col cols="12" class="mt-4">
|
|
550
550
|
<v-number-input
|
|
551
|
-
v-model="facility.
|
|
551
|
+
v-model="facility.maxNumberGuestLimit"
|
|
552
552
|
:reverse="false"
|
|
553
553
|
controlVariant="default"
|
|
554
554
|
label="Maximum no. of guests"
|
|
@@ -1015,30 +1015,30 @@ const handlePolicy = (newContent: string) => {
|
|
|
1015
1015
|
|
|
1016
1016
|
function onToggleBookingUnitLimit(val: any) {
|
|
1017
1017
|
if (val) {
|
|
1018
|
-
|
|
1018
|
+
facility.value.isBookingUnitLimitEnabled = true;
|
|
1019
1019
|
facility.value.bookingUnitLimit = 1;
|
|
1020
1020
|
} else {
|
|
1021
|
-
|
|
1021
|
+
facility.value.isBookingUnitLimitEnabled = false;
|
|
1022
1022
|
facility.value.bookingUnitLimit = null;
|
|
1023
1023
|
}
|
|
1024
1024
|
}
|
|
1025
1025
|
|
|
1026
1026
|
function onToggleMaxNumberGuestLimit(val: any) {
|
|
1027
1027
|
if (val) {
|
|
1028
|
-
|
|
1029
|
-
facility.value.
|
|
1028
|
+
facility.value.isMaxNumberGuestLimitEnabled = true;
|
|
1029
|
+
facility.value.maxNumberGuestLimit = 1;
|
|
1030
1030
|
} else {
|
|
1031
|
-
|
|
1032
|
-
facility.value.
|
|
1031
|
+
facility.value.isMaxNumberGuestLimitEnabled = false;
|
|
1032
|
+
facility.value.maxNumberGuestLimit = null;
|
|
1033
1033
|
}
|
|
1034
1034
|
}
|
|
1035
1035
|
|
|
1036
1036
|
function onToggleCancelAllowedLimit(val: any) {
|
|
1037
1037
|
if (val) {
|
|
1038
|
-
|
|
1038
|
+
facility.value.isCancelAllowedLimitEnabled = true;
|
|
1039
1039
|
facility.value.daysAllowedCancel = 1;
|
|
1040
1040
|
} else {
|
|
1041
|
-
|
|
1041
|
+
facility.value.isCancelAllowedLimitEnabled = false;
|
|
1042
1042
|
facility.value.daysAllowedCancel = null;
|
|
1043
1043
|
}
|
|
1044
1044
|
}
|
|
@@ -267,7 +267,7 @@ const { create: _add, updateById: _update, getAll: _getAll } = useOnlineFormConf
|
|
|
267
267
|
|
|
268
268
|
const { data: existingFormsData } = useLazyAsyncData(
|
|
269
269
|
`online-form-configurations-filter-${siteId}-${Date.now()}`,
|
|
270
|
-
() => _getAll({ site: siteId, org: orgId, limit: 100 })
|
|
270
|
+
() => _getAll({ site: siteId, org: orgId, status: "active", limit: 100 })
|
|
271
271
|
);
|
|
272
272
|
|
|
273
273
|
const availableTemplateNames = computed(() => {
|
|
@@ -32,6 +32,16 @@
|
|
|
32
32
|
>
|
|
33
33
|
<v-icon>mdi-refresh</v-icon>
|
|
34
34
|
</v-btn>
|
|
35
|
+
<v-text-field
|
|
36
|
+
v-model="search"
|
|
37
|
+
density="compact"
|
|
38
|
+
variant="outlined"
|
|
39
|
+
placeholder="Search..."
|
|
40
|
+
prepend-inner-icon="mdi-magnify"
|
|
41
|
+
clearable
|
|
42
|
+
hide-details
|
|
43
|
+
style="width: 220px; margin-left: 12px;"
|
|
44
|
+
/>
|
|
35
45
|
</template>
|
|
36
46
|
|
|
37
47
|
<template #append>
|
|
@@ -263,6 +273,8 @@
|
|
|
263
273
|
<script setup lang="ts">
|
|
264
274
|
import OnlineFormConfigurationForm from "./OnlineFormConfigurationForm.vue";
|
|
265
275
|
import OnlineFormRenderPreview from "./OnlineFormRenderPreview.vue";
|
|
276
|
+
import useFile from "../composables/useFile";
|
|
277
|
+
import useOnlineFormConfiguration from "../composables/useOnlineFormConfiguration";
|
|
266
278
|
|
|
267
279
|
definePageMeta({
|
|
268
280
|
middleware: ["01-auth", "02-org"],
|
|
@@ -306,13 +318,13 @@ const props = defineProps({
|
|
|
306
318
|
},
|
|
307
319
|
});
|
|
308
320
|
|
|
309
|
-
const { headerSearch } = useLocal();
|
|
310
321
|
const { getAll: _getAll, deleteById: _deleteById } = useOnlineFormConfiguration();
|
|
311
322
|
const { getFileUrl } = useFile();
|
|
312
323
|
|
|
313
324
|
const page = ref(1);
|
|
314
325
|
const pages = ref(0);
|
|
315
326
|
const pageRange = ref("-- - -- of --");
|
|
327
|
+
const search = ref("");
|
|
316
328
|
|
|
317
329
|
const message = ref("");
|
|
318
330
|
const messageSnackbar = ref(false);
|
|
@@ -333,7 +345,8 @@ const {
|
|
|
333
345
|
} = useLazyAsyncData("get-all-online-form-configuration", () =>
|
|
334
346
|
_getAll({
|
|
335
347
|
page: page.value,
|
|
336
|
-
search:
|
|
348
|
+
search: search.value,
|
|
349
|
+
status: "active",
|
|
337
350
|
org: orgId,
|
|
338
351
|
site: siteId,
|
|
339
352
|
})
|
|
@@ -341,6 +354,15 @@ const {
|
|
|
341
354
|
|
|
342
355
|
const loading = computed(() => getAllReqStatus.value === "pending");
|
|
343
356
|
|
|
357
|
+
let searchDebounce: ReturnType<typeof setTimeout> | null = null;
|
|
358
|
+
watch(search, () => {
|
|
359
|
+
if (searchDebounce) clearTimeout(searchDebounce);
|
|
360
|
+
searchDebounce = setTimeout(() => {
|
|
361
|
+
page.value = 1;
|
|
362
|
+
getOnlineFormConfigurations();
|
|
363
|
+
}, 400);
|
|
364
|
+
});
|
|
365
|
+
|
|
344
366
|
watchEffect(() => {
|
|
345
367
|
if (getOnlineFormConfigurationReq.value) {
|
|
346
368
|
items.value = getOnlineFormConfigurationReq.value.items;
|