@7365admin1/layer-common 1.11.20 → 1.11.22

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.
@@ -1,34 +1,95 @@
1
1
  <template>
2
2
  <v-row no-gutters>
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="handleAddNew">
3
+ <TableMain
4
+ :headers="headers"
5
+ :items="items"
6
+ :loading="getVisitorPending"
7
+ :page="page"
8
+ :pages="pages"
9
+ :extension-height="110"
10
+ :offset="300"
11
+ :pageRange="pageRange"
12
+ :canCreate="canAddVisitor"
13
+ :canScanVisitorQRCode="canScanVisitorQRCode"
14
+ @refresh="getVisitorRefresh"
15
+ @update:page="handleUpdatePage"
16
+ createLabel="Add Visitor"
17
+ show-header
18
+ @row-click="handleRowClick"
19
+ @create="handleAddNew"
20
+ @scan="dialog.scanVisitorQRCode = true"
21
+ >
7
22
  <template #extension>
8
23
  <v-row no-gutters class="w-100 d-flex flex-column">
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.value" :key="tab.value" class="text-capitalize">
24
+ <v-tabs
25
+ v-model="activeTab"
26
+ color="primary"
27
+ :height="40"
28
+ @update:model-value="toRoute"
29
+ class="w-100"
30
+ >
31
+ <v-tab
32
+ v-for="tab in tabOptions"
33
+ :value="tab.value"
34
+ :key="tab.value"
35
+ class="text-capitalize"
36
+ >
11
37
  {{ tab.name }}
12
38
  </v-tab>
13
39
  </v-tabs>
14
40
 
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="displayNotCheckedOut" class="text-subtitle-2" hide-details>
41
+ <v-card
42
+ class="w-100 px-3 d-flex align-center ga-5 py-2"
43
+ flat
44
+ :height="60"
45
+ >
46
+ <v-text-field
47
+ v-model="searchInput"
48
+ density="compact"
49
+ placeholder="Search"
50
+ clearable
51
+ max-width="300"
52
+ append-inner-icon="mdi-magnify"
53
+ hide-details
54
+ />
55
+ <v-checkbox
56
+ v-model="displayNotCheckedOut"
57
+ class="text-subtitle-2"
58
+ hide-details
59
+ >
19
60
  <template #label>
20
61
  <span class="text-caption">Not Checked Out</span>
21
62
  </template>
22
63
  </v-checkbox>
23
- <InputDatePicker v-model="dateFrom" density="compact" hide-details />
64
+ <InputDatePicker
65
+ v-model="dateFrom"
66
+ density="compact"
67
+ hide-details
68
+ />
24
69
  <InputDatePicker v-model="dateTo" density="compact" hide-details />
25
- <v-select v-if="activeTab == 'registered'" v-model="filterTypes" label="Filter by types" item-title="label"
26
- item-value="value" :items="visitorSelection" density="compact" clearable multiple max-width="200"
27
- hide-details>
70
+ <v-select
71
+ v-if="activeTab == 'registered'"
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
+ >
28
83
  <template v-slot:selection="{ item, index }">
29
84
  <div class="d-flex align-center text-caption text-nowrap">
30
- <v-chip v-if="index === 0" color="error" :text="filterTypeSelectionLabel()" size="x-small"
31
- variant="tonal" class="ml-2" />
85
+ <v-chip
86
+ v-if="index === 0"
87
+ color="error"
88
+ :text="filterTypeSelectionLabel()"
89
+ size="x-small"
90
+ variant="tonal"
91
+ class="ml-2"
92
+ />
32
93
  </div>
33
94
  </template>
34
95
  </v-select>
@@ -43,8 +104,9 @@
43
104
  </span>
44
105
  <span class="text-capitalize">{{ item?.name }}</span>
45
106
  </span>
46
- <span class="text-grey text-caption" v-if="item?.members?.length > 0">( +{{ item?.members?.length }}
47
- members)</span>
107
+ <span class="text-grey text-caption" v-if="item?.members?.length > 0"
108
+ >( +{{ item?.members?.length }} members)</span
109
+ >
48
110
  </template>
49
111
 
50
112
  <template v-slot:item.type-company="{ item }">
@@ -52,7 +114,7 @@
52
114
  <v-icon icon="mdi-user" size="15" />
53
115
  <span v-if="item.type === 'contractor'" class="text-capitalize">{{
54
116
  formatCamelCaseToWords(item.contractorType)
55
- }}</span>
117
+ }}</span>
56
118
  <span v-else class="text-capitalize">{{ formatType(item) }}</span>
57
119
  </span>
58
120
  <span class="d-flex align-center ga-2">
@@ -88,109 +150,220 @@
88
150
  <template v-slot:item.checkin-out="{ item }">
89
151
  <v-row no-gutters class="d-flex flex-column py-2">
90
152
  <span class="d-flex align-center ga-2">
91
- <v-icon icon="mdi-clock-time-four-outline" color="green" size="20" />
153
+ <v-icon
154
+ icon="mdi-clock-time-four-outline"
155
+ color="green"
156
+ size="20"
157
+ />
92
158
  <span class="text-capitalize">{{
93
159
  UTCToLocalTIme(item.checkIn) || "-"
94
160
  }}</span>
95
161
  <span>
96
- <v-icon v-if="item?.snapshotEntryImage" size="17" icon="mdi-image"
97
- @click.stop="handleViewImage(item.snapshotEntryImage)" />
162
+ <v-icon
163
+ v-if="item?.snapshotEntryImage"
164
+ size="17"
165
+ icon="mdi-image"
166
+ @click.stop="handleViewImage(item.snapshotEntryImage)"
167
+ />
98
168
  </span>
99
169
  </span>
100
- <span class="d-flex align-center ga-2">
170
+
171
+ <span
172
+ v-if="!item.checkOut && (item?.status === 'registered' || item?.status === 'unregistered') && canCheckoutVisitor">
173
+ <span class="d-flex align-center ga-2" v-bind="menuProps" style="cursor:pointer">
174
+ <v-icon icon="mdi-clock-time-eight-outline" color="red" size="20" />
175
+ <v-btn size="x-small" class="text-capitalize" color="red" text="Checkout"
176
+ :loading="loading.checkingOut && item?._id === selectedVisitorId" @click.stop="handleCheckout(item._id)" />
177
+ </span>
178
+ </span>
179
+ <span v-else class="d-flex align-center ga-2">
101
180
  <v-icon icon="mdi-clock-time-eight-outline" color="red" size="20" />
102
181
  <template v-if="item.checkOut">
103
182
  <span class="text-capitalize">{{
104
183
  UTCToLocalTIme(item.checkOut) || "-"
105
184
  }}</span>
106
185
  <span>
