@iservice365/layer-common 1.2.0 → 1.3.1
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 +21 -0
- package/components/BuildingForm.vue +303 -0
- package/components/BuildingManagement/buildings.vue +395 -0
- package/components/BuildingManagement/units.vue +391 -0
- package/components/BuildingUnitFormAdd.vue +338 -0
- package/components/BuildingUnitFormEdit.vue +278 -0
- package/components/Chat/Information.vue +1 -1
- package/components/Input/DateTimePicker.vue +5 -4
- package/components/Input/FileV2.vue +0 -5
- package/components/Input/InputPhoneNumberV2.vue +0 -1
- package/components/Input/NRICNumber.vue +12 -0
- package/components/Input/VehicleNumber.vue +8 -0
- package/components/PeopleForm.vue +64 -32
- package/components/TableMain.vue +5 -1
- package/components/VisitorForm.vue +114 -279
- package/components/VisitorManagement.vue +95 -174
- package/components/WorkOrder/Create.vue +22 -4
- package/components/WorkOrder/Main.vue +7 -3
- package/composables/useBuilding.ts +1 -1
- package/composables/usePeople.ts +9 -1
- package/composables/useVisitor.ts +74 -50
- package/composables/useWorkOrder.ts +3 -3
- package/package.json +1 -1
- package/types/building.d.ts +2 -0
- package/types/people.d.ts +8 -7
- package/types/visitor.d.ts +1 -1
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
:counter="maxlength"
|
|
8
8
|
@input="onInput"
|
|
9
9
|
outlined
|
|
10
|
+
:disabled="disabled"
|
|
11
|
+
:readonly="readonly"
|
|
10
12
|
clearable
|
|
11
13
|
/>
|
|
12
14
|
</template>
|
|
@@ -25,6 +27,12 @@ const props = defineProps({
|
|
|
25
27
|
maxlength: {
|
|
26
28
|
type: [Number, String],
|
|
27
29
|
default: false
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
},
|
|
34
|
+
readonly: {
|
|
35
|
+
type: Boolean,
|
|
28
36
|
}
|
|
29
37
|
})
|
|
30
38
|
|
|
@@ -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 }} {{
|
|
6
|
+
{{ prop.mode }} {{ prop.type === 'visitor' ? 'Guest' : prop.type }}
|
|
7
7
|
</span>
|
|
8
8
|
</v-row>
|
|
9
9
|
</v-toolbar>
|
|
@@ -34,15 +34,14 @@
|
|
|
34
34
|
<v-row>
|
|
35
35
|
<v-col cols="12">
|
|
36
36
|
<InputLabel class="text-capitalize" title="NRIC/Passport/ID No." />
|
|
37
|
-
<InputNRICNumber v-model.trim="form.nric"
|
|
37
|
+
<InputNRICNumber v-model.trim="form.nric" density="comfortable" />
|
|
38
38
|
</v-col>
|
|
39
39
|
</v-row>
|
|
40
40
|
</v-col>
|
|
41
41
|
|
|
42
42
|
<v-col cols="12">
|
|
43
43
|
<InputLabel class="text-capitalize" title="Phone Number" required />
|
|
44
|
-
<InputPhoneNumberV2 v-model="form.contact"
|
|
45
|
-
density="comfortable" :rules="[requiredRule]" />
|
|
44
|
+
<InputPhoneNumberV2 v-model="form.contact" density="comfortable" :rules="[requiredRule]" />
|
|
46
45
|
</v-col>
|
|
47
46
|
|
|
48
47
|
<v-col cols="12">
|
|
@@ -65,19 +64,18 @@
|
|
|
65
64
|
|
|
66
65
|
<v-col cols="12">
|
|
67
66
|
<InputLabel class="text-capitalize" title="Unit" required />
|
|
68
|
-
<v-select v-model="form.unit" :items="unitsArray" @update:model-value="handleUpdateUnit"
|
|
69
|
-
:loading="unitsStatus === 'pending'"
|
|
67
|
+
<v-select v-model="form.unit" :items="unitsArray" @update:model-value="handleUpdateUnit"
|
|
68
|
+
density="comfortable" :disabled="!form.level" :loading="unitsStatus === 'pending'"
|
|
69
|
+
:rules="[requiredRule]" />
|
|
70
70
|
</v-col>
|
|
71
71
|
|
|
72
72
|
<v-col cols="12">
|
|
73
73
|
<InputLabel class="text-capitalize" title="Start Date" required />
|
|
74
|
-
<InputDateTimePicker v-model:utc="form.start" ref="startDateRef"
|
|
75
|
-
:rules="[validStartDateRule]" />
|
|
74
|
+
<InputDateTimePicker v-model:utc="form.start" ref="startDateRef" name="start_date" :rules="[validStartDateRule]" />
|
|
76
75
|
</v-col>
|
|
77
76
|
<v-col cols="12">
|
|
78
77
|
<InputLabel class="text-capitalize" title="End Date" required />
|
|
79
|
-
<InputDateTimePicker v-model:utc="form.end" ref="endDateRef"
|
|
80
|
-
:rules="[validExpiryDateRule]" />
|
|
78
|
+
<InputDateTimePicker v-model:utc="form.end" ref="endDateRef" name="end_date" :rules="[validExpiryDateRule]" />
|
|
81
79
|
</v-col>
|
|
82
80
|
|
|
83
81
|
<v-col cols="12">
|
|
@@ -144,12 +142,20 @@ const prop = defineProps({
|
|
|
144
142
|
type: {
|
|
145
143
|
type: String as PropType<TPeopleType>,
|
|
146
144
|
required: true
|
|
145
|
+
},
|
|
146
|
+
activeId: {
|
|
147
|
+
type: String as PropType<string | null>, // id of person you are trying to update
|
|
148
|
+
default: null
|
|
149
|
+
},
|
|
150
|
+
people: {
|
|
151
|
+
type: Object as PropType<TPeople>,
|
|
152
|
+
required: false
|
|
147
153
|
}
|
|
148
154
|
});
|
|
149
155
|
|
|
150
156
|
const { requiredRule, formatDateISO8601 } = useUtils();
|
|
151
157
|
const { getSiteById, getSiteLevels, getSiteUnits } = useSiteSettings();
|
|
152
|
-
const { create } = usePeople();
|
|
158
|
+
const { create, updateById } = usePeople();
|
|
153
159
|
|
|
154
160
|
const emit = defineEmits(['back', 'select', 'done', 'done:more', 'error', 'close']);
|
|
155
161
|
|
|
@@ -164,7 +170,7 @@ const form = reactive<Partial<TPeoplePayload>>({
|
|
|
164
170
|
unit: "",
|
|
165
171
|
unitName: "",
|
|
166
172
|
remarks: "",
|
|
167
|
-
start:
|
|
173
|
+
start: "",
|
|
168
174
|
end: "",
|
|
169
175
|
type: prop.type
|
|
170
176
|
})
|
|
@@ -199,21 +205,21 @@ const contractorTypes = [
|
|
|
199
205
|
|
|
200
206
|
const { data: siteData, refresh: refreshSiteData, status: blockStatus } = useLazyAsyncData(
|
|
201
207
|
`fetch-site-data-${prop.site}`,
|
|
202
|
-
() => getSiteById(prop.site));
|
|
208
|
+
() => getSiteById(prop.site),);
|
|
203
209
|
|
|
204
210
|
const { data: levelsData, refresh: refreshLevelsData, status: levelsStatus } = useLazyAsyncData(
|
|
205
211
|
`fetch-levels-data-${prop.site}-${form.block}`,
|
|
206
212
|
async () => {
|
|
207
213
|
if (!form.block) return Promise.resolve(null);
|
|
208
214
|
return await getSiteLevels(prop.site, { block: Number(form.block) })
|
|
209
|
-
});
|
|
215
|
+
}, { watch: [() => form.block],});
|
|
210
216
|
|
|
211
217
|
const { data: unitsData, refresh: refreshUnitsData, status: unitsStatus } = useLazyAsyncData(
|
|
212
218
|
`fetch-units-data-${prop.site}-${form.level}`,
|
|
213
219
|
async () => {
|
|
214
220
|
if (!form.level) return Promise.resolve(null);
|
|
215
221
|
return await getSiteUnits(prop.site, Number(form.block), form.level)
|
|
216
|
-
});
|
|
222
|
+
}, { watch: [()=> form.level]});
|
|
217
223
|
|
|
218
224
|
watch(
|
|
219
225
|
siteData,
|
|
@@ -267,12 +273,10 @@ watch(
|
|
|
267
273
|
function handleChangeBlock(value: any) {
|
|
268
274
|
form.level = '';
|
|
269
275
|
form.unit = '';
|
|
270
|
-
refreshLevelsData();
|
|
271
276
|
}
|
|
272
277
|
|
|
273
278
|
function handleChangeLevel(value: any) {
|
|
274
279
|
form.unit = '';
|
|
275
|
-
refreshUnitsData();
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
function handleUpdateUnit(value: any) {
|
|
@@ -280,7 +284,7 @@ function handleUpdateUnit(value: any) {
|
|
|
280
284
|
form.unitName = selectedUnit?.title || ''
|
|
281
285
|
}
|
|
282
286
|
|
|
283
|
-
function dateToday(){
|
|
287
|
+
function dateToday() {
|
|
284
288
|
const today = new Date()
|
|
285
289
|
return today.toISOString()
|
|
286
290
|
}
|
|
@@ -362,33 +366,44 @@ async function submit() {
|
|
|
362
366
|
errorMessage.value = '';
|
|
363
367
|
processing.value = true;
|
|
364
368
|
|
|
365
|
-
let payload: Partial<TPeoplePayload> = {
|
|
366
|
-
org: prop.org,
|
|
367
|
-
site: prop.site
|
|
368
|
-
}
|
|
369
|
+
let payload: Partial<TPeoplePayload> = {}
|
|
369
370
|
|
|
370
371
|
if (prop.mode === 'add') {
|
|
371
372
|
payload = {
|
|
372
373
|
...payload,
|
|
374
|
+
org: prop.org,
|
|
375
|
+
site: prop.site,
|
|
373
376
|
...form,
|
|
374
377
|
}
|
|
375
378
|
|
|
376
379
|
} else if (prop.mode === 'edit') {
|
|
380
|
+
const { type, ...rest } = form
|
|
381
|
+
payload = {
|
|
382
|
+
...payload,
|
|
383
|
+
...rest
|
|
384
|
+
}
|
|
377
385
|
|
|
378
386
|
}
|
|
379
387
|
try {
|
|
388
|
+
if (prop.mode === 'add') {
|
|
389
|
+
await create(payload)
|
|
390
|
+
} else if (prop.mode === 'edit'){
|
|
391
|
+
const userId = prop.activeId
|
|
392
|
+
if(!userId) {
|
|
393
|
+
throw new Error('User Id prop is not defined')
|
|
394
|
+
}
|
|
380
395
|
|
|
381
|
-
|
|
382
|
-
if (res) {
|
|
383
|
-
if (createMore.value) {
|
|
384
|
-
resetForm()
|
|
385
|
-
step.value = 1;
|
|
386
|
-
errorMessage.value = ""
|
|
387
|
-
emit("done:more")
|
|
388
|
-
createMore.value = false
|
|
389
|
-
} else emit("done")
|
|
396
|
+
await updateById(userId, payload)
|
|
390
397
|
}
|
|
391
398
|
|
|
399
|
+
if (createMore.value) {
|
|
400
|
+
resetForm()
|
|
401
|
+
step.value = 1;
|
|
402
|
+
errorMessage.value = ""
|
|
403
|
+
emit("done:more")
|
|
404
|
+
createMore.value = false
|
|
405
|
+
} else emit("done")
|
|
406
|
+
|
|
392
407
|
} catch (error: any) {
|
|
393
408
|
const err = error?.data?.message
|
|
394
409
|
errorMessage.value = err || `Failed to ${prop.mode === 'add' ? 'add' : 'update'} ${prop.type}. Please try again.`;
|
|
@@ -406,9 +421,27 @@ watch(() => [form.end, form.start], () => {
|
|
|
406
421
|
(startDateRef.value as any)?.validate();
|
|
407
422
|
});
|
|
408
423
|
|
|
424
|
+
async function mountExistingData() {
|
|
425
|
+
setTimeout(() => {
|
|
426
|
+
const people = prop.people
|
|
427
|
+
if (!people) return
|
|
428
|
+
|
|
429
|
+
(Object.keys(form) as (keyof typeof form)[]).forEach((key) => {
|
|
430
|
+
if (key in people) {
|
|
431
|
+
form[key] = people[key as keyof TPeople]
|
|
432
|
+
}
|
|
433
|
+
})
|
|
434
|
+
}, 100)
|
|
435
|
+
}
|
|
436
|
+
|
|
409
437
|
onMounted(() => {
|
|
410
438
|
step.value = 1;
|
|
411
439
|
createMore.value = false;
|
|
440
|
+
if(prop.mode === 'edit'){
|
|
441
|
+
mountExistingData()
|
|
442
|
+
} else {
|
|
443
|
+
form.start = dateToday()
|
|
444
|
+
}
|
|
412
445
|
})
|
|
413
446
|
|
|
414
447
|
</script>
|
|
@@ -416,5 +449,4 @@ onMounted(() => {
|
|
|
416
449
|
.button-outline-class {
|
|
417
450
|
border: 1px solid rgba(var(--v-theme-primary));
|
|
418
451
|
}
|
|
419
|
-
|
|
420
452
|
</style>
|
package/components/TableMain.vue
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
<!-- Data Table -->
|
|
44
44
|
<v-data-table :headers="headers" :items="items" :item-value="itemValue" :items-per-page="itemsPerPage"
|
|
45
45
|
fixed-header hide-default-footer :hide-default-header="!showHeader"
|
|
46
|
-
@click:row="(_: any, data: any) => emits('row-click', data)" style="max-height: calc(100vh - (
|
|
46
|
+
@click:row="(_: any, data: any) => emits('row-click', data)" :style="`max-height: calc(100vh - (${offset}px))`">
|
|
47
47
|
<template v-for="(_, slotName) in $slots" #[slotName]="slotProps">
|
|
48
48
|
<slot :name="slotName" v-bind="slotProps" />
|
|
49
49
|
</template>
|
|
@@ -103,6 +103,10 @@ const props = defineProps({
|
|
|
103
103
|
extensionHeight: {
|
|
104
104
|
type: Number,
|
|
105
105
|
default: 50
|
|
106
|
+
},
|
|
107
|
+
offset: {
|
|
108
|
+
type: Number,
|
|
109
|
+
default: 200
|
|
106
110
|
}
|
|
107
111
|
});
|
|
108
112
|
|