@7365admin1/layer-common 3.2.7 → 3.2.8-staging.201

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 (283) hide show
  1. package/assets/css/primitives.css +1113 -0
  2. package/assets/css/screens.css +1097 -0
  3. package/assets/css/shell.css +258 -0
  4. package/assets/css/tokens.css +236 -0
  5. package/components/AcceptDialog.vue +17 -18
  6. package/components/AccessCard/AvailableStats.vue +24 -16
  7. package/components/AccessCardAddForm.vue +42 -42
  8. package/components/AccessCardAssignToUnitForm.vue +13 -21
  9. package/components/AccessCardDeleteDialog.vue +41 -39
  10. package/components/AccessCardDetailsDialog.vue +125 -79
  11. package/components/AccessCardPreviewDialog.vue +58 -84
  12. package/components/AccessCardQrTagging.vue +60 -63
  13. package/components/AccessCardReplaceForm.vue +27 -23
  14. package/components/AccessManagement.vue +86 -85
  15. package/components/AddEqupmentForm.vue +18 -22
  16. package/components/AddPassKeyToVisitor.vue +95 -73
  17. package/components/AppButton.vue +62 -0
  18. package/components/AppCard.vue +20 -0
  19. package/components/AppDateField.vue +49 -0
  20. package/components/AppField.vue +76 -0
  21. package/components/AppKpiTile.vue +65 -0
  22. package/components/AppSegmented.vue +38 -0
  23. package/components/AppSelect.vue +247 -0
  24. package/components/AreaChecklistHistoryLogs.vue +51 -44
  25. package/components/AreaChecklistHistoryMain.vue +14 -7
  26. package/components/AreaFormDialog.vue +71 -59
  27. package/components/AreaMain.vue +73 -107
  28. package/components/AttachmentsViewer.vue +84 -22
  29. package/components/AttendanceCheckInOutDialog.vue +85 -88
  30. package/components/AttendanceDetailsDialog.vue +57 -63
  31. package/components/AttendanceMain.vue +4 -3
  32. package/components/AttendanceMapSearchDialog.vue +42 -44
  33. package/components/AttendanceSettingsDialog.vue +79 -63
  34. package/components/Avatar/Main.vue +54 -2
  35. package/components/BillingMain.vue +26 -30
  36. package/components/BtnUploadFile.vue +53 -11
  37. package/components/BuildingForm.vue +34 -27
  38. package/components/BuildingManagement/buildings.vue +39 -39
  39. package/components/BuildingManagement/units.vue +26 -42
  40. package/components/BuildingUnitFormAdd.vue +20 -23
  41. package/components/BuildingUnitFormEdit.vue +8 -4
  42. package/components/BulletinBoardForm.vue +19 -24
  43. package/components/BulletinBoardManagement.vue +49 -57
  44. package/components/BulletinBoardView.vue +9 -6
  45. package/components/BulletinExpirationChip.vue +13 -4
  46. package/components/Button/Close.vue +2 -2
  47. package/components/CameraForm.vue +21 -22
  48. package/components/CameraMain.vue +50 -49
  49. package/components/Card/DeleteConfirmation.vue +24 -22
  50. package/components/Card/MemberInfoSummary.vue +28 -3
  51. package/components/Card/Toggle.vue +15 -3
  52. package/components/CardToolbar.vue +37 -0
  53. package/components/Carousel.vue +56 -36
  54. package/components/Chat/Bubbles.vue +43 -14
  55. package/components/Chat/Information.vue +49 -32
  56. package/components/Chat/ListCard.vue +38 -9
  57. package/components/Chat/Message.vue +41 -15
  58. package/components/Chat/Navigation.vue +27 -15
  59. package/components/Chat/SkeletonLoader.vue +9 -2
  60. package/components/ChecklistItemRow.vue +25 -1
  61. package/components/CleaningScheduleMain.vue +44 -49
  62. package/components/ClientDetailForm.vue +81 -56
  63. package/components/ClientMain.vue +92 -82
  64. package/components/ConfirmDialog.vue +14 -8
  65. package/components/Container/Standard.vue +9 -7
  66. package/components/CreateSubsciptionPlan.vue +148 -89
  67. package/components/DashboardEmptyState.vue +48 -3
  68. package/components/DashboardMain.vue +924 -676
  69. package/components/DashboardPanel.vue +84 -21
  70. package/components/DeliveryCompany.vue +34 -20
  71. package/components/Dialog/DeleteConfirmation.vue +20 -21
  72. package/components/Dialog/ReplaceAutofillPrompt.vue +19 -26
  73. package/components/Dialog/ReusablePrompt.vue +30 -29
  74. package/components/Dialog/UpdateMoreAction.vue +62 -59
  75. package/components/DocumentForm.vue +14 -21
  76. package/components/DocumentManagement.vue +162 -108
  77. package/components/DocumentViewer.vue +29 -12
  78. package/components/DrawImage.vue +29 -21
  79. package/components/EntryPass/QrTemplatePreview.vue +27 -16
  80. package/components/EntryPassInformation.vue +40 -10
  81. package/components/EntryPassMain.vue +49 -27
  82. package/components/EquipmentItemMain.vue +84 -97
  83. package/components/EquipmentManagementMain.vue +81 -103
  84. package/components/Facility/BookingSetup.vue +43 -52
  85. package/components/Feedback/Form.vue +26 -12
  86. package/components/FeedbackMain.vue +35 -49
  87. package/components/FileInput.vue +75 -58
  88. package/components/FileInputWithList.vue +59 -12
  89. package/components/FormDialog.vue +60 -21
  90. package/components/HidAccessLogDashboard.vue +512 -490
  91. package/components/HidCameraCaptureDialog.vue +216 -0
  92. package/components/HidEnabledGate.vue +67 -9
  93. package/components/HidIntercomManagement.vue +1322 -653
  94. package/components/HidQrCodeConfiguration.vue +1030 -258
  95. package/components/HidReaderForm.vue +142 -59
  96. package/components/HidReaderManagement.vue +211 -323
  97. package/components/HidServiceSettingsPanel.vue +44 -13
  98. package/components/HidUserEnrollment.vue +1185 -412
  99. package/components/HygieneUpdateMoreAction.vue +44 -44
  100. package/components/IncidentReport/Authorities.vue +30 -18
  101. package/components/IncidentReport/IncidentInformation.vue +10 -10
  102. package/components/IncidentReport/IncidentInformationDownload.vue +3 -4
  103. package/components/IncidentReport/affectedEntities.vue +41 -20
  104. package/components/Input/Date.vue +3 -0
  105. package/components/Input/DatePicker.vue +1 -2
  106. package/components/Input/DateTimePicker.vue +1 -1
  107. package/components/Input/File.vue +55 -10
  108. package/components/Input/FileV2.vue +39 -6
  109. package/components/Input/InputPhoneNumberV2.vue +2 -1
  110. package/components/Input/ListGroupSelection.vue +56 -8
  111. package/components/Input/NRICNumber.vue +1 -0
  112. package/components/Input/NewDate.vue +1 -0
  113. package/components/Input/Number.vue +1 -0
  114. package/components/Input/Password.vue +1 -0
  115. package/components/Input/PhoneNumber.vue +21 -1
  116. package/components/Input/VehicleNumber.vue +1 -0
  117. package/components/InputLabel.vue +2 -2
  118. package/components/InvitationClientForm.vue +21 -19
  119. package/components/InvitationForm.vue +15 -21
  120. package/components/InvitationMain.vue +46 -61
  121. package/components/Layout/Header.vue +263 -36
  122. package/components/Layout/NavigationDrawer.vue +300 -30
  123. package/components/ListItem.vue +33 -3
  124. package/components/LocalPagination.vue +27 -3
  125. package/components/ManageChecklistMain.vue +136 -86
  126. package/components/MemberInformation.vue +32 -16
  127. package/components/MemberMain.vue +113 -93
  128. package/components/MyAttendanceMain.vue +3 -5
  129. package/components/NavigationItem.vue +83 -3
  130. package/components/Nfc/NFCPatrolReportMain.vue +47 -33
  131. package/components/Nfc/NFCPatrolRouteForm.vue +18 -20
  132. package/components/Nfc/NFCPatrolRouteMain.vue +116 -103
  133. package/components/Nfc/NFCPatrolSettings.vue +14 -4
  134. package/components/Nfc/NFCTagForm.vue +22 -8
  135. package/components/Nfc/NFCTagMain.vue +41 -43
  136. package/components/Nfc/PatrolReport/DailyReportTab.vue +8 -1
  137. package/components/Nfc/PatrolReport/MonthlyReportTab.vue +8 -1
  138. package/components/Nfc/PatrolReport/MonthlyReportTable.vue +5 -3
  139. package/components/Nfc/PatrolReport/PatrolActivityTable.vue +26 -6
  140. package/components/Nfc/PatrolReport/PatrolReportTab.vue +8 -0
  141. package/components/Nfc/PatrolReport/PatrolRouteSummary.vue +41 -9
  142. package/components/Nfc/PatrolReport/RemarksDialog.vue +39 -9
  143. package/components/Nfc/PatrolReport/ReportEmptyState.vue +29 -9
  144. package/components/Nfc/PatrolReport/ReportFilters.vue +19 -10
  145. package/components/Nfc/PatrolReport/ReportLocationHeader.vue +32 -6
  146. package/components/Nfc/PatrolReport/SummaryReportTable.vue +28 -6
  147. package/components/NotificationSettings.vue +373 -0
  148. package/components/NumberSettingField.vue +9 -2
  149. package/components/OnlineFormConfigurationForm.vue +725 -237
  150. package/components/OnlineFormFill.vue +213 -106
  151. package/components/OnlineFormRenderPreview.vue +25 -30
  152. package/components/OnlineFormsConfiguration.vue +113 -109
  153. package/components/OrgViewDialog.vue +34 -16
  154. package/components/OvernightParkingAvailability.vue +49 -26
  155. package/components/OvernightParkingManagement.vue +78 -18
  156. package/components/PageHeader.vue +43 -0
  157. package/components/PassInformation.vue +109 -53
  158. package/components/PasswordConfirmation.vue +44 -26
  159. package/components/PeopleForm.vue +41 -20
  160. package/components/PhotoUpload.vue +110 -48
  161. package/components/PlaceholderComponent.vue +35 -19
  162. package/components/PlanActionsMenu.vue +12 -2
  163. package/components/PlanStatusBadge.vue +7 -8
  164. package/components/PlateNumberDisplay.vue +9 -6
  165. package/components/QrTemplate/PrintDialog.vue +66 -43
  166. package/components/RolePermissionFormCreate.vue +104 -79
  167. package/components/RolePermissionFormPreviewUpdate.vue +111 -109
  168. package/components/RolePermissionMain.vue +183 -81
  169. package/components/ScanVisitorQRCode.vue +99 -35
  170. package/components/ScheduleAreaMain.vue +34 -59
  171. package/components/ScheduleTaskForm.vue +61 -42
  172. package/components/ScheduleTaskMain.vue +56 -69
  173. package/components/SearchVehicleNumberUser.vue +39 -37
  174. package/components/ServiceProviderFormCreate.vue +29 -20
  175. package/components/ServiceProviderInvitationPrompt.vue +155 -0
  176. package/components/ServiceProviderMain.vue +601 -432
  177. package/components/Signature.vue +40 -34
  178. package/components/SignaturePad.vue +5 -29
  179. package/components/SiteSettings.vue +41 -11
  180. package/components/SiteSettingsWorkOrder.vue +61 -30
  181. package/components/SlideCardGroup.vue +35 -11
  182. package/components/Snackbar.vue +36 -3
  183. package/components/SpecificAttr.vue +18 -8
  184. package/components/StatusChip.vue +156 -0
  185. package/components/StockCard.vue +17 -12
  186. package/components/SubscriptionPlanTable.vue +207 -140
  187. package/components/SwitchContext.vue +201 -9
  188. package/components/TableHygiene.vue +36 -46
  189. package/components/TableList.vue +10 -10
  190. package/components/TableListSecondary.vue +105 -54
  191. package/components/TableMain.vue +251 -78
  192. package/components/TableV3.vue +61 -70
  193. package/components/TiptapEditor.vue +33 -40
  194. package/components/TiptapEditorQr.vue +5 -2
  195. package/components/Tooltip/Info.vue +69 -24
  196. package/components/UnitMain.vue +40 -60
  197. package/components/UnitPersonCard.vue +42 -13
  198. package/components/VehicleAddSelection.vue +48 -32
  199. package/components/VehicleForm.vue +112 -129
  200. package/components/VehicleManagement.vue +26 -12
  201. package/components/VehicleUpdateMoreAction.vue +59 -46
  202. package/components/VisitorDataFromScannedQRCodeForm.vue +90 -65
  203. package/components/VisitorForm.vue +774 -210
  204. package/components/VisitorFormSelection.vue +40 -37
  205. package/components/VisitorManagement.vue +239 -82
  206. package/components/VisitorPassKeyQRScanner.vue +65 -18
  207. package/components/VisitorSearchResultSummary.vue +60 -16
  208. package/components/VisitorSocketPopUp.vue +22 -14
  209. package/components/VisitorsReportPreview.vue +44 -29
  210. package/components/WorkOrder/Create.vue +26 -17
  211. package/components/WorkOrder/ListView.vue +38 -7
  212. package/components/WorkOrder/Main.vue +62 -59
  213. package/composables/useFeedback.ts +3 -3
  214. package/composables/useHidAmico.ts +269 -0
  215. package/composables/useHidNavigation.ts +2 -9
  216. package/composables/useMember.ts +3 -3
  217. package/composables/useNFCPatrolDailyReport.ts +13 -0
  218. package/composables/useNFCPatrolMonthlyReport.ts +22 -56
  219. package/composables/useNFCPatrolReport.ts +13 -0
  220. package/composables/useNotificationPreference.ts +87 -0
  221. package/composables/useOnlineFormPages.ts +2 -0
  222. package/composables/useRole.ts +22 -0
  223. package/composables/useServiceProvider.ts +3 -3
  224. package/composables/useServiceProviderInvitation.ts +145 -0
  225. package/composables/useSipWebPhone.ts +336 -0
  226. package/composables/useSubscriptionPlan.ts +62 -0
  227. package/composables/useThemePreference.ts +63 -0
  228. package/composables/useVisitor.ts +6 -1
  229. package/composables/useWebUsb.ts +127 -37
  230. package/composables/useWorkOrder.ts +17 -3
  231. package/error.vue +30 -6
  232. package/nuxt.config.ts +36 -0
  233. package/package.json +25 -4
  234. package/pages/[org]/[site]/access-mgmt/administrator/index.vue +2 -2
  235. package/pages/[org]/[site]/access-mgmt/{identity-mapping → hid-cards}/index.vue +2 -2
  236. package/pages/[org]/[site]/access-mgmt/intercom/index.vue +1 -1
  237. package/pages/notification-settings.vue +19 -0
  238. package/pages/payment-method-linked.vue +34 -10
  239. package/pages/require-customer.vue +48 -10
  240. package/pages/require-organization-membership.vue +32 -8
  241. package/pages/unauthorized.vue +29 -4
  242. package/plugins/secure-member.client.ts +21 -56
  243. package/plugins/vuetify.ts +69 -2
  244. package/types/nfc-patrol-report.ts +3 -2
  245. package/types/site.d.ts +71 -0
  246. package/types/subscription.ts +18 -11
  247. package/utils/breadcrumb.test.ts +108 -0
  248. package/utils/breadcrumb.ts +82 -0
  249. package/utils/dashboard.test.ts +118 -0
  250. package/utils/dashboard.ts +53 -0
  251. package/utils/data.test.ts +95 -0
  252. package/utils/data.ts +40 -2
  253. package/utils/hid-discover.test.ts +102 -0
  254. package/utils/list-page.test.ts +60 -0
  255. package/utils/list-page.ts +38 -0
  256. package/utils/materialSymbols.ts +363 -0
  257. package/utils/nav-sections.test.ts +190 -0
  258. package/utils/nav-sections.ts +151 -0
  259. package/utils/nfc-patrol-report.test.ts +130 -0
  260. package/utils/nfc-patrol-report.ts +101 -0
  261. package/utils/role.test.ts +69 -0
  262. package/utils/role.ts +10 -0
  263. package/utils/route-name.test.ts +85 -0
  264. package/utils/route-name.ts +24 -0
  265. package/utils/status.test.ts +110 -0
  266. package/utils/status.ts +135 -0
  267. package/utils/table-card.test.ts +84 -0
  268. package/utils/theme-aa-ledger.ts +148 -0
  269. package/utils/theme.test.ts +485 -7
  270. package/utils/theme.ts +295 -110
  271. package/.changeset/README.md +0 -8
  272. package/.changeset/config.json +0 -11
  273. package/.editorconfig +0 -12
  274. package/.github/workflows/main.yml +0 -17
  275. package/.github/workflows/publish-staging.yml +0 -47
  276. package/.github/workflows/publish.yml +0 -39
  277. package/PUBLISHING.md +0 -269
  278. package/components/HidIdentityMapping.vue +0 -975
  279. package/components/ScheduleTaskAreaFormDialog.vue +0 -144
  280. package/components/ScheduleTaskAreaUpdateMoreAction.vue +0 -109
  281. package/components/ScheduleTastTicketMain.vue +0 -182
  282. package/components/TableWithButton.vue +0 -94
  283. package/test/visitor-socket.test.mjs +0 -36
