@iservice365/layer-common 1.3.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 +6 -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/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/usePeople.ts +13 -5
- package/composables/useVisitor.ts +74 -51
- package/package.json +1 -1
- package/types/building.d.ts +2 -0
- package/types/people.d.ts +2 -1
- package/types/visitor.d.ts +1 -1
|
@@ -1,95 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
|
-
<TableMain
|
|
4
|
-
:
|
|
5
|
-
:
|
|
6
|
-
|
|
7
|
-
:page="page"
|
|
8
|
-
:pages="pages"
|
|
9
|
-
:extension-height="110"
|
|
10
|
-
:pageRange="pageRange"
|
|
11
|
-
:canCreate="canAddVisitor"
|
|
12
|
-
@refresh="getVisitorRefresh"
|
|
13
|
-
@update:page="handleUpdatePage"
|
|
14
|
-
createLabel="Add Visitor"
|
|
15
|
-
show-header
|
|
16
|
-
@row-click="handleRowClick"
|
|
17
|
-
@create="dialog.showSelection = true"
|
|
18
|
-
>
|
|
3
|
+
<TableMain :headers="headers" :items="items" :loading="getVisitorPending" :page="page" :pages="pages"
|
|
4
|
+
:extension-height="110" :offset="300" :pageRange="pageRange" :canCreate="canAddVisitor"
|
|
5
|
+
@refresh="getVisitorRefresh" @update:page="handleUpdatePage" createLabel="Add Visitor" show-header
|
|
6
|
+
@row-click="handleRowClick" @create="dialog.showSelection = true">
|
|
19
7
|
<template #extension>
|
|
20
8
|
<v-row no-gutters class="w-100 d-flex flex-column">
|
|
21
|
-
<v-tabs
|
|
22
|
-
v-
|
|
23
|
-
color="primary"
|
|
24
|
-
:height="40"
|
|
25
|
-
@update:model-value="toRoute"
|
|
26
|
-
class="w-100"
|
|
27
|
-
>
|
|
28
|
-
<v-tab
|
|
29
|
-
v-for="tab in tabOptions"
|
|
30
|
-
:value="tab.status"
|
|
31
|
-
:key="tab.status"
|
|
32
|
-
class="text-capitalize"
|
|
33
|
-
>
|
|
9
|
+
<v-tabs v-model="activeTab" color="primary" :height="40" @update:model-value="toRoute" class="w-100">
|
|
10
|
+
<v-tab v-for="tab in tabOptions" :value="tab.status" :key="tab.status" class="text-capitalize">
|
|
34
11
|
{{ tab.name }}
|
|
35
12
|
</v-tab>
|
|
36
13
|
</v-tabs>
|
|
37
14
|
|
|
38
|
-
<v-card
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
>
|
|
43
|
-
<v-text-field
|
|
44
|
-
v-model="searchInput"
|
|
45
|
-
density="compact"
|
|
46
|
-
placeholder="Search"
|
|
47
|
-
clearable
|
|
48
|
-
max-width="300"
|
|
49
|
-
append-inner-icon="mdi-magnify"
|
|
50
|
-
hide-details
|
|
51
|
-
/>
|
|
52
|
-
<v-checkbox
|
|
53
|
-
v-model="displayCheckedOutOnly"
|
|
54
|
-
class="text-subtitle-2"
|
|
55
|
-
hide-details
|
|
56
|
-
>
|
|
15
|
+
<v-card class="w-100 px-3 d-flex align-center ga-5 py-2" flat :height="60">
|
|
16
|
+
<v-text-field v-model="searchInput" density="compact" placeholder="Search" clearable max-width="300"
|
|
17
|
+
append-inner-icon="mdi-magnify" hide-details />
|
|
18
|
+
<v-checkbox v-model="displayCheckedOutOnly" class="text-subtitle-2" hide-details>
|
|
57
19
|
<template #label>
|
|
58
20
|
<span class="text-caption">Not Checked Out</span>
|
|
59
21
|
</template>
|
|
60
22
|
</v-checkbox>
|
|
61
|
-
<InputDateTimePicker
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
hide-details
|
|
65
|
-
/>
|
|
66
|
-
<InputDateTimePicker
|
|
67
|
-
v-model:utc="dateTo"
|
|
68
|
-
density="compact"
|
|
69
|
-
hide-details
|
|
70
|
-
/>
|
|
71
|
-
<v-select
|
|
72
|
-
v-model="filterTypes"
|
|
73
|
-
label="Filter by types"
|
|
74
|
-
item-title="label"
|
|
75
|
-
item-value="value"
|
|
76
|
-
:items="visitorSelection"
|
|
77
|
-
density="compact"
|
|
78
|
-
clearable
|
|
79
|
-
multiple
|
|
80
|
-
max-width="200"
|
|
81
|
-
hide-details
|
|
82
|
-
>
|
|
23
|
+
<InputDateTimePicker v-model:utc="dateFrom" density="compact" hide-details />
|
|
24
|
+
<InputDateTimePicker v-model:utc="dateTo" density="compact" hide-details />
|
|
25
|
+
<v-select v-model="filterTypes" label="Filter by types" item-title="label" item-value="value"
|
|
26
|
+
:items="visitorSelection" density="compact" clearable multiple max-width="200" hide-details>
|
|
83
27
|
<template v-slot:selection="{ item, index }">
|
|
84
28
|
<div class="d-flex align-center text-caption text-nowrap">
|
|
85
|
-
<v-chip
|
|
86
|
-
|
|
87
|
-
color="error"
|
|
88
|
-
:text="filterTypeSelectionLabel()"
|
|
89
|
-
size="x-small"
|
|
90
|
-
variant="tonal"
|
|
91
|
-
class="ml-2"
|
|
92
|
-
/>
|
|
29
|
+
<v-chip v-if="index === 0" color="error" :text="filterTypeSelectionLabel()" size="x-small"
|
|
30
|
+
variant="tonal" class="ml-2" />
|
|
93
31
|
</div>
|
|
94
32
|
</template>
|
|
95
33
|
</v-select>
|
|
@@ -111,7 +49,7 @@
|
|
|
111
49
|
<v-icon icon="mdi-user" size="15" />
|
|
112
50
|
<span v-if="item.type === 'contractor'" class="text-capitalize">{{
|
|
113
51
|
formatCamelCaseToWords(item.contractorType)
|
|
114
|
-
|
|
52
|
+
}}</span>
|
|
115
53
|
<span v-else class="text-capitalize">{{ formatType(item) }}</span>
|
|
116
54
|
</span>
|
|
117
55
|
<span class="d-flex align-center ga-2">
|
|
@@ -149,100 +87,57 @@
|
|
|
149
87
|
<v-icon icon="mdi-clock-time-four-outline" color="green" size="20" />
|
|
150
88
|
<span class="text-capitalize">{{
|
|
151
89
|
UTCToLocalTIme(item.checkIn) || "-"
|
|
152
|
-
|
|
90
|
+
}}</span>
|
|
153
91
|
</span>
|
|
154
92
|
<span class="d-flex align-center ga-2">
|
|
155
93
|
<v-icon icon="mdi-clock-time-eight-outline" color="red" size="20" v-if="item.checkOut" />
|
|
156
94
|
<template v-if="item.checkOut">
|
|
157
95
|
<span class="text-capitalize">{{
|
|
158
96
|
UTCToLocalTIme(item.checkOut) || "_"
|
|
159
|
-
|
|
97
|
+
}}</span>
|
|
160
98
|
<span v-if="item?.manualCheckout">
|
|
161
|
-
<TooltipInfo
|
|
162
|
-
text="Manual Checkout"
|
|
163
|
-
density="compact"
|
|
164
|
-
size="x-small"
|
|
165
|
-
/>
|
|
99
|
+
<TooltipInfo text="Manual Checkout" density="compact" size="x-small" />
|
|
166
100
|
</span>
|
|
167
101
|
</template>
|
|
168
102
|
<span v-else>
|
|
169
|
-
<v-btn
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
color="red"
|
|
173
|
-
text="Checkout"
|
|
174
|
-
:loading="loading.checkingOut && item?._id === selectedVisitorId"
|
|
175
|
-
@click.stop="handleCheckout(item._id)"
|
|
176
|
-
v-if="canCheckoutVisitor"
|
|
177
|
-
/>
|
|
103
|
+
<v-btn size="x-small" class="text-capitalize" color="red" text="Checkout"
|
|
104
|
+
:loading="loading.checkingOut && item?._id === selectedVisitorId" @click.stop="handleCheckout(item._id)"
|
|
105
|
+
v-if="canCheckoutVisitor" />
|
|
178
106
|
</span>
|
|
179
107
|
</span>
|
|
180
108
|
</template>
|
|
181
109
|
</TableMain>
|
|
182
110
|
|
|
183
111
|
<v-dialog v-model="dialog.showSelection" width="450" persistent>
|
|
184
|
-
<VisitorFormSelection
|
|
185
|
-
@cancel="dialog.showSelection = false"
|
|
186
|
-
@select="handleSelectVisitorType"
|
|
187
|
-
/>
|
|
112
|
+
<VisitorFormSelection @cancel="dialog.showSelection = false" @select="handleSelectVisitorType" />
|
|
188
113
|
</v-dialog>
|
|
189
114
|
|
|
190
|
-
<v-dialog
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
width="450"
|
|
194
|
-
persistent
|
|
195
|
-
>
|
|
196
|
-
<VisitorForm
|
|
197
|
-
mode="add"
|
|
198
|
-
:org="orgId"
|
|
199
|
-
:site="siteId"
|
|
200
|
-
:type="activeVisitorFormType"
|
|
201
|
-
@back="handleClickBack"
|
|
202
|
-
@done="handleVisitorFormDone"
|
|
203
|
-
@done:more="handleVisitorFormCreateMore"
|
|
204
|
-
/>
|
|
115
|
+
<v-dialog v-model="dialog.addVisitor" v-if="activeVisitorFormType" width="450" persistent>
|
|
116
|
+
<VisitorForm mode="add" :org="orgId" :site="siteId" :type="activeVisitorFormType" @back="handleClickBack"
|
|
117
|
+
@done="handleVisitorFormDone" @done:more="handleVisitorFormCreateMore" />
|
|
205
118
|
</v-dialog>
|
|
206
119
|
|
|
207
120
|
<v-dialog v-model="dialog.viewVisitor" width="450" persistent>
|
|
208
|
-
<VehicleUpdateMoreAction
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
:can-delete="canDeleteVisitor"
|
|
212
|
-
@close="dialog.viewVisitor = false"
|
|
213
|
-
edit-button-label="Edit Visitor"
|
|
214
|
-
delete-button-label="Delete Visitor"
|
|
215
|
-
@delete="handleDeleteVisitor"
|
|
216
|
-
>
|
|
121
|
+
<VehicleUpdateMoreAction title="Preview" :can-update="canUpdateVisitor" :can-delete="canDeleteVisitor"
|
|
122
|
+
@close="dialog.viewVisitor = false" edit-button-label="Edit Visitor" delete-button-label="Delete Visitor"
|
|
123
|
+
@delete="handleDeleteVisitor">
|
|
217
124
|
<template v-slot:content>
|
|
218
125
|
<v-row no-gutters class="mb-4">
|
|
219
126
|
<v-col v-for="(label, key) in formattedFields" :key="key" cols="12">
|
|
220
|
-
<span
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
127
|
+
<span v-if="
|
|
128
|
+
key === 'checkOut' &&
|
|
129
|
+
!selectedVisitorObject[key] &&
|
|
130
|
+
canCheckoutVisitor
|
|
131
|
+
" class="d-flex align-center">
|
|
224
132
|
<strong>{{ label }}:</strong>
|
|
225
|
-
<v-btn
|
|
226
|
-
|
|
227
|
-
class="ml-3 text-capitalize"
|
|
228
|
-
color="red"
|
|
229
|
-
text="Checkout"
|
|
230
|
-
:disabled="loading.checkingOut"
|
|
231
|
-
@click="handleCheckout(selectedVisitorId as string)"
|
|
232
|
-
/>
|
|
133
|
+
<v-btn size="x-small" class="ml-3 text-capitalize" color="red" text="Checkout"
|
|
134
|
+
:disabled="loading.checkingOut" @click="handleCheckout(selectedVisitorId as string)" />
|
|
233
135
|
</span>
|
|
234
136
|
|
|
235
|
-
<span
|
|
236
|
-
|
|
237
|
-
class="d-flex ga-3 align-center"
|
|
238
|
-
><strong>{{ label }}:</strong>
|
|
137
|
+
<span v-else-if="selectedVisitorObject[key]" class="d-flex ga-3 align-center"><strong>{{ label
|
|
138
|
+
}}:</strong>
|
|
239
139
|
{{ formatValues(key, selectedVisitorObject[key]) }}
|
|
240
|
-
<TooltipInfo
|
|
241
|
-
v-if="key === 'checkOut'"
|
|
242
|
-
text="Manual Checkout"
|
|
243
|
-
density="compact"
|
|
244
|
-
size="x-small"
|
|
245
|
-
/>
|
|
140
|
+
<TooltipInfo v-if="key === 'checkOut'" text="Manual Checkout" density="compact" size="x-small" />
|
|
246
141
|
</span>
|
|
247
142
|
</v-col>
|
|
248
143
|
</v-row>
|
|
@@ -251,12 +146,9 @@
|
|
|
251
146
|
</v-dialog>
|
|
252
147
|
|
|
253
148
|
<v-dialog v-model="dialog.deleteConfirmation" width="450" persistent>
|
|
254
|
-
<CardDeleteConfirmation
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
@close="dialog.deleteConfirmation = false"
|
|
258
|
-
@delete="handleProceedDeleteVisitor"
|
|
259
|
-
/>
|
|
149
|
+
<CardDeleteConfirmation prompt-title="Are you sure want to delete this visitor?"
|
|
150
|
+
:loading="loading.deletingVisitor" @close="dialog.deleteConfirmation = false"
|
|
151
|
+
@delete="handleProceedDeleteVisitor" />
|
|
260
152
|
</v-dialog>
|
|
261
153
|
|
|
262
154
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
@@ -309,18 +201,21 @@ const {
|
|
|
309
201
|
const { debounce, formatCamelCaseToWords, formatDate, UTCToLocalTIme } =
|
|
310
202
|
useUtils();
|
|
311
203
|
const { formatLocation } = useSecurityUtils();
|
|
312
|
-
const { status: visitorStatus } = useRoute().query;
|
|
313
|
-
|
|
204
|
+
// const { status: visitorStatus, search } = useRoute().query as { status: string, search: string};
|
|
205
|
+
|
|
206
|
+
const route = useRoute()
|
|
207
|
+
const router = useRouter()
|
|
208
|
+
const { org: orgId, site: siteId } = route.params as {
|
|
314
209
|
org: string;
|
|
315
210
|
site: string;
|
|
316
211
|
};
|
|
317
|
-
const routeName =
|
|
212
|
+
const routeName = route.name;
|
|
318
213
|
|
|
319
214
|
const items = ref<Array<Record<string, any>>>([]);
|
|
320
215
|
const page = ref(1);
|
|
321
216
|
const pages = ref(0);
|
|
322
217
|
const pageRange = ref("-- - -- of --");
|
|
323
|
-
const activeTab = ref(
|
|
218
|
+
const activeTab = ref("registered");
|
|
324
219
|
const activeVisitorFormType = ref<TVisitorType | null>(null);
|
|
325
220
|
const selectedVisitorId = ref<string | null>(""); // selected visitor for viewing/actions
|
|
326
221
|
|
|
@@ -328,7 +223,7 @@ const selectedVisitorId = ref<string | null>(""); // selected visitor for viewin
|
|
|
328
223
|
const searchInput = ref("");
|
|
329
224
|
const dateFrom = ref("");
|
|
330
225
|
const dateTo = ref("");
|
|
331
|
-
const filterTypes = ref([]);
|
|
226
|
+
const filterTypes = ref<TVisitorType[]>([]);
|
|
332
227
|
const displayCheckedOutOnly = ref<boolean>(false);
|
|
333
228
|
|
|
334
229
|
const message = ref("");
|
|
@@ -393,21 +288,20 @@ const {
|
|
|
393
288
|
refresh: getVisitorRefresh,
|
|
394
289
|
pending: getVisitorPending,
|
|
395
290
|
} = await useLazyAsyncData(
|
|
396
|
-
`get-all-visitors-${
|
|
291
|
+
`get-all-visitors-${activeTab.value}-${page.value}`
|
|
292
|
+
,
|
|
397
293
|
() =>
|
|
398
294
|
getVisitors({
|
|
399
295
|
page: page.value,
|
|
400
|
-
org: orgId,
|
|
401
296
|
site: siteId,
|
|
402
297
|
search: searchInput.value,
|
|
403
298
|
dateTo: dateTo.value,
|
|
404
299
|
dateFrom: dateFrom.value,
|
|
405
300
|
type: filterTypes.value.filter(Boolean).join(","),
|
|
406
|
-
|
|
407
|
-
status: activeTab.value as string
|
|
301
|
+
status: activeTab.value as string,
|
|
408
302
|
}),
|
|
409
303
|
{
|
|
410
|
-
watch: [page,
|
|
304
|
+
watch: [page, () => route.query],
|
|
411
305
|
}
|
|
412
306
|
);
|
|
413
307
|
|
|
@@ -420,9 +314,9 @@ watch(getVisitorReq, (newData: any) => {
|
|
|
420
314
|
});
|
|
421
315
|
|
|
422
316
|
const selectedVisitorObject = computed(() => {
|
|
423
|
-
const obj = items.value.find((x) => x?._id === selectedVisitorId.value);
|
|
317
|
+
const obj = items.value.find((x: any) => x?._id === selectedVisitorId.value);
|
|
424
318
|
if (!obj) return {};
|
|
425
|
-
const type = obj?.type;
|
|
319
|
+
const type = obj?.type as TVisitorType | undefined;
|
|
426
320
|
if (!type) return {};
|
|
427
321
|
let includedKeys: string[] = ["checkIn", "checkOut"];
|
|
428
322
|
includedKeys.unshift(...(typeFieldMap[type] ?? []));
|
|
@@ -554,16 +448,42 @@ function getUTCDates() {
|
|
|
554
448
|
return { dateYesterday, dateToday };
|
|
555
449
|
}
|
|
556
450
|
|
|
557
|
-
|
|
558
|
-
const
|
|
451
|
+
|
|
452
|
+
const updateRouteQuery = debounce(
|
|
453
|
+
(search: string, from: string, to: string, types: string[], status) => {
|
|
454
|
+
router.replace({
|
|
455
|
+
query: {
|
|
456
|
+
...route.query,
|
|
457
|
+
search: search || undefined,
|
|
458
|
+
dateFrom: from || undefined,
|
|
459
|
+
dateTo: to || undefined,
|
|
460
|
+
type: types.filter(Boolean).join(",") || undefined,
|
|
461
|
+
status: status || undefined,
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
},
|
|
465
|
+
500 // wait 500ms after last input
|
|
466
|
+
);
|
|
559
467
|
|
|
560
468
|
watch(
|
|
561
|
-
[searchInput,
|
|
562
|
-
([]) => {
|
|
563
|
-
|
|
469
|
+
[searchInput, dateFrom, dateTo, filterTypes, activeTab],
|
|
470
|
+
([search, from, to, types, status]) => {
|
|
471
|
+
updateRouteQuery(search, from, to, types, status)
|
|
472
|
+
|
|
564
473
|
},
|
|
565
|
-
{
|
|
474
|
+
{ deep: true }
|
|
566
475
|
);
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
onMounted(() => {
|
|
480
|
+
activeTab.value = (route.query.status as string) || "unregistered"
|
|
481
|
+
searchInput.value = (route.query.search as string) || "";
|
|
482
|
+
dateFrom.value = (route.query.dateFrom as string) || "";
|
|
483
|
+
dateTo.value = (route.query.dateTo as string) || "";
|
|
484
|
+
filterTypes.value = ((route.query.type as string)?.split(",") || []).filter(Boolean) as TVisitorType[];
|
|
485
|
+
|
|
486
|
+
})
|
|
567
487
|
</script>
|
|
568
488
|
|
|
569
489
|
<style scoped></style>
|
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
variant="outlined"
|
|
27
27
|
density="compact"
|
|
28
28
|
class="mb-2"
|
|
29
|
-
clearable
|
|
29
|
+
:clearable="
|
|
30
|
+
props.createdFrom === 'feedback' && workOrder.subject !== ''
|
|
31
|
+
? false
|
|
32
|
+
: true
|
|
33
|
+
"
|
|
30
34
|
:readonly="
|
|
31
35
|
props.createdFrom === 'feedback' && workOrder.subject !== ''
|
|
32
36
|
? true
|
|
@@ -222,7 +222,7 @@ export default function useBuilding() {
|
|
|
222
222
|
|
|
223
223
|
function updateById(
|
|
224
224
|
id: string,
|
|
225
|
-
data: Pick<TBuilding, "name" | "block" | "levels">
|
|
225
|
+
data: Pick<TBuilding, "name" | "block" | "levels" | "buildingFloorPlan">
|
|
226
226
|
) {
|
|
227
227
|
return useNuxtApp().$api(`/api/buildings/id/${id}`, {
|
|
228
228
|
method: "PATCH",
|
package/composables/usePeople.ts
CHANGED
|
@@ -13,36 +13,44 @@ export default function(){
|
|
|
13
13
|
type="",
|
|
14
14
|
displayNoCheckOut=false
|
|
15
15
|
} = {}) {
|
|
16
|
-
return await
|
|
16
|
+
return await useNuxtApp().$api<Record<string, any>>("/api/people", {
|
|
17
17
|
method: "GET",
|
|
18
18
|
query: { page, limit, sort, search, org, site, dateTo, dateFrom, type }
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
async function findPersonByNRIC(nric: string): Promise<null | Partial<TPeople>> {
|
|
23
|
+
return await $fetch<Record<string, any>>(`/api/people/nric/${nric}`, {
|
|
24
|
+
method: "GET",
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
async function create(payload: Partial<TPeoplePayload>){
|
|
23
|
-
return await
|
|
29
|
+
return await useNuxtApp().$api<Record<string, any>>("/api/people", {
|
|
24
30
|
method: "POST",
|
|
25
31
|
body: payload,
|
|
26
32
|
});
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
async function updateById(_id: string, payload: Partial<TPeoplePayload>){
|
|
30
|
-
return await
|
|
36
|
+
return await useNuxtApp().$api<Record<string, any>>(`/api/people/id/${_id}`, {
|
|
31
37
|
method: "PUT",
|
|
32
38
|
body: payload,
|
|
33
39
|
});
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
async function deleteById(_id: string){
|
|
37
|
-
return await
|
|
43
|
+
return await useNuxtApp().$api<Record<string, any>>(`/api/people/id/${_id}`, {
|
|
38
44
|
method: "DELETE",
|
|
39
45
|
});
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
|
|
42
49
|
return {
|
|
43
50
|
create,
|
|
44
51
|
getAll,
|
|
45
52
|
updateById,
|
|
46
|
-
deleteById
|
|
53
|
+
deleteById,
|
|
54
|
+
findPersonByNRIC
|
|
47
55
|
}
|
|
48
56
|
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
export default function(){
|
|
2
|
-
|
|
1
|
+
export default function () {
|
|
3
2
|
type TVisitorSelection = {
|
|
4
3
|
label: string;
|
|
5
|
-
value: TVisitorType
|
|
6
|
-
}
|
|
4
|
+
value: TVisitorType;
|
|
5
|
+
};
|
|
7
6
|
|
|
8
7
|
const visitorSelection: TVisitorSelection[] =[
|
|
8
|
+
{ label: "Guest", value: "guest" },
|
|
9
9
|
{ label: "Contractor", value: "contractor" },
|
|
10
10
|
{ label: "Delivery", value: "delivery" },
|
|
11
|
-
{ label: "Walk-In", value: "walk-in"},
|
|
12
|
-
{ label: "Pick-Up", value: "pick-up"},
|
|
13
|
-
{ label: "Drop-Off", value: "drop-off"}
|
|
11
|
+
{ label: "Walk-In", value: "walk-in" },
|
|
12
|
+
{ label: "Pick-Up", value: "pick-up" },
|
|
13
|
+
{ label: "Drop-Off", value: "drop-off" },
|
|
14
14
|
];
|
|
15
15
|
|
|
16
16
|
const typeFieldMap: Record<TVisitorType, (keyof TVisitorPayload)[]> = {
|
|
17
|
+
guest: ['name', 'nric', 'contact', 'block', 'level', 'unit' , 'unitName', 'remarks'],
|
|
17
18
|
contractor: ['contractorType', 'name', 'nric', 'company', 'contact', 'plateNumber', 'block', 'level', 'unit', 'unitName', 'remarks'],
|
|
18
19
|
delivery: ['attachments', 'name', 'deliveryType', 'company', 'nric', 'contact', 'plateNumber', 'block', 'level', 'unit' , 'unitName', 'remarks'],
|
|
19
20
|
'walk-in': ['name', 'company', 'nric', 'contact', 'block', 'level', 'unit' , 'unitName', 'remarks'],
|
|
@@ -22,59 +23,81 @@ export default function(){
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const contractorTypes = [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
]
|
|
30
|
-
|
|
26
|
+
{ title: "Estate Contractor", value: "estate-contractor" },
|
|
27
|
+
{ title: "Home Contractor", value: "home-contractor" },
|
|
28
|
+
{ title: "Property Agent", value: "property-agent" },
|
|
29
|
+
{ title: "House Mover", value: "house-mover" },
|
|
30
|
+
];
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
async function getVisitors({
|
|
33
|
+
page = 1,
|
|
34
|
+
limit = 10,
|
|
35
|
+
sort = "asc",
|
|
36
|
+
search = "",
|
|
37
|
+
org = "",
|
|
38
|
+
site = "",
|
|
39
|
+
dateTo = "",
|
|
40
|
+
dateFrom = "",
|
|
41
|
+
type = "",
|
|
42
|
+
status = "registered",
|
|
43
|
+
// status = "registered"
|
|
44
|
+
} = {}) {
|
|
45
|
+
return await useNuxtApp().$api<Record<string, any>>(
|
|
46
|
+
"/api/visitor-transactions",
|
|
47
|
+
{
|
|
46
48
|
method: "GET",
|
|
47
|
-
query: {
|
|
48
|
-
|
|
49
|
+
query: {
|
|
50
|
+
page,
|
|
51
|
+
limit,
|
|
52
|
+
sort,
|
|
53
|
+
search,
|
|
54
|
+
org,
|
|
55
|
+
site,
|
|
56
|
+
dateTo,
|
|
57
|
+
dateFrom,
|
|
58
|
+
type,
|
|
59
|
+
status,
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
);
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
async function createVisitor(payload: Partial<TVisitorPayload>) {
|
|
66
|
+
return await useNuxtApp().$api<Record<string, any>>(
|
|
67
|
+
"/api/visitor-transactions",
|
|
68
|
+
{
|
|
53
69
|
method: "POST",
|
|
54
70
|
body: payload,
|
|
55
|
-
}
|
|
56
|
-
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
async function updateVisitor(_id: string, payload: Partial<TVisitorPayload>) {
|
|
76
|
+
return await useNuxtApp().$api<Record<string, any>>(
|
|
77
|
+
`/api/visitor-transactions/id/${_id}`,
|
|
78
|
+
{
|
|
60
79
|
method: "PUT",
|
|
61
80
|
body: payload,
|
|
62
|
-
}
|
|
63
|
-
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}
|
|
64
84
|
|
|
65
|
-
|
|
66
|
-
|
|
85
|
+
async function deleteVisitor(_id: string) {
|
|
86
|
+
return await useNuxtApp().$api<Record<string, any>>(
|
|
87
|
+
`/api/visitor-transactions/id/${_id}`,
|
|
88
|
+
{
|
|
67
89
|
method: "DELETE",
|
|
68
|
-
}
|
|
69
|
-
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
}
|
|
70
93
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
94
|
+
return {
|
|
95
|
+
typeFieldMap,
|
|
96
|
+
visitorSelection,
|
|
97
|
+
contractorTypes,
|
|
98
|
+
createVisitor,
|
|
99
|
+
getVisitors,
|
|
100
|
+
updateVisitor,
|
|
101
|
+
deleteVisitor,
|
|
102
|
+
};
|
|
103
|
+
}
|
package/package.json
CHANGED
package/types/building.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ declare type TBuilding = {
|
|
|
4
4
|
name: string;
|
|
5
5
|
block: number | null;
|
|
6
6
|
levels: string[];
|
|
7
|
+
buildingFloorPlan: string[]
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
declare type TBuildingUnit = {
|
|
@@ -16,4 +17,5 @@ declare type TBuildingUnit = {
|
|
|
16
17
|
level: string | null;
|
|
17
18
|
category: string;
|
|
18
19
|
status: string;
|
|
20
|
+
buildingUnitFiles: string[]
|
|
19
21
|
};
|
package/types/people.d.ts
CHANGED
package/types/visitor.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ declare type TVisitor = {
|
|
|
21
21
|
manualCheckout?: boolean;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
declare type TVisitorType = "contractor" | "delivery" | "walk-in" | "pick-up" | "drop-off";
|
|
24
|
+
declare type TVisitorType = "contractor" | "delivery" | "walk-in" | "pick-up" | "drop-off" | "guest";
|
|
25
25
|
|
|
26
26
|
declare type TVisitorPayload = Pick<TVisitor, "name" | "type" | "company" | "block" | "level" | "unit" | "unitName" | "contact" | "plateNumber" | "checkOut" | "contractorType" | "deliveryType" | "nric" | "contact" | "remarks" | "attachments" | "org" | "site"> & {
|
|
27
27
|
members?: TMemberInfo[]
|