@iservice365/layer-common 1.3.0 → 1.3.2
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/BuildingForm.vue +303 -0
- package/components/BuildingManagement/buildings.vue +395 -0
- package/components/BuildingManagement/units.vue +412 -0
- package/components/BuildingUnitFormAdd.vue +441 -0
- package/components/BuildingUnitFormEdit.vue +382 -0
- package/components/Chat/Information.vue +1 -1
- package/components/Input/NRICNumber.vue +12 -0
- package/components/TableMain.vue +5 -1
- package/components/VisitorForm.vue +114 -279
- package/components/VisitorManagement.vue +89 -169
- package/components/WorkOrder/Create.vue +5 -1
- package/composables/useBuilding.ts +1 -1
- package/composables/useCommonPermission.ts +77 -0
- package/composables/usePeople.ts +13 -5
- package/composables/useVisitor.ts +74 -51
- package/package.json +1 -1
- package/types/building.d.ts +6 -0
- package/types/people.d.ts +2 -1
- package/types/visitor.d.ts +1 -1
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters>
|
|
3
|
+
<v-col cols="12" class="mb-2">
|
|
4
|
+
<v-row no-gutters>
|
|
5
|
+
<v-btn
|
|
6
|
+
class="text-none"
|
|
7
|
+
rounded="pill"
|
|
8
|
+
variant="tonal"
|
|
9
|
+
@click="setBuilding()"
|
|
10
|
+
size="large"
|
|
11
|
+
v-if="canCreate && canCreateUnit"
|
|
12
|
+
>
|
|
13
|
+
Add Unit
|
|
14
|
+
</v-btn>
|
|
15
|
+
</v-row>
|
|
16
|
+
</v-col>
|
|
17
|
+
<v-col cols="12">
|
|
18
|
+
<v-card
|
|
19
|
+
width="100%"
|
|
20
|
+
variant="outlined"
|
|
21
|
+
border="thin"
|
|
22
|
+
rounded="lg"
|
|
23
|
+
:loading="loading"
|
|
24
|
+
>
|
|
25
|
+
<v-toolbar density="compact" color="grey-lighten-4">
|
|
26
|
+
<template #prepend>
|
|
27
|
+
<v-btn fab icon density="comfortable" @click="getBuildingUnit()">
|
|
28
|
+
<v-icon>mdi-refresh</v-icon>
|
|
29
|
+
</v-btn>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<template #append>
|
|
33
|
+
<v-row no-gutters justify="end" align="center">
|
|
34
|
+
<span class="mr-2 text-caption text-fontgray">
|
|
35
|
+
{{ pageRange }}
|
|
36
|
+
</span>
|
|
37
|
+
<local-pagination
|
|
38
|
+
v-model="page"
|
|
39
|
+
:length="pages"
|
|
40
|
+
@update:value="getBuildingUnit()"
|
|
41
|
+
/>
|
|
42
|
+
</v-row>
|
|
43
|
+
</template>
|
|
44
|
+
</v-toolbar>
|
|
45
|
+
|
|
46
|
+
<v-data-table
|
|
47
|
+
:headers="props.headers"
|
|
48
|
+
:items="items"
|
|
49
|
+
item-value="_id"
|
|
50
|
+
items-per-page="20"
|
|
51
|
+
fixed-header
|
|
52
|
+
hide-default-footer
|
|
53
|
+
hide-default-header
|
|
54
|
+
@click:row="tableRowClickHandler"
|
|
55
|
+
style="max-height: calc(100vh - (200px))"
|
|
56
|
+
>
|
|
57
|
+
<template #item.block="{ value }">
|
|
58
|
+
{{ value ? `blk ${value}` : "" }}
|
|
59
|
+
</template>
|
|
60
|
+
</v-data-table>
|
|
61
|
+
</v-card>
|
|
62
|
+
</v-col>
|
|
63
|
+
|
|
64
|
+
<!-- Create Dialog -->
|
|
65
|
+
<v-dialog v-model="createDialog" width="450" persistent>
|
|
66
|
+
<BuildingUnitFormAdd
|
|
67
|
+
:site="site"
|
|
68
|
+
@cancel="createDialog = false"
|
|
69
|
+
@success="successCreate()"
|
|
70
|
+
@success:create-more="getBuildingUnit()"
|
|
71
|
+
/>
|
|
72
|
+
</v-dialog>
|
|
73
|
+
|
|
74
|
+
<!-- Edit Dialog -->
|
|
75
|
+
<v-dialog v-model="dialogEdit" width="450" persistent>
|
|
76
|
+
<BuildingUnitFormEdit
|
|
77
|
+
v-if="selectedBuildingUnit"
|
|
78
|
+
@cancel="dialogEdit = false"
|
|
79
|
+
@success="successUpdate()"
|
|
80
|
+
:roomFacility="selectedBuildingUnit"
|
|
81
|
+
/>
|
|
82
|
+
</v-dialog>
|
|
83
|
+
|
|
84
|
+
<!-- Preview Dialog -->
|
|
85
|
+
<v-dialog v-if="canViewUnitDetails" v-model="dialogPreview" width="450" persistent>
|
|
86
|
+
<v-card width="100%">
|
|
87
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
|
|
88
|
+
<v-row no-gutters v-if="selectedBuildingUnit" class="mb-4">
|
|
89
|
+
<v-col cols="12">
|
|
90
|
+
<strong>Name:</strong> {{ selectedBuildingUnit.name }}
|
|
91
|
+
</v-col>
|
|
92
|
+
|
|
93
|
+
<v-col cols="12">
|
|
94
|
+
<strong>Block:</strong>
|
|
95
|
+
{{ selectedBuildingUnit.block }}
|
|
96
|
+
</v-col>
|
|
97
|
+
|
|
98
|
+
<v-col cols="12">
|
|
99
|
+
<strong>Floors:</strong>
|
|
100
|
+
{{ selectedBuildingUnit.level }}
|
|
101
|
+
</v-col>
|
|
102
|
+
|
|
103
|
+
<v-col cols="12">
|
|
104
|
+
<strong>Category:</strong>
|
|
105
|
+
{{ selectedBuildingUnit.category }}
|
|
106
|
+
</v-col>
|
|
107
|
+
</v-row>
|
|
108
|
+
</v-card-text>
|
|
109
|
+
|
|
110
|
+
<v-toolbar class="pa-0" density="compact">
|
|
111
|
+
<v-row no-gutters>
|
|
112
|
+
<v-col cols="6" class="pa-0">
|
|
113
|
+
<v-btn
|
|
114
|
+
block
|
|
115
|
+
variant="text"
|
|
116
|
+
class="text-none"
|
|
117
|
+
size="large"
|
|
118
|
+
@click="dialogPreview = false"
|
|
119
|
+
height="48"
|
|
120
|
+
>
|
|
121
|
+
Close
|
|
122
|
+
</v-btn>
|
|
123
|
+
</v-col>
|
|
124
|
+
|
|
125
|
+
<v-col cols="6" class="pa-0" v-if="canUpdate">
|
|
126
|
+
<v-menu>
|
|
127
|
+
<template #activator="{ props }">
|
|
128
|
+
<v-btn
|
|
129
|
+
block
|
|
130
|
+
variant="flat"
|
|
131
|
+
color="black"
|
|
132
|
+
class="text-none"
|
|
133
|
+
height="48"
|
|
134
|
+
v-bind="props"
|
|
135
|
+
tile
|
|
136
|
+
:disabled="!canUpdateUnit && !canDeleteUnit"
|
|
137
|
+
>
|
|
138
|
+
More actions
|
|
139
|
+
</v-btn>
|
|
140
|
+
</template>
|
|
141
|
+
|
|
142
|
+
<v-list class="pa-0">
|
|
143
|
+
<v-list-item v-if="canUpdateUnit" @click="openEditDialog()">
|
|
144
|
+
<v-list-item-title class="text-subtitle-2">
|
|
145
|
+
Edit Unit
|
|
146
|
+
</v-list-item-title>
|
|
147
|
+
</v-list-item>
|
|
148
|
+
|
|
149
|
+
<v-list-item
|
|
150
|
+
v-if="canDeleteUnit"
|
|
151
|
+
@click="openDeleteDialog()"
|
|
152
|
+
class="text-red"
|
|
153
|
+
>
|
|
154
|
+
<v-list-item-title class="text-subtitle-2">
|
|
155
|
+
Delete Unit
|
|
156
|
+
</v-list-item-title>
|
|
157
|
+
</v-list-item>
|
|
158
|
+
</v-list>
|
|
159
|
+
</v-menu>
|
|
160
|
+
</v-col>
|
|
161
|
+
</v-row>
|
|
162
|
+
</v-toolbar>
|
|
163
|
+
</v-card>
|
|
164
|
+
</v-dialog>
|
|
165
|
+
|
|
166
|
+
<v-dialog
|
|
167
|
+
v-model="dialogDelete"
|
|
168
|
+
:loading="deleteLoading"
|
|
169
|
+
width="450"
|
|
170
|
+
persistent
|
|
171
|
+
>
|
|
172
|
+
<v-card width="100%">
|
|
173
|
+
<v-toolbar density="compact" class="pl-4">
|
|
174
|
+
<span class="font-weight-medium text-h5">Delete Unit</span>
|
|
175
|
+
</v-toolbar>
|
|
176
|
+
|
|
177
|
+
<v-card-text>
|
|
178
|
+
<p class="text-subtitle-2 text-center">
|
|
179
|
+
Are you sure you want to delete this unit? This action cannot be
|
|
180
|
+
undone.
|
|
181
|
+
</p>
|
|
182
|
+
|
|
183
|
+
<v-row v-if="message" no-gutters justify="center" class="mt-4">
|
|
184
|
+
<span class="text-caption text-error text-center">
|
|
185
|
+
{{ message }}
|
|
186
|
+
</span>
|
|
187
|
+
</v-row>
|
|
188
|
+
</v-card-text>
|
|
189
|
+
|
|
190
|
+
<v-toolbar density="compact">
|
|
191
|
+
<v-row no-gutters>
|
|
192
|
+
<v-col cols="6">
|
|
193
|
+
<v-btn
|
|
194
|
+
tile
|
|
195
|
+
block
|
|
196
|
+
size="48"
|
|
197
|
+
variant="text"
|
|
198
|
+
class="text-none"
|
|
199
|
+
@click="dialogDelete = false"
|
|
200
|
+
:disabled="deleteLoading"
|
|
201
|
+
>
|
|
202
|
+
Close
|
|
203
|
+
</v-btn>
|
|
204
|
+
</v-col>
|
|
205
|
+
<v-col cols="6">
|
|
206
|
+
<v-btn
|
|
207
|
+
tile
|
|
208
|
+
block
|
|
209
|
+
size="48"
|
|
210
|
+
color="black"
|
|
211
|
+
variant="flat"
|
|
212
|
+
class="text-none"
|
|
213
|
+
@click="handleDeleteBuildingUnit"
|
|
214
|
+
:loading="deleteLoading"
|
|
215
|
+
>
|
|
216
|
+
Delete Unit
|
|
217
|
+
</v-btn>
|
|
218
|
+
</v-col>
|
|
219
|
+
</v-row>
|
|
220
|
+
</v-toolbar>
|
|
221
|
+
</v-card>
|
|
222
|
+
</v-dialog>
|
|
223
|
+
|
|
224
|
+
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
225
|
+
</v-row>
|
|
226
|
+
</template>
|
|
227
|
+
|
|
228
|
+
<script setup lang="ts">
|
|
229
|
+
const props = defineProps({
|
|
230
|
+
headers: {
|
|
231
|
+
type: Array as PropType<Array<Record<string, any>>>,
|
|
232
|
+
default: () => [
|
|
233
|
+
{
|
|
234
|
+
title: "Name",
|
|
235
|
+
value: "name",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
title: "Building",
|
|
239
|
+
value: "buildingName",
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
title: "Block",
|
|
243
|
+
value: "block",
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
title: "Floor",
|
|
247
|
+
value: "level",
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
title: "Category",
|
|
251
|
+
value: "category",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
title: "Type",
|
|
255
|
+
value: "type",
|
|
256
|
+
},
|
|
257
|
+
{ title: "Action", value: "action-table" },
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
canCreate: {
|
|
261
|
+
type: Boolean,
|
|
262
|
+
default: true,
|
|
263
|
+
},
|
|
264
|
+
canUpdate: {
|
|
265
|
+
type: Boolean,
|
|
266
|
+
default: true,
|
|
267
|
+
},
|
|
268
|
+
canDelete: {
|
|
269
|
+
type: Boolean,
|
|
270
|
+
default: true,
|
|
271
|
+
},
|
|
272
|
+
canCreateUnit: {
|
|
273
|
+
type: Boolean,
|
|
274
|
+
default: true,
|
|
275
|
+
},
|
|
276
|
+
canUpdateUnit: {
|
|
277
|
+
type: Boolean,
|
|
278
|
+
default: true,
|
|
279
|
+
},
|
|
280
|
+
canDeleteUnit: {
|
|
281
|
+
type: Boolean,
|
|
282
|
+
default: true,
|
|
283
|
+
},
|
|
284
|
+
canViewUnitDetails: {
|
|
285
|
+
type: Boolean,
|
|
286
|
+
default: true,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const site = (useRoute().params.site as string) ?? "";
|
|
291
|
+
const status = (useRoute().params.status as string) ?? "active";
|
|
292
|
+
|
|
293
|
+
const { toOrdinal } = useUtils();
|
|
294
|
+
|
|
295
|
+
const { headerSearch } = useLocal();
|
|
296
|
+
const { getAll, deleteById } = useBuildingUnit();
|
|
297
|
+
|
|
298
|
+
const page = ref(1);
|
|
299
|
+
const pages = ref(0);
|
|
300
|
+
const pageRange = ref("-- - -- of --");
|
|
301
|
+
|
|
302
|
+
const message = ref("");
|
|
303
|
+
const messageSnackbar = ref(false);
|
|
304
|
+
const messageColor = ref("");
|
|
305
|
+
|
|
306
|
+
const items = ref<Array<Record<string, any>>>([]);
|
|
307
|
+
|
|
308
|
+
const {
|
|
309
|
+
data: getBuildingReq,
|
|
310
|
+
refresh: getBuildingUnit,
|
|
311
|
+
status: getBuildingReqStatus,
|
|
312
|
+
} = useLazyAsyncData(
|
|
313
|
+
"get-all-building-units",
|
|
314
|
+
() =>
|
|
315
|
+
getAll({
|
|
316
|
+
page: page.value,
|
|
317
|
+
search: headerSearch.value,
|
|
318
|
+
status,
|
|
319
|
+
site: site,
|
|
320
|
+
}),
|
|
321
|
+
{
|
|
322
|
+
watch: [page, headerSearch],
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
const loading = computed(() => getBuildingReqStatus.value === "pending");
|
|
327
|
+
|
|
328
|
+
watchEffect(() => {
|
|
329
|
+
if (getBuildingReq.value) {
|
|
330
|
+
items.value = getBuildingReq.value.items;
|
|
331
|
+
pages.value = getBuildingReq.value.pages;
|
|
332
|
+
pageRange.value = getBuildingReq.value.pageRange;
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
function tableRowClickHandler(_: any, data: any) {
|
|
337
|
+
selectedBuildingUnit.value = data.item;
|
|
338
|
+
dialogPreview.value = true;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const createDialog = ref(false);
|
|
342
|
+
const dialogEdit = ref(false);
|
|
343
|
+
const dialogPreview = ref(false);
|
|
344
|
+
const selectedBuildingUnit = ref<TBuildingUnit | null>(null);
|
|
345
|
+
|
|
346
|
+
function successCreate() {
|
|
347
|
+
createDialog.value = false;
|
|
348
|
+
getBuildingUnit();
|
|
349
|
+
showMessage("Unit created successfully!", "success");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function successUpdate() {
|
|
353
|
+
dialogEdit.value = false;
|
|
354
|
+
dialogPreview.value = false;
|
|
355
|
+
getBuildingUnit();
|
|
356
|
+
showMessage("Unit updated successfully!", "success");
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function openEditDialog() {
|
|
360
|
+
dialogEdit.value = true;
|
|
361
|
+
if (dialogPreview.value) {
|
|
362
|
+
dialogPreview.value = false;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const dialogDelete = ref(false);
|
|
367
|
+
const deleteLoading = ref(false);
|
|
368
|
+
|
|
369
|
+
function openDeleteDialog() {
|
|
370
|
+
dialogDelete.value = true;
|
|
371
|
+
message.value = "";
|
|
372
|
+
if (dialogPreview.value) {
|
|
373
|
+
dialogPreview.value = false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function showMessage(msg: string, color: string) {
|
|
378
|
+
message.value = msg;
|
|
379
|
+
messageColor.value = color;
|
|
380
|
+
messageSnackbar.value = true;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function handleDeleteBuildingUnit() {
|
|
384
|
+
deleteLoading.value = true;
|
|
385
|
+
try {
|
|
386
|
+
await deleteById(selectedBuildingUnit.value?._id ?? "");
|
|
387
|
+
await getBuildingUnit();
|
|
388
|
+
dialogDelete.value = false;
|
|
389
|
+
selectedBuildingUnit.value = null;
|
|
390
|
+
} catch (error: any) {
|
|
391
|
+
message.value = error?.response?._data?.message || "Failed to delete unit";
|
|
392
|
+
} finally {
|
|
393
|
+
deleteLoading.value = false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function setBuilding({
|
|
398
|
+
mode = "create",
|
|
399
|
+
dialog = true,
|
|
400
|
+
data = {} as TBuildingUnit,
|
|
401
|
+
} = {}) {
|
|
402
|
+
if (mode === "create") {
|
|
403
|
+
createDialog.value = dialog;
|
|
404
|
+
} else if (mode === "edit") {
|
|
405
|
+
dialogEdit.value = dialog;
|
|
406
|
+
selectedBuildingUnit.value = data;
|
|
407
|
+
} else if (mode === "preview") {
|
|
408
|
+
dialogPreview.value = dialog;
|
|
409
|
+
selectedBuildingUnit.value = data;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
</script>
|