@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
@@ -1,30 +1,40 @@
1
1
  <template>
2
2
  <v-dialog v-model="showDialog" max-width="450">
3
- <v-card>
4
- <v-toolbar>
5
- <template v-if="$slots.header">
6
- <slot
7
- name="header"
8
- :title="
9
- prop.mode === 'edit'
10
- ? `Edit ${prop.entityType}`
11
- : `Add New ${prop.entityType}`
12
- "
13
- :close="close"
14
- />
15
- </template>
16
- <template v-else>
17
- <v-row no-gutters class="fill-height px-6" align="center">
18
- <span class="font-weight-bold text-h6 text-capitalize">{{
19
- prop.mode === "edit"
20
- ? `Edit ${prop.entityType}`
21
- : `Add New ${prop.entityType}`
22
- }}</span>
23
- </v-row>
24
- </template>
25
- </v-toolbar>
3
+ <v-card class="screen-modal">
4
+ <!-- Was a bare `v-toolbar`, which Vuetify paints from its own `surface` -
5
+ a grey slab across the top of the card, visibly lighter than the card
6
+ on the dark theme - carrying a `text-h6` (20px/500 Roboto) heading.
7
+ The design's modal heading is the `v-card-title` row on the card's own
8
+ surface, and it carries the design's own title size and weight. The
9
+ `header` slot keeps its title/close payload unchanged. -->
10
+ <template v-if="$slots.header">
11
+ <slot
12
+ name="header"
13
+ :title="
14
+ prop.mode === 'edit'
15
+ ? `Edit ${prop.entityType}`
16
+ : `Add New ${prop.entityType}`
17
+ "
18
+ :close="close"
19
+ />
20
+ </template>
21
+ <v-card-title v-else class="d-flex align-center text-capitalize">
22
+ {{
23
+ prop.mode === "edit"
24
+ ? `Edit ${prop.entityType}`
25
+ : `Add New ${prop.entityType}`
26
+ }}
27
+ <v-spacer />
28
+ <v-btn
29
+ variant="text"
30
+ icon="mdi-close"
31
+ class="screen-modal__close"
32
+ aria-label="Close"
33
+ @click="close"
34
+ />
35
+ </v-card-title>
26
36
 
27
- <v-card-text class="pa-4">
37
+ <v-card-text class="screen-modal__body">
28
38
  <v-form ref="formRef" v-model="valid">
29
39
  <v-row no-gutters class="pa-0">
30
40
  <v-col v-if="prop.showType" cols="12" class="pa-0 mb-2">
@@ -35,7 +45,7 @@
35
45
  density="comfortable"
36
46
  variant="outlined"
37
47
  hide-details
38
- class="w-100 mb-0"
48
+ class="filter-field w-100 mb-0"
39
49
  />
40
50
  </v-col>
41
51
 
@@ -49,7 +59,7 @@
49
59
  <v-text-field
50
60
  v-model="model"
51
61
  :rules="[requiredRule]"
52
- class="mb-0"
62
+ class="filter-field mb-0"
53
63
  />
54
64
  </v-col>
55
65
 
@@ -68,18 +78,21 @@
68
78
  chips
69
79
  closable-chips
70
80
  placeholder="Select units"
71
- class="mb-0"
81
+ class="filter-field mb-0"
72
82
  />
73
83
  </v-col>
74
84
 
75
85
  <v-col v-if="prop.showOptional" cols="12" class="mb-4">
76
86
  <v-row dense justify="center">
77
87
  <v-col cols="6" class="pa-0">
88
+ <!-- `color="primary"` on a `v-btn` is the design's FOREGROUND
89
+ token; this is a plain text toggle, so it takes the
90
+ accent's INK form, which the theme test already holds at
91
+ >= 4.5:1 on the card. -->
78
92
  <v-btn
79
93
  block
80
- color="primary"
81
94
  variant="text"
82
- class="text-none font-weight-bold"
95
+ class="text-none font-weight-bold area-form-dialog__optional"
83
96
  text="Optional"
84
97
  @click="show = !show"
85
98
  ></v-btn>
@@ -101,6 +114,7 @@
101
114
  density="comfortable"
