@7365admin1/layer-common 1.10.6 → 1.10.8
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/AccessCardQrTagging.vue +314 -34
- package/components/AccessCardQrTaggingPrintQr.vue +75 -0
- package/components/{AddSupplyForm.vue → AddEqupmentForm.vue} +5 -5
- package/components/AreaChecklistHistoryLogs.vue +9 -0
- package/components/BuildingForm.vue +36 -5
- package/components/BuildingManagement/buildings.vue +18 -9
- package/components/BuildingManagement/units.vue +13 -115
- package/components/BuildingUnitFormAdd.vue +42 -33
- package/components/BuildingUnitFormEdit.vue +334 -139
- package/components/CleaningScheduleMain.vue +60 -13
- package/components/Dialog/DeleteConfirmation.vue +2 -2
- package/components/Dialog/UpdateMoreAction.vue +2 -2
- package/components/EntryPassInformation.vue +443 -0
- package/components/{CheckoutItemMain.vue → EquipmentItemMain.vue} +88 -85
- package/components/{SupplyManagement.vue → EquipmentManagement.vue} +3 -3
- package/components/Input/DateTimePicker.vue +17 -11
- package/components/Input/InputPhoneNumberV2.vue +8 -0
- package/components/ManageChecklistMain.vue +400 -36
- package/components/ScheduleAreaMain.vue +56 -0
- package/components/TableHygiene.vue +47 -430
- package/components/UnitPersonCard.vue +123 -0
- package/components/VehicleAddSelection.vue +2 -2
- package/components/VehicleForm.vue +78 -19
- package/components/VehicleManagement.vue +164 -40
- package/components/VisitorForm.vue +95 -20
- package/components/VisitorFormSelection.vue +13 -2
- package/components/VisitorManagement.vue +83 -55
- package/composables/useAccessManagement.ts +52 -0
- package/composables/useCleaningPermission.ts +7 -7
- package/composables/useDashboardData.ts +2 -2
- package/composables/{useSupply.ts → useEquipment.ts} +11 -11
- package/composables/{useCheckout.ts → useEquipmentItem.ts} +7 -7
- package/composables/{useCheckoutPermission.ts → useEquipmentItemPermission.ts} +13 -13
- package/composables/useEquipmentManagementPermission.ts +96 -0
- package/composables/{useSupplyPermission.ts → useEquipmentPermission.ts} +9 -9
- package/composables/usePeople.ts +4 -3
- package/composables/useVehicle.ts +35 -2
- package/composables/useVisitor.ts +3 -3
- package/composables/useWorkOrder.ts +25 -3
- package/package.json +3 -2
- package/types/building.d.ts +1 -1
- package/types/cleaner-schedule.d.ts +1 -0
- package/types/{checkout-item.d.ts → equipment-item.d.ts} +3 -3
- package/types/{supply.d.ts → equipment.d.ts} +2 -2
- package/types/html2pdf.d.ts +19 -0
- package/types/people.d.ts +5 -2
- package/types/site.d.ts +8 -0
- package/types/vehicle.d.ts +4 -3
- package/types/visitor.d.ts +2 -1
- package/.playground/app.vue +0 -41
- package/.playground/eslint.config.mjs +0 -6
- package/.playground/nuxt.config.ts +0 -22
- package/.playground/pages/feedback.vue +0 -30
|
@@ -1,64 +1,186 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-card width="100%">
|
|
2
|
+
<v-card width="100%" :loading="getUnitPeoplePending || loading.ownerProcessing" :disabled="loading.ownerProcessing">
|
|
3
3
|
<v-toolbar>
|
|
4
4
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
|
-
<span class="font-weight-bold text-h5">
|
|
5
|
+
<span class="font-weight-bold text-h5"> Unit Info ( {{ buildingUnit.name }} ) </span>
|
|
6
6
|
</v-row>
|
|
7
7
|
</v-toolbar>
|
|
8
|
-
<v-
|
|
9
|
-
<v-
|
|
10
|
-
<v-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
8
|
+
<v-toolbar density="compact">
|
|
9
|
+
<v-tabs v-model="tab" class="mt-0" active-class="bg-success">
|
|
10
|
+
<v-tab value="general">General</v-tab>
|
|
11
|
+
<v-tab value="residents">Residents/Tenants</v-tab>
|
|
12
|
+
<v-tab value="vehicles">Vehicles</v-tab>
|
|
13
|
+
<v-tab value="others">Others</v-tab>
|
|
14
|
+
</v-tabs>
|
|
15
|
+
</v-toolbar>
|
|
16
|
+
<v-card-text style="max-height: 100vh; min-height: 60svh; overflow-y: auto">
|
|
17
|
+
<template v-if="tab === 'general'">
|
|
18
|
+
<v-form v-model="validForm" :disabled="disable">
|
|
19
|
+
<v-row>
|
|
20
|
+
<v-col cols="12" md="6" lg="4" class="mt-2">
|
|
21
|
+
<v-row no-gutters>
|
|
22
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Unit Name" />
|
|
23
|
+
<v-col cols="12">
|
|
24
|
+
<v-text-field v-model="buildingUnit.name" density="comfortable"
|
|
25
|
+
:rules="[requiredRule]"></v-text-field>
|
|
26
|
+
</v-col>
|
|
27
|
+
</v-row>
|
|
28
|
+
</v-col>
|
|
29
|
+
|
|
30
|
+
<v-col cols="12" md="6" lg="4" class="mt-2">
|
|
31
|
+
<v-row no-gutters>
|
|
32
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Level" required />
|
|
33
|
+
<v-col cols="12">
|
|
34
|
+
<v-select v-model="buildingUnit.level" :items="buildingLevels" density="comfortable"
|
|
35
|
+
:rules="[requiredRule]"></v-select>
|
|
36
|
+
</v-col>
|
|
37
|
+
</v-row>
|
|
38
|
+
</v-col>
|
|
39
|
+
|
|
40
|
+
<v-col cols="12" md="6" lg="4">
|
|
41
|
+
<v-row>
|
|
42
|
+
<v-col cols="12" class="mt-2">
|
|
43
|
+
<v-row no-gutters>
|
|
44
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Block Name" />
|
|
45
|
+
<v-col cols="12">
|
|
46
|
+
<v-text-field :model-value="`Block ${buildingUnit.block} (${buildingUnit.buildingName})`"
|
|
47
|
+
density="comfortable" readonly class="no-pointer"></v-text-field>
|
|
48
|
+
</v-col>
|
|
49
|
+
</v-row>
|
|
50
|
+
</v-col>
|
|
51
|
+
</v-row>
|
|
52
|
+
</v-col>
|
|
53
|
+
</v-row>
|
|
54
|
+
|
|
55
|
+
<v-divider class="mb-10" />
|
|
56
|
+
<v-row>
|
|
57
|
+
<v-col cols="12" md="6" class="mt-2">
|
|
58
|
+
<v-row no-gutters>
|
|
59
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Billing Address Line 1" />
|
|
60
|
+
<v-col cols="12">
|
|
61
|
+
<v-text-field :model-value="buildingUnit?.site?.address?.line1" density="compact" readonly
|
|
62
|
+
class="no-pointer"></v-text-field>
|
|
63
|
+
</v-col>
|
|
64
|
+
</v-row>
|
|
65
|
+
</v-col>
|
|
66
|
+
<v-col cols="12" md="6" class="mt-2">
|
|
67
|
+
<v-row no-gutters>
|
|
68
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Billing Address Line 2" />
|
|
69
|
+
<v-col cols="12">
|
|
70
|
+
<v-text-field :model-value="buildingUnit?.site?.address?.line2" density="compact" readonly
|
|
71
|
+
class="no-pointer"></v-text-field>
|
|
72
|
+
</v-col>
|
|
73
|
+
</v-row>
|
|
74
|
+
</v-col>
|
|
75
|
+
<v-col cols="12" md="4" lg="4" class="mt-2">
|
|
76
|
+
<v-row no-gutters>
|
|
77
|
+
<InputLabel class="text-capitalize font-weight-bold" title="City" />
|
|
78
|
+
<v-col cols="12">
|
|
79
|
+
<v-text-field :model-value="buildingUnit?.site?.address?.city" density="compact" readonly
|
|
80
|
+
class="no-pointer"></v-text-field>
|
|
81
|
+
</v-col>
|
|
82
|
+
</v-row>
|
|
83
|
+
</v-col>
|
|
84
|
+
<v-col cols="12" md="4" lg="4" class="mt-2">
|
|
85
|
+
<v-row no-gutters>
|
|
86
|
+
<InputLabel class="text-capitalize font-weight-bold" title="State" />
|
|
87
|
+
<v-col cols="12">
|
|
88
|
+
<v-text-field :model-value="buildingUnit?.site?.address?.state" density="compact" readonly
|
|
89
|
+
class="no-pointer"></v-text-field>
|
|
90
|
+
</v-col>
|
|
91
|
+
</v-row>
|
|
92
|
+
</v-col>
|
|
93
|
+
<v-col cols="12" md="4" lg="4" class="mt-2">
|
|
94
|
+
<v-row no-gutters>
|
|
95
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Country" />
|
|
96
|
+
<v-col cols="12">
|
|
97
|
+
<v-text-field :model-value="buildingUnit?.site?.address?.country" density="compact" readonly
|
|
98
|
+
class="no-pointer"></v-text-field>
|
|
99
|
+
</v-col>
|
|
100
|
+
</v-row>
|
|
101
|
+
</v-col>
|
|
102
|
+
<v-col cols="12" md="4" lg="4" class="mt-2">
|
|
103
|
+
<v-row no-gutters>
|
|
104
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Postal Code" />
|
|
105
|
+
<v-col cols="12">
|
|
106
|
+
<v-text-field :model-value="buildingUnit?.site?.address?.postalCode" density="compact" readonly
|
|
107
|
+
class="no-pointer"></v-text-field>
|
|
108
|
+
</v-col>
|
|
109
|
+
</v-row>
|
|
110
|
+
</v-col>
|
|
111
|
+
</v-row>
|
|
112
|
+
</v-form>
|
|
113
|
+
</template>
|
|
114
|
+
|
|
115
|
+
<template v-else-if="tab === 'residents'">
|
|
116
|
+
<v-card width="100%">
|
|
117
|
+
<v-expansion-panels v-model="panels" variant="accordion">
|
|
118
|
+
|
|
119
|
+
<!-- Residents -->
|
|
120
|
+
<v-expansion-panel value="residents">
|
|
121
|
+
<v-expansion-panel-title class="bg-primary">
|
|
122
|
+
Residents ({{ unitResidentsArray.length }})
|
|
123
|
+
</v-expansion-panel-title>
|
|
124
|
+
|
|
125
|
+
<v-expansion-panel-text>
|
|
126
|
+
<template v-if="unitResidentsArray.length" v-for="resident, residentIndex in unitResidentsArray"
|
|
127
|
+
:key="residentIndex">
|
|
128
|
+
<UnitPersonCard :person="resident" :readOnly="true" show-owner-option
|
|
129
|
+
@update:owner="handleUpdateOwner" :loading-owner-processing="loading.ownerProcessing" />
|
|
130
|
+
<v-divider v-if="(residentIndex + 1) !== unitResidentsArray.length" thickness="2" color="primary"
|
|
131
|
+
class="my-4" />
|
|
132
|
+
</template>
|
|
133
|
+
<p v-else class="font-weight-semibold text-caption ml-2 mt-5">
|
|
134
|
+
**No residents to display**
|
|
135
|
+
</p>
|
|
136
|
+
</v-expansion-panel-text>
|
|
137
|
+
</v-expansion-panel>
|
|
138
|
+
|
|
139
|
+
<!-- Tenants -->
|
|
140
|
+
<v-expansion-panel value="tenants">
|
|
141
|
+
<v-expansion-panel-title class="bg-primary">
|
|
142
|
+
Tenants ({{ unitTenantsArray.length }})
|
|
143
|
+
</v-expansion-panel-title>
|
|
144
|
+
|
|
145
|
+
<v-expansion-panel-text>
|
|
146
|
+
<template v-if="unitTenantsArray.length" v-for="(tenant, tenantIndex) in unitTenantsArray"
|
|
147
|
+
:key="tenant._id || tenantIndex">
|
|
148
|
+
<UnitPersonCard :person="tenant" :readOnly="true" />
|
|
149
|
+
<v-divider v-if="(tenantIndex + 1) !== unitTenantsArray.length" thickness="2" color="primary"
|
|
150
|
+
class="my-4" />
|
|
151
|
+
</template>
|
|
152
|
+
<p v-else class=" font-weight-semibold text-caption ml-2 mt-5">
|
|
153
|
+
**No tenants to display**
|
|
154
|
+
</p>
|
|
155
|
+
</v-expansion-panel-text>
|
|
156
|
+
</v-expansion-panel>
|
|
157
|
+
</v-expansion-panels>
|
|
158
|
+
</v-card>
|
|
159
|
+
</template>
|
|
160
|
+
<template v-else-if="tab === 'vehicles'">
|
|
161
|
+
<TableMain :headers="vehicleHeaders" :show-header="true" :page="vehiclePage" :pages="vehicleTotalPages"
|
|
162
|
+
:pageRange="vehiclePageRange" :items="unitVehicleItems" @refresh="getUnitVehiclesRefresh" @update:page="handleUpdateVehiclePage">
|
|
163
|
+
|
|
164
|
+
<template #item.status="{value}">
|
|
165
|
+
<v-chip :color="formatVehicleStatus(value).color" class="ma-0" small>
|
|
166
|
+
{{ formatVehicleStatus(value).label }}
|
|
167
|
+
</v-chip>
|
|
168
|
+
</template>
|
|
169
|
+
</TableMain>
|
|
170
|
+
</template>
|
|
171
|
+
|
|
172
|
+
<template v-else-if="tab === 'others'">
|
|
173
|
+
<v-row>
|
|
174
|
+
<!-- <v-col cols="12" md="6" class="mt-2">
|
|
175
|
+
<v-row no-gutters>
|
|
176
|
+
<InputLabel class="text-capitalize font-weight-bold" title="Owner" />
|
|
177
|
+
<v-col cols="12">
|
|
178
|
+
<v-autocomplete v-model="buildingUnit.ownerName" v-model:search="ownerNameInput" :items="peopleItems"
|
|
179
|
+
item-title="name" return-object density="comfortable">
|
|
180
|
+
</v-autocomplete>
|
|
58
181
|
</v-col>
|
|
59
182
|
</v-row>
|
|
60
|
-
</v-col>
|
|
61
|
-
|
|
183
|
+
</v-col> -->
|
|
62
184
|
|
|
63
185
|
<v-col cols="12">
|
|
64
186
|
<v-row>
|
|
@@ -83,7 +205,6 @@
|
|
|
83
205
|
</v-row>
|
|
84
206
|
</v-col>
|
|
85
207
|
|
|
86
|
-
|
|
87
208
|
<v-col cols="12">
|
|
88
209
|
<v-row>
|
|
89
210
|
<v-col cols="12" md="6" class="mt-2">
|
|
@@ -106,65 +227,52 @@
|
|
|
106
227
|
|
|
107
228
|
</v-row>
|
|
108
229
|
</v-col>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<v-col cols="12" md="6" class="mt-2">
|
|
112
|
-
<v-row no-gutters>
|
|
113
|
-
<InputLabel class="text-capitalize font-weight-bold" title="Category" required />
|
|
114
|
-
<v-col cols="12">
|
|
115
|
-
<v-autocomplete v-model="buildingUnit.category" :items="unitCategories" density="comfortable"
|
|
116
|
-
:rules="[requiredRule]"></v-autocomplete>
|
|
117
|
-
</v-col>
|
|
118
|
-
</v-row>
|
|
119
|
-
</v-col>
|
|
120
|
-
|
|
121
|
-
<v-col cols="12">
|
|
122
|
-
<v-row>
|
|
123
|
-
<v-col cols="6" md="6" class="mt-2">
|
|
124
|
-
<v-row no-gutters>
|
|
125
|
-
<InputLabel class="text-capitalize font-weight-bold" title="Level" required />
|
|
126
|
-
<v-col cols="12">
|
|
127
|
-
<v-select v-model="buildingUnit.level" :items="buildingLevels" density="comfortable"
|
|
128
|
-
:rules="[requiredRule]"></v-select>
|
|
129
|
-
</v-col>
|
|
130
|
-
</v-row>
|
|
131
|
-
</v-col>
|
|
132
|
-
</v-row>
|
|
133
|
-
</v-col>
|
|
134
|
-
|
|
135
|
-
<v-col cols="12" class="mt-5">
|
|
136
|
-
<InputLabel class="text-capitalize" title="Upload Files (Lease of Contract, Cert. of Occupancy)" />
|
|
137
|
-
<InputFileV2 v-model="buildingUnit.buildingUnitFiles" :multiple="false" :max-length="10"
|
|
138
|
-
title="Upload PDF Files" accept="application/pdf" />
|
|
139
|
-
</v-col>
|
|
140
|
-
|
|
141
|
-
<v-col cols="12" class="my-2">
|
|
142
|
-
<v-row no-gutters>
|
|
143
|
-
<v-col cols="12" class="text-center">
|
|
144
|
-
<span class="text-none text-subtitle-2 font-weight-medium text-error">
|
|
145
|
-
{{ message }}
|
|
146
|
-
</span>
|
|
147
|
-
</v-col>
|
|
148
|
-
</v-row>
|
|
149
|
-
</v-col>
|
|
150
230
|
</v-row>
|
|
151
|
-
</
|
|
231
|
+
</template>
|
|
152
232
|
</v-card-text>
|
|
153
233
|
|
|
154
|
-
<v-
|
|
234
|
+
<v-col cols="12" class="my-2">
|
|
155
235
|
<v-row no-gutters>
|
|
156
|
-
<v-col cols="
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
</
|
|
236
|
+
<v-col cols="12" class="text-center">
|
|
237
|
+
<span class="text-none text-subtitle-2 font-weight-medium text-error">
|
|
238
|
+
{{ message }}
|
|
239
|
+
</span>
|
|
160
240
|
</v-col>
|
|
241
|
+
</v-row>
|
|
242
|
+
</v-col>
|
|
161
243
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
244
|
+
<v-toolbar class="pa-0" density="compact">
|
|
245
|
+
<v-row no-gutters>
|
|
246
|
+
<v-col :cols="canUpdateUnit || canDeleteUnit ? 6 : 12" class="pa-0">
|
|
247
|
+
<v-btn block variant="text" class="text-none" size="large" @click="emit('cancel')" height="48">
|
|
248
|
+
Close
|
|
166
249
|
</v-btn>
|
|
167
250
|
</v-col>
|
|
251
|
+
|
|
252
|
+
<v-col v-if="canUpdateUnit || canDeleteUnit" cols="6" class="pa-0">
|
|
253
|
+
<v-menu>
|
|
254
|
+
<template #activator="{ props }">
|
|
255
|
+
<v-btn block variant="flat" color="black" class="text-none" height="48" v-bind="props" tile
|
|
256
|
+
:disabled="!canUpdateUnit && !canDeleteUnit">
|
|
257
|
+
More actions
|
|
258
|
+
</v-btn>
|
|
259
|
+
</template>
|
|
260
|
+
|
|
261
|
+
<v-list class="pa-0">
|
|
262
|
+
<v-list-item v-if="canUpdateUnit" @click="submit">
|
|
263
|
+
<v-list-item-title class="text-subtitle-2">
|
|
264
|
+
Save
|
|
265
|
+
</v-list-item-title>
|
|
266
|
+
</v-list-item>
|
|
267
|
+
|
|
268
|
+
<v-list-item v-if="canDeleteUnit" @click="emit('delete-unit')" class="text-red">
|
|
269
|
+
<v-list-item-title class="text-subtitle-2">
|
|
270
|
+
Delete Unit
|
|
271
|
+
</v-list-item-title>
|
|
272
|
+
</v-list-item>
|
|
273
|
+
</v-list>
|
|
274
|
+
</v-menu>
|
|
275
|
+
</v-col>
|
|
168
276
|
</v-row>
|
|
169
277
|
</v-toolbar>
|
|
170
278
|
</v-card>
|
|
@@ -178,37 +286,39 @@ const prop = defineProps({
|
|
|
178
286
|
},
|
|
179
287
|
roomFacility: {
|
|
180
288
|
type: Object as PropType<TBuildingUnit>,
|
|
181
|
-
|
|
182
|
-
_id: "",
|
|
183
|
-
site: "",
|
|
184
|
-
name: "",
|
|
185
|
-
owner: "",
|
|
186
|
-
ownerName: "",
|
|
187
|
-
building: "",
|
|
188
|
-
buildingName: "",
|
|
189
|
-
category: "",
|
|
190
|
-
block: null,
|
|
191
|
-
level: 0,
|
|
192
|
-
status: "active",
|
|
193
|
-
buildingUnitFiles: [],
|
|
194
|
-
companyName: "",
|
|
195
|
-
companyRegistrationNumber: "",
|
|
196
|
-
leaseStart: "",
|
|
197
|
-
leaseEnd: "",
|
|
198
|
-
}),
|
|
289
|
+
required: true,
|
|
199
290
|
},
|
|
291
|
+
canUpdateUnit: {
|
|
292
|
+
type: Boolean,
|
|
293
|
+
default: true,
|
|
294
|
+
},
|
|
295
|
+
canDeleteUnit: {
|
|
296
|
+
type: Boolean,
|
|
297
|
+
default: true,
|
|
298
|
+
}
|
|
200
299
|
});
|
|
201
300
|
|
|
202
301
|
const buildingUnit = ref({
|
|
203
302
|
_id: "",
|
|
204
|
-
site:
|
|
303
|
+
site: {
|
|
304
|
+
_id: "",
|
|
305
|
+
name: "",
|
|
306
|
+
address: {
|
|
307
|
+
line1: "",
|
|
308
|
+
line2: "",
|
|
309
|
+
city: "",
|
|
310
|
+
state: "",
|
|
311
|
+
country: "",
|
|
312
|
+
postalCode: "",
|
|
313
|
+
},
|
|
314
|
+
},
|
|
205
315
|
name: "",
|
|
206
316
|
owner: "",
|
|
207
317
|
ownerName: "",
|
|
208
318
|
building: "",
|
|
209
319
|
buildingName: "",
|
|
210
320
|
level: 0,
|
|
211
|
-
category: "",
|
|
321
|
+
// category: "",
|
|
212
322
|
block: null,
|
|
213
323
|
status: "active",
|
|
214
324
|
buildingUnitFiles: [],
|
|
@@ -218,20 +328,43 @@ const buildingUnit = ref({
|
|
|
218
328
|
leaseEnd: "",
|
|
219
329
|
});
|
|
220
330
|
|
|
331
|
+
|
|
221
332
|
buildingUnit.value = JSON.parse(JSON.stringify(prop.roomFacility));
|
|
222
333
|
|
|
223
|
-
const emit = defineEmits(["cancel", "success", "success:create-more"]);
|
|
334
|
+
const emit = defineEmits(["cancel", "success", "success:create-more", "delete-unit"]);
|
|
335
|
+
|
|
224
336
|
|
|
225
337
|
const ownerNameInput = ref("");
|
|
338
|
+
const panels = ref<string[]>(['residents']);
|
|
339
|
+
|
|
340
|
+
const tab = ref('general')
|
|
226
341
|
|
|
227
342
|
const validForm = ref(false);
|
|
228
343
|
|
|
229
344
|
const { getAll } = useBuilding();
|
|
230
|
-
const {
|
|
345
|
+
const { getPeopleByUnit, updateById: updatePeopleById } = usePeople();
|
|
231
346
|
const { debounce } = useUtils();
|
|
347
|
+
const { searchMultipleVehiclesByUnitId, formatVehicleStatus } = useVehicle();
|
|
348
|
+
|
|
349
|
+
const loading = reactive({
|
|
350
|
+
ownerProcessing: false,
|
|
351
|
+
})
|
|
232
352
|
|
|
233
353
|
const buildings = ref<Record<string, any>[]>([]);
|
|
234
|
-
const peopleItems = ref<
|
|
354
|
+
const peopleItems = ref<TPeople[]>([]);
|
|
355
|
+
const unitVehicleItems = ref<TVehicle[]>([]);
|
|
356
|
+
|
|
357
|
+
const vehiclePage = ref(1);
|
|
358
|
+
const vehiclePageRange = ref("-- - -- of --");
|
|
359
|
+
const vehicleTotalPages = ref(0);
|
|
360
|
+
|
|
361
|
+
const vehicleHeaders = [
|
|
362
|
+
{ title: "Plate Number", value: "plateNumber" },
|
|
363
|
+
{ title: "Owner Name", value: "name" },
|
|
364
|
+
{ title: "NRIC", value: "nric" },
|
|
365
|
+
{ title: "Type", value: "type" },
|
|
366
|
+
{ title: "Status", value: "status" },
|
|
367
|
+
];
|
|
235
368
|
|
|
236
369
|
const { data: getBuildingReq } = useLazyAsyncData(
|
|
237
370
|
"get-all-buildings",
|
|
@@ -248,26 +381,48 @@ watchEffect(() => {
|
|
|
248
381
|
}
|
|
249
382
|
});
|
|
250
383
|
|
|
251
|
-
const { data: getUnitPeople, refresh: getUnitPeopleRefresh } = useLazyAsyncData(
|
|
384
|
+
const { data: getUnitPeople, refresh: getUnitPeopleRefresh, pending: getUnitPeoplePending } = useLazyAsyncData(
|
|
252
385
|
"get-unit-people",
|
|
253
|
-
async () =>
|
|
386
|
+
async () => await getPeopleByUnit(buildingUnit.value._id, { limit: 10, site: prop.site })
|
|
254
387
|
);
|
|
255
388
|
|
|
256
|
-
watch(getUnitPeople, (newData:
|
|
389
|
+
watch(getUnitPeople, (newData: TPeople[]) => {
|
|
257
390
|
peopleItems.value = newData ?? [];
|
|
258
391
|
});
|
|
259
392
|
|
|
260
|
-
|
|
393
|
+
const { data: getUnitVehicles, refresh: getUnitVehiclesRefresh } = useLazyAsyncData(
|
|
394
|
+
"get-unit-vehicles",
|
|
395
|
+
async () => await searchMultipleVehiclesByUnitId({unitId: buildingUnit.value._id, page: 1, limit: 10})
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
watch(getUnitVehicles, (newData) => {
|
|
399
|
+
unitVehicleItems.value = Array.isArray(newData?.items) ? newData.items : [];
|
|
400
|
+
vehiclePage.value = newData?.page || 1;
|
|
401
|
+
vehiclePageRange.value = newData?.pageRange || "-- - -- of --";
|
|
402
|
+
vehicleTotalPages.value = newData?.totalPages || 0;
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const unitResidentsArray = computed(() => {
|
|
406
|
+
return peopleItems.value.filter((person) => person?.type === 'resident');
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
const unitTenantsArray = computed(() => {
|
|
410
|
+
return peopleItems.value.filter((person) => person?.type === 'tenant');
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
// buildingUnit.value.site = prop.site;
|
|
261
415
|
|
|
262
416
|
const selectedBuilding = computed(() => {
|
|
263
417
|
return buildings.value.find((b) => b.value === buildingUnit.value.building);
|
|
264
418
|
});
|
|
265
419
|
|
|
266
420
|
const buildingLevels = computed(() => {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
421
|
+
const levels = selectedBuilding.value?.levels ?? [];
|
|
422
|
+
return levels.map((level: string) => ({
|
|
423
|
+
title: level,
|
|
424
|
+
value: level,
|
|
425
|
+
}))
|
|
271
426
|
});
|
|
272
427
|
|
|
273
428
|
const disable = ref(false);
|
|
@@ -285,7 +440,7 @@ function arraysAreEqual(a: any[], b: any[]): boolean {
|
|
|
285
440
|
const hasChanges = computed(() => {
|
|
286
441
|
return (
|
|
287
442
|
prop.roomFacility.name !== buildingUnit.value.name ||
|
|
288
|
-
prop.roomFacility.category !== buildingUnit.value.category ||
|
|
443
|
+
// prop.roomFacility.category !== buildingUnit.value.category ||
|
|
289
444
|
prop.roomFacility.level !== buildingUnit.value.level ||
|
|
290
445
|
!arraysAreEqual(
|
|
291
446
|
prop.roomFacility.buildingUnitFiles,
|
|
@@ -306,7 +461,7 @@ async function submit() {
|
|
|
306
461
|
await updateById(buildingUnit.value._id ?? "", {
|
|
307
462
|
name: buildingUnit.value.name,
|
|
308
463
|
level: buildingUnit.value.level,
|
|
309
|
-
category: buildingUnit.value.category,
|
|
464
|
+
// category: buildingUnit.value.category,
|
|
310
465
|
buildingUnitFiles: buildingUnit.value.buildingUnitFiles || [],
|
|
311
466
|
companyName: buildingUnit.value.companyName,
|
|
312
467
|
companyRegistrationNumber: buildingUnit.value.companyRegistrationNumber || "",
|
|
@@ -325,6 +480,40 @@ async function submit() {
|
|
|
325
480
|
}
|
|
326
481
|
}
|
|
327
482
|
|
|
483
|
+
|
|
484
|
+
const handleUpdateOwner = async ({ person, isOwner }: { person: TPeople; isOwner: boolean }) => {
|
|
485
|
+
const owners = peopleItems.value.filter(p => p.isOwner)
|
|
486
|
+
message.value = ""
|
|
487
|
+
// console.log('Updating owner status for', person._id, 'to', isOwner)
|
|
488
|
+
|
|
489
|
+
const userId = person._id ?? null;
|
|
490
|
+
|
|
491
|
+
if (!isOwner && owners.length <= 1 && owners[0]._id === person._id) {
|
|
492
|
+
message.value = "There must be at least one owner for this unit."
|
|
493
|
+
return
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (!userId) return message.value = "Resident user ID is missing."
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
try {
|
|
500
|
+
loading.ownerProcessing = true;
|
|
501
|
+
await updatePeopleById(userId, { isOwner })
|
|
502
|
+
getUnitPeopleRefresh();
|
|
503
|
+
} catch (error: any) {
|
|
504
|
+
message.value = error.response?._data?.message || "Failed to update owner status."
|
|
505
|
+
} finally {
|
|
506
|
+
loading.ownerProcessing = false;
|
|
507
|
+
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function handleUpdateVehiclePage(newPageNum: number) {
|
|
513
|
+
vehiclePage.value = newPageNum;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
|
|
328
517
|
function cancel() {
|
|
329
518
|
message.value = "";
|
|
330
519
|
emit("cancel");
|
|
@@ -338,3 +527,9 @@ watch(ownerNameInput, (newVal) => {
|
|
|
338
527
|
debounceSearchOwner();
|
|
339
528
|
}, { immediate: false });
|
|
340
529
|
</script>
|
|
530
|
+
|
|
531
|
+
<style lang="scss" scoped>
|
|
532
|
+
.no-pointer {
|
|
533
|
+
pointer-events: none;
|
|
534
|
+
}
|
|
535
|
+
</style>
|