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

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 +241 -79
  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
@@ -1,65 +1,65 @@
1
1
  <template>
2
- <v-row no-gutters>
3
- <v-col cols="12" class="mb-2">
4
- <v-row no-gutters>
5
- <v-btn
6
- v-if="props.seatManagement !== 'index'"
7
- class="text-none"
8
- rounded="pill"
9
- variant="tonal"
2
+ <div>
3
+ <!--
4
+ THE DESIGN'S PAGE SCAFFOLD.
5
+
6
+ The handoff opens Members with a 22px title row and puts the tabs INSIDE
7
+ the card's first row, with the pagination on the far end of that same
8
+ line. Before this the screen had no title at all - the page name existed
9
+ only in the rail and the browser tab - and the tabs sat in a toolbar
10
+ extension, i.e. a second stacked bar below a mostly empty one.
11
+
12
+ Nothing here changes what the screen does: the same two tabs route the
13
+ same way, the same refresh and pager call the same `getAll()`, the same
14
+ `headers` prop drives the same columns, and the same menu carries the
15
+ same four actions behind the same permission conditions.
16
+ -->
17
+ <PageHeader :title="props.title">
18
+ <template v-if="props.seatManagement !== 'index'" #actions>
19
+ <AppButton
10
20
  :to="{
11
21
  name: props.seatManagement,
12
22
  params: { organization: props.orgId },
13
23
  }"
14
- size="large"
15
24
  >
16
25
  Manage seats
17
- </v-btn>
18
- </v-row>
19
- </v-col>
20
-
21
- <v-col cols="12">
22
- <v-card width="100%" variant="outlined" border="thin" rounded="lg">
23
- <v-toolbar density="compact" color="grey-lighten-4">
24
- <template #prepend>
25
- <v-btn fab icon density="comfortable" @click="getAll()">
26
- <v-icon>mdi-refresh</v-icon>
27
- </v-btn>
28
- </template>
29
-
30
- <template #append>
31
- <v-row no-gutters justify="end" align="center">
32
- <span class="mr-2 text-caption text-font gray">
33
- {{ pageRange }}
34
- </span>
35
- <local-pagination
36
- v-model="page"
37
- :length="pages"
38
- @update:value="getAll()"
39
- />
40
- </v-row>
41
- </template>
42
-
43
- <template #extension>
44
- <v-tabs
45
- v-model="selectedStatus"
46
- color="primary"
47
- :height="40"
48
- @update:model-value="toRoute"
49
- class="w-100"
50
- >
51
- <v-tab
52
- v-for="(tab, i) in tabOptions"
53
- :value="tab.status"
54
- :key="i"
55
- class="text-capitalize"
56
- >
57
- {{ tab.name }}
58
- </v-tab>
59
- </v-tabs>
60
- </template>
61
- </v-toolbar>
62
-
26
+ </AppButton>
27
+ </template>
28
+ </PageHeader>
29
+
30
+ <AppCard class="table-card">
31
+ <CardToolbar :count="pageRange">
32
+ <template #tabs>
33
+ <button
34
+ v-for="(tab, i) in tabOptions"
35
+ :key="i"
36
+ type="button"
37
+ role="tab"
38
+ class="app-tab"
39
+ :class="{ 'app-tab--active': selectedStatus === tab.status }"
40
+ :aria-selected="selectedStatus === tab.status"
41
+ @click="toRoute(tab.status)"
42
+ >
43
+ {{ tab.name }}
44
+ </button>
45
+ </template>
46
+
47
+ <template #right>
48
+ <AppButton
49
+ variant="icon"
50
+ icon="mdi-refresh"
51
+ aria-label="Refresh"
52
+ @click="getAll()"
53
+ />
54
+ <local-pagination
55
+ v-model="page"
56
+ :length="pages"
57
+ @update:value="getAll()"
58
+ />
59
+ </template>
60
+ </CardToolbar>
61
+
62
+ <div class="app-table-scroll">
63
63
  <v-data-table
64
64
  :headers="props.headers"
65
65
  :items="items"