102
115
  type="number"
103
116
  min="1"
117
+ class="filter-field"
104
118
  ></v-text-field>
105
119
  </v-col>
106
120
  </v-row>
@@ -111,36 +125,24 @@
111
125
  </v-form>
112
126
  </v-card-text>
113
127
 
114
- <v-toolbar class="pa-0" density="compact">
115
- <v-row no-gutters>
116
- <v-col cols="6" class="pa-0">
117
- <v-btn
118
- block
119
- variant="text"
120
- class="text-none"
121
- size="large"
122
- @click="close"
123
- height="48"
124
- >
125
- Cancel
126
- </v-btn>
127
- </v-col>
128
-
129
- <v-col cols="6" class="pa-0">
130
- <v-btn
131
- block
132
- variant="flat"
133
- color="black"
134
- class="text-none font-weight-bold rounded-0"
135
- height="48"
136
- :loading="submitting"
137
- @click="submit"
138
- >
139
- {{ prop.mode === "edit" ? "Save" : "Create" }}
140
- </v-btn>
141
- </v-col>
142
- </v-row>
143
- </v-toolbar>
128
+ <!-- Was a second `v-toolbar` holding two square 48px bars - the primary a
129
+ hardcoded `color="black"`, which is neither theme's accent and reads
130
+ as a hole in the dark modal - with `rounded-0` forcing 0px corners.
131
+ This is the design's shared modal footer: a bordered strip with a
132
+ ghost secondary and the primary beside it, both 40px at 10px. -->
133
+ <div class="screen-modal__footer">
134
+ <v-btn class="text-none screen-btn-ghost" variant="outlined" @click="close">
135
+ Cancel
136
+ </v-btn>
137
+ <v-btn
138
+ class="text-none screen-btn-primary"
139
+ variant="flat"
140
+ :loading="submitting"
141
+ @click="submit"
142
+ >
143
+ {{ prop.mode === "edit" ? "Save" : "Create" }}
144
+ </v-btn>
145
+ </div>
144
146
  </v-card>
145
147
  </v-dialog>
146
148
  </template>
@@ -268,3 +270,13 @@ async function submit() {
268
270
  }
269
271
  }
270
272
  </script>
273
+
274
+ <style scoped>
275
+ /* The "Optional" reveal is plain text, not a filled button, so it takes the
276
+ accent's INK form. `--accent-strong` is the FILL that a white label sits on;
277
+ `--accent-text` is the one `utils/theme.test.ts` holds at >= 4.5:1 against
278
+ the card in both themes. */
279
+ .area-form-dialog__optional {
280
+ color: var(--accent-text);
281
+ }
282
+ </style>
@@ -19,23 +19,24 @@
19
19
  >
20
20
  <template #extension>
21
21
  <v-row no-gutters class="w-100 d-flex flex-column">
22
- <v-card
23
- class="w-100 px-3 d-flex align-center ga-5 py-2"
24
- flat
25
- :height="60"
26
- >
22
+ <!--
23
+ A bare `v-card` here paints Vuetify's own `surface`, a slab a
24
+ shade off the table card it sits inside. A plain row on the
25
+ card's own background, with the filter on the design's field.
26
+ -->
27
+ <div class="w-100 px-3 d-flex align-center ga-5 py-2">
27
28
  <v-select
28
29
  v-model="areaTypeFilter"
29
30
  :items="typeOptions"
30
31
  density="compact"
31
32
  hide-details
32
- class="mx-2"
33
+ class="mx-2 filter-field"
33
34
  style="max-width: 160px"
34
35
  item-title="title"
35
36
  item-value="value"
36
37
  label="Type"
37
38
  />
38
- </v-card>
39
+ </div>
39
40
  </v-row>
40
41
  </template>
41
42
 
@@ -49,10 +50,8 @@
49
50
  <!-- Primary action -->
50
51
  <v-btn
51
52
  v-if="canCreateArea"
52
- class="text-none mr-3"
53
- rounded="pill"
54
- variant="tonal"
55
- size="large"
53
+ class="text-none mr-3 screen-btn-primary"
54
+ variant="flat"
56
55
  @click="onCreateItem"