107
- <v-icon v-if="item?.snapshotExitImage" size="17" icon="mdi-image"
108
- @click.stop="handleViewImage(item.snapshotExitImage)" />
186
+ <v-icon
187
+ v-if="item?.snapshotExitImage"
188
+ size="17"
189
+ icon="mdi-image"
190
+ @click.stop="handleViewImage(item.snapshotExitImage)"
191
+ />
109
192
  </span>
110
193
  <span v-if="item?.manualCheckout">
111
- <TooltipInfo text="Manual Checkout" density="compact" size="x-small" />
194
+ <TooltipInfo
195
+ text="Manual Checkout"
196
+ density="compact"
197
+ size="x-small"
198
+ />
112
199
  </span>
113
200
  </template>
114
- <span v-else-if="!item?.checkOut && (item?.status === 'registered' || item?.status === 'unregistered')">
115
- <v-btn size="x-small" class="text-capitalize" color="red" text="Checkout"
116
- :loading="loading.checkingOut && item?._id === selectedVisitorId" @click.stop="handleCheckout(item._id)"
117
- v-if="canCheckoutVisitor" />
118
- </span>
119
201
  </span>
120
- <div v-if="(item.visitorPass?.length ?? 0) > 0 || (item.passKeys?.length ?? 0) > 0"
121
- class="d-flex flex-wrap ga-1 mt-1" @click.stop="handleCheckout(item._id)">
122
- <v-chip v-for="pass in item.visitorPass" :key="(pass as any)._id ?? (pass as any).keyId"
123
- prepend-icon="mdi-card-bulleted-outline" size="x-small" variant="tonal" color="blue">
124
- {{ (pass as any)?.prefixAndName }}
125
- </v-chip>
126
- <v-chip v-for="key in item.passKeys" :key="(key as any)._id ?? (key as any).keyId" prepend-icon="mdi-key"
127
- size="x-small" variant="tonal" color="orange">
128
- {{ (key as any)?.prefixAndName }}
129
- </v-chip>
130
- </div>
131
- <div v-if="showAddPassKeyButton(item)" class="d-flex flex-wrap ga-1 mt-1 mt-2"
132
- @click.stop="handleCheckout(item._id)">
133
- <v-chip size="x-small" variant="tonal" prepend-icon="mdi-key" @click.stop="handleOpenAddPassKey(item)">
134
- Add Pass/Key
135
- </v-chip>
136
202
 
203
+ <div
204
+ v-if="showAddPassKeyButton(item)"
205
+ class="d-flex flex-wrap ga-1 mt-1"
206
+ v-bind="menuProps"
207
+ style="cursor: pointer"
208
+ >
209
+ <v-chip
210
+ size="x-small"
211
+ variant="tonal"
212
+ prepend-icon="mdi-key"
213
+ @click.stop="handleOpenAddPassKey(item)"
214
+ >Add Pass/Key</v-chip
215
+ >
137
216
  </div>
217
+
218
+ <v-menu :close-on-content-click="true">
219
+ <template v-slot:activator="{ props: menuProps }">
220
+ <div
221
+ v-if="
222
+ (item.visitorPass?.length ?? 0) > 0 ||
223
+ (item.passKeys?.length ?? 0) > 0
224
+ "
225
+ class="d-flex flex-wrap ga-1 mt-1"
226
+ v-bind="menuProps"
227
+ style="cursor: pointer"
228
+ >
229
+ <v-chip
230
+ v-for="pass in item.visitorPass"
231
+ :key="(pass as any)._id ?? (pass as any).keyId"
232
+ prepend-icon="mdi-card-bulleted-outline"
233
+ size="x-small"
234
+ variant="tonal"
235
+ color="blue"
236
+ >
237
+ {{ (pass as any)?.prefixAndName }}
238
+ </v-chip>
239
+ <v-chip
240
+ v-for="key in item.passKeys"
241
+ :key="(key as any)._id ?? (key as any).keyId"
242
+ prepend-icon="mdi-key"
243
+ size="x-small"
244
+ variant="tonal"
245
+ color="orange"
246
+ >
247
+ {{ (key as any)?.prefixAndName }}
248
+ </v-chip>
249
+ </div>
250
+ </template>
251
+ <v-list density="compact">
252
+ <v-list-item v-if="!item?.checkOut" prepend-icon="mdi-logout" title="Checkout" @click.stop="handleCheckout(item._id)" />
253
+ <v-list-item v-if="(item.visitorPass?.length ?? 0) > 0 || (item.passKeys?.length ?? 0) > 0"
254
+ prepend-icon="mdi-card-bulleted-outline" :title="item.checkOut ? 'View Pass/Key' :'Edit Pass/Key'"
255
+ @click.stop="handleOpenEditPassKey(item)" />
256
+ <v-list-item v-if="showAddPassKeyButton(item)" prepend-icon="mdi-plus" title="Add Pass/Key"
257
+ @click.stop="handleOpenAddPassKey(item)" />
258
+ </v-list>
259
+ </v-menu>
138
260
  </v-row>
139
261
  </template>
140
262
 
141
263
  <template v-slot:item.action="{ item }">
142
- <v-btn v-if="activeTab === 'unregistered' && canAddVisitor" size="small" color="primary" text="Register"
143
- @click.stop="handleRegistrationUnregisteredVisitor(item)" />
264
+ <v-btn
265
+ v-if="activeTab === 'unregistered' && canAddVisitor"
266
+ size="small"
267
+ color="primary"
268
+ text="Register"
269
+ @click.stop="handleRegistrationUnregisteredVisitor(item)"
270
+ />
144
271
  </template>
145
272
 
146
273
  <template v-slot:item.checkInRemarks="{ item }">
147
274
  <span>
148
- <v-btn variant="text" color="blue-darken-2" density="compact" size="small"
149
- @click.stop="handleOpenRemarks(item, 'checkIn')">{{ item.checkInRemarks ? "View Remarks" : "Add Remarks"
150
- }}</v-btn>
275
+ <v-btn
276
+ variant="text"
277
+ color="blue-darken-2"
278
+ density="compact"
279
+ size="small"
280
+ @click.stop="handleOpenRemarks(item, 'checkIn')"
281
+ >{{ item.checkInRemarks ? "View Remarks" : "Add Remarks" }}</v-btn
282
+ >
151
283
  </span>
152
284
  </template>
153
285
  <template v-slot:item.checkOutRemarks="{ item }">
154
286
  <span>
155
- <v-btn variant="text" color="blue-darken-2" density="compact" size="small"
156
- @click.stop="handleOpenRemarks(item, 'checkOut')">{{ item.checkOutRemarks ? "View Remarks" : "Add Remarks"
157
- }}</v-btn>
287
+ <v-btn
288
+ variant="text"
289
+ color="blue-darken-2"
290
+ density="compact"
291
+ size="small"
292
+ @click.stop="handleOpenRemarks(item, 'checkOut')"
293
+ >{{ item.checkOutRemarks ? "View Remarks" : "Add Remarks" }}</v-btn
294
+ >
158
295
  </span>
