@iservice365/layer-common 1.5.7 → 1.7.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 +12 -0
- package/components/AccessCardAddForm.vue +363 -0
- package/components/AccessManagement.vue +414 -0
- package/components/BuildingUnitFormEdit.vue +47 -0
- package/components/DocumentForm.vue +67 -3
- package/components/DocumentManagement.vue +188 -4
- package/components/Editor.vue +59 -25
- package/components/EntryPassMain.vue +231 -0
- package/components/ImageCarousel.vue +74 -34
- package/components/Input/FileV2.vue +1 -1
- package/components/Input/InputPhoneNumberV2.vue +1 -0
- package/components/Input/NRICNumber.vue +2 -2
- package/components/Input/VehicleNumber.vue +1 -1
- package/components/Nfc/NFCTagForm.vue +210 -0
- package/components/Nfc/NFCTagMain.vue +342 -0
- package/components/VideoPlayer.vue +125 -0
- package/components/VisitorForm.vue +143 -62
- package/components/VisitorManagement.vue +1 -14
- package/composables/useCard.ts +46 -0
- package/composables/useDocument.ts +33 -13
- package/composables/useFile.ts +11 -5
- package/composables/useNFCPatrolTag.ts +51 -0
- package/composables/usePeople.ts +19 -1
- package/composables/useVisitor.ts +1 -1
- package/package.json +1 -1
- package/types/building.d.ts +2 -0
- package/types/card.d.ts +22 -0
- package/types/document.d.ts +1 -1
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters>
|
|
3
|
+
<v-col cols="12" class="mb-2">
|
|
4
|
+
<v-row no-gutters align="center" justify="space-between">
|
|
5
|
+
<v-btn
|
|
6
|
+
class="text-none"
|
|
7
|
+
rounded="pill"
|
|
8
|
+
variant="tonal"
|
|
9
|
+
size="large"
|
|
10
|
+
@click="setCard()"
|
|
11
|
+
v-if="canCreate && canCreateAccessCard"
|
|
12
|
+
>
|
|
13
|
+
Add Access Card
|
|
14
|
+
</v-btn>
|
|
15
|
+
|
|
16
|
+
<v-text-field
|
|
17
|
+
v-model="searchText"
|
|
18
|
+
placeholder="Search Card, Unit..."
|
|
19
|
+
variant="outlined"
|
|
20
|
+
density="comfortable"
|
|
21
|
+
clearable
|
|
22
|
+
hide-details
|
|
23
|
+
class="ml-2"
|
|
24
|
+
style="max-width: 250px"
|
|
25
|
+
/>
|
|
26
|
+
</v-row>
|
|
27
|
+
</v-col>
|
|
28
|
+
<v-col cols="12">
|
|
29
|
+
<v-card
|
|
30
|
+
width="100%"
|
|
31
|
+
variant="outlined"
|
|
32
|
+
border="thin"
|
|
33
|
+
rounded="lg"
|
|
34
|
+
:loading="loading"
|
|
35
|
+
>
|
|
36
|
+
<v-toolbar density="compact" color="grey-lighten-4">
|
|
37
|
+
<template #prepend>
|
|
38
|
+
<v-btn fab icon density="comfortable" @click="getCards">
|
|
39
|
+
<v-icon>mdi-refresh</v-icon>
|
|
40
|
+
</v-btn>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<template #append>
|
|
44
|
+
<v-row no-gutters justify="end" align="center">
|
|
45
|
+
<span class="mr-2 text-caption text-fontgray">
|
|
46
|
+
{{ pageRange }}
|
|
47
|
+
</span>
|
|
48
|
+
<local-pagination
|
|
49
|
+
v-model="page"
|
|
50
|
+
:length="pages"
|
|
51
|
+
@update:value="getCards"
|
|
52
|
+
/>
|
|
53
|
+
</v-row>
|
|
54
|
+
</template>
|
|
55
|
+
</v-toolbar>
|
|
56
|
+
<v-data-table
|
|
57
|
+
:headers="headers"
|
|
58
|
+
:items="items"
|
|
59
|
+
item-value="_id"
|
|
60
|
+
items-per-page="10"
|
|
61
|
+
fixed-header
|
|
62
|
+
hide-default-footer
|
|
63
|
+
@click:row="tableRowClickHandler"
|
|
64
|
+
style="max-height: calc(100vh - (200px))"
|
|
65
|
+
/>
|
|
66
|
+
</v-card>
|
|
67
|
+
</v-col>
|
|
68
|
+
|
|
69
|
+
<!-- Create Dialog -->
|
|
70
|
+
<v-dialog v-model="createDialog" width="650" persistent>
|
|
71
|
+
<AccessCardAddForm
|
|
72
|
+
@cancel="createDialog = false"
|
|
73
|
+
@success="successCreate()"
|
|
74
|
+
/>
|
|
75
|
+
</v-dialog>
|
|
76
|
+
|
|
77
|
+
<!-- Edit Dialog -->
|
|
78
|
+
<v-dialog v-model="editDialog" width="650" persistent>
|
|
79
|
+
<AccessCardAddForm
|
|
80
|
+
mode="edit"
|
|
81
|
+
@cancel="editDialog = false"
|
|
82
|
+
@success="successUpdate()"
|
|
83
|
+
:card="selectedCard"
|
|
84
|
+
/>
|
|
85
|
+
</v-dialog>
|
|
86
|
+
|
|
87
|
+
<!-- Preview Dialog -->
|
|
88
|
+
<v-dialog v-model="previewDialog" width="450" persistent>
|
|
89
|
+
<v-card width="100%">
|
|
90
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
|
|
91
|
+
<v-row no-gutters class="mb-4">
|
|
92
|
+
<v-col cols="12">
|
|
93
|
+
<strong>Card:</strong> {{ selectedCard?.cardNumber ?? "N/A" }}
|
|
94
|
+
</v-col>
|
|
95
|
+
<v-col cols="12">
|
|
96
|
+
<strong>Access Type:</strong>
|
|
97
|
+
{{ selectedCard?.accessCardType ?? "N/A" }}
|
|
98
|
+
</v-col>
|
|
99
|
+
<!-- <v-col cols="12">
|
|
100
|
+
<strong>Visitor Type:</strong>
|
|
101
|
+
{{ selectedCard?.visitorType ?? "N/A" }}
|
|
102
|
+
</v-col> -->
|
|
103
|
+
<v-col cols="12">
|
|
104
|
+
<strong>Unit:</strong>
|
|
105
|
+
{{ selectedCard?.unit || "N/A" }}
|
|
106
|
+
</v-col>
|
|
107
|
+
<v-col cols="12">
|
|
108
|
+
<strong>Assign:</strong> {{ selectedCard?.assign || "N/A" }}
|
|
109
|
+
</v-col>
|
|
110
|
+
<v-col cols="12">
|
|
111
|
+
<strong>Status:</strong> {{ selectedCard?.status ?? "N/A" }}
|
|
112
|
+
</v-col>
|
|
113
|
+
</v-row></v-card-text
|
|
114
|
+
>
|
|
115
|
+
<v-toolbar class="pa-0" density="compact">
|
|
116
|
+
<v-row no-gutters>
|
|
117
|
+
<v-col cols="6" class="pa-0">
|
|
118
|
+
<v-btn
|
|
119
|
+
block
|
|
120
|
+
variant="text"
|
|
121
|
+
class="text-none"
|
|
122
|
+
size="large"
|
|
123
|
+
@click="previewDialog = false"
|
|
124
|
+
height="48"
|
|
125
|
+
>
|
|
126
|
+
Close
|
|
127
|
+
</v-btn>
|
|
128
|
+
</v-col>
|
|
129
|
+
<v-col cols="6" class="pa-0" v-if="canUpdate">
|
|
130
|
+
<v-menu>
|
|
131
|
+
<template #activator="{ props }">
|
|
132
|
+
<v-btn
|
|
133
|
+
block
|
|
134
|
+
variant="flat"
|
|
135
|
+
color="black"
|
|
136
|
+
class="text-none"
|
|
137
|
+
height="48"
|
|
138
|
+
v-bind="props"
|
|
139
|
+
tile
|
|
140
|
+
:disabled="!canUpdateAccessCard && !canDeleteAccessCard"
|
|
141
|
+
>
|
|
142
|
+
More actions
|
|
143
|
+
</v-btn>
|
|
144
|
+
</template>
|
|
145
|
+
<v-list class="pa-0">
|
|
146
|
+
<v-list-item @click="openEditDialog()">
|
|
147
|
+
<v-list-item-title class="text-subtitle-2">
|
|
148
|
+
Edit Card
|
|
149
|
+
</v-list-item-title>
|
|
150
|
+
</v-list-item>
|
|
151
|
+
<v-list-item @click="openReplaceDialog()">
|
|
152
|
+
<v-list-item-title class="text-subtitle-2">
|
|
153
|
+
Replace Card
|
|
154
|
+
</v-list-item-title>
|
|
155
|
+
</v-list-item>
|
|
156
|
+
<v-list-item @click="openDeleteDialog()" class="text-red">
|
|
157
|
+
<v-list-item-title class="text-subtitle-2">
|
|
158
|
+
Delete Card
|
|
159
|
+
</v-list-item-title>
|
|
160
|
+
</v-list-item>
|
|
161
|
+
</v-list>
|
|
162
|
+
</v-menu>
|
|
163
|
+
</v-col>
|
|
164
|
+
</v-row>
|
|
165
|
+
</v-toolbar></v-card
|
|
166
|
+
>
|
|
167
|
+
</v-dialog>
|
|
168
|
+
|
|
169
|
+
<!-- Delete Dialog -->
|
|
170
|
+
<v-dialog
|
|
171
|
+
v-model="confirmDialog"
|
|
172
|
+
:loading="deleteLoading"
|
|
173
|
+
width="450"
|
|
174
|
+
persistent
|
|
175
|
+
>
|
|
176
|
+
<v-card width="100%">
|
|
177
|
+
<v-toolbar density="compact" class="pl-4">
|
|
178
|
+
<span class="font-weight-medium text-h5">Delete Card</span>
|
|
179
|
+
</v-toolbar>
|
|
180
|
+
<v-card-text>
|
|
181
|
+
<p class="text-subtitle-2 text-center">
|
|
182
|
+
Are you sure you want to delete this card? This action cannot be
|
|
183
|
+
undone.
|
|
184
|
+
</p>
|
|
185
|
+
|
|
186
|
+
<v-row v-if="message" no-gutters justify="center" class="mt-4">
|
|
187
|
+
<span class="text-caption text-error text-center">
|
|
188
|
+
{{ message }}
|
|
189
|
+
</span>
|
|
190
|
+
</v-row></v-card-text
|
|
191
|
+
>
|
|
192
|
+
<v-toolbar density="compact">
|
|
193
|
+
<v-row no-gutters>
|
|
194
|
+
<v-col cols="6">
|
|
195
|
+
<v-btn
|
|
196
|
+
tile
|
|
197
|
+
block
|
|
198
|
+
size="48"
|
|
199
|
+
variant="text"
|
|
200
|
+
class="text-none"
|
|
201
|
+
@click="confirmDialog = false"
|
|
202
|
+
:disabled="deleteLoading"
|
|
203
|
+
>
|
|
204
|
+
Close
|
|
205
|
+
</v-btn>
|
|
206
|
+
</v-col>
|
|
207
|
+
<v-col cols="6">
|
|
208
|
+
<v-btn
|
|
209
|
+
tile
|
|
210
|
+
block
|
|
211
|
+
size="48"
|
|
212
|
+
color="black"
|
|
213
|
+
variant="flat"
|
|
214
|
+
class="text-none"
|
|
215
|
+
@click="handleDeleteCard"
|
|
216
|
+
:loading="deleteLoading"
|
|
217
|
+
>
|
|
218
|
+
Delete Card
|
|
219
|
+
</v-btn>
|
|
220
|
+
</v-col>
|
|
221
|
+
</v-row></v-toolbar
|
|
222
|
+
>
|
|
223
|
+
</v-card>
|
|
224
|
+
</v-dialog>
|
|
225
|
+
|
|
226
|
+
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
227
|
+
</v-row>
|
|
228
|
+
</template>
|
|
229
|
+
<script setup lang="ts">
|
|
230
|
+
definePageMeta({
|
|
231
|
+
middleware: ["01-auth", "02-org"],
|
|
232
|
+
memberOnly: true,
|
|
233
|
+
});
|
|
234
|
+
const props = defineProps({
|
|
235
|
+
headers: {
|
|
236
|
+
type: Array as PropType<Array<Record<string, any>>>,
|
|
237
|
+
default: () => [
|
|
238
|
+
{
|
|
239
|
+
title: "Card",
|
|
240
|
+
value: "cardNumber",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
title: "Unit",
|
|
244
|
+
value: "unit",
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
title: "Assign",
|
|
248
|
+
value: "assign",
|
|
249
|
+
},
|
|
250
|
+
{ title: "Action", value: "action-table" },
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
canCreate: {
|
|
254
|
+
type: Boolean,
|
|
255
|
+
default: true,
|
|
256
|
+
},
|
|
257
|
+
canUpdate: {
|
|
258
|
+
type: Boolean,
|
|
259
|
+
default: true,
|
|
260
|
+
},
|
|
261
|
+
canDelete: {
|
|
262
|
+
type: Boolean,
|
|
263
|
+
default: true,
|
|
264
|
+
},
|
|
265
|
+
canCreateAccessCard: {
|
|
266
|
+
type: Boolean,
|
|
267
|
+
default: true,
|
|
268
|
+
},
|
|
269
|
+
canUpdateAccessCard: {
|
|
270
|
+
type: Boolean,
|
|
271
|
+
default: true,
|
|
272
|
+
},
|
|
273
|
+
canDeleteAccessCard: {
|
|
274
|
+
type: Boolean,
|
|
275
|
+
default: true,
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// const { headerSearch } = useLocal();
|
|
280
|
+
const page = ref(1);
|
|
281
|
+
const pages = ref(0);
|
|
282
|
+
const pageRange = ref("-- - -- of --");
|
|
283
|
+
|
|
284
|
+
const message = ref("");
|
|
285
|
+
const messageSnackbar = ref(false);
|
|
286
|
+
const messageColor = ref("");
|
|
287
|
+
|
|
288
|
+
const items = ref<Array<Record<string, any>>>([]);
|
|
289
|
+
const createDialog = ref(false);
|
|
290
|
+
const editDialog = ref(false);
|
|
291
|
+
const previewDialog = ref(false);
|
|
292
|
+
const deleteLoading = ref(false);
|
|
293
|
+
const confirmDialog = ref(false);
|
|
294
|
+
const searchText = ref("");
|
|
295
|
+
const replaceDialog = ref(false);
|
|
296
|
+
|
|
297
|
+
const selectedCard = ref<TCard>({
|
|
298
|
+
_id: "",
|
|
299
|
+
name: "",
|
|
300
|
+
accessCardType: "",
|
|
301
|
+
// visitorType: "",
|
|
302
|
+
type: "",
|
|
303
|
+
cardNumber: "",
|
|
304
|
+
startDate: "",
|
|
305
|
+
endDate: "",
|
|
306
|
+
door: "",
|
|
307
|
+
accessGroup: [],
|
|
308
|
+
cardType: "",
|
|
309
|
+
pinNo: "",
|
|
310
|
+
useAsLiftCard: false,
|
|
311
|
+
liftAccessLevel: "",
|
|
312
|
+
isActivate: true,
|
|
313
|
+
isAntiPassBack: false,
|
|
314
|
+
status: "",
|
|
315
|
+
org: "",
|
|
316
|
+
site: "",
|
|
317
|
+
unit: "",
|
|
318
|
+
assign: "",
|
|
319
|
+
});
|
|
320
|
+
const selectedCardId = ref<string | null>(null);
|
|
321
|
+
|
|
322
|
+
const { getAll: _getAllCards, deleteById: _deleteCard } = useCard();
|
|
323
|
+
|
|
324
|
+
const {
|
|
325
|
+
data: getCardReq,
|
|
326
|
+
refresh: getCards,
|
|
327
|
+
status: getAllReqStatus,
|
|
328
|
+
} = useLazyAsyncData(
|
|
329
|
+
"get-all-cards",
|
|
330
|
+
() =>
|
|
331
|
+
_getAllCards({
|
|
332
|
+
page: page.value,
|
|
333
|
+
search: searchText.value,
|
|
334
|
+
// search: headerSearch.value,
|
|
335
|
+
}),
|
|
336
|
+
{
|
|
337
|
+
watch: [page, searchText],
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const loading = computed(() => getAllReqStatus.value === "pending");
|
|
342
|
+
|
|
343
|
+
watchEffect(() => {
|
|
344
|
+
if (getCardReq.value) {
|
|
345
|
+
items.value = getCardReq.value.items;
|
|
346
|
+
pages.value = getCardReq.value.pages;
|
|
347
|
+
pageRange.value = getCardReq.value.pageRange;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
function setCard({ mode = "create", dialog = true, data = {} as TCard } = {}) {
|
|
352
|
+
if (mode === "create") {
|
|
353
|
+
createDialog.value = dialog;
|
|
354
|
+
} else if (mode === "edit") {
|
|
355
|
+
editDialog.value = dialog;
|
|
356
|
+
selectedCard.value = data;
|
|
357
|
+
} else if (mode === "preview") {
|
|
358
|
+
previewDialog.value = dialog;
|
|
359
|
+
selectedCard.value = data;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function successCreate() {
|
|
364
|
+
createDialog.value = false;
|
|
365
|
+
getCards();
|
|
366
|
+
showMessage("Card created successfully!", "success");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function successUpdate() {
|
|
370
|
+
editDialog.value = false;
|
|
371
|
+
previewDialog.value = false;
|
|
372
|
+
getCards();
|
|
373
|
+
showMessage("Card updated successfully!", "success");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function showMessage(msg: string, color: string) {
|
|
377
|
+
message.value = msg;
|
|
378
|
+
messageColor.value = color;
|
|
379
|
+
messageSnackbar.value = true;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function tableRowClickHandler(_: any, data: any) {
|
|
383
|
+
selectedCard.value = data.item as TCard;
|
|
384
|
+
previewDialog.value = true;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function openEditDialog() {
|
|
388
|
+
editDialog.value = true;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function openDeleteDialog() {
|
|
392
|
+
confirmDialog.value = true;
|
|
393
|
+
message.value = "";
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function openReplaceDialog() {
|
|
397
|
+
replaceDialog.value = true;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async function handleDeleteCard() {
|
|
401
|
+
deleteLoading.value = true;
|
|
402
|
+
try {
|
|
403
|
+
await _deleteCard(selectedCard.value._id ?? "");
|
|
404
|
+
await getCards();
|
|
405
|
+
selectedCardId.value = null;
|
|
406
|
+
confirmDialog.value = false;
|
|
407
|
+
previewDialog.value = false;
|
|
408
|
+
} catch (error: any) {
|
|
409
|
+
message.value = error?.response?._data?.message || "Failed to delete card";
|
|
410
|
+
} finally {
|
|
411
|
+
deleteLoading.value = false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
</script>
|
|
@@ -60,6 +60,28 @@
|
|
|
60
60
|
</v-row>
|
|
61
61
|
</v-col>
|
|
62
62
|
|
|
63
|
+
<v-col cols="12">
|
|
64
|
+
<v-row>
|
|
65
|
+
<v-col cols="12" class="mt-2">
|
|
66
|
+
<v-row no-gutters>
|
|
67
|
+
<InputLabel
|
|
68
|
+
class="text-capitalize font-weight-bold"
|
|
69
|
+
title="Owner"
|
|
70
|
+
/>
|
|
71
|
+
<v-col cols="12">
|
|
72
|
+
<v-autocomplete
|
|
73
|
+
v-model="buildingUnit.ownerName"
|
|
74
|
+
:items="peopleItems"
|
|
75
|
+
item-title="name"
|
|
76
|
+
return-object
|
|
77
|
+
density="comfortable">
|
|
78
|
+
</v-autocomplete>
|
|
79
|
+
</v-col>
|
|
80
|
+
</v-row>
|
|
81
|
+
</v-col>
|
|
82
|
+
</v-row>
|
|
83
|
+
</v-col>
|
|
84
|
+
|
|
63
85
|
<v-col cols="12">
|
|
64
86
|
<v-row>
|
|
65
87
|
<v-col cols="12" class="mt-2">
|
|
@@ -258,6 +280,8 @@ const prop = defineProps({
|
|
|
258
280
|
_id: "",
|
|
259
281
|
site: "",
|
|
260
282
|
name: "",
|
|
283
|
+
owner: "",
|
|
284
|
+
ownerName: "",
|
|
261
285
|
building: "",
|
|
262
286
|
buildingName: "",
|
|
263
287
|
category: "",
|
|
@@ -277,6 +301,8 @@ const buildingUnit = ref({
|
|
|
277
301
|
_id: "",
|
|
278
302
|
site: "",
|
|
279
303
|
name: "",
|
|
304
|
+
owner: "",
|
|
305
|
+
ownerName: "",
|
|
280
306
|
building: "",
|
|
281
307
|
buildingName: "",
|
|
282
308
|
level: 0,
|
|
@@ -297,8 +323,10 @@ const emit = defineEmits(["cancel", "success", "success:create-more"]);
|
|
|
297
323
|
const validForm = ref(false);
|
|
298
324
|
|
|
299
325
|
const { getAll } = useBuilding();
|
|
326
|
+
const { getPeopleByUnit } = usePeople();
|
|
300
327
|
|
|
301
328
|
const buildings = ref<Record<string, any>[]>([]);
|
|
329
|
+
const peopleItems = ref<Array<Record<string, any>>>([]);
|
|
302
330
|
|
|
303
331
|
const { data: getBuildingReq } = useLazyAsyncData(
|
|
304
332
|
"get-all-buildings",
|
|
@@ -315,6 +343,17 @@ watchEffect(() => {
|
|
|
315
343
|
}
|
|
316
344
|
});
|
|
317
345
|
|
|
346
|
+
const { data: getUnitPeople } = useLazyAsyncData(
|
|
347
|
+
"get-unit-people",
|
|
348
|
+
async () => getPeopleByUnit(prop.roomFacility._id as string)
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
watch(getUnitPeople, (newData: any) => {
|
|
352
|
+
if (newData) {
|
|
353
|
+
peopleItems.value = newData ?? [];
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
318
357
|
buildingUnit.value.site = prop.site;
|
|
319
358
|
|
|
320
359
|
const selectedBuilding = computed(() => {
|
|
@@ -355,6 +394,12 @@ const hasChanges = computed(() => {
|
|
|
355
394
|
async function submit() {
|
|
356
395
|
disable.value = true;
|
|
357
396
|
try {
|
|
397
|
+
|
|
398
|
+
if (buildingUnit.value.ownerName) {
|
|
399
|
+
buildingUnit.value.owner = (buildingUnit.value.ownerName as any)._id
|
|
400
|
+
buildingUnit.value.ownerName = (buildingUnit.value.ownerName as any).name
|
|
401
|
+
}
|
|
402
|
+
|
|
358
403
|
await updateById(buildingUnit.value._id ?? "", {
|
|
359
404
|
name: buildingUnit.value.name,
|
|
360
405
|
level: buildingUnit.value.level,
|
|
@@ -364,6 +409,8 @@ async function submit() {
|
|
|
364
409
|
companyRegistrationNumber: buildingUnit.value.companyRegistrationNumber || "",
|
|
365
410
|
leaseStart: buildingUnit.value.leaseStart,
|
|
366
411
|
leaseEnd: buildingUnit.value.leaseEnd,
|
|
412
|
+
owner: buildingUnit.value.owner || "",
|
|
413
|
+
ownerName: buildingUnit.value.ownerName || ""
|
|
367
414
|
});
|
|
368
415
|
|
|
369
416
|
emit("success");
|
|
@@ -15,10 +15,19 @@
|
|
|
15
15
|
v-model="document.attachment"
|
|
16
16
|
:multiple="false"
|
|
17
17
|
:max-length="10"
|
|
18
|
-
title="Upload
|
|
18
|
+
title="Upload PDF Files"
|
|
19
|
+
accept=".pdf, .doc, .docx, .xls, .xlsx, .txt"
|
|
19
20
|
/>
|
|
20
21
|
</v-col>
|
|
21
22
|
|
|
23
|
+
<v-col cols="12" class="px-6">
|
|
24
|
+
<InputLabel class="text-capitalize" title="Document Name" />
|
|
25
|
+
<v-text-field
|
|
26
|
+
v-model.trim="document.name"
|
|
27
|
+
density="comfortable"
|
|
28
|
+
></v-text-field>
|
|
29
|
+
</v-col>
|
|
30
|
+
|
|
22
31
|
<v-col cols="12">
|
|
23
32
|
<v-row no-gutters>
|
|
24
33
|
<v-col cols="12" class="text-center">
|
|
@@ -57,7 +66,12 @@
|
|
|
57
66
|
color="black"
|
|
58
67
|
class="text-none"
|
|
59
68
|
size="48"
|
|
60
|
-
:disabled="
|
|
69
|
+
:disabled="
|
|
70
|
+
!validForm ||
|
|
71
|
+
disable ||
|
|
72
|
+
document.attachment.length == 0 ||
|
|
73
|
+
document.name == ''
|
|
74
|
+
"
|
|
61
75
|
@click="submit"
|
|
62
76
|
:loading="disable"
|
|
63
77
|
>
|
|
@@ -78,17 +92,42 @@ const prop = defineProps({
|
|
|
78
92
|
type: Object as PropType<TDocument>,
|
|
79
93
|
default: () => ({
|
|
80
94
|
name: "",
|
|
81
|
-
attachment:
|
|
95
|
+
attachment: [],
|
|
82
96
|
}),
|
|
83
97
|
},
|
|
84
98
|
});
|
|
85
99
|
|
|
86
100
|
const emit = defineEmits(["cancel", "success"]);
|
|
87
101
|
|
|
102
|
+
const { add, updateById } = useDocument();
|
|
103
|
+
const { getFileById } = useFile();
|
|
104
|
+
|
|
88
105
|
const validForm = ref(false);
|
|
89
106
|
const disable = ref(false);
|
|
90
107
|
const message = ref("");
|
|
91
108
|
|
|
109
|
+
const document = ref<Record<string, any>>({
|
|
110
|
+
name: "",
|
|
111
|
+
attachment: [],
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (prop.mode === "edit") {
|
|
115
|
+
document.value.name = prop.document.name;
|
|
116
|
+
document.value.attachment = [prop.document.attachment];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
watch(
|
|
120
|
+
() => document.value.attachment,
|
|
121
|
+
async (newVal) => {
|
|
122
|
+
if (newVal) {
|
|
123
|
+
const fileData = await getFileById(newVal);
|
|
124
|
+
if (fileData) {
|
|
125
|
+
document.value.name = fileData.data.name;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
|
|
92
131
|
function cancel() {
|
|
93
132
|
// createMore.value = false;
|
|
94
133
|
message.value = "";
|
|
@@ -97,5 +136,30 @@ function cancel() {
|
|
|
97
136
|
|
|
98
137
|
async function submit() {
|
|
99
138
|
disable.value = true;
|
|
139
|
+
try {
|
|
140
|
+
if (prop.mode === "add") {
|
|
141
|
+
const payload = {
|
|
142
|
+
name: document.value.name,
|
|
143
|
+
attachment: document.value.attachment,
|
|
144
|
+
status: "active",
|
|
145
|
+
};
|
|
146
|
+
await add(payload);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (prop.mode === "edit") {
|
|
150
|
+
const payload = {
|
|
151
|
+
name: document.value.name,
|
|
152
|
+
attachment: document.value.attachment,
|
|
153
|
+
}
|
|
154
|
+
await updateById(prop.document._id ?? "", payload);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
emit("success");
|
|
158
|
+
} catch (error: any) {
|
|
159
|
+
message.value =
|
|
160
|
+
error.response?._data?.message || "Failed to create document";
|
|
161
|
+
} finally {
|
|
162
|
+
disable.value = false;
|
|
163
|
+
}
|
|
100
164
|
}
|
|
101
165
|
</script>
|