@7365admin1/layer-common 1.8.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.
Files changed (198) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +11 -0
  3. package/.editorconfig +12 -0
  4. package/.github/workflows/main.yml +17 -0
  5. package/.github/workflows/publish.yml +39 -0
  6. package/.nuxtrc +1 -0
  7. package/.playground/app.vue +41 -0
  8. package/.playground/eslint.config.mjs +6 -0
  9. package/.playground/nuxt.config.ts +22 -0
  10. package/.playground/pages/feedback.vue +30 -0
  11. package/CHANGELOG.md +263 -0
  12. package/README.md +73 -0
  13. package/app.vue +3 -0
  14. package/components/AccessCardAddForm.vue +363 -0
  15. package/components/AccessManagement.vue +420 -0
  16. package/components/Avatar/Main.vue +68 -0
  17. package/components/BillingMain.vue +66 -0
  18. package/components/BtnUploadFile.vue +139 -0
  19. package/components/BuildingForm.vue +303 -0
  20. package/components/BuildingManagement/buildings.vue +335 -0
  21. package/components/BuildingManagement/units.vue +350 -0
  22. package/components/BuildingUnitFormAdd.vue +441 -0
  23. package/components/BuildingUnitFormEdit.vue +429 -0
  24. package/components/CameraForm.vue +264 -0
  25. package/components/CameraMain.vue +352 -0
  26. package/components/Card/DeleteConfirmation.vue +51 -0
  27. package/components/Card/MemberInfoSummary.vue +44 -0
  28. package/components/Card/Toggle.vue +25 -0
  29. package/components/Chat/Bubbles.vue +53 -0
  30. package/components/Chat/Information.vue +416 -0
  31. package/components/Chat/ListCard.vue +62 -0
  32. package/components/Chat/Message.vue +158 -0
  33. package/components/Chat/Navigation.vue +150 -0
  34. package/components/ConfirmDialog.vue +66 -0
  35. package/components/Container/Standard.vue +33 -0
  36. package/components/DashboardPlaceholder.vue +1524 -0
  37. package/components/Dialog/DeleteConfirmation.vue +51 -0
  38. package/components/Dialog/ReplaceAutofillPrompt.vue +49 -0
  39. package/components/Dialog/UpdateMoreAction.vue +103 -0
  40. package/components/DocumentForm.vue +187 -0
  41. package/components/DocumentManagement.vue +376 -0
  42. package/components/Editor.vue +95 -0
  43. package/components/EntryPassMain.vue +518 -0
  44. package/components/Feedback/Form.vue +173 -0
  45. package/components/FeedbackDetail.vue +599 -0
  46. package/components/FeedbackMain.vue +588 -0
  47. package/components/FormDialog.vue +65 -0
  48. package/components/ImageCarousel.vue +138 -0
  49. package/components/Input/Date.vue +177 -0
  50. package/components/Input/DateTimePicker.vue +131 -0
  51. package/components/Input/File.vue +236 -0
  52. package/components/Input/FileV2.vue +234 -0
  53. package/components/Input/InputPhoneNumberV2.vue +164 -0
  54. package/components/Input/ListGroupSelection.vue +96 -0
  55. package/components/Input/NRICNumber.vue +53 -0
  56. package/components/Input/NewDate.vue +123 -0
  57. package/components/Input/Number.vue +124 -0
  58. package/components/Input/Password.vue +22 -0
  59. package/components/Input/PhoneNumber.vue +188 -0
  60. package/components/Input/VehicleNumber.vue +49 -0
  61. package/components/InputLabel.vue +22 -0
  62. package/components/InvitationForm.vue +359 -0
  63. package/components/InvitationMain.vue +310 -0
  64. package/components/Layout/Header.vue +129 -0
  65. package/components/Layout/NavigationDrawer.vue +44 -0
  66. package/components/ListItem.vue +35 -0
  67. package/components/ListView.vue +87 -0
  68. package/components/LocalPagination.vue +31 -0
  69. package/components/MemberMain.vue +459 -0
  70. package/components/NFC/NFCPatrolReportMain.vue +591 -0
  71. package/components/NFC/NFCPatrolRouteForm.vue +596 -0
  72. package/components/NFC/NFCPatrolRouteMain.vue +539 -0
  73. package/components/NFC/NFCTagForm.vue +236 -0
  74. package/components/NFC/NFCTagMain.vue +337 -0
  75. package/components/NFC/PatrolSettings.vue +130 -0
  76. package/components/NavigationItem.vue +83 -0
  77. package/components/NumberSettingField.vue +107 -0
  78. package/components/OnlineFormConfigurationForm.vue +290 -0
  79. package/components/OnlineFormsConfiguration.vue +429 -0
  80. package/components/PeopleForm.vue +452 -0
  81. package/components/PlaceholderComponent.vue +34 -0
  82. package/components/RolePermissionFormCreate.vue +161 -0
  83. package/components/RolePermissionFormPreviewUpdate.vue +183 -0
  84. package/components/RolePermissionMain.vue +361 -0
  85. package/components/SearchVehicleNumberUser.vue +91 -0
  86. package/components/ServiceProviderFormCreate.vue +154 -0
  87. package/components/ServiceProviderMain.vue +547 -0
  88. package/components/SignaturePad.vue +73 -0
  89. package/components/Snackbar.vue +23 -0
  90. package/components/SpecificAttr.vue +53 -0
  91. package/components/SupplyManagement.vue +292 -0
  92. package/components/SwitchContext.vue +108 -0
  93. package/components/TableList.vue +150 -0
  94. package/components/TableListSecondary.vue +164 -0
  95. package/components/TableMain.vue +142 -0
  96. package/components/TableWithButton.vue +94 -0
  97. package/components/VehicleUpdateMoreAction.vue +84 -0
  98. package/components/VideoPlayer.vue +125 -0
  99. package/components/VisitorForm.vue +659 -0
  100. package/components/VisitorFormSelection.vue +53 -0
  101. package/components/VisitorManagement.vue +490 -0
  102. package/components/WorkOrder/Create.vue +284 -0
  103. package/components/WorkOrder/Detail.vue +71 -0
  104. package/components/WorkOrder/ListView.vue +96 -0
  105. package/components/WorkOrder/Main.vue +489 -0
  106. package/components/Workorder.vue +1 -0
  107. package/composables/useAddress.ts +107 -0
  108. package/composables/useBuilding.ts +250 -0
  109. package/composables/useBuildingUnit.ts +116 -0
  110. package/composables/useCard.ts +46 -0
  111. package/composables/useCommonPermission.ts +207 -0
  112. package/composables/useCustomer.ts +113 -0
  113. package/composables/useCustomerSite.ts +56 -0
  114. package/composables/useDashboard.ts +31 -0
  115. package/composables/useDashboardData.ts +425 -0
  116. package/composables/useDocument.ts +57 -0
  117. package/composables/useFacility.ts +246 -0
  118. package/composables/useFeedback.ts +119 -0
  119. package/composables/useFile.ts +55 -0
  120. package/composables/useInvoice.ts +18 -0
  121. package/composables/useLocal.ts +131 -0
  122. package/composables/useLocalAuth.ts +137 -0
  123. package/composables/useLocalSetup.ts +13 -0
  124. package/composables/useMember.ts +111 -0
  125. package/composables/useNFCPatrolRoute.ts +77 -0
  126. package/composables/useNFCPatrolSettings.ts +19 -0
  127. package/composables/useNFCPatrolTag.ts +53 -0
  128. package/composables/useOnlineForm.ts +67 -0
  129. package/composables/useOrg.ts +129 -0
  130. package/composables/usePDFDownload.ts +25 -0
  131. package/composables/usePaymentMethod.ts +101 -0
  132. package/composables/usePeople.ts +81 -0
  133. package/composables/usePermission.ts +54 -0
  134. package/composables/usePhoneCountries.ts +561 -0
  135. package/composables/usePrice.ts +15 -0
  136. package/composables/usePromoCode.ts +36 -0
  137. package/composables/useRecapPermission.ts +26 -0
  138. package/composables/useRole.ts +104 -0
  139. package/composables/useSecurityUtils.ts +18 -0
  140. package/composables/useServiceProvider.ts +224 -0
  141. package/composables/useSite.ts +109 -0
  142. package/composables/useSiteEntryPassSettings.ts +46 -0
  143. package/composables/useSiteSettings.ts +123 -0
  144. package/composables/useSubscription.ts +150 -0
  145. package/composables/useUser.ts +132 -0
  146. package/composables/useUtils.ts +445 -0
  147. package/composables/useVerification.ts +34 -0
  148. package/composables/useVisitor.ts +120 -0
  149. package/composables/useWorkOrder.ts +85 -0
  150. package/error.vue +41 -0
  151. package/layouts/plain.vue +7 -0
  152. package/middleware/01.auth.ts +20 -0
  153. package/middleware/02.org.ts +21 -0
  154. package/middleware/03.customer.ts +13 -0
  155. package/middleware/member.ts +4 -0
  156. package/nuxt.config.ts +54 -0
  157. package/package.json +39 -0
  158. package/pages/index.vue +3 -0
  159. package/pages/payment-method-linked.vue +31 -0
  160. package/pages/require-customer.vue +56 -0
  161. package/pages/require-organization-membership.vue +47 -0
  162. package/pages/unauthorized.vue +29 -0
  163. package/plugins/API.ts +21 -0
  164. package/plugins/iconify.client.ts +5 -0
  165. package/plugins/secure-member.client.ts +86 -0
  166. package/plugins/vuetify.ts +62 -0
  167. package/public/bg-camera.jpg +0 -0
  168. package/public/bg-city.jpg +0 -0
  169. package/public/bg-condo.jpg +0 -0
  170. package/public/images/icons/delete-icon.png +0 -0
  171. package/public/sprite.svg +1 -0
  172. package/tsconfig.json +3 -0
  173. package/types/address.d.ts +13 -0
  174. package/types/building.d.ts +27 -0
  175. package/types/camera.d.ts +31 -0
  176. package/types/card.d.ts +22 -0
  177. package/types/customer.d.ts +27 -0
  178. package/types/document.d.ts +6 -0
  179. package/types/feedback.d.ts +68 -0
  180. package/types/local.d.ts +74 -0
  181. package/types/member.d.ts +21 -0
  182. package/types/online-form.d.ts +15 -0
  183. package/types/org.d.ts +13 -0
  184. package/types/people.d.ts +24 -0
  185. package/types/permission.d.ts +25 -0
  186. package/types/phone-number.d.ts +10 -0
  187. package/types/price.d.ts +17 -0
  188. package/types/promo-code.d.ts +19 -0
  189. package/types/role.d.ts +11 -0
  190. package/types/select.d.ts +4 -0
  191. package/types/service-provider.d.ts +15 -0
  192. package/types/site.d.ts +20 -0
  193. package/types/subscription.d.ts +23 -0
  194. package/types/user.d.ts +19 -0
  195. package/types/verification.d.ts +20 -0
  196. package/types/visitor.d.ts +42 -0
  197. package/types/work-order.d.ts +42 -0
  198. package/utils/phoneMasks.ts +1703 -0