159
296
  </template>
160
-
161
297
  </TableMain>
162
298
 
163
299
  <v-dialog v-model="dialog.showSelection" width="450" persistent>
164
- <VisitorFormSelection :mode="mode" @cancel="dialog.showSelection = false" @select="handleSelectVisitorType" />
300
+ <VisitorFormSelection
301
+ :mode="mode"
302
+ @cancel="dialog.showSelection = false"
303
+ @select="handleSelectVisitorType"
304
+ />
165
305
  </v-dialog>
166
306
 
167
- <v-dialog v-model="dialog.showForm" v-if="activeVisitorFormType" width="450" persistent>
168
- <VisitorForm :mode="mode" :org="orgId" :site="siteId" :visitor-data="selectedVisitorDataObject"
169
- :type="activeVisitorFormType" @back="handleClickBack" @done="handleVisitorFormDone"
170
- @done:more="handleVisitorFormCreateMore" @close:all="handleCloseAll" />
307
+ <v-dialog
308
+ v-model="dialog.showForm"
309
+ v-if="activeVisitorFormType"
310
+ width="450"
311
+ persistent
312
+ >
313
+ <VisitorForm
314
+ :mode="mode"
315
+ :org="orgId"
316
+ :site="siteId"
317
+ :visitor-data="selectedVisitorDataObject"
318
+ :type="activeVisitorFormType"
319
+ @back="handleClickBack"
320
+ @done="handleVisitorFormDone"
321
+ @done:more="handleVisitorFormCreateMore"
322
+ @close:all="handleCloseAll"
323
+ />
171
324
  </v-dialog>
172
325
 
173
326
  <v-dialog v-model="dialog.viewVisitor" width="450" persistent>
174
- <VehicleUpdateMoreAction title="Preview" :can-update="false" :can-delete="canDeleteVisitor"
175
- @close="dialog.viewVisitor = false" edit-button-label="Edit Visitor" delete-button-label="Delete Visitor"
176
- @delete="handleDeleteVisitor">
327
+ <VehicleUpdateMoreAction
328
+ title="Preview"
329
+ :can-update="false"
330
+ :can-delete="false"
331
+ @close="dialog.viewVisitor = false"
332
+ edit-button-label="Edit Visitor"
333
+ >
177
334
  <template v-slot:content>
178
335
  <v-row no-gutters class="mb-4">
179
336
  <v-col v-for="(label, key) in formattedFields" :key="key" cols="12">
180
- <span v-if="
181
- key === 'checkOut' &&
182
- !selectedVisitorObject[key] &&
183
- canCheckoutVisitor
184
- " class="d-flex align-center">
337
+ <span
338
+ v-if="
339
+ key === 'checkOut' &&
340
+ !selectedVisitorObject[key] &&
341
+ canCheckoutVisitor
342
+ "
343
+ class="d-flex align-center"
344
+ >
185
345
  <strong>{{ label }}:</strong>
186
- <v-btn size="x-small" class="ml-3 text-capitalize" color="red" text="Checkout"
187
- :disabled="loading.checkingOut" @click="handleCheckout(selectedVisitorId as string)" />
346
+ <v-btn
347
+ size="x-small"
348
+ class="ml-3 text-capitalize"
349
+ color="red"
350
+ text="Checkout"
351
+ :disabled="loading.checkingOut"
352
+ @click="handleCheckout(selectedVisitorId as string)"
353
+ />
188
354
  </span>
189
355
 
190
- <span v-else-if="selectedVisitorObject[key]" class="d-flex ga-3 align-center"><strong>{{ label
191
- }}:</strong>
356
+ <span
357
+ v-else-if="selectedVisitorObject[key]"
358
+ class="d-flex ga-3 align-center"
359
+ ><strong>{{ label }}:</strong>
192
360
  {{ formatValues(key, selectedVisitorObject[key]) }}
193
- <TooltipInfo v-if="key === 'checkOut'" text="Manual Checkout" density="compact" size="x-small" />
361
+ <TooltipInfo
362
+ v-if="key === 'checkOut'"
363
+ text="Manual Checkout"
364
+ density="compact"
365
+ size="x-small"
366
+ />
194
367
  </span>
195
368
  </v-col>
196
369
  </v-row>
@@ -198,17 +371,15 @@
198
371
  </VehicleUpdateMoreAction>
199
372
  </v-dialog>
200
373
 
201
- <v-dialog v-model="dialog.deleteConfirmation" width="450" persistent>
202
- <CardDeleteConfirmation prompt-title="Are you sure want to delete this visitor?"
203
- :loading="loading.deletingVisitor" @close="dialog.deleteConfirmation = false"
204
- @delete="handleProceedDeleteVisitor" />
205
- </v-dialog>
206
-
207
374
  <v-dialog v-model="dialog.snapshotImage" max-width="700">
208
375
  <v-card>
209
376
  <v-card-title class="d-flex justify-space-between align-center">
210
377
  <span>Snapshot</span>
211
- <v-btn icon="mdi-close" variant="text" @click="dialog.snapshotImage = false" />
378
+ <v-btn
379
+ icon="mdi-close"
380
+ variant="text"
381
+ @click="dialog.snapshotImage = false"
382
+ />
212
383
  </v-card-title>
213
384
  <v-card-text class="pa-2 d-flex justify-center">
214
385
  <v-img :src="snapshotImageUrl" max-height="600" contain />
@@ -218,23 +389,51 @@
218
389
 
219
390
  <v-dialog v-model="dialog.remarks" max-width="450" persistent>
220
391
  <v-card>
221
- <v-card-title class="d-flex justify-space-between align-center pt-4 px-4">
222
- <span>{{ remarksType === 'checkIn' ? 'Check-In Remarks' : 'Check-Out Remarks' }}</span>
223
- <v-btn icon="mdi-close" variant="text" @click="dialog.remarks = false" />
392
+ <v-card-title
393
+ class="d-flex justify-space-between align-center pt-4 px-4"
394
+ >
395
+ <span>{{
396
+ remarksType === "checkIn" ? "Check-In Remarks" : "Check-Out Remarks"
397
+ }}</span>
398
+ <v-btn
399
+ icon="mdi-close"
400
+ variant="text"
401
+ @click="dialog.remarks = false"
402
+ />
224
403
  </v-card-title>
225
404
  <v-card-text class="px-4 pb-2">
226
- <v-textarea v-model="remarksInput" label="Remarks" rows="4" auto-grow variant="outlined"
227
- :readonly="remarksViewOnly" />
405
+ <v-textarea
406
+ v-model="remarksInput"
407
+ label="Remarks"
408
+ rows="4"
409
+ auto-grow
410
+ variant="outlined"
411
+ :readonly="remarksViewOnly"
412
+ />
228
413
  </v-card-text>
