@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.
Files changed (54) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/components/AccessCardQrTagging.vue +314 -34
  3. package/components/AccessCardQrTaggingPrintQr.vue +75 -0
  4. package/components/{AddSupplyForm.vue → AddEqupmentForm.vue} +5 -5
  5. package/components/AreaChecklistHistoryLogs.vue +9 -0
  6. package/components/BuildingForm.vue +36 -5
  7. package/components/BuildingManagement/buildings.vue +18 -9
  8. package/components/BuildingManagement/units.vue +13 -115
  9. package/components/BuildingUnitFormAdd.vue +42 -33
  10. package/components/BuildingUnitFormEdit.vue +334 -139
  11. package/components/CleaningScheduleMain.vue +60 -13
  12. package/components/Dialog/DeleteConfirmation.vue +2 -2
  13. package/components/Dialog/UpdateMoreAction.vue +2 -2
  14. package/components/EntryPassInformation.vue +443 -0
  15. package/components/{CheckoutItemMain.vue → EquipmentItemMain.vue} +88 -85
  16. package/components/{SupplyManagement.vue → EquipmentManagement.vue} +3 -3
  17. package/components/Input/DateTimePicker.vue +17 -11
  18. package/components/Input/InputPhoneNumberV2.vue +8 -0
  19. package/components/ManageChecklistMain.vue +400 -36
  20. package/components/ScheduleAreaMain.vue +56 -0
  21. package/components/TableHygiene.vue +47 -430
  22. package/components/UnitPersonCard.vue +123 -0
  23. package/components/VehicleAddSelection.vue +2 -2
  24. package/components/VehicleForm.vue +78 -19
  25. package/components/VehicleManagement.vue +164 -40
  26. package/components/VisitorForm.vue +95 -20
  27. package/components/VisitorFormSelection.vue +13 -2
  28. package/components/VisitorManagement.vue +83 -55
  29. package/composables/useAccessManagement.ts +52 -0
  30. package/composables/useCleaningPermission.ts +7 -7
  31. package/composables/useDashboardData.ts +2 -2
  32. package/composables/{useSupply.ts → useEquipment.ts} +11 -11
  33. package/composables/{useCheckout.ts → useEquipmentItem.ts} +7 -7
  34. package/composables/{useCheckoutPermission.ts → useEquipmentItemPermission.ts} +13 -13
  35. package/composables/useEquipmentManagementPermission.ts +96 -0
  36. package/composables/{useSupplyPermission.ts → useEquipmentPermission.ts} +9 -9
  37. package/composables/usePeople.ts +4 -3
  38. package/composables/useVehicle.ts +35 -2
  39. package/composables/useVisitor.ts +3 -3
  40. package/composables/useWorkOrder.ts +25 -3
  41. package/package.json +3 -2
  42. package/types/building.d.ts +1 -1
  43. package/types/cleaner-schedule.d.ts +1 -0
  44. package/types/{checkout-item.d.ts → equipment-item.d.ts} +3 -3
  45. package/types/{supply.d.ts → equipment.d.ts} +2 -2
  46. package/types/html2pdf.d.ts +19 -0
  47. package/types/people.d.ts +5 -2
  48. package/types/site.d.ts +8 -0
  49. package/types/vehicle.d.ts +4 -3
  50. package/types/visitor.d.ts +2 -1
  51. package/.playground/app.vue +0 -41
  52. package/.playground/eslint.config.mjs +0 -6
  53. package/.playground/nuxt.config.ts +0 -22
  54. 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"> Edit Unit </span>
5
+ <span class="font-weight-bold text-h5"> Unit Info ( {{ buildingUnit.name }} ) </span>
6
6
  </v-row>
7
7
  </v-toolbar>
8
- <v-card-text style="max-height: 100vh; overflow-y: auto">
9
- <v-form v-model="validForm" :disabled="disable">
10
- <v-row no-gutters>
11
- <v-col cols="12">
12
- <v-row>
13
- <v-col cols="12" class="mt-2">
14
- <v-row no-gutters>
15
- <InputLabel class="text-capitalize font-weight-bold" title="Building" />
16
- <v-col cols="12">
17
- {{ buildingUnit.buildingName }}
18
- </v-col>
19
- </v-row>
20
- </v-col>
21
- </v-row>
22
- </v-col>
23
-
24
- <v-col cols="12">
25
- <v-row>
26
- <v-col cols="12" class="mt-2">
27
- <v-row no-gutters>
28
- <InputLabel class="text-capitalize font-weight-bold" title="Block" />
29
- <v-col cols="12">
30
- {{ buildingUnit.block }}
31
- </v-col>
32
- </v-row>
33
- </v-col>
34
- </v-row>
35
- </v-col>
36
-
37
- <v-col cols="12">
38
- <v-row>
39
- <v-col cols="12" md="6" class="mt-2">
40
- <v-row no-gutters>
41
- <InputLabel class="text-capitalize font-weight-bold" title="Unit Name" />
42
- <v-col cols="12">
43
- <v-text-field v-model="buildingUnit.name" density="comfortable"
44
- :rules="[requiredRule]"></v-text-field>
45
- </v-col>
46
- </v-row>
47
- </v-col>
48
-
49
- <v-col cols="12" md="6" class="mt-2">
50
- <v-row no-gutters>
51
- <InputLabel class="text-capitalize font-weight-bold" title="Owner" />
52
- <v-col cols="12">
53
- <v-autocomplete v-model="buildingUnit.ownerName" v-model:search="ownerNameInput"
54
- :items="peopleItems" item-title="name" return-object density="comfortable">
55
- </v-autocomplete>
56
- </v-col>
57
- </v-row>
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
- </v-form>
231
+ </template>
152
232
  </v-card-text>
153
233
 
154
- <v-toolbar density="compact">
234
+ <v-col cols="12" class="my-2">
155
235
  <v-row no-gutters>
156
- <v-col cols="6">
157
- <v-btn tile block variant="text" class="text-none" size="48" @click="cancel">
158
- Cancel
159
- </v-btn>
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
- <v-col cols="6">
163
- <v-btn tile block variant="flat" color="black" class="text-none" size="48" :disabled="!validForm || disable"
164
- @click="submit" :loading="disable">
165
- Submit
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
- default: () => ({
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 { getAll: getAllPeople } = usePeople();
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<Array<Record<string, any>>>([]);
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 () => getAllPeople({ limit: 10, site: prop.site, type: "tenant", search: ownerNameInput.value })
386
+ async () => await getPeopleByUnit(buildingUnit.value._id, { limit: 10, site: prop.site })
254
387
  );
255
388
 
256
- watch(getUnitPeople, (newData: any) => {
389
+ watch(getUnitPeople, (newData: TPeople[]) => {
257
390
  peopleItems.value = newData ?? [];
258
391
  });
259
392
 
260
- buildingUnit.value.site = prop.site;
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
- return Array.from(
268
- { length: selectedBuilding.value?.levels || 0 },
269
- (_, i) => i + 1
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>