@@ -0,0 +1,539 @@
1
+ <template>
2
+ <v-row no-gutters>
3
+ <v-col cols="12">
4
+ <v-row no-gutters class="mb-4" align="center">
5
+ <v-col cols="12" md="6">
6
+ <v-btn
7
+ rounded="pill"
8
+ variant="outlined"
9
+
10
+ size="large"
11
+ class="text-none px-8"
12
+ @click="dialogAdd = true"
13
+ >
14
+ Add Route
15
+ </v-btn>
16
+ </v-col>
17
+ <v-col cols="12" md="6" class="d-flex justify-end">
18
+ <v-text-field
19
+ v-model="searchInput"
20
+ density="comfortable"
21
+ placeholder="Search"
22
+ clearable
23
+ append-inner-icon="mdi-magnify"
24
+ hide-details
25
+ variant="outlined"
26
+ rounded="lg"
27
+ style="max-width: 400px"
28
+ bg-color="white"
29
+ />
30
+ </v-col>
31
+ </v-row>
32
+
33
+ <v-card width="100%" variant="outlined" border="thin" rounded="lg">
34
+
35
+ <v-card-text class="pa-0">
36
+ <v-data-table
37
+ :headers="headers"
38
+ :items="items"
39
+ :items-per-page="20"
40
+ fixed-header
41
+ hide-default-footer
42
+ @click:row="handleRowClick"
43
+ style="max-height: calc(100vh - 300px)"
44
+ class="nfc-route-table"
45
+ hover
46
+ >
47
+ <template #item.numberOfCheckpoints="{ value }">
48
+ <div class="text-center">{{ value || "--" }}</div>
49
+ </template>
50
+
51
+ <template #item.tolerance="{ item }">
52
+ <div class="text-center">
53
+ <div>{{ item.tolerance ? `${item.tolerance} mins` : "--" }}</div>
54
+ <div class="text-grey">{{ item.totalTravelTime ? `${item.totalTravelTime} mins` : "--" }}</div>
55
+ </div>
56
+ </template>
57
+
58
+ <template #item.schedules="{ value }">
59
+ <span v-if="Array.isArray(value) && value.length > 0">
60
+ {{ value.map(s => `${s.start}-${s.end}`).join(", ") }}
61
+ </span>
62
+ <span v-else>--</span>
63
+ </template>
64
+
65
+ <template #item.repeatDays="{ value }">
66
+ <span>{{ value || "--" }} </span>
67
+ </template>
68
+ </v-data-table>
69
+ </v-card-text>
70
+
71
+ <v-toolbar density="compact" color="grey-lighten-4">
72
+ <template #append>
73
+ <v-row no-gutters justify="end" align="center">
74
+ <span class="mr-2 text-caption text-fontgray">
75
+ {{ pageRange }}
76
+ </span>
77
+ <local-pagination v-model="page" :length="pages" />
78
+ </v-row>
79
+ </template>
80
+ </v-toolbar>
81
+ </v-card>
82
+ </v-col>
83
+
84
+ <!-- Add Dialog -->
85
+ <v-dialog v-model="dialogAdd" persistent max-width="900">
86
+ <NFCPatrolRouteForm
87
+ title="Add Route"
88
+ :site="props.site"
89
+ :org-id="props.orgId"
90
+ @cancel="dialogAdd = false"
91
+ @success="handleSuccess"
92
+ @error="handleError"
93
+ />
94
+ </v-dialog>
95
+
96
+ <!-- Edit Dialog -->
97
+ <v-dialog v-model="dialogEdit" persistent max-width="900">
98
+ <NFCPatrolRouteForm
99
+ title="Edit Route"
100
+ :site="props.site"
101
+ :org-id="props.orgId"
102
+ @cancel="dialogEdit = false"
103
+ @success="handleSuccess"
104
+ @error="handleError"
105
+ mode="edit"
106
+ :route="selectedRoute"
107
+ />
108
+ </v-dialog>
109
+
110
+ <!-- Preview Dialog -->
111
+ <v-dialog v-model="dialogPreview" persistent width="540">
112
+ <v-card width="100%">
113
+ <v-toolbar>
114
+ <v-row no-gutters class="fill-height px-6" align="center">
115
+ <span class="font-weight-bold text-h5 text-capitalize">
116
+ Route Details
117
+ </span>
118
+ </v-row>
119
+ </v-toolbar>
120
+
121
+ <v-card-text
122
+ style="max-height: 100vh; overflow-y: auto"
123
+ class="pa-5 my-5 px-7"
124
+ >
125
+ <v-row no-gutters>
126
+ <v-col cols="12" class="mb-2">
127
+ Route Name:
128
+ <span class="font-weight-bold">
129
+ {{ selectedRoute.routeName }}
130
+ </span>
131
+ </v-col>
132
+
133
+ <v-col cols="12" class="mb-2" v-if="selectedRoute.numberOfCheckpoints">
134
+ Number of Checkpoints:
135
+ <span class="font-weight-bold">
136
+ {{ selectedRoute.numberOfCheckpoints }}
137
+ </span>
138
+ </v-col>
139
+
140
+ <v-col cols="12" class="mb-2" v-if="selectedRoute.tolerance">
141
+ Tolerance:
142
+ <span class="font-weight-bold">
143
+ {{ selectedRoute.tolerance }} mins
144
+ </span>
145
+ </v-col>
146
+
147
+ <v-col
148
+ cols="12"
149
+ class="mb-2"
150
+ v-if="selectedRoute.totalTravelTime"
151
+ >
152
+ Total Travel Time:
153
+ <span class="font-weight-bold">
154
+ {{ selectedRoute.totalTravelTime }} mins
155
+ </span>
156
+ </v-col>
157
+
158
+ <v-col cols="12" class="mb-2" v-if="selectedRoute.repeatDays">
159
+ Repeat Every:
160
+ <span class="font-weight-bold">
161
+ {{ selectedRoute.repeatDays }}
162
+ </span>
163
+ </v-col>
164
+
165
+ <v-col
166
+ cols="12"
167
+ class="mb-2"
168
+ v-if="selectedRoute.schedules && selectedRoute.schedules.length"
169
+ >
170
+ Security Check Schedule:
171
+ <span class="font-weight-bold">
172
+ {{ selectedRoute.schedules.map(s => `${s.start}-${s.end}`).join(", ") }}
173
+ </span>
174
+ </v-col>
175
+
176
+ <v-col
177
+ cols="12"
178
+ class="mb-2"
179
+ v-if="selectedRoute.checkpoints && selectedRoute.checkpoints.length"
180
+ >
181
+ Checkpoints:
182
+ <div class="font-weight-bold">
183
+ <div v-for="(cp, idx) in selectedRoute.checkpoints" :key="idx" class="my-1">
184
+ {{ idx + 1 }}. NFC Tag ID: {{ cp.nfcTagId }} - Travel Time: {{ cp.travelTime }} min
185
+ </div>
186
+ </div>
187
+ </v-col>
188
+ </v-row>
189
+ </v-card-text>
190
+
191
+ <v-toolbar class="pa-0" density="compact">
192
+ <v-row no-gutters>
193
+ <v-col cols="6" class="pa-0">
194
+ <v-btn
195
+ block
196
+ variant="text"
197
+ class="text-none"
198
+ size="large"
199
+ @click="dialogPreview = false"
200
+ height="48"
201
+ >
202
+ Close
203
+ </v-btn>
204
+ </v-col>
205
+
206
+ <v-col cols="6" class="pa-0">
207
+ <v-menu>
208
+ <template #activator="{ props }">
209
+ <v-btn
210
+ block
211
+ variant="flat"
212
+ color="black"
213
+ class="text-none"
214
+ height="48"
215
+ v-bind="props"
216
+ tile
217
+ >
218
+ More actions
219
+ </v-btn>
220
+ </template>
221
+
222
+ <v-list class="pa-0">
223
+ <v-list-item @click="openDialogEdit()">
224
+ <v-list-item-title class="text-subtitle-2">
225
+ Edit Route
226
+ </v-list-item-title>
227
+ </v-list-item>
228
+
229
+ <v-list-item @click="openDialogDelete()" class="text-red">
230
+ <v-list-item-title class="text-subtitle-2">
231
+ Delete Route
232
+ </v-list-item-title>
233
+ </v-list-item>
234
+ </v-list>
235
+ </v-menu>
236
+ </v-col>
237
+ </v-row>
238
+ </v-toolbar>
239
+ </v-card>
240
+ </v-dialog>
241
+
242
+ <!-- Delete Dialog -->
243
+ <v-dialog v-model="dialogDelete" persistent width="540">
244
+ <v-card width="100%">
245
+ <v-card-text
246
+ style="max-height: 100vh; overflow-y: auto"
247
+ class="pa-5 my-5 px-7 text-center"
248
+ >
249
+ Are you sure you want to delete this route?
250
+ </v-card-text>
251
+
252
+ <v-toolbar class="pa-0" density="compact">
253
+ <v-row no-gutters>
254
+ <v-col cols="6" class="pa-0">
255
+ <v-btn
256
+ block
257
+ variant="text"
258
+ class="text-none"
259
+ size="large"
260
+ tile
261
+ @click="dialogDelete = false"
262
+ height="48"
263
+ >
264
+ Cancel
265
+ </v-btn>
266
+ </v-col>
267
+
268
+ <v-col cols="6" class="pa-0">
269
+ <v-btn
270
+ block
271
+ tile
272
+ variant="flat"
273
+ class="text-none"
274
+ size="large"
275
+ height="48"
276
+ color="black"
277
+ @click="submitDelete()"
278
+ >
279
+ Delete
280
+ </v-btn>
281
+ </v-col>
282
+ </v-row>
283
+ </v-toolbar>
284
+ </v-card>
285
+ </v-dialog>
286
+
287
+ <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
288
+ </v-row>
289
+ </template>
290
+
291
+ <script setup lang="ts">
292
+ import useNFCPatrolRoute from "../../composables/useNFCPatrolRoute";
293
+
294
+ const props = defineProps({
295
+ site: {
296
+ type: String,
297
+ required: true,
298
+ },
299
+ siteName: {
300
+ type: String,
301
+ default: "",
302
+ },
303
+ orgId: {
304
+ type: String,
305
+ required: true,
306
+ },
307
+ headers: {
308
+ type: Array as PropType<Array<any>>,
309
+ default: () => [
310
+ { title: "Route Name", value: "routeName", align: "start" },
311
+ { title: "Checkpoints", value: "numberOfCheckpoints", align: "center" },
312
+ {
313
+ title: "Tolerance (mins)\nTotal Travel Time (mins)",
314
+ value: "tolerance",
315
+ align: "center",
316
+ sortable: false
317
+ },
318
+ { title: "Security Check Schedule", value: "schedules", align: "start" },
319
+ { title: "Route Schedule", value: "repeatDays", align: "start" },
320
+ ],
321
+ },
322
+ });
323
+
324
+ const items = ref<Array<any>>([]);
325
+ const page = ref(1);
326
+ const pages = ref(0);
327
+ const pageRange = ref("1-20 of 1");
328
+ const searchInput = ref("");
329
+
330
+ const { getAll: getAllRoutes, getById: getRouteById, deleteById: deleteRouteById } =
331
+ useNFCPatrolRoute();
332
+
333
+ function calculateEndTime(startTime: string, toleranceMinutes: number): string {
334
+ if (!startTime) return '';
335
+
336
+ const [hours, minutes] = startTime.split(':').map(Number);
337
+ if (isNaN(hours) || isNaN(minutes)) return startTime;
338
+
339
+ const totalMinutes = hours * 60 + minutes + toleranceMinutes;
340
+ const wrappedMinutes = ((totalMinutes % 1440) + 1440) % 1440;
341
+
342
+ const endHours = String(Math.floor(wrappedMinutes / 60)).padStart(2, '0');
343
+ const endMins = String(wrappedMinutes % 60).padStart(2, '0');
344
+
345
+ return `${endHours}:${endMins}`;
346
+ }
347
+
348
+ // Use a reactive trigger for manual refresh
349
+ const refreshTrigger = ref(0);
350
+
351
+ const { data: getRoutesReq, refresh: getRoutesRefresh } =
352
+ await useLazyAsyncData(
353
+ `get-nfc-routes-${props.site}`,
354
+ () =>
355
+ getAllRoutes({
356
+ site: props.site,
357
+ page: page.value,
358
+ search: searchInput.value,
359
+ }),
360
+ {
361
+ watch: [page, searchInput, refreshTrigger],
362
+ }
363
+ );
364
+
365
+ watchEffect(() => {
366
+ if (getRoutesReq.value) {
367
+ items.value = getRoutesReq.value.items?.map((item: any) => ({
368
+ // Original API fields for editing
369
+ _id: item._id,
370
+ name: item.name,
371
+ checkPointNumber: item.checkPointNumber,
372
+ tolerance: item.tolerance,
373
+ totalTravelTime: item.totalTravelTime,
374
+ days: item.days,
375
+ startTimes: item.startTimes || [],
376
+ checkPoints: item.checkPoints || [],
377
+ // Display fields for the table
378
+ routeName: item.name,
379
+ numberOfCheckpoints: item.checkPointNumber,
380
+ schedules: item.startTimes?.map((time: string) => ({
381
+ start: time,
382
+ end: calculateEndTime(time, item.tolerance || 0)
383
+ })) || [],
384
+ repeatDays: item.days?.map((d: number) => {
385
+ const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
386
+ return dayNames[d];
387
+ }).join(', ') || '--',
388
+ checkpoints: item.checkPoints?.map((cp: any) => ({
389
+ nfcTagId: cp.nfcTag_id,
390
+ travelTime: cp.travelTime
391
+ })) || []
392
+ })) || [];
393
+
394
+ pageRange.value = getRoutesReq.value.pageRange;
395
+ pages.value = getRoutesReq.value.pages;
396
+ }
397
+ });
398
+
399
+ const dialogAdd = ref(false);
400
+ const dialogEdit = ref(false);
401
+ const dialogPreview = ref(false);
402
+ const dialogDelete = ref(false);
403
+
404
+ const message = ref("");
405
+ const messageSnackbar = ref(false);
406
+ const messageColor = ref("");
407
+
408
+ async function openDialogEdit() {
409
+ try {
410
+ // Fetch the full route details from the API
411
+ const response = await getRouteById(selectedRoute.value._id);
412
+
413
+ // Extract the nfcPatrolRoute from the nested response
414
+ const fullRouteData = response.data?.nfcPatrolRoute || response.nfcPatrolRoute || response;
415
+
416
+ // Update selectedRoute with the full data from API
417
+ selectedRoute.value = {
418
+ ...selectedRoute.value,
419
+ ...fullRouteData,
420
+ // Ensure the display fields are preserved
421
+ routeName: fullRouteData.name,
422
+ numberOfCheckpoints: fullRouteData.checkPointNumber,
423
+ };
424
+
425
+ dialogEdit.value = true;
426
+ if (dialogPreview.value) dialogPreview.value = false;
427
+ } catch (error) {
428
+ console.error('Error fetching route details:', error);
429
+ handleError(error);
430
+ }
431
+ }
432
+
433
+ function openDialogDelete() {
434
+ dialogDelete.value = true;
435
+
436
+ if (dialogPreview.value) dialogPreview.value = false;
437
+ }
438
+
439
+ async function handleSuccess() {
440
+ try {
441
+ // Small delay to ensure backend has processed the update
442
+ await new Promise(resolve => setTimeout(resolve, 300));
443
+
444
+ // Trigger refresh by incrementing the refresh trigger
445
+ refreshTrigger.value++;
446
+
447
+ // Also call refresh to ensure data is fetched
448
+ await getRoutesRefresh();
449
+
450
+ // Wait for next tick to ensure reactivity completes
451
+ await nextTick();
452
+
453
+ if (dialogAdd.value) {
454
+ dialogAdd.value = false;
455
+ showMessage("Route created successfully!", "success");
456
+ }
457
+
458
+ if (dialogEdit.value) {
459
+ dialogEdit.value = false;
460
+ showMessage("Route updated successfully!", "success");
461
+ }
462
+
463
+ if (dialogPreview.value) dialogPreview.value = false;
464
+
465
+ if (dialogDelete.value) dialogDelete.value = false;
466
+ } catch (error) {
467
+ console.error('Error refreshing routes:', error);
468
+ }
469
+ }
470
+
471
+ function handleError(error: any) {
472
+ const errorMessage =
473
+ error?.data?.message || error?.message || "An error occurred";
474
+ showMessage(errorMessage, "error");
475
+ }
476
+
477
+ function showMessage(msg: string, color: string) {
478
+ message.value = msg;
479
+ messageColor.value = color;
480
+ messageSnackbar.value = true;
481
+ }
482
+
483
+ const selectedRoute = ref<any>({
484
+ _id: "",
485
+ name: "",
486
+ routeName: "",
487
+ checkPointNumber: 5,
488
+ numberOfCheckpoints: 5,
489
+ tolerance: undefined,
490
+ totalTravelTime: undefined,
491
+ days: [],
492
+ repeatDays: "",
493
+ startTimes: [],
494
+ schedules: [],
495
+ checkPoints: [],
496
+ checkpoints: [],
497
+ });
498
+
499
+ function handleRowClick(_: any, data: any) {
500
+ dialogPreview.value = true;
501
+ selectedRoute.value = JSON.parse(JSON.stringify(data.item));
502
+ }
503
+
504
+ async function submitDelete() {
505
+ try {
506
+ await deleteRouteById(selectedRoute.value._id ?? "");
507
+ await getRoutesRefresh();
508
+ dialogDelete.value = false;
509
+ showMessage("Route deleted successfully!", "success");
510
+ } catch (error) {
511
+ console.error("Error deleting route:", error);
512
+ handleError(error);
513
+ }
514
+ }
515
+ </script>
516
+
517
+ <style scoped>
518
+ .nfc-route-table :deep(.v-data-table__th) {
519
+ background-color: rgb(250, 250, 250);
520
+ font-weight: 500;
521
+ white-space: pre-line;
522
+ padding: 16px 12px !important;
523
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12);
524
+ }
525
+
526
+ .nfc-route-table :deep(.v-data-table__td) {
527
+ padding: 16px 12px !important;
528
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
529
+ }
530
+
531
+ .nfc-route-table :deep(tbody tr:hover) {
532
+ background-color: rgba(0, 0, 0, 0.02) !important;
533
+ cursor: pointer;
534
+ }
535
+
536
+ .nfc-route-table :deep(.v-data-table__tr) {
537
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
538
+ }
539
+ </style>