229
414
  <v-toolbar class="pa-0" density="compact">
230
415
  <v-row no-gutters>
231
416
  <v-col cols="6">
232
- <v-btn variant="text" block :disabled="loading.savingRemarks"
233
- @click="dialog.remarks = false">Cancel</v-btn>
417
+ <v-btn
418
+ variant="text"
419
+ block
420
+ :disabled="loading.savingRemarks"
421
+ @click="dialog.remarks = false"
422
+ >Cancel</v-btn
423
+ >
234
424
  </v-col>
235
425
  <v-col cols="6">
236
- <v-btn color="primary" variant="flat" height="48" rounded="0" block :loading="loading.savingRemarks"
237
- :disabled="!remarksInput.trim()" @click="handleSaveRemarks">Save</v-btn>
426
+ <v-btn
427
+ color="primary"
428
+ variant="flat"
429
+ height="48"
430
+ rounded="0"
431
+ block
432
+ :loading="loading.savingRemarks"
433
+ :disabled="!remarksInput.trim()"
434
+ @click="handleSaveRemarks"
435
+ >Save</v-btn
436
+ >
238
437
  </v-col>
239
438
  </v-row>
240
439
  </v-toolbar>
@@ -244,54 +443,134 @@
244
443
  <v-dialog v-model="dialog.returnPassesKeys" max-width="450" persistent>
245
444
  <v-card>
246
445
  <v-toolbar density="compact" color="">
247
- <v-row no-gutters class="d-flex fill-height justify-space-between align-center px-4">
446
+ <v-row
447
+ no-gutters
448
+ class="d-flex fill-height justify-space-between align-center px-4"
449
+ >
248
450
  <span class="font-weight-bold">Return Passes &amp; Keys</span>
249
- <v-btn icon="mdi-close" variant="text" @click="dialog.returnPassesKeys = false" />
451
+ <v-btn
452
+ icon="mdi-close"
453
+ variant="text"
454
+ @click="dialog.returnPassesKeys = false"
455
+ />
250
456
  </v-row>
251
457
  </v-toolbar>
252
458
  <v-card-text class="px-4 pb-2">
253
- <p class="text-body-2 mb-3">Please ensure all passes and keys are returned before checking out.</p>
459
+ <p class="text-body-2 mb-3">
460
+ Please ensure all passes and keys are returned before checking out.
461
+ </p>
254
462
  <div v-if="passReturnStatuses.length > 0" class="mb-2">
255
463
  <p class="text-caption text-medium-emphasis mb-1">Passes</p>
256
- <v-row no-gutters v-for="pass in passReturnStatuses" :key="(pass as any)._id ?? (pass as any).keyId"
257
- class="d-flex flex-wrap justify-space-between align-center ga-5 mb-2">
258
- <v-chip prepend-icon="mdi-card-bulleted-outline" size="small" variant="tonal" color="blue">
464
+ <v-row
465
+ no-gutters
466
+ v-for="pass in passReturnStatuses"
467
+ :key="(pass as any)._id ?? (pass as any).keyId"
468
+ class="d-flex flex-wrap justify-space-between align-center ga-5 mb-2"
469
+ >
470
+ <v-chip
471
+ prepend-icon="mdi-card-bulleted-outline"
472
+ size="small"
473
+ variant="tonal"
474
+ color="blue"
475
+ >
259
476
  {{ (pass as any)?.prefixAndName }}
260
477
  </v-chip>
261
- <v-select hide-details max-width="200px" density="compact" :items="passStatusOptions" item-title="label"
262
- item-value="value" v-model="pass.status" :disabled="selectedVisitorObject.checkOut"></v-select>
263
- <v-textarea v-if="pass.status === 'Lost' || pass.status === 'Damaged'" no-resize rows="3" class="w-100"
264
- density="compact" v-model="pass.remarks" :disabled="selectedVisitorObject.checkOut"></v-textarea>
478
+ <v-select
479
+ hide-details
480
+ max-width="200px"
481
+ density="compact"
482
+ :items="passStatusOptions"
483
+ item-title="label"
484
+ item-value="value"
485
+ v-model="pass.status"
486
+ :disabled="selectedVisitorObject.checkOut"
487
+ ></v-select>
488
+ <v-textarea
489
+ v-if="pass.status === 'Lost' || pass.status === 'Damaged'"
490
+ no-resize
491
+ rows="3"
492
+ class="w-100"
493
+ density="compact"
494
+ v-model="pass.remarks"
495
+ :disabled="selectedVisitorObject.checkOut"
496
+ ></v-textarea>
265
497
  </v-row>
266
498
  </div>
267
- <div v-if="(keyReturnStatuses.length > 0)" class="mb-2">
499
+ <div v-if="keyReturnStatuses.length > 0" class="mb-2">
268
500
  <p class="text-caption text-medium-emphasis mb-1">Keys</p>
269
- <v-row no-gutters v-for="key in keyReturnStatuses" :key="(key as any)._id ?? (key as any).keyId"
270
- class="d-flex flex-wrap justify-space-between align-center ga-5 mb-2">
271
- <v-chip prepend-icon="mdi-key" size="small" variant="tonal" color="orange">
501
+ <v-row
502
+ no-gutters
503
+ v-for="key in keyReturnStatuses"
504
+ :key="(key as any)._id ?? (key as any).keyId"
505
+ class="d-flex flex-wrap justify-space-between align-center ga-5 mb-2"
506
+ >
507
+ <v-chip
508
+ prepend-icon="mdi-key"
509
+ size="small"
510
+ variant="tonal"
511
+ color="orange"
512
+ >
272
513
  {{ (key as any)?.prefixAndName }}
273
514
  </v-chip>
274
- <v-select hide-details max-width="200px" density="compact" :items="passStatusOptions" item-title="label"
275
- item-value="value" v-model="key.status" :disabled="selectedVisitorObject.checkOut"></v-select>
276
- <v-textarea v-if="key.status === 'Lost' || key.status === 'Damaged'" no-resize rows="3" class="w-100"
277
- density="compact" v-model="key.remarks" :disabled="selectedVisitorObject.checkOut"></v-textarea>
515
+ <v-select
516
+ hide-details
517
+ max-width="200px"
518
+ density="compact"
519
+ :items="passStatusOptions"
520
+ item-title="label"
521
+ item-value="value"
522
+ v-model="key.status"
523
+ :disabled="selectedVisitorObject.checkOut"
524
+ ></v-select>
525
+ <v-textarea
526
+ v-if="key.status === 'Lost' || key.status === 'Damaged'"
527
+ no-resize
528
+ rows="3"
529
+ class="w-100"
530
+ density="compact"
531
+ v-model="key.remarks"
532
+ :disabled="selectedVisitorObject.checkOut"
533
+ ></v-textarea>
278
534
  </v-row>