@@ -73,6 +73,13 @@
73
73
  <template #item.nature="{ item }">
74
74
  {{ replaceMatch(item.nature, "_", " ") }}
75
75
  </template>
76
+ <!-- The role is a soft pill in the design, not a plain word. Same
77
+ text, same column, same source field. -->
78
+ <template #item.roleName="{ item }">
79
+ <StatusChip v-if="item.roleName" :dot="false" pill tone="info">
80
+ {{ item.roleName }}
81
+ </StatusChip>
82
+ </template>
76
83
  <template #item.dateInvited="{ item }">
77
84
  {{ formatDateInvited(item.dateInvited) }}
78
85
  </template>
@@ -89,8 +96,13 @@
89
96
  offset-y
90
97
  width="150"
91
98
  >
92
- <template v-slot:activator="{ props }">
93
- <v-icon v-bind="props">mdi-dots-vertical</v-icon>
99
+ <template v-slot:activator="{ props: menuProps }">
100
+ <AppButton
101
+ v-bind="menuProps"
102
+ variant="row"
103
+ icon="mdi-dots-vertical"
104
+ aria-label="Member actions"
105
+ />
94
106
  </template>
95
107
  <v-list>
96
108
  <v-list-item
@@ -128,8 +140,9 @@
128
140
  </v-menu>
129
141
  </template>
130
142
  </v-data-table>
131
- </v-card>
132
- </v-col>
143
+ </div>
144
+ </AppCard>
145
+
133
146
  <ConfirmDialog
134
147
  v-model="confirmDialog"
135
148
  :loading="updateLoading"
@@ -171,13 +184,20 @@
171
184
 
172
185
  <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
173
186
 
174
- <v-dialog v-model="assignRoleDialog" max-width="400px">
175
- <v-card>
176
- <v-card-title class="text-h5">Assign Role</v-card-title>
177
- <v-card-text>
178
- <v-form v-model="memberRoleForm" @submit.prevent="updateMemberRole()">
187
+ <!--
188
+ Was a `text-h5` title, an untokenised select, and two block buttons - the
189
+ submit one on `color="black"`, not a token, so it drew a light-theme fill
190
+ on the dark theme. The shared `.screen-modal` shape now. The footer stays
191
+ INSIDE the `v-form` because Submit is a `type="submit"` and moving it out
192
+ would break the form's own submit.
193
+ -->
194
+ <v-dialog v-model="assignRoleDialog" max-width="520">
195
+ <v-card class="screen-modal">
196
+ <v-card-title>Assign Role</v-card-title>
197
+ <v-form v-model="memberRoleForm" @submit.prevent="updateMemberRole()">
198
+ <v-card-text class="screen-modal__body">
179
199
  <v-row no-gutters>
180
- <v-col cols="12" class="mb-2">
200
+ <v-col cols="12">
181
201
  <v-row no-gutters>
182
202
  <InputLabel class="text-capitalize" title="Name" required />
183
203
  <v-col cols="12">
@@ -194,6 +214,7 @@
194
214
  : ''
195
215
  "
196
216
  persistent-hint
217
+ class="filter-field"
197
218
  ></v-select>
198
219
  </v-col>
199
220
 
@@ -202,41 +223,40 @@
202
223
  </v-col>
203
224
  </v-row>
204
225
  </v-col>
205
-
206
- <v-col cols="12">
207
- <v-row>
208
- <v-col cols="6">
209
- <v-btn
210
- block
211
- variant="text"
212
- @click="setMember({ mode: 'assign-role' })"
213
- >
214
- Cancel
215
- </v-btn>
216
- </v-col>
217
- <v-col cols="6">
218
- <v-btn
219
- block
220
- variant="flat"
221
- color="black"
222
- :disabled="!memberRoleForm"
223
- type="submit"
224
- >
225
- Submit
226
- </v-btn>
227
- </v-col>
228
- </v-row>
229
- </v-col>
230
226
  </v-row>