@@ -10,10 +10,10 @@
10
10
  </v-col>
11
11
  <v-spacer />
12
12
  <v-col v-if="isScheduleClosed" cols="auto" class="d-flex align-center">
13
- <v-chip color="error" variant="tonal" class="text-capitalize">
14
- <v-icon start>mdi-lock</v-icon>
13
+ <StatusChip status="Closed" class="text-capitalize">
14
+ <v-icon size="14">mdi-lock</v-icon>
15
15
  Closed – View Only
16
- </v-chip>
16
+ </StatusChip>
17
17
  </v-col>
18
18
  </v-row>
19
19
  <TableHygiene
@@ -29,16 +29,34 @@
29
29
  :show-header="true"
30
30
  @refresh="getUnitCleanerChecklistRefresh"
31
31
  >
32
+ <!--
33
+ A failed request is not a schedule with no checklist. Without this the
34
+ table drew its neutral "No checklist found" for a 500, which reads as
35
+ "nothing is scheduled here" - a statement the server never made.
36
+ -->
37
+ <template v-if="getUnitCleanerChecklistError" #no-data>
38
+ <DashboardEmptyState error />
39
+ </template>
40
+
32
41
  <!-- Status icon driven by local activeActions state -->
33
42
  <template #item-prepend="{ item, group }">