279
535
  </div>
280
536
 
281
537
  <v-row no-gutters class="my-5">
282
- <v-btn variant="flat" color="blue" density="comfortable" class="text-capitalize" :disabled="selectedVisitorObject.checkOut"
283
- :loading="loading.updatingPassKeys" @click.stop="handleUpdatePassKeys" >Update Pass/Keys</v-btn>
538
+ <v-btn
539
+ variant="flat"
540
+ color="blue"
541
+ density="comfortable"
542
+ class="text-capitalize"
543
+ :disabled="selectedVisitorObject.checkOut"
544
+ :loading="loading.updatingPassKeys"
545
+ @click.stop="handleUpdatePassKeys"
546
+ >Update Pass/Keys</v-btn
547
+ >
284
548
  </v-row>
285
549
  </v-card-text>
286
550
  <v-toolbar class="pa-0" density="compact">
287
551
  <v-row no-gutters>
288
552
  <v-col cols="6">
289
- <v-btn variant="text" block
290
- @click="dialog.returnPassesKeys = false">Close</v-btn>
553
+ <v-btn
554
+ variant="text"
555
+ block
556
+ @click="dialog.returnPassesKeys = false"
557
+ >Close</v-btn
558
+ >
291
559
  </v-col>
292
560
  <v-col cols="6">
293
- <v-btn color="red" variant="flat" height="48" rounded="0" block :loading="loading.checkingOut"
294
- :disabled="!canConfirmCheckout || selectedVisitorObject.checkOut" @click="proceedCheckout">Confirm Checkout</v-btn>
561
+ <v-btn
562
+ color="red"
563
+ variant="flat"
564
+ height="48"
565
+ rounded="0"
566
+ block
567
+ :loading="loading.checkingOut"
568
+ :disabled="
569
+ !canConfirmCheckout || selectedVisitorObject.checkOut
570
+ "
571
+ @click="proceedCheckout"
572
+ >Confirm Checkout</v-btn
573
+ >
295
574
  </v-col>
296
575
  </v-row>
297
576
  </v-toolbar>
@@ -299,10 +578,40 @@
299
578
  </v-dialog>
300
579
 
301
580
  <v-dialog v-model="dialog.addPassKey" width="450" persistent>
302
- <AddPassKeyToVisitor :visitor="selectedVisitorDataObject" :site="siteId" @close="dialog.addPassKey = false"
303
- @update="getVisitorRefresh" />
581
+ <AddPassKeyToVisitor
582
+ mode="add"
583
+ :visitor="selectedVisitorDataObject"
584
+ :site="siteId"
585
+ @close="dialog.addPassKey = false"
586
+ @done="
587
+ () => {
588
+ dialog.addPassKey = false;
589
+ getVisitorRefresh();
590
+ }
591
+ "
592
+ />
593
+ </v-dialog>
594
+
595
+ <v-dialog v-model="dialog.editPassKey" width="450" persistent>
596
+ <AddPassKeyToVisitor
597
+ mode="edit"
598
+ :visitor="selectedVisitorDataObject"
599
+ :site="siteId"
600
+ @close="dialog.editPassKey = false"
601
+ @done="
602
+ () => {
603
+ dialog.editPassKey = false;
604
+ getVisitorRefresh();
605
+ }
606
+ "
607
+ />
304
608
  </v-dialog>
305
609
 
610
+ <ScanVisitorQRCode
611
+ :dialog="dialog.scanVisitorQRCode"
612
+ @close-dialog="dialog.scanVisitorQRCode = false"
613
+ />
614
+
306
615
  <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
307
616
  </v-row>
308
617
  </template>
@@ -317,15 +626,15 @@ const props = defineProps({
317
626
  type: Boolean,
318
627
  default: true,
319
628
  },
320
- canViewVisitor: {
629
+ canScanVisitorQRCode: {
321
630
  type: Boolean,
322
631
  default: true,
323
632
  },
324
- canUpdateVisitor: {
633
+ canViewVisitor: {
325
634
  type: Boolean,
326
635
  default: true,
327
636
  },
328
- canDeleteVisitor: {
637
+ canUpdateVisitor: {
329
638
  type: Boolean,
330
639
  default: true,
331
640
  },
@@ -335,21 +644,16 @@ const props = defineProps({
335
644
  },
336
645
  });
337
646
 
338
- const {
339
- getVisitors,
340
- visitorSelection,
341
- typeFieldMap,
342
- deleteVisitor,
343
- updateVisitor,
344
- } = useVisitor();
647
+ const { getVisitors, visitorSelection, typeFieldMap, updateVisitor } =
648
+ useVisitor();
345
649
  const { debounce, formatCamelCaseToWords, formatDate, UTCToLocalTIme } =
346
650
  useUtils();
347
651
  const { formatLocation } = useSecurityUtils();
348
652
  const { getFileUrlAnpr } = useFile();
349
653
  // const { status: visitorStatus, search } = useRoute().query as { status: string, search: string};
350
654
 
351
- const route = useRoute()
352
- const router = useRouter()
655
+ const route = useRoute();
656
+ const router = useRouter();
353
657
  const { org: orgId, site: siteId } = route.params as {
354
658
  org: string;
355
659
  site: string;
@@ -377,7 +681,6 @@ const messageColor = ref("");
377
681
  const messageSnackbar = ref(false);
378
682
 
379
683
  const loading = reactive({
380
- deletingVisitor: false,
381
684
  fetchingVisitors: false,
382
685
  checkingOut: false,
383
686
  savingRemarks: false,
@@ -388,15 +691,16 @@ const dialog = reactive({
388
691
  showSelection: false,
389
692
  showForm: false,
390
693
  viewVisitor: false,
391
- deleteConfirmation: false,
392
694
  snapshotImage: false,
393
695
  remarks: false,
394
696
  returnPassesKeys: false,
395
- addPassKey: false
697
+ addPassKey: false,
698
+ editPassKey: false,
699
+ scanVisitorQRCode: false,
396
700
  });
397
701
 
398
702
  const snapshotImageUrl = ref("");
399
- const remarksType = ref<'checkIn' | 'checkOut'>('checkIn');
703
+ const remarksType = ref<"checkIn" | "checkOut">("checkIn");
400
704
  const remarksInput = ref("");
401
705
  const remarksViewOnly = ref(false);
402
706
 
@@ -406,10 +710,16 @@ const headers = computed(() => [
406
710
  { title: "Location", value: "location" },
407
711
  { title: "Contact/Vehicle No.", value: "contact-vehicleNumber" },
408
712
  { title: "Check In/Out", value: "checkin-out" },
409
- ...(activeTab.value === "resident-transactions" ? [{ title: "Check-in Remarks", value: "checkInRemarks" }, { title: "Check-out Remarks", value: "checkOutRemarks" }] : []),
410
- ...(activeTab.value === 'unregistered' ? [{ title: "Action", value: "action" }] : [])
411
- ])
412
-
713
+ ...(activeTab.value === "resident-transactions"
714
+ ? [
715
+ { title: "Check-in Remarks", value: "checkInRemarks" },
716
+ { title: "Check-out Remarks", value: "checkOutRemarks" },
717
+ ]
718
+ : []),
719
+ ...(activeTab.value === "unregistered"
720
+ ? [{ title: "Action", value: "action" }]
721
+ : []),
722
+ ]);
413
723
 
414
724
  const tabOptions = [
415
725
  { name: "Registered", value: "registered" },
@@ -452,7 +762,6 @@ const formattedFields = {
452
762
  checkOut: "Check Out",
453
763
  snapshotExitImage: "Exit Image",
454
764
  remarks: "Remarks",
455
-
456
765
  } as const;
457
766
 
458
767
  function filterTypeSelectionLabel() {
@@ -465,14 +774,14 @@ const passStatusOptions = [
465
774
  { label: "Not Returned", value: "In Use" },
466
775
  { label: "Damaged", value: "Damaged" },
467
776
  { label: "Lost", value: "Lost" },
468
- ]
777
+ ];
469
778
 
470
779
  function toRoute(tab: any) {
471
- items.value = []
780
+ items.value = [];
472
781
 
473
782
  const obj = tabOptions.find((x) => x.value === tab);
474
783
  if (!obj) return;
475
- page.value = 1
784
+ page.value = 1;
476
785
  navigateTo({
477
786
  name: routeName,
478
787
  params: {
@@ -483,54 +792,51 @@ function toRoute(tab: any) {
483
792
  // },
484
793
  });
485
794
  }
486
-
487
795
  const {
488
796
  data: getVisitorReq,
489
797
  refresh: getVisitorRefresh,
490
798
  pending: getVisitorPending,
491
799
  } = await useLazyAsyncData(
492
- `get-all-visitors-${activeTab.value}-${page.value}-${siteId}`,
800
+ "get-all-visitors",
493
801
  async () => {
494
-
495
- // Optional delay (if needed)
496
- await new Promise(resolve => setTimeout(resolve, 100))
497
-
498
802
  const params: any = {
499
803
  page: page.value,
500
804
  site: siteId,
501
805
  search: searchInput.value,
502
806
  dateTo: normalizeDateOnly(dateTo.value),
503
807
  dateFrom: normalizeDateOnly(dateFrom.value),
504
- type: (filterTypes.value.length === 0 && activeTab.value === 'registered' ? "contractor,delivery,walk-in,pick-up,drop-off,guest" : filterTypes.value.filter(Boolean).join(",")),
505
- checkedOut: displayNotCheckedOut.value ? false : undefined
506
- }
507
-
508
- // if (activeTab.value !== "guests") {
509
- // params.status = activeTab.value
510
- // } else if (activeTab.value === "guests") {
511
- // params.type = "guest"
512
- // params.status = "pending"
513
- // }
808
+ type:
809
+ filterTypes.value.length === 0 && activeTab.value === "registered"
810
+ ? "contractor,delivery,walk-in,pick-up,drop-off,guest"
811
+ : filterTypes.value.filter(Boolean).join(","),
812
+ checkedOut: displayNotCheckedOut.value ? false : undefined,
813
+ };
514
814
 
515
815
  if (activeTab.value === "guests") {
516
- params.type = "guest"
517
- params.status = "pending"
816
+ params.type = "guest";
817
+ params.status = "pending";
518
818
  } else if (activeTab.value === "resident-transactions") {
519
- params.status = "registered"
520
- params.type = "resident,tenant"
819
+ params.status = "registered";
820
+ params.type = "resident,tenant";
521
821
  } else {
522
- params.status = activeTab.value
822
+ params.status = activeTab.value;
523
823
  }
524
824
 
525
- return await getVisitors(params)
825
+ return await getVisitors(params);
526
826
  },
527
827
  {
528
828
  watch: [
529
829
  page,
830
+ searchInput,
831
+ dateFrom,
832
+ dateTo,
833
+ filterTypes,
834
+ activeTab,
835
+ displayNotCheckedOut,
530
836
  ],
531
- immediate: false
837
+ immediate: true,
532
838
  }
533
- )
839
+ );
534
840
 
535
841
  watch(getVisitorReq, (newData: any) => {
536
842
  if (newData) {
@@ -542,11 +848,16 @@ watch(getVisitorReq, (newData: any) => {
542
848
  });
543
849
 
544
850
  const selectedVisitorObject = computed(() => {
545
-
546
851
  const obj = items.value.find((x: any) => x?._id === selectedVisitorId.value);
547
852
  if (!obj) return {};
548
853
  const type = obj?.type as TVisitorType | undefined;
549
- let includedKeys: string[] = ["checkIn", "checkOut", "plateNumber", "snapshotEntryImage", "snapshotExitImage"];
854
+ let includedKeys: string[] = [
855
+ "checkIn",
856
+ "checkOut",
857
+ "plateNumber",
858
+ "snapshotEntryImage",
859
+ "snapshotExitImage",
860
+ ];
550
861
  includedKeys.unshift(...(typeFieldMap[type] ?? []));
551
862
  return Object.fromEntries(
552
863
  Object.entries(obj).filter(([key]) => includedKeys.includes(key))
@@ -567,8 +878,6 @@ function formatValues(key: string, value: any) {
567
878
  return value;
568
879
  }
569
880
 
570
-
571
-
572
881
  function handleAddNew() {
573
882
  dialog.showSelection = true;
574
883
  activeVisitorFormType.value = null;
@@ -588,9 +897,17 @@ function showAddPassKeyButton(item: any) {
588
897
  const hasPasses = (item?.visitorPass?.length ?? 0) > 0;
589
898
  const hasKeys = (item?.passKeys?.length ?? 0) > 0;
590
899
 
591
- const isTypeWithPassKey = ["contractor", "guest", "walk-in"].includes(item?.type);
900
+ const isTypeWithPassKey = ["contractor", "guest", "walk-in"].includes(
901
+ item?.type
902
+ );
592
903
 
593
- return !hasPasses && !hasKeys && isTypeWithPassKey && item?.status === "registered" && !item?.checkOut;
904
+ return (
905
+ !hasPasses &&
906
+ !hasKeys &&
907
+ isTypeWithPassKey &&
908
+ item?.status === "registered" &&
909
+ !item?.checkOut
910
+ );
594
911
  }
595
912
 
596
913
  function handleSelectVisitorType(type: TVisitorType) {
@@ -616,11 +933,6 @@ function handleVisitorFormCreateMore() {
616
933
  dialog.showForm = false;
617
934
  }
618
935
 
619
- function handleDeleteVisitor() {
620
- dialog.deleteConfirmation = true;
621
- dialog.viewVisitor = false;
622
- }
623
-
624
936
  function showMessage(msg: string, color: string) {
625
937
  message.value = msg;
626
938
  messageColor.value = color;
@@ -650,10 +962,19 @@ function handleOpenAddPassKey(item: any) {
650
962
  dialog.addPassKey = true;
651
963
  }
652
964
 
653
- function handleOpenRemarks(item: any, type: 'checkIn' | 'checkOut') {
965
+ function handleOpenEditPassKey(item: any) {
966
+ selectedVisitorId.value = item?._id;
967
+ if (selectedVisitorDataObject.value.checkOut) {
968
+ dialog.returnPassesKeys = true;
969
+ handleCheckout(selectedVisitorId.value as string);
970
+ } else dialog.editPassKey = true;
971
+ }
972
+
973
+ function handleOpenRemarks(item: any, type: "checkIn" | "checkOut") {
654
974
  selectedVisitorId.value = item?._id;
655
975
  remarksType.value = type;
656
- const existingRemarks = type === 'checkIn' ? item?.checkInRemarks : item?.checkOutRemarks;
976
+ const existingRemarks =
977
+ type === "checkIn" ? item?.checkInRemarks : item?.checkOutRemarks;
657
978
  remarksInput.value = existingRemarks || "";
658
979
  remarksViewOnly.value = !!existingRemarks;
659
980
  dialog.remarks = true;
@@ -663,16 +984,20 @@ async function handleSaveRemarks() {
663
984
  if (!remarksInput.value.trim() || !selectedVisitorId.value) return;
664
985
  try {
665
986
  loading.savingRemarks = true;
666
- const payload = remarksType.value === 'checkIn'
667
- ? { checkInRemarks: remarksInput.value.trim() }
668
- : { checkOutRemarks: remarksInput.value.trim() };
987
+ const payload =
988
+ remarksType.value === "checkIn"
989
+ ? { checkInRemarks: remarksInput.value.trim() }
990
+ : { checkOutRemarks: remarksInput.value.trim() };
669
991
  await updateVisitor(selectedVisitorId.value, payload);
670
992
  showMessage("Remarks saved successfully!", "info");
671
993
  await getVisitorRefresh();
672
994
  dialog.remarks = false;
673
995
  } catch (error: any) {
674
996
  const errorMessage = error?.response?._data?.message;
675
- showMessage(errorMessage || "Something went wrong. Please try again later.", "error");
997
+ showMessage(
998
+ errorMessage || "Something went wrong. Please try again later.",
999
+ "error"
1000
+ );
676
1001
  } finally {
677
1002
  loading.savingRemarks = false;
678
1003
  }
@@ -684,11 +1009,19 @@ async function handleUpdatePassKeys() {
684
1009
  loading.updatingPassKeys = true;
685
1010
  const payload: any = {};
686
1011
  if (passReturnStatuses.value.length > 0) {
687
- const passReturnStatusesPayload = passReturnStatuses.value.map(p => ({ keyId: p.keyId, status: p.status, remarks: p.remarks }));
1012
+ const passReturnStatusesPayload = passReturnStatuses.value.map((p) => ({
1013
+ keyId: p.keyId,
1014
+ status: p.status,
1015
+ remarks: p.remarks,
1016
+ }));
688
1017
  payload.visitorPass = passReturnStatusesPayload;
689
1018
  }
690
1019
  if (keyReturnStatuses.value.length > 0) {
691
- const keyReturnStatusesPayload = keyReturnStatuses.value.map(k => ({ keyId: k.keyId, status: k.status, remarks: k.remarks }));
1020
+ const keyReturnStatusesPayload = keyReturnStatuses.value.map((k) => ({
1021
+ keyId: k.keyId,
1022
+ status: k.status,
1023
+ remarks: k.remarks,
1024
+ }));
692
1025
  payload.passKeys = keyReturnStatusesPayload;
693
1026
  }
694
1027
  await updateVisitor(selectedVisitorId.value, payload);
@@ -696,50 +1029,35 @@ async function handleUpdatePassKeys() {
696
1029
  await getVisitorRefresh();
697
1030
  } catch (error: any) {
698
1031
  const errorMessage = error?.response?._data?.message;
699
- showMessage(errorMessage || "Something went wrong. Please try again later.", "error");
700
- } finally {
701
- loading.updatingPassKeys = false;
702
- }
703
- }
704
-
705
-
706
- async function handleProceedDeleteVisitor() {
707
- try {
708
- loading.deletingVisitor = true;
709
- const userId = selectedVisitorId.value;
710
- const res = await deleteVisitor(userId as string);
711
- if (res) {
712
- showMessage("Visitor successfully deleted!", "info");
713
- await getVisitorRefresh();
714
- dialog.deleteConfirmation = false;
715
- }
716
- } catch (error: any) {
717
- const errorMessage = error?.response?._data?.message;
718
- console.log("[ERROR]", error);
719
1032
  showMessage(
720
1033
  errorMessage || "Something went wrong. Please try again later.",
721
1034
  "error"
722
1035
  );
723
1036
  } finally {
724
- loading.deletingVisitor = false;
1037
+ loading.updatingPassKeys = false;
725
1038
  }
726
1039
  }
727
1040
 
728
-
729
- const passReturnStatuses = ref<{ keyId: string, status: string, prefixAndName: string, remarks: string }[]>([]);
730
- const keyReturnStatuses = ref<{ keyId: string, status: string, prefixAndName: string, remarks: string }[]>([]);
1041
+ const passReturnStatuses = ref<
1042
+ { keyId: string; status: string; prefixAndName: string; remarks: string }[]
1043
+ >([]);
1044
+ const keyReturnStatuses = ref<
1045
+ { keyId: string; status: string; prefixAndName: string; remarks: string }[]
1046
+ >([]);
731
1047
 
732
1048
  const canConfirmCheckout = computed(() => {
733
1049
  const allEntries = [...passReturnStatuses.value, ...keyReturnStatuses.value];
734
1050
  return allEntries.every((entry) => {
735
- if (!entry.status || entry.status === 'In Use') return false;
736
- if ((entry.status === 'Lost' || entry.status === 'Damaged') && !entry.remarks.trim()) return false;
1051
+ if (!entry.status || entry.status === "In Use") return false;
1052
+ if (
1053
+ (entry.status === "Lost" || entry.status === "Damaged") &&
1054
+ !entry.remarks.trim()
1055
+ )
1056
+ return false;
737
1057
  return true;
738
1058
  });
739
1059
  });
740
1060
 
741
-
742
-
743
1061
  function handleCheckout(userId: string) {
744
1062
  if (!userId) {
745
1063
  showMessage("Invalid userId", "error");
@@ -753,8 +1071,22 @@ function handleCheckout(userId: string) {
753
1071
 
754
1072
  if (hasPasses || hasKeys) {
755
1073
  const visitor = items.value.find((x: any) => x?._id === userId);
756
- passReturnStatuses.value = ((visitor?.visitorPass as any[]) || []).map((p: any) => ({ keyId: p.keyId, status: p.status ?? "In Use", remarks: '', prefixAndName: p.prefixAndName }));
757
- keyReturnStatuses.value = ((visitor?.passKeys as any[]) || []).map((k: any) => ({ keyId: k.keyId, status: k.status ?? "In Use", remarks: '', prefixAndName: k.prefixAndName }));
1074
+ passReturnStatuses.value = ((visitor?.visitorPass as any[]) || []).map(
1075
+ (p: any) => ({
1076
+ keyId: p.keyId,
1077
+ status: p.status ?? "In Use",
1078
+ remarks: "",
1079
+ prefixAndName: p.prefixAndName,
1080
+ })
1081
+ );
1082
+ keyReturnStatuses.value = ((visitor?.passKeys as any[]) || []).map(
1083
+ (k: any) => ({
1084
+ keyId: k.keyId,
1085
+ status: k.status ?? "In Use",
1086
+ remarks: "",
1087
+ prefixAndName: k.prefixAndName,
1088
+ })
1089
+ );
758
1090
  dialog.returnPassesKeys = true;
759
1091
  return;
760
1092
  }
@@ -769,13 +1101,25 @@ async function proceedCheckout() {
769
1101
  try {
770
1102
  loading.checkingOut = true;
771
1103
 
772
- const passReturnStatusesPayload = passReturnStatuses.value.map(p => ({ keyId: p.keyId, status: p.status, remarks: p.remarks }));
773
- const keyReturnStatusesPayload = keyReturnStatuses.value.map(k => ({ keyId: k.keyId, status: k.status, remarks: k.remarks }));
1104
+ const passReturnStatusesPayload = passReturnStatuses.value.map((p) => ({
1105
+ keyId: p.keyId,
1106
+ status: p.status,
1107
+ remarks: p.remarks,
1108
+ }));
1109
+ const keyReturnStatusesPayload = keyReturnStatuses.value.map((k) => ({
1110
+ keyId: k.keyId,
1111
+ status: k.status,
1112
+ remarks: k.remarks,
1113
+ }));
774
1114
 
775
1115
  const res = await updateVisitor(userId as string, {
776
1116
  checkOut: new Date().toISOString(),
777
- ...(passReturnStatuses.value.length > 0 ? { visitorPass: passReturnStatusesPayload } : {}),
778
- ...(keyReturnStatuses.value.length > 0 ? { passKeys: keyReturnStatusesPayload } : {}),
1117
+ ...(passReturnStatuses.value.length > 0
1118
+ ? { visitorPass: passReturnStatusesPayload }
1119
+ : {}),
1120
+ ...(keyReturnStatuses.value.length > 0
1121
+ ? { passKeys: keyReturnStatusesPayload }
1122
+ : {}),
779
1123
  });
780
1124
  if (res) {
781
1125
  showMessage("Visitor successfully checked-out!", "info");
@@ -795,11 +1139,23 @@ async function proceedCheckout() {
795
1139
  }
796
1140
  }
797
1141
 
798
-
799
-
800
1142
  const updateRouteQuery = debounce(
801
1143
  // (search: string, from: string, to: string, types: string[], status, checkedOut) => {
802
- ({ search, from, to, types, tab, checkedOut }: { search: string, from: string, to: string, types: string[], tab: string, checkedOut: boolean }) => {
1144
+ ({
1145
+ search,
1146
+ from,
1147
+ to,
1148
+ types,
1149
+ tab,
1150
+ checkedOut,
1151
+ }: {
1152
+ search: string;
1153
+ from: string;
1154
+ to: string;
1155
+ types: string[];
1156
+ tab: string;
1157
+ checkedOut: boolean;
1158
+ }) => {
803
1159
  router.replace({
804
1160
  query: {
805
1161
  ...route.query,
@@ -808,7 +1164,9 @@ const updateRouteQuery = debounce(
808
1164
  dateTo: to || undefined,
809
1165
  type: types.filter(Boolean).join(",") || undefined,
810
1166
  tab: tab || undefined,
811
- ...(checkedOut === true ? { checkedOut: "true" } : { checkedOut: undefined })
1167
+ ...(checkedOut === true
1168
+ ? { checkedOut: "true" }
1169
+ : { checkedOut: undefined }),
812
1170
  },
813
1171
  });
814
1172
  },
@@ -824,22 +1182,33 @@ watch(
824
1182
  dateTo.value = normalizedTo;
825
1183
 
826
1184
  // updateRouteQuery(search, from, to, types, status, checkedOut)
827
- updateRouteQuery({ search, from: normalizedFrom, to: normalizedTo, types, tab, checkedOut })
828
- getVisitorRefresh();
1185
+ updateRouteQuery({
1186
+ search,
1187
+ from: normalizedFrom,
1188
+ to: normalizedTo,
1189
+ types,
1190
+ tab,
1191
+ checkedOut,
1192
+ });
1193
+ // getVisitorRefresh();
829
1194
  },
830
1195
  { deep: true }
831
1196
  );
832
-
833
-
1197
+ watch([searchInput, dateFrom, dateTo, filterTypes, activeTab], () => {
1198
+ page.value = 1;
1199
+ });
834
1200
 
835
1201
  onMounted(() => {
836
- activeTab.value = (route.query.tab as string) || "unregistered"
1202
+ activeTab.value = (route.query.tab as string) || "unregistered";
837
1203
  searchInput.value = (route.query.search as string) || "";
838
1204
  dateFrom.value = normalizeDateOnly((route.query.dateFrom as string) || "");
839
1205
  dateTo.value = normalizeDateOnly((route.query.dateTo as string) || "");
840
- filterTypes.value = ((route.query.type as string)?.split(",") || []).filter(Boolean) as TVisitorType[];
841
- displayNotCheckedOut.value = (route.query.checkedOut as string) == 'true' || false
842
- })
1206
+ filterTypes.value = ((route.query.type as string)?.split(",") || []).filter(
1207
+ Boolean
1208
+ ) as TVisitorType[];
1209
+ displayNotCheckedOut.value =
1210
+ (route.query.checkedOut as string) == "true" || false;
1211
+ });
843
1212
  </script>
844
1213
 
845
1214
  <style scoped></style>