231
- </v-form>
232
- </v-card-text>
227
+ </v-card-text>
228
+
229
+ <div class="screen-modal__footer">
230
+ <v-btn
231
+ class="screen-btn-ghost"
232
+ variant="outlined"
233
+ @click="setMember({ mode: 'assign-role' })"
234
+ >
235
+ Cancel
236
+ </v-btn>
237
+ <v-btn
238
+ class="screen-btn-primary"
239
+ variant="flat"
240
+ :disabled="!memberRoleForm"
241
+ type="submit"
242
+ >
243
+ Submit
244
+ </v-btn>
245
+ </div>
246
+ </v-form>
233
247
  </v-card>
234
248
  </v-dialog>
235
- </v-row>
249
+ </div>
236
250
  </template>
237
251
 
238
252
  <script setup lang="ts">
239
253
  const props = defineProps({
254
+ /** The design's page title. Every app that mounts this screen calls it
255
+ Members; a caller that names it otherwise passes its own. */
256
+ title: {
257
+ type: String,
258
+ default: "Members",
259
+ },
240
260
  orgId: {
241
261
  type: String,
242
262
  default: "",
@@ -17,10 +17,8 @@
17
17
  <v-row no-gutters align="center" class="w-100">
18
18
  <v-col cols="auto" v-if="canCheckInOut">
19
19
  <v-btn
20
- class="text-none"
21
- rounded="pill"
22
- variant="tonal"
23
- size="large"
20
+ class="text-none screen-btn-primary"
21
+ variant="flat"
24
22
  @click="onCreateItem"
25
23
  >
26
24
  {{ hasCheckedInToday ? "Check Out" : "Check In" }}
@@ -28,7 +26,7 @@
28
26
  </v-col>
29
27
  <v-spacer />
30
28
 
31
- <v-col cols="auto">
29
+ <v-col cols="auto" class="filter-field">
32
30
  <v-text-field
33
31
  v-model="searchInput"
34
32
  density="compact"
@@ -11,7 +11,7 @@
11
11
  v-bind="groupProps"
12
12
  :prepend-icon="icon"
13
13
  color="primary"
14
- class="text-subtitle-2"
14
+ class="nav-item"
15
15
  @click.stop="onParentClick"
16
16
  >
17
17
  {{ title }}
@@ -33,7 +33,7 @@
33
33
  :prepend-icon="icon"
34
34
  :to="routeTo"
35
35
  color="primary"
36
- class="text-subtitle-2"
36
+ class="nav-item"
37
37
  >
38
38
  {{ title }}
39
39
  </v-list-item>
@@ -43,7 +43,7 @@
43
43
  :prepend-icon="icon"
44
44
  :href="props.link"
45
45
  color="primary"
46
- class="text-subtitle-2"
46
+ class="nav-item"
47
47
  >
48
48
  {{ title }}
49
49
  </v-list-item>
@@ -97,3 +97,83 @@ const routeTo = computed(() => {
97
97
  return null;
98
98
  });
99
99
  </script>
100
+
101
+ <style scoped>
102
+ /**
103
+ * The sidebar menu row, taken literally from the handoff's `<aside>` — line 56
104
+ * of `iService365 Redesign.dc.html` for the row and line 57 for its icon:
105
+ *
106
+ * padding:8px 12px; border-radius:10px; font-size:13px;
107
+ * font-weight: 800 when active else 600;
108
+ * color: var(--accent-text) when active else var(--text2);
109
+ * icon: font-size:19px; width:20px; color: var(--accent-text)/var(--muted);
110
+ *
111
+ * What this replaced was `text-subtitle-2` — Vuetify's own type scale, 14px/500
112
+ * with 0.1px tracking — and no inactive colour at all, so an unselected item
113
+ * was full-strength body ink and read exactly as loud as the page you are on.
114
+ *
115
+ * STATED HERE RATHER THAN ONLY IN THE DRAWER because five of this component's
116
+ * six call sites are `layouts/*` in the ORG app, outside `.brand-drawer`.
117
+ * `LayoutNavigationDrawer` already states the same shape for the rows it
118
+ * contains; the values below are deliberately IDENTICAL to that block, so the
119
+ * specificity tie between them cannot change what is drawn.
120
+ *
121
+ * `margin: 1px 10px` from the handoff is NOT set here: the drawer insets its
122
+ * own list (`.v-list { padding: 0 8px 12px }`), and a margin as well would
123
+ * double the inset in the ten apps that do use the drawer.
124
+ */
125
+ .nav-item {
126
+ min-height: 38px;
127
+ padding-top: 8px;
128
+ padding-bottom: 8px;
129
+ padding-inline: 12px;
130
+ /* `!important` is not carelessness: Vuetify puts the `rounded-0` UTILITY on
131
+ the item, and utilities are themselves `!important`. Measured without it,
132
+ this row drew `border-radius: 0px`. */
133
+ border-radius: var(--r-inner) !important;
134
+ font-family: var(--font-sans);
135
+ font-size: var(--fs-nav);
136
+ font-weight: var(--fw-cell);
137
+ letter-spacing: 0;
138
+ color: var(--text2);
139
+ }
140
+
141
+ .nav-item.v-list-item--active {
142
+ font-weight: var(--fw-section-label);
143
+ }
144
+
145
+ /**
146
+ * The active row's INK is not set here on purpose. `color="primary"` puts
147
+ * Vuetify's `text-primary` on the item, that utility is `!important`, and
148
+ * `primary` is mapped to `--accent-text` — which is the colour the handoff
149
+ * names for an active row. So the rule above wins for an inactive row and
150
+ * loses, correctly, for an active one.
151
+ */
152
+ .nav-item :deep(.v-list-item__prepend > .v-icon) {
153
+ font-size: 19px;
154
+ width: 20px;
155
+ text-align: center;
156
+ opacity: 1;
157
+ }
158
+
159
+ /* Muted only while inactive — an explicit colour on the icon would also
160
+ out-rank the inherited `--accent-text` on the row you are actually on. */
161
+ .nav-item:not(.v-list-item--active) :deep(.v-list-item__prepend > .v-icon) {
162
+ color: var(--muted);
163
+ }
164
+
165
+ /**
166
+ * The handoff's 10px between icon and label. Vuetify holds that distance in a
167
+ * spacer element, so a margin on the icon leaves it where it was.
168
+ *
169
+ * The selector is Vuetify's own shape ON PURPOSE. Vuetify sets the gap with
170
+ * `.v-list-item__prepend > .v-icon ~ .v-list-item__spacer { width: 32px }` —
171
+ * three classes. A scoped `.nav-item :deep(.v-list-item__spacer)` is also
172
+ * three (the scope attribute counts), so it TIES and loses on source order.
173
+ * Measured: the gap stayed at Vuetify's 32px. Matching the shape makes it four
174
+ * and it wins on specificity rather than on load order.
175
+ */
176
+ .nav-item :deep(.v-list-item__prepend > .v-icon ~ .v-list-item__spacer) {
177
+ width: 10px;
178
+ }
179
+ </style>
@@ -1,39 +1,46 @@
1
1
  <template>
2
- <v-row no-gutters class="border-thin pa-6 rounded-lg">
2
+ <v-row no-gutters>
3
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
- variant="text"
8
- prepend-icon="mdi-chevron-left"
9
- class="text-none"
10
- @click="goBack"
11
- >
4
+ <!--
5
+ The screen had no page name at all - it opened on a bare back button.
6
+ The design opens every screen with its name; the back link keeps its
7
+ own `router.back()` and moves onto that row as the ghost action.
8
+ -->
9
+ <PageHeader title="Patrol Report">
10
+ <template #actions>
11
+ <AppButton variant="ghost" icon="mdi-chevron-left" @click="goBack">
12
12
  Patrol Report Log
13
- </v-btn>
14
- </v-col>
15
- </v-row>
16
-
17
- <v-tabs
18
- v-model="activeTab"
19
- class="mb-6"
20
- bg-color="transparent"
21
- grow
22
- >
23
- <v-tab value="patrol" class="text-none border-thin">
24
- Patrol Report
25
- </v-tab>
26
-
27
- <v-tab value="daily" class="text-none border-thin">
28
- Daily Report
29
- </v-tab>
30
-
31
- <v-tab value="monthly" class="text-none border-thin">
32
- Monthly Report
33
- </v-tab>
34
- </v-tabs>
35
-
36
- <v-window v-model="activeTab" class="pt-4">
13
+ </AppButton>
14
+ </template>
15
+ </PageHeader>
16
+ </v-col>
17
+
18
+ <v-col cols="12">
19
+ <!--
20
+ The three report tabs were a `grow` `v-tabs` strip floating above the
21
+ content with its own `border-thin` boxes. The design makes the tabs the
22
+ card's own first row, so they become the ONE `CardToolbar`'s tabs. Same
23
+ `activeTab` model, same three values, same `v-window`.
24
+ -->
25
+ <AppCard>
26
+ <CardToolbar>
27
+ <template #tabs>
28
+ <button
29
+ v-for="tab in reportTabs"
30
+ :key="tab.value"
31
+ type="button"
32
+ role="tab"
33
+ class="app-tab"
34
+ :class="{ 'app-tab--active': activeTab === tab.value }"
35
+ :aria-selected="activeTab === tab.value"
36
+ @click="activeTab = tab.value"
37
+ >
38
+ {{ tab.label }}
39
+ </button>
40
+ </template>
41
+ </CardToolbar>
42
+
43
+ <v-window v-model="activeTab" class="pt-4 px-6 pb-6">
37
44
  <v-window-item value="patrol">
38
45
  <div v-if="activeTab === 'patrol'">
39
46
  <PatrolReportTab
@@ -73,6 +80,7 @@
73
80
  </div>
74
81
  </v-window-item>
75
82
  </v-window>
83
+ </AppCard>
76
84
  </v-col>
77
85
  </v-row>
78
86
  </template>
@@ -103,6 +111,12 @@ const router = useRouter();
103
111
 
104
112
  const activeTab = ref<NFCPatrolReportTab>("patrol");
105
113
 
114
+ const reportTabs: Array<{ value: NFCPatrolReportTab; label: string }> = [
115
+ { value: "patrol", label: "Patrol Report" },
116
+ { value: "daily", label: "Daily Report" },
117
+ { value: "monthly", label: "Monthly Report" },
118
+ ];
119
+
106
120
  const { filters, options, fetchOptions } =
107
121
  useNFCPatrolReportFilters(props.site);
108
122
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <v-card width="100%" max-width="800">
3
- <v-toolbar color="white" elevation="0">
3
+ <v-toolbar class="screen-dialog-bar" elevation="0">
4
4
  <v-row no-gutters class="fill-height px-6" align="center">
5
5
  <span class="font-weight-bold text-h5">
6
6
  {{ title }}
@@ -15,8 +15,8 @@
15
15
  <v-row no-gutters>
16
16
  <!-- Route Name -->
17
17
  <v-col cols="12" class="mb-4">
18
- <label class="text-caption text-grey-darken-1 mb-1 d-block">
19
- Route Name <span class="text-red">*</span>
18
+ <label class="text-caption screen-hint mb-1 d-block">
19
+ Route Name <span class="text-error">*</span>
20
20
  </label>
21
21
  <v-text-field
22
22
  v-model="form.name"
@@ -30,8 +30,8 @@
30
30
 
31
31
  <!-- Checkpoints, Tolerance, Repeat Every -->
32
32
  <v-col cols="12" md="4" class="mb-4 pr-md-2">
33
- <label class="text-caption text-grey-darken-1 mb-1 d-block">
34
- Checkpoints <span class="text-red">*</span>
33
+ <label class="text-caption screen-hint mb-1 d-block">
34
+ Checkpoints <span class="text-error">*</span>
35
35
  </label>
36
36
  <v-select
37
37
  v-model="form.checkPointNumber"
@@ -44,8 +44,8 @@
44
44
  </v-col>
45
45
 
46
46
  <v-col cols="12" md="4" class="mb-4 px-md-1">
47
- <label class="text-caption text-grey-darken-1 mb-1 d-block">
48
- Tolerance (mins) <span class="text-red">*</span>
47
+ <label class="text-caption screen-hint mb-1 d-block">
48
+ Tolerance (mins) <span class="text-error">*</span>
49
49
  </label>
50
50
  <v-text-field
51
51
  v-model="form.tolerance"
@@ -57,8 +57,8 @@
57
57
  </v-col>
58
58
 
59
59
  <v-col cols="12" md="4" class="mb-4 pl-md-2">
60
- <label class="text-caption text-grey-darken-1 mb-1 d-block">
61
- Days <span class="text-red">*</span>
60
+ <label class="text-caption screen-hint mb-1 d-block">
61
+ Days <span class="text-error">*</span>
62
62
  </label>
63
63
  <v-select
64
64
  v-model="form.days"
@@ -76,7 +76,7 @@
76
76
  <v-card variant="outlined" class="pa-4" rounded="lg">
77
77
  <div class="d-flex align-center justify-space-between mb-3">
78
78
  <span class="text-h6 font-weight-medium">Start Times</span>
79
- <span class="text-body-2 text-grey-darken-1">Schedule</span>
79
+ <span class="text-body-2 screen-hint">Schedule</span>
80
80
  </div>
81
81
 
82
82
  <!-- Start Time Slots -->
@@ -96,7 +96,6 @@
96
96
  prepend-inner-icon="mdi-clock-outline"
97
97
  hide-details
98
98
  type="time"
99
- bg-color="grey-lighten-4"
100
99
  rounded="lg"
101
100
  @update:model-value="syncEndTimeAt(index)"
102
101
  />
@@ -116,7 +115,6 @@
116
115
  prepend-inner-icon="mdi-clock-outline"
117
116
  hide-details
118
117
  type="time"
119
- bg-color="grey-lighten-2"
120
118
  rounded="lg"
121
119
  readonly
122
120
  />
@@ -160,19 +158,19 @@
160
158
  <v-row no-gutters class="mb-2">
161
159
  <v-col
162
160
  cols="2"
163
- class="text-caption text-grey-darken-1 font-weight-medium"
161
+ class="text-caption screen-hint font-weight-medium"
164
162
  >
165
163
  Checkpoints
166
164
  </v-col>
167
165
  <v-col
168
166
  cols="6"
169
- class="text-caption text-grey-darken-1 font-weight-medium pl-4"
167
+ class="text-caption screen-hint font-weight-medium pl-4"
170
168
  >
171
169
  NFC Tag
172
170
  </v-col>
173
171
  <v-col
174
172
  cols="4"
175
- class="text-caption text-grey-darken-1 font-weight-medium text-right"
173
+ class="text-caption screen-hint font-weight-medium text-right"
176
174
  >
177
175
  Travel time
178
176
  </v-col>
@@ -218,15 +216,15 @@
218
216
  <!-- Summary -->
219
217
  <v-col cols="12">
220
218
  <v-row no-gutters class="mb-2">
221
- <v-col cols="6" class="text-body-2 text-grey-darken-1">
219
+ <v-col cols="6" class="text-body-2 screen-hint">
222
220
  Tolerance Balance:
223
- <span class="font-weight-bold text-grey-darken-3"
221
+ <span class="font-weight-bold"
224
222
  >{{ toleranceBalance }} min</span
225
223
  >
226
224
  </v-col>
227
- <v-col cols="6" class="text-body-2 text-grey-darken-1 text-right">
225
+ <v-col cols="6" class="text-body-2 screen-hint text-right">
228
226
  Total Travel Time:
229
- <span class="font-weight-bold text-grey-darken-3"
227
+ <span class="font-weight-bold"
230
228
  >{{ totalTravelTime }} min</span
231
229
  >
232
230
  </v-col>
@@ -238,7 +236,7 @@
238
236
 
239
237
  <v-divider />
240
238
 
241
- <v-toolbar class="pa-0" density="compact" color="white" elevation="0">
239
+ <v-toolbar class="pa-0 screen-dialog-bar" density="compact" elevation="0">
242
240
  <v-row no-gutters>
243
241
  <v-col cols="6" class="pa-0">
244
242
  <v-btn