43
+ <!--
44
+ `success` and `error` ARE this theme's tokens (`utils/theme.ts` maps
45
+ them to `p.ok` / `p.err`), so they stay. `grey-lighten-2` was not -
46
+ it is Vuetify's raw grey, and it drew the idle circle at 1.32:1
47
+ against the card where a non-text indicator needs 3:1. The design's
48
+ de-emphasis token is `--muted`, applied by class because `color`
49
+ takes a theme name, not a custom property.
50
+ -->
34
51
  <v-icon
35
52
  size="20"
53
+ :class="{ 'checklist-icon--idle': !activeActions[getKey(item, group.set)] }"
36
54
  :color="
37
55
  activeActions[getKey(item, group.set)] === 'approve'
38
56
  ? 'success'
39
57
  : activeActions[getKey(item, group.set)] === 'reject'
40
58
  ? 'error'
41
- : 'grey-lighten-2'
59
+ : undefined
42
60
  "
43
61
  >
44
62
  {{
@@ -85,7 +103,7 @@
85
103
  <v-sheet
86
104
  border
87
105
  rounded="lg"
88
- class="d-inline-flex flex-column pa-3 bg-grey-lighten-5"
106
+ class="d-inline-flex flex-column pa-3"
89
107
  style="max-width: 420px"
90
108
  >
91
109
  <div class="d-flex align-center ga-2 mb-2">
@@ -93,9 +111,7 @@
93
111
  <span class="text-caption font-weight-bold">
94
112
  Rejection details
95
113
  </span>
96
- <v-chip size="x-small" color="error" variant="tonal">
97
- Rejected
98
- </v-chip>
114
+ <StatusChip status="Rejected" :dot="false" />
99
115
  </div>
100
116
  <div
101
117
  v-if="item.remarks"
@@ -173,32 +189,36 @@
173
189
  <template #group-header-append="{ group }">
174
190
  <v-row no-gutters align="center" class="ga-2">
175
191
  <v-col v-if="isGroupAnyApproved(group)" cols="auto">
176
- <v-chip
177
- size="x-small"
178
- :color="isGroupComplete(group) ? 'success' : 'warning'"
179
- variant="tonal"
180
- :prepend-icon="
181
- isGroupComplete(group)
182
- ? 'mdi-check-circle-outline'
183
- : 'mdi-progress-clock'
184
- "
192
+ <StatusChip
193
+ :status="isGroupComplete(group) ? 'Completed' : 'Ongoing'"
194
+ :tone="isGroupComplete(group) ? 'ok' : 'warn'"
195
+ :dot="false"
185
196
  class="text-none"
186
197
  >
198
+ <v-icon size="12">
199
+ {{
200
+ isGroupComplete(group)
201
+ ? "mdi-check-circle-outline"
202
+ : "mdi-progress-clock"
203
+ }}
204
+ </v-icon>
187
205
  {{ isGroupComplete(group) ? "Completed" : "Ongoing" }}
188
206
  <template v-if="getGroupCompletedByName(group)">
189
207
  · {{ getGroupCompletedByName(group) }}
190
208
  </template>
191
- </v-chip>
209
+ </StatusChip>
192
210
  </v-col>
193
211
  <v-col
194
212
  v-if="group.attachments && group.attachments.length > 0"
195
213
  cols="auto"
196
214
  >
215
+ <!-- `variant="tonal"` was Vuetify's own tinted slab in the row -
216
+ the same off-design control `EquipmentManagementMain` had.
217
+ The design's ghost button. -->
197
218
  <v-btn
198
- size="x-small"
199
- variant="tonal"
200
- color="primary"
201
- class="text-none"
219
+ size="small"
220
+ variant="outlined"
221
+ class="screen-btn-ghost"
202
222
  prepend-icon="mdi-paperclip"
203
223
  @click.stop="openAttachmentDialog(group.set, group.attachments)"
204
224
  >
@@ -213,9 +233,16 @@
213
233
  </v-col>
214
234
  </v-row>
215
235
 
236
+ <!--
237
+ Was a bare `v-card` (Vuetify's own `surface`, a shade off the design's card)
238
+ with a `text-h5` title, and a `v-card-actions` footer whose Cancel sat on
239
+ `color="grey"` - not a token, so it drew the same grey on both themes and
240
+ the two buttons were right-aligned rather than the design's two equal
241
+ halves. It is the shared `.screen-modal` shape now.
242
+ -->
216
243
  <v-dialog v-model="showCompletionModal" max-width="600" persistent>
217
- <v-card>
218
- <v-card-title class="text-h5 pa-4">
244
+ <v-card class="screen-modal">
245
+ <v-card-title>
219
246
  {{
220
247
  modalData.currentSet !== undefined
221
248
  ? `Set ${modalData.currentSet} Completed`
@@ -225,15 +252,17 @@
225
252
 
226
253
  <v-divider />
227
254
 
228
- <v-card-text class="pa-4">
255
+ <v-card-text class="screen-modal__body pa-4">
229
256
  <v-row>
230
257
  <v-col cols="12">
231
258
  <InputLabel title="Remarks" :required="false" class="mb-2" />
259
+ <!-- `.filter-field` is the design's field on a `v-textarea`: the
260
+ 10px corner and 13.5px type, without taking the binding away. -->
232
261
  <v-textarea
233
262
  v-model="modalData.remark"
263
+ class="filter-field"
234
264
  placeholder="Enter your remarks here"
235
265
  rows="4"
236
- variant="outlined"
237
266
  density="comfortable"
238
267
  hide-details
239
268
  />
@@ -252,38 +281,47 @@
252
281
  </v-row>
253
282
  </v-card-text>
254
283
 
255
- <v-divider />
256
-
257
- <v-card-actions class="pa-4">
258
- <v-spacer />
259
- <v-btn color="grey" variant="text" @click="closeModal"> Cancel </v-btn>
284
+ <div class="screen-modal__footer">
260
285
  <v-btn
261
- color="primary"
286
+ class="screen-btn-ghost"
287
+ variant="outlined"
288
+ @click="closeModal"
289
+ >
290
+ Cancel
291
+ </v-btn>
292
+ <v-btn
293
+ class="screen-btn-primary"
262
294
  variant="flat"
263
295
  @click="submitModal"
264
296
  :disabled="!isModalValid"
265
297
  >
266
298
  Submit
267
299
  </v-btn>
268
- </v-card-actions>
300
+ </div>
269
301
  </v-card>
270
302
  </v-dialog>
271
303
 
304
+ <!--
305
+ Same shape, and this one carried BOTH of the defects that repeated across
306
+ this claim: a `v-toolbar` as the footer bar (Vuetify's `surface`, a grey
307
+ slab that stays grey on dark) and `color="black"` on the confirm button -
308
+ not a token, so a black slab painted on the dark theme too.
309
+ -->
272
310
  <v-dialog v-model="showRejectModal" max-width="600" persistent>
273
- <v-card>
274
- <v-card-title class="text-h5 pa-4">Reject Checklist Item</v-card-title>
311
+ <v-card class="screen-modal">
312
+ <v-card-title>Reject Checklist Item</v-card-title>
275
313
 
276
314
  <v-divider />
277
315
 
278
- <v-card-text class="pa-4">
316
+ <v-card-text class="screen-modal__body pa-4">
279
317
  <v-row>
280
318
  <v-col cols="12">
281
319
  <InputLabel title="Remarks" :required="true" class="mb-2" />
282
320
  <v-textarea
283
321
  v-model="rejectModal.remarks"
322
+ class="filter-field"
284
323
  placeholder="Enter remarks"
285
324
  rows="4"
286
- variant="outlined"
287
325
  density="comfortable"
288
326
  hide-details
289
327
  />
@@ -302,61 +340,50 @@
302
340
  </v-row>
303
341
  </v-card-text>
304
342
 
305
- <v-divider />
306
-
307
- <v-toolbar class="pa-0" density="compact">
308
- <v-row no-gutters>
309
- <v-col cols="6" class="pa-0">
310
- <v-btn
311
- block
312
- variant="text"
313
- class="text-none"
314
- size="large"
315
- height="48"
316
- :disabled="rejectModal.submitting"
317
- @click="closeRejectDialog"
318
- >
319
- Cancel
320
- </v-btn>
321
- </v-col>
322
-
323
- <v-col cols="6" class="pa-0">
324
- <v-btn
325
- block
326
- variant="flat"
327
- color="black"
328
- class="text-none font-weight-bold rounded-0"
329
- height="48"
330
- :loading="rejectModal.submitting"
331
- :disabled="!isRejectModalValid || rejectModal.submitting"
332
- @click="submitRejectDialog"
333
- >
334
- Confirm
335
- </v-btn>
336
- </v-col>
337
- </v-row>
338
- </v-toolbar>
343
+ <div class="screen-modal__footer">
344
+ <v-btn
345
+ class="screen-btn-ghost"
346
+ variant="outlined"
347
+ :disabled="rejectModal.submitting"
348
+ @click="closeRejectDialog"
349
+ >
350
+ Cancel
351
+ </v-btn>
352
+ <v-btn
353
+ class="screen-btn-primary"
354
+ variant="flat"
355
+ :loading="rejectModal.submitting"
356
+ :disabled="!isRejectModalValid || rejectModal.submitting"
357
+ @click="submitRejectDialog"
358
+ >
359
+ Confirm
360
+ </v-btn>
361
+ </div>
339
362
  </v-card>
340
363
  </v-dialog>
341
364
 
365
+ <!--
366
+ The design's modal close control is the borderless 32px square
367
+ `.screen-modal__close`, not the bordered toolbar icon button. The title was
368
+ a hand-set `text-h6 font-weight-bold`; `.screen-modal .v-card-title` is the
369
+ design's card-title size and weight, so the local pair goes.
370
+ -->
342
371
  <v-dialog v-model="showAttachmentDialog" max-width="700" scrollable>
343
- <v-card>
344
- <v-card-title class="d-flex align-center pa-4">
345
- <span class="text-h6 font-weight-bold">
346
- Set {{ attachmentDialogSetNum }} — Attachments
347
- </span>
372
+ <v-card class="screen-modal">
373
+ <v-card-title class="d-flex align-center">
374
+ <span>Set {{ attachmentDialogSetNum }} — Attachments</span>
348
375
  <v-spacer />
349
376
  <v-btn
350
377
  icon="mdi-close"
351
378
  variant="text"
352
- size="small"
379
+ class="screen-modal__close"
353
380
  @click="showAttachmentDialog = false"
354
381
  />
355
382
  </v-card-title>
356
383
 
357
384
  <v-divider />
358
385
 
359
- <v-card-text class="pa-4">
386
+ <v-card-text class="screen-modal__body pa-4">
360
387
  <v-row>
361
388
  <v-col
362
389
  v-for="(id, index) in attachmentDialogIds"
@@ -404,11 +431,16 @@
404
431
  </v-dialog>
405
432
 
406
433
  <v-dialog v-model="showLightbox" max-width="900">
407
- <v-card>
434
+ <v-card class="screen-modal">
408
435
  <v-card-actions class="pa-2 justify-end">
409
- <v-btn icon="mdi-close" variant="text" @click="showLightbox = false" />
436
+ <v-btn
437
+ icon="mdi-close"
438
+ variant="text"
439
+ class="screen-modal__close"
440
+ @click="showLightbox = false"
441
+ />
410
442
  </v-card-actions>
411
- <v-card-text class="pa-2 pt-0">
443
+ <v-card-text class="screen-modal__body pa-2 pt-0">
412
444
  <v-img :src="lightboxSrc" contain max-height="80vh" />
413
445
  </v-card-text>
414
446
  </v-card>
@@ -418,6 +450,7 @@
418
450
  </template>
419
451
 
420
452
  <script setup lang="ts">
453
+ import { readListPage } from "../utils/list-page";
421
454
  import useCleaningSchedules from "../composables/useCleaningSchedules";
422
455
  import useCustomerSite from "../composables/useCustomerSite";
423
456
  import useFile from "../composables/useFile";
@@ -628,6 +661,7 @@ const {
628
661
  data: getUnitCleanerChecklistReq,
629
662
  refresh: getUnitCleanerChecklistRefresh,
630
663
  pending: loading,
664
+ error: getUnitCleanerChecklistError,
631
665
  } = await useLazyAsyncData(
632
666
  `get-all-unit-cleaner-checklist`,
633
667
  () =>
@@ -652,13 +686,20 @@ watchEffect(() => {
652
686
  }
653
687
  });
654
688
 
689
+ // The page totals are the server's count of the WHOLE list, read through the
690
+ // one helper that knows how a paginated reply is shaped - never re-derived
691
+ // from the rows on this page. Applied unconditionally so that when a request
692
+ // fails the reply goes null and the header falls back to the placeholder,
693
+ // instead of leaving the previous page's total on screen as if it still held.
694
+ // `page` still only moves when the server states it, so a failed request does
695
+ // not knock the reader back to page 1.
655
696
  watchEffect(() => {
656
- if (getUnitCleanerChecklistReq.value) {
657
- items.value = getUnitCleanerChecklistReq.value.items;
697
+ const listPage = readListPage<TChecklistSet>(getUnitCleanerChecklistReq.value);
698
+ items.value = listPage.items;
699
+ if (getUnitCleanerChecklistReq.value?.page)
658
700
  page.value = getUnitCleanerChecklistReq.value.page;
659
- pages.value = getUnitCleanerChecklistReq.value.pages;
660
- pageRange.value = getUnitCleanerChecklistReq.value.pageRange;
661
- }
701
+ pages.value = listPage.pages;
702
+ pageRange.value = listPage.pageRange;
662
703
  });
663
704
 
664
705
  watchEffect(() => {
@@ -1006,3 +1047,12 @@ async function _updateUnitChecklist({
1006
1047
  }
1007
1048
  }
1008
1049
  </script>
1050
+
1051
+ <style scoped>
1052
+ /* The idle checklist circle. `--muted` is the design's de-emphasis token and
1053
+ clears the 3:1 bar a non-text indicator needs; Vuetify's `grey-lighten-2`
1054
+ read 1.32:1. */
1055
+ .checklist-icon--idle {
1056
+ color: var(--muted);
1057
+ }
1058
+ </style>
@@ -1,9 +1,12 @@
1
1
  <template>
2
2
  <v-row no-gutters class="w-100">
3
- <v-card class="w-100">
4
- <v-card-text>
5
- <v-btn block color="primary-button" :height="40" text="Scan QR Code" class="text-capitalize"
6
- prepend-icon="mdi-qrcode" @click="handleScanQRPass" />
3
+ <AppCard class="w-100 pa-4">
4
+ <!-- GHOST, not primary: the handoff names "Scan QR Code" in its
5
+ ghost/secondary list, alongside Bulk Upload, Download Report and
6
+ Export. Stays a `v-btn` because `block` has no AppButton
7
+ equivalent, so the design's button is applied as a class. -->
8
+ <v-btn block :height="38" text="Scan QR Code" variant="outlined"
9
+ class="screen-btn-ghost" prepend-icon="mdi-qrcode" @click="handleScanQRPass" />
7
10
  <v-form ref="formRef" v-model="validForm" :disabled="processing" @click="errorScanPassMessage = ''">
8
11
  <v-row no-gutters class="pt-5 ga-2">
9
12
  <v-col cols="12">
@@ -75,27 +78,32 @@
75
78
  v-model:cards="memberPassCards" :settings="props.settings" :loading="props.settingsLoading"
76
79
  :site-id="props.site" :unit-id="props.unitId" :visitor-type="props.type"
77
80
  :hid-qr-code-enabled="props.hidQrCodeEnabled" :hid-qr-printer-configured="props.hidQrPrinterConfigured"
81
+ :hid-reader-name="props.hidReaderName" :hid-portal-name="props.hidPortalName"
78
82
  :excluded-card-ids="props.selectedNfcCards.map((c) => c._id)" />
79
83
  </v-col>
80
84
 
81
85
  <v-row class="pt-3" justify="space-between">
82
86
  <v-col cols="6">
83
- <v-btn text="Add Member" :disabled="!validForm" prepend-icon="mdi-plus" color="primary-button"
84
- class="text-capitalize" @click="handleAddMember" />
87
+ <!-- The primitive rather than a class on a v-btn: these two
88
+ need nothing Vuetify owns, and AppButton is the only way
89
+ they draw at the handoff's 40px / 38px. -->
90
+ <AppButton icon="mdi-plus" :disabled="!validForm" @click="handleAddMember">
91
+ Add Member
92
+ </AppButton>
85
93
  </v-col>
86
94
  <v-col cols="6" align="end">
87
- <v-btn text="Clear Form" prepend-icon="mdi-refresh" color="primary-button" class="text-capitalize"
88
- @click.stop="handleClearForm" />
95
+ <AppButton variant="ghost" icon="mdi-refresh" @click.stop="handleClearForm">
96
+ Clear Form
97
+ </AppButton>
89
98
  </v-col>
90
99
  </v-row>
91
100
  </v-row>
92
101
  </v-form>
93
- </v-card-text>
94
- </v-card>
102
+ </AppCard>
95
103
  <visitor-pass-key-q-r-scanner :dialog="dialog.scanQRCode" v-model:scannedValue="scannedPassValue"
96
104
  @close-dialog="dialog.scanQRCode = false" />
97
105
  <v-dialog v-model="dialog.memberAutofillOptions" max-width="430">
98
- <v-card v-if="memberSelectedSearchResult" class="nric-options-card">
106
+ <v-card v-if="memberSelectedSearchResult" class="nric-options-card screen-modal">
99
107
  <v-card-actions class="justify-end pa-1">
100
108
  <v-btn icon="mdi-close" variant="text" size="small" @click="memberCloseAutofillOptions" />
101
109
  </v-card-actions>
@@ -126,10 +134,10 @@
126
134
  </v-card-text>
127
135
 
128
136
  <v-card-actions class="justify-end px-4 pb-4">
129
- <v-btn variant="text" class="text-none" size="small" @click="memberCloseAutofillOptions">
137
+ <v-btn variant="outlined" class="screen-btn-ghost" size="small" @click="memberCloseAutofillOptions">
130
138
  Cancel
131
139
  </v-btn>
132
- <v-btn color="primary-button" variant="flat" class="text-none px-5" size="small"
140
+ <v-btn variant="flat" class="screen-btn-primary px-5" size="small"
133
141
  @click="memberConfirmAutofillOptions">
134
142
  Select
135
143
  </v-btn>
@@ -192,6 +200,14 @@ const props = defineProps({
192
200
  type: Boolean,
193
201
  default: false,
194
202
  },
203
+ hidReaderName: {
204
+ type: String,
205
+ default: "",
206
+ },
207
+ hidPortalName: {
208
+ type: String,
209
+ default: "",
210
+ },
195
211
  selectedNfcCards: {
196
212
  type: Array as PropType<{ _id: string; cardNo: string }[]>,
197
213
  default: () => [],
@@ -617,13 +633,13 @@ function handleRemoveMember(index: number) {
617
633
  }
618
634
 
619
635
  .nric-options-title {
620
- color: #06253b;
636
+ color: var(--text);
621
637
  font-size: 1.45rem;
622
638
  line-height: 1.2;
623
639
  }
624
640
 
625
641
  .nric-options-section-title {
626
- color: #06253b;
642
+ color: var(--text);
627
643
  font-size: 1.05rem;
628
644
  line-height: 1.25;
629
645
  }
@@ -631,7 +647,7 @@ function handleRemoveMember(index: number) {
631
647
  .nric-selected-person {
632
648
  border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
633
649
  border-radius: 12px;
634
- color: #06253b;
650
+ color: var(--text);
635
651
  font-size: 0.95rem;
636
652
  min-height: 52px;
637
653
  padding: 10px 14px;