57
56
  >
58
57
  {{ createLabel }}
@@ -63,10 +62,8 @@
63
62
  <template #activator="{ props: t }">
64
63
  <v-btn
65
64
  v-bind="t"
66
- class="ma-1"
67
- variant="tonal"
68
- size="large"
69
- rounded="pill"
65
+ class="ma-1 screen-icon-btn"
66
+ variant="flat"
70
67
  href="/files/area-sample-data.xlsx"
71
68
  target="_blank"
72
69
  download
@@ -81,10 +78,8 @@
81
78
  <template #activator="{ props: t }">
82
79
  <v-btn
83
80
  v-bind="t"
84
- class="ma-1"
85
- variant="tonal"
86
- size="large"
87
- rounded="pill"
81
+ class="ma-1 screen-icon-btn"
82
+ variant="flat"
88
83
  @click="onImportData"
89
84
  >
90
85
  <v-icon>mdi-upload</v-icon>
@@ -97,10 +92,8 @@
97
92
  <template #activator="{ props: t }">
98
93
  <v-btn
99
94
  v-bind="t"
100
- class="ma-1"
101
- variant="tonal"
102
- size="large"
103
- rounded="pill"
95
+ class="ma-1 screen-icon-btn"
96
+ variant="flat"
104
97
  @click="handleDownloadExcel"
105
98
  :loading="isDownloading"
106
99
  >
@@ -114,7 +107,7 @@
114
107
 
115
108
  <v-spacer />
116
109
 
117
- <v-col cols="auto">
110
+ <v-col cols="auto" class="filter-field">
118
111
  <v-text-field
119
112
  v-model="searchInput"
120
113
  density="compact"
@@ -221,64 +214,50 @@
221
214
  </HygieneUpdateMoreAction>
222
215
  </v-dialog>
223
216
 
224
- <v-dialog v-model="dialogDeleteItem" max-width="450">
225
- <v-card>
226
- <v-toolbar>
227
- <v-row no-gutters class="fill-height px-6" align="center">
228
- <span class="font-weight-bold text-h6 text-capitalize">
229
- Delete {{ selectedItem?.name || entityTypeLabel }}
230
- </span>
231
- </v-row>
232
- </v-toolbar>
233
- <v-card-text>
234
- <span class="text-subtitle-2"
235
- >Are you sure you want to delete this {{ entityTypeLabel }}?</span
236
- >
217
+ <!--
218
+ Both dialogs were `v-toolbar` title bars over toolbar footers of two block
219
+ buttons, the confirm one on `color="black"` - not a token, so it painted a
220
+ light-theme fill on the dark theme, and the toolbar surface sat visibly
221
+ lighter than the card. The shared `.screen-modal` shape now, same copy,
222
+ same labels, same handlers, same busy states.
223
+ -->
224
+ <v-dialog v-model="dialogDeleteItem" max-width="520">
225
+ <v-card class="screen-modal">
226
+ <v-card-title class="text-capitalize">
227
+ Delete {{ selectedItem?.name || entityTypeLabel }}
228
+ </v-card-title>
229
+
230
+ <v-card-text class="screen-modal__body">
231
+ Are you sure you want to delete this {{ entityTypeLabel }}?
237
232
  </v-card-text>
238
233
 
239
- <v-toolbar class="pa-0" density="compact">
240
- <v-row no-gutters>
241
- <v-col cols="6" class="pa-0">
242
- <v-btn
243
- block
244
- variant="text"
245
- class="text-none"
246
- size="large"
247
- @click="dialogDeleteItem = false"
248
- height="48"
249
- >
250
- Cancel
251
- </v-btn>
252
- </v-col>
253
-
254
- <v-col cols="6" class="pa-0">
255
- <v-btn
256
- block
257
- variant="flat"
258
- color="black"
259
- class="text-none font-weight-bold rounded-0"
260
- height="48"
261
- :loading="submitting"
262
- @click="_deleteItem"
263
- >
264
- Delete
265
- </v-btn>
266
- </v-col>
267
- </v-row>
268
- </v-toolbar>
234
+ <div class="screen-modal__footer">
235
+ <v-btn
236
+ class="screen-btn-ghost"
237
+ variant="outlined"
238
+ :disabled="submitting"
239
+ @click="dialogDeleteItem = false"
240
+ >
241
+ Cancel
242
+ </v-btn>
243
+ <v-btn
244
+ class="screen-btn-primary"
245
+ variant="flat"
246
+ :loading="submitting"
247
+ @click="_deleteItem"
248
+ >
249
+ Delete
250
+ </v-btn>
251
+ </div>
269
252
  </v-card>
270
253
  </v-dialog>
271
254
 
272
- <v-dialog v-if="isToiletLocation" v-model="dialogShowQR" max-width="500">
273
- <v-card>
274
- <v-toolbar>
275
- <v-row no-gutters class="fill-height px-6" align="center">
276
- <span class="font-weight-bold text-h6 text-capitalize">
277
- QR Code for {{ selectedItem?.name || "Toilet Location" }}
278
- </span>
279
- </v-row>
280
- </v-toolbar>
281
- <v-card-text class="d-flex justify-center pa-6">
255
+ <v-dialog v-if="isToiletLocation" v-model="dialogShowQR" max-width="520">
256
+ <v-card class="screen-modal">
257
+ <v-card-title class="text-capitalize">
258
+ QR Code for {{ selectedItem?.name || "Toilet Location" }}
259
+ </v-card-title>
260
+ <v-card-text class="screen-modal__body d-flex justify-center">
282
261
  <v-row no-gutters class="d-flex justify-center">
283
262
  <v-col cols="12" class="text-center">
284
263
  <div v-if="qrLoading" class="d-flex flex-column align-center">
@@ -309,36 +288,23 @@
309
288
  </v-row>
310
289
  </v-card-text>
311
290
 
312
- <v-toolbar class="pa-0" density="compact">
313
- <v-row no-gutters>
314
- <v-col cols="6" class="pa-0">
315
- <v-btn
316
- block
317
- variant="text"
318
- class="text-none"
319
- size="large"
320
- @click="dialogShowQR = false"
321
- height="48"
322
- >
323
- Cancel
324
- </v-btn>
325
- </v-col>
326
-
327
- <v-col cols="6" class="pa-0">
328
- <v-btn
329
- block
330
- variant="flat"
331
- color="black"
332
- class="text-none font-weight-bold rounded-0"
333
- height="48"
334
- :loading="qrLoading"
335
- @click="onDownloadQrCode"
336
- >
337
- Download
338
- </v-btn>
339
- </v-col>
340
- </v-row>
341
- </v-toolbar>
291
+ <div class="screen-modal__footer">
292
+ <v-btn
293
+ class="screen-btn-ghost"
294
+ variant="outlined"
295
+ @click="dialogShowQR = false"
296
+ >
297
+ Cancel
298
+ </v-btn>
299
+ <v-btn
300
+ class="screen-btn-primary"
301
+ variant="flat"
302
+ :loading="qrLoading"
303
+ @click="onDownloadQrCode"
304
+ >
305
+ Download
306
+ </v-btn>
307
+ </div>
342
308
  </v-card>
343
309
  </v-dialog>
344
310
 
@@ -6,8 +6,10 @@
6
6
 
7
7
  <!-- Loading Skeleton -->
8
8
  <template v-if="loading && files?.length > 0">
9
- <v-card v-for="(file, index) in files" :key="index" height="50px" flat border="sm black"
10
- class="mb-2">
9
+ <!-- `border="sm black"` painted a literal black hairline on
10
+ both themes; the design's rule is `--border`. -->
11
+ <v-card v-for="(file, index) in files" :key="index" height="50px" flat
12
+ class="att-skeleton mb-2">
11
13
  <v-skeleton-loader type="list-item" class="mb-2" />
12
14
  </v-card>
13
15
  </template>
@@ -17,7 +19,7 @@
17
19
 
18
20
  <!-- Videos -->
19
21
  <template v-if="videosArray.length > 0">
20
- <div v-if="showFileTypeTitle" class="text-caption text-medium-emphasis mb-1">Videos ({{
22
+ <div v-if="showFileTypeTitle" class="att-group mb-1">Videos ({{
21
23
  videosArray.length }})</div>
22
24
  <v-list density="compact" class="pa-0 rounded-lg border mb-2">
23
25
  <template v-for="(item, i) in videosArray" :key="item._id">
@@ -26,11 +28,11 @@
26
28
  :subtitle="item.mimeType" class="cursor-pointer"
27
29
  @click="openMediaViewer(item._id, item.mimeType)">
28
30
  <template #prepend>
29
- <v-icon :color="getFileIconColor(item.mimeType)" class="mr-3">{{
31
+ <v-icon :class="[getFileIconClass(item.mimeType), 'mr-3']">{{
30
32
  getFileIcon(item.mimeType) }}</v-icon>
31
33
  </template>
32
34
  <template #append>
33
- <v-icon size="16" color="grey-lighten-1">mdi-play-circle-outline</v-icon>
35
+ <v-icon size="16" class="att-icon--muted">mdi-play-circle-outline</v-icon>
34
36
  </template>
35
37
  </v-list-item>
36
38
  </template>
@@ -39,7 +41,7 @@
39
41
 
40
42
  <!-- Photos -->
41
43
  <template v-if="photosArray.length > 0">
42
- <div v-if="showFileTypeTitle" class="text-caption text-medium-emphasis mb-1"
44
+ <div v-if="showFileTypeTitle" class="att-group mb-1"
43
45
  :class="{ 'mt-3': videosArray.length > 0 }">
44
46
  Photos ({{ photosArray.length }})</div>
45
47
  <v-list density="compact" class="pa-0 rounded-lg border mb-2">
@@ -50,16 +52,16 @@
50
52
  <v-avatar size="36" rounded="sm" class="mr-3">
51
53
  <v-img :src="imageCover(item._id)" cover>
52
54
  <template #error>
53
- <v-icon color="green" size="20">mdi-image</v-icon>
55
+ <v-icon size="20" class="att-icon--ok">mdi-image</v-icon>
54
56
  </template>
55
57
  </v-img>
56
58
  </v-avatar>
57
59
  </template>
58
- <v-list-item-title class="text-body-2">{{ item.file.name }}</v-list-item-title>
59
- <v-list-item-subtitle class="text-caption">{{ item.mimeType
60
+ <v-list-item-title class="att-name">{{ item.file.name }}</v-list-item-title>
61
+ <v-list-item-subtitle class="att-meta">{{ item.mimeType
60
62
  }}</v-list-item-subtitle>
61
63
  <template #append>
62
- <v-icon size="16" color="grey-lighten-1">mdi-eye-outline</v-icon>
64
+ <v-icon size="16" class="att-icon--muted">mdi-eye-outline</v-icon>
63
65
  </template>
64
66
  </v-list-item>
65
67
  </template>
@@ -68,7 +70,7 @@
68
70
 
69
71
  <!-- Documents & Other Files -->
70
72
  <template v-if="filesArray.length > 0">
71
- <div v-if="showFileTypeTitle" class="text-caption text-medium-emphasis mb-1"
73
+ <div v-if="showFileTypeTitle" class="att-group mb-1"
72
74
  :class="{ 'mt-3': videosArray.length > 0 || photosArray.length > 0 }">Files ({{
73
75
  filesArray.length }})</div>
74
76
  <v-list density="compact" class="pa-0 rounded-lg border mb-2">
@@ -77,14 +79,14 @@
77
79
  <v-list-item class="cursor-pointer"
78
80
  @click="openDocumentViewer(item._id, item.file.name, item.mimeType)">
79
81
  <template #prepend>
80
- <v-icon :color="getFileIconColor(item.mimeType)" class="mr-3">{{
82
+ <v-icon :class="[getFileIconClass(item.mimeType), 'mr-3']">{{
81
83
  getFileIcon(item.mimeType) }}</v-icon>
82
84
  </template>
83
- <v-list-item-title class="text-body-2">{{ item.file.name }}</v-list-item-title>
84
- <v-list-item-subtitle class="text-caption">{{ item.mimeType
85
+ <v-list-item-title class="att-name">{{ item.file.name }}</v-list-item-title>
86
+ <v-list-item-subtitle class="att-meta">{{ item.mimeType
85
87
  }}</v-list-item-subtitle>
86
88
  <template #append>
87
- <v-icon size="16" color="grey-lighten-1">mdi-open-in-new</v-icon>
89
+ <v-icon size="16" class="att-icon--muted">mdi-open-in-new</v-icon>
88
90
  </template>
89
91
  </v-list-item>
90
92
  </template>
@@ -185,13 +187,20 @@ function getFileIcon(mimeType: string): string {
185
187
  return 'mdi-file-outline';
186
188
  }
187
189
 
188
- function getFileIconColor(mimeType: string): string {
189
- if (mimeType === 'application/pdf') return 'red';
190
- if (mimeType.includes('word') || mimeType.includes('document')) return 'blue';
191
- if (mimeType.includes('excel') || mimeType.includes('spreadsheet')) return 'green';
192
- if (mimeType.includes('powerpoint') || mimeType.includes('presentation')) return 'orange';
193
- if (mimeType.startsWith('video/')) return 'purple';
194
- return 'grey';
190
+ /**
191
+ * Was Vuetify's raw palette names - `red`, `blue`, `green`, `orange`, `purple`,
192
+ * `grey` - which are the same six hexes in both themes and none of them a token.
193
+ * The handoff draws NO file-type icon palette, so this keeps the distinctions
194
+ * the screen already made and states each one in the token that already carries
195
+ * that tone. `purple` has no counterpart at all, so video takes the muted tone
196
+ * with the rest; that one IS a change of meaning and is recorded as such.
197
+ */
198
+ function getFileIconClass(mimeType: string): string {
199
+ if (mimeType === 'application/pdf') return 'att-icon--err';
200
+ if (mimeType.includes('word') || mimeType.includes('document')) return 'att-icon--info';
201
+ if (mimeType.includes('excel') || mimeType.includes('spreadsheet')) return 'att-icon--ok';
202
+ if (mimeType.includes('powerpoint') || mimeType.includes('presentation')) return 'att-icon--warn';
203
+ return 'att-icon--muted';
195
204
  }
196
205
 
197
206
  function getByType(prefix: 'image/' | 'video/' | 'other') {
@@ -311,3 +320,56 @@ function inferMimeType(ext?: string): string {
311
320
  return mimeMap[ext] || 'application/octet-stream';
312
321
  }
313
322
  </script>
323
+
324
+ <style scoped>
325
+ /* The group heading was `text-caption text-medium-emphasis` - Vuetify's 12px
326
+ Roboto at 60% alpha. The design's sub-line is `--muted` at the card's own
327
+ caption size. */
328
+ .att-group {
329
+ font-family: var(--font-sans);
330
+ font-size: 12px;
331
+ font-weight: 700;
332
+ color: var(--muted);
333
+ }
334
+
335
+ /* Row title and meta were `text-body-2` / `text-caption`, i.e. Roboto again.
336
+ These take the design's cell type, the same pair every converted table row
337
+ uses. */
338
+ .att-name {
339
+ font-family: var(--font-sans);
340
+ font-size: 13.5px;
341
+ font-weight: 600;
342
+ color: var(--text);
343
+ }
344
+
345
+ .att-meta {
346
+ font-family: var(--font-sans);
347
+ font-size: 12px;
348
+ color: var(--muted);
349
+ }
350
+
351
+ .att-skeleton {
352
+ border: 1px solid var(--border);
353
+ border-radius: var(--r-inner);
354
+ }
355
+
356
+ .att-icon--err {
357
+ color: var(--err);
358
+ }
359
+
360
+ .att-icon--info {
361
+ color: var(--info);
362
+ }
363
+
364
+ .att-icon--ok {
365
+ color: var(--ok);
366
+ }
367
+
368
+ .att-icon--warn {
369
+ color: var(--warn);
370
+ }
371
+
372
+ .att-icon--muted {
373
+ color: var(--muted);
374
+ }
375
+ </style>