@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,7 +1,17 @@
1
1
  <template>
2
- <v-row no-gutters>
2
+ <div>
3
+ <!-- The design's title row: the page's name at 22px and its primary
4
+ action on the right of that same line. Placement only - the same
5
+ button opens the same dialog under the same permission. -->
6
+ <PageHeader title="Feedbacks">
7
+ <template v-if="canCreateFeedback" #actions>
8
+ <AppButton @click="showCreateDialog = true">Create Feedback</AppButton>
9
+ </template>
10
+ </PageHeader>
11
+
12
+ <v-row no-gutters>
3
13
  <v-col cols="12" class="mb-2">
4
- <v-row no-gutters align="center">
14
+ <v-row no-gutters align="center" class="filter-bar">
5
15
  <v-text-field
6
16
  v-model="searchText"
7
17
  placeholder="Search feedback..."
@@ -50,51 +60,32 @@
50
60
  <v-date-picker v-model="endDate" width="320" :locale="locale" />
51
61
  </v-card>
52
62
  </v-dialog>
53
- <v-btn
54
- v-if="canCreateFeedback"
55
- text="create feedback"
56
- class="text-none text-capitalize ml-2"
57
- rounded="pill"
58
- variant="tonal"
59
- size="large"
60
- @click="showCreateDialog = true"
61
- />
62
63
  </v-row>
63
64
  </v-col>
64
65
 
65
66
  <v-col cols="12">
66
- <v-card
67
- width="100%"
68
- variant="outlined"
69
- border="thin"
70
- rounded="lg"
71
- :loading="loading"
72
- >
73
- <v-toolbar density="compact" color="grey-lighten-4">
74
- <template #prepend>
75
- <v-btn
76
- fab
77
- icon
78
- density="comfortable"
67
+ <AppCard class="table-card">
68
+ <!-- One row inside the card - refresh, the range and the pager - in
69
+ place of a `v-toolbar` that stacked them above the table. Same
70
+ three controls, same handlers. -->
71
+ <CardToolbar :count="pageRange">
72
+ <template #left>
73
+ <AppButton
74
+ variant="icon"
75
+ icon="mdi-refresh"
76
+ aria-label="Refresh"
79
77
  @click="(page = 1), refreshFeedbacks()"
80
- >
81
- <v-icon icon="mdi-refresh" />
82
- </v-btn>
78
+ />
83
79
  </template>
84
80
 
85
- <template #append>
86
- <v-row no-gutters justify="end" align="center">
87
- <span class="mr-2 text-caption text-fontgray">
88
- {{ pageRange }}
89
- </span>
90
- <local-pagination
91
- v-model="page"
92
- :length="pages"
93
- @update:value="updatePage"
94
- />
95
- </v-row>
81
+ <template #right>
82
+ <local-pagination
83
+ v-model="page"
84
+ :length="pages"
85
+ @update:value="updatePage"
86
+ />
96
87
  </template>
97
- </v-toolbar>
88
+ </CardToolbar>
98
89
 
99
90
  <v-data-table
100
91
  :headers="headers"
@@ -104,6 +95,7 @@
104
95
  fixed-header
105
96
  hide-default-footer
106
97
  :hide-default-header="false"
98
+ :loading="loading"
107
99
  @click:row="tableRowClickHandler"
108
100
  style="max-height: calc(100vh - (200px))"
109
101
  >
@@ -139,13 +131,7 @@
139
131
  </template>
140
132
  <template #item.status="{ value }">
141
133
  <span class="d-inline-block text-truncate">
142
- <v-chip
143
- :color="getStatusColor(value ?? '')"
144
- class="pa-5 text-capitalize text-center whitespace-nowrap text-body-1"
145
- variant="flat"
146
- >
147
- {{ value }}
148
- </v-chip>
134
+ <StatusChip class="text-capitalize" :status="value" />
149
135
  </span>
150
136
  </template>
151
137
  <template #item.assigneeInfo="{ item, index }">
@@ -183,9 +169,10 @@
183
169
  <span v-else class="mt-1 text-wrap"> Not Assigned </span>
184
170
  </template>
185
171
  </v-data-table>
186
- </v-card>
172
+ </AppCard>
187
173
  </v-col>
188
- </v-row>
174
+ </v-row>
175
+ </div>
189
176
 
190
177
  <!-- <FeedbackForm
191
178
  v-model="showCreateDialog"
@@ -660,7 +647,6 @@ const _feedback = ref({
660
647
  });
661
648
 
662
649
  const {
663
- getStatusColor,
664
650
  debounce,
665
651
  standardFormatDateTime,
666
652
  standardFormatDate,
@@ -6,6 +6,9 @@
6
6
  accept="image/*"
7
7
  :prepend-icon="prependIcon"
8
8
  :loading="isFileUploading"
9
+ variant="outlined"
10
+ density="comfortable"
11
+ class="filter-field"
9
12
  hide-details
10
13
  chips
11
14
  multiple
@@ -16,7 +19,16 @@
16
19
  >
17
20
  <template v-slot:append v-if="hasLabel">
18
21
  <slot name="append">
19
- <v-btn color="primary" height="50px" @click="openCameraDialog">
22
+ <!-- `color="primary"` on a `v-btn` is the design's FOREGROUND token,
23
+ so this drew accent-on-accent; the fill is `primary-button`, which
24
+ is what `.screen-btn-primary` states. `height="50px"` was also
25
+ 10px taller than the design's 40px button. -->
26
+ <v-btn
27
+ class="text-none screen-btn-primary"
28
+ variant="flat"
29
+ aria-label="Take a picture"
30
+ @click="openCameraDialog"
31
+ >
20
32
  <v-icon>mdi-camera</v-icon>
21
33
  </v-btn>
22
34
  </slot>
@@ -32,64 +44,69 @@
32
44
  persistent
33
45
  @after-enter="startCamera"
34
46
  >
35
- <v-container
36
- class="d-flex justify-center"
37
- max-height="90vh"
38
- width="800"
39
- max-width="800"
40
- >
41
- <v-card elevation="2" class="d-flex flex-column align-center pa-2">
42
- <v-toolbar>
43
- <v-card-title class="text-h5">Take a Picture</v-card-title>
44
- <v-spacer></v-spacer>
45
- <v-btn
46
- color="grey-darken-1"
47
- icon="mdi-close"
48
- @click="closeCameraDialog"
49
- ></v-btn>
50
- </v-toolbar>
51
-
52
- <div
53
- id="reader"
54
- class="d-flex justify-center align-center"
55
- style="
56
- position: relative;
57
- width: 500px;
58
- min-width: 400px;
59
- height: 400px;
60
- "
47
+ <!-- Was a `v-container` wrapping a factory 4px `v-card` with a bare
48
+ `v-toolbar` across the top - Vuetify paints that toolbar from its own
49
+ `surface`, a grey slab visibly lighter than the card on dark. The
50
+ design's modal is the card itself: 16px radius on `--card`, a
51
+ `v-card-title` row, and the borderless 32px close. -->
52
+ <v-card class="screen-modal d-flex flex-column align-center">
53
+ <v-card-title class="d-flex align-center w-100">
54
+ Take a Picture
55
+ <v-spacer />
56
+ <v-btn
57
+ variant="text"
58
+ icon="mdi-close"
59
+ class="screen-modal__close"
60
+ aria-label="Close camera"
61
+ @click="closeCameraDialog"
62
+ />
63
+ </v-card-title>
64
+
65
+ <div
66
+ id="reader"
67
+ class="d-flex justify-center align-center"
68
+ style="
69
+ position: relative;
70
+ width: 500px;
71
+ min-width: 400px;
72
+ height: 400px;
73
+ "
74
+ >
75
+ <video
76
+ ref="video"
77
+ style="flex: 1; height: 400px; min-width: 300px"
78
+ class="video-shutter"
79
+ autoplay
80
+ ></video>
81
+ <canvas
82
+ ref="canvas"
83
+ style="flex: 1; height: 400px; min-width: 300px; display: none"
84
+ ></canvas>
85
+ </div>
86
+
87
+ <!-- Was a two-column `v-row` of Vuetify `primary` / `secondary` icon
88
+ buttons - `secondary` is not a design token at all, and `primary` is
89
+ the foreground one. The design's icon button is the 36px bordered
90
+ square, and the capture action is the primary of the pair, so it
91
+ sits on the shared modal footer in the primary's place. -->
92
+ <div class="screen-modal__footer w-100">
93
+ <v-btn
94
+ class="text-none screen-btn-ghost"
95
+ variant="outlined"
96
+ aria-label="Switch camera"
97
+ @click="switchCamera"
98
+ >
99
+ <v-icon>mdi-camera-switch</v-icon>
100
+ </v-btn>
101
+ <v-btn
102
+ class="text-none screen-btn-primary"
103
+ variant="flat"
104
+ @click="captureImageFromCamera"
61
105
  >
62
- <video
63
- ref="video"
64
- style="flex: 1; height: 400px; min-width: 300px"
65
- class="video-shutter"
66
- autoplay
67
- ></video>
68
- <canvas
69
- ref="canvas"
70
- style="flex: 1; height: 400px; min-width: 300px; display: none"
71
- ></canvas>
72
- </div>
73
-
74
- <v-row align="center" justify="center">
75
- <v-col cols="6">
76
- <v-btn color="primary" icon class="mt-4" @click="switchCamera">
77
- <v-icon>mdi-camera-switch</v-icon>
78
- </v-btn>
79
- </v-col>
80
- <v-col cols="6">
81
- <v-btn
82
- color="secondary"
83
- icon
84
- class="mt-4"
85
- @click="captureImageFromCamera"
86
- >
87
- <v-icon large>mdi-camera-outline</v-icon>
88
- </v-btn>
89
- </v-col>
90
- </v-row>
91
- </v-card>
92
- </v-container>
106
+ <v-icon>mdi-camera-outline</v-icon>
107
+ </v-btn>
108
+ </div>
109
+ </v-card>
93
110
  </v-dialog>
94
111
  </div>
95
112
 
@@ -13,10 +13,16 @@
13
13
  @update:modelValue="handleFileSelect"
14
14
  @click:clear="handleClear"
15
15
  :hide-input="hasHideInput"
16
+ class="filter-field"
16
17
  >
17
18
  <template v-slot:append v-if="hasLabel">
18
19
  <slot name="append">
19
- <v-btn color="primary" height="50px" @click="openCameraDialog">
20
+ <v-btn
21
+ variant="text"
22
+ class="screen-icon-btn"
23
+ aria-label="Take a picture"
24
+ @click="openCameraDialog"
25
+ >
20
26
  <v-icon>mdi-camera</v-icon>
21
27
  </v-btn>
22
28
  </slot>
@@ -29,7 +35,7 @@
29
35
  <template v-for="(file, index) in files" :key="file.name">
30
36
  <v-chip
31
37
  closable
32
- class="text-wrap text-caption custom-chip"
38
+ class="text-wrap custom-chip file-list__chip"
33
39
  @click:close="removeFile(index)"
34
40
  >
35
41
  <span class="chip-text">{{ file.name }}</span>
@@ -54,16 +60,18 @@
54
60
  width="800"
55
61
  max-width="800"
56
62
  >
57
- <v-card elevation="2" class="d-flex flex-column align-center pa-2">
58
- <v-toolbar>
59
- <v-card-title class="text-h5">Take a Picture</v-card-title>
60
- <v-spacer></v-spacer>
63
+ <v-card elevation="0" class="screen-modal d-flex flex-column align-center">
64
+ <v-card-title class="d-flex align-center">
65
+ Take a Picture
66
+ <v-spacer />
61
67
  <v-btn
62
- color="grey-darken-1"
68
+ variant="text"
63
69
  icon="mdi-close"
70
+ class="screen-modal__close"
71
+ aria-label="Close"
64
72
  @click="closeCameraDialog"
65
73
  ></v-btn>
66
- </v-toolbar>
74
+ </v-card-title>
67
75
 
68
76
  <div
69
77
  id="reader"
@@ -89,15 +97,25 @@
89
97
 
90
98
  <v-row align="center" justify="center">
91
99
  <v-col cols="6">
92
- <v-btn color="primary" icon class="mt-4" @click="switchCamera">
100
+ <v-btn
101
+ variant="text"
102
+ class="screen-icon-btn mt-4"
103
+ aria-label="Switch camera"
104
+ @click="switchCamera"
105
+ >
93
106
  <v-icon>mdi-camera-switch</v-icon>
94
107
  </v-btn>
95
108
  </v-col>
96
109
  <v-col cols="6">
110
+ <!--
111
+ Was `color="secondary"`, which is NOT one of the four theme
112
+ names `utils/theme.ts` maps onto the design's palette - it fell
113
+ through to Vuetify's own secondary and drew an off-palette slab.
114
+ This is the capture button, so it is the design's PRIMARY.
115
+ -->
97
116
  <v-btn
98
- color="secondary"
99
- icon
100
- class="mt-4"
117
+ class="screen-btn-primary mt-4"
118
+ aria-label="Take the picture"
101
119
  @click="captureImageFromCamera"
102
120
  >
103
121
  <v-icon large>mdi-camera-outline</v-icon>
@@ -289,6 +307,21 @@ onUnmounted(() => {
289
307
  </script>
290
308
 
291
309
  <style scoped>
310
+ /**
311
+ * The attachment tags under the field. They were Vuetify's default chip on
312
+ * `text-caption` - a grey pill on the Roboto scale - which is the one thing in
313
+ * the chat composer that did not match the tags the rest of the product draws.
314
+ * The design's tag radius and chip type, on tokens, so it follows the theme.
315
+ */
316
+ .file-list__chip {
317
+ border-radius: var(--r-tag);
318
+ background: var(--hover);
319
+ color: var(--text2);
320
+ font-family: var(--font-sans);
321
+ font-size: var(--fs-chip);
322
+ font-weight: var(--fw-chip);
323
+ }
324
+
292
325
  .custom-chip {
293
326
  max-width: 100%;
294
327
  height: auto !important;
@@ -301,4 +334,18 @@ onUnmounted(() => {
301
334
  white-space: normal;
302
335
  line-height: 1.2;
303
336
  }
337
+
338
+ /**
339
+ * The attach icon (mdi-paperclip) was drawing at Vuetify's default
340
+ * `.v-input__prepend > .v-icon { opacity: var(--v-medium-emphasis-opacity) }`
341
+ * (0.64) - the same field-icon dimming ~200 other call sites rely on, so it is
342
+ * overridden here only, not in the layer's token. Full opacity, `--text2` -
343
+ * the same colour `.screen-icon-btn` already uses for an icon at rest -
344
+ * matches a sibling icon drawn outside a field (e.g. a composer's chat icon,
345
+ * which is never subject to this Vuetify rule in the first place).
346
+ */
347
+ .filter-field :deep(.v-input__prepend > .v-icon) {
348
+ opacity: 1;
349
+ color: var(--text2);
350
+ }
304
351
  </style>
@@ -1,31 +1,35 @@
1
+ <!--
2
+ PHASE 3 - THE MODAL.
3
+
4
+ 520px, 16px radius and the design's overlay and shadow, with the BODY as the
5
+ only thing that scrolls so the footer never leaves the screen. Same dialog,
6
+ same slots, same close behaviour, same `persistent`.
7
+
8
+ The two `theme.name.value === ...` branches are gone, and that is a fix, not
9
+ a preference: they hard-coded `bg-white` and Vuetify's `grey-darken-4`, so
10
+ the card was painted by a literal colour instead of by the theme it is in.
11
+ `--card` is that surface in each theme.
12
+ -->
1
13
  <template>
2
- <v-dialog v-model="model" max-width="600" persistent>
3
- <v-card
4
- class="px-3 d-flex flex-column"
5
- :class="`${theme.name.value === 'light' ? 'bg-white' : ''} ${
6
- mdAndUp ? 'rounded-xl' : ''
7
- }`"
8
- :style="{ border: 'none', boxShadow: 'none' }"
9
- >
14
+ <v-dialog v-model="model" :max-width="520" persistent class="form-dialog">
15
+ <v-card class="d-flex flex-column form-dialog__card" :style="{ border: 'none' }">
10
16
  <v-toolbar
11
- :color="theme.name.value === 'dark' ? 'grey-darken-4' : 'white'"
12
- class="flex-shrink-0 mb-3"
17
+ color="transparent"
18
+ class="flex-shrink-0 form-dialog__head"
13
19
  style="position: sticky; top: 0; z-index: 10"
14
20
  >
15
21
  <slot name="title">
16
- <span class="text-h6 font-weight-medium pt-1 text-capitalize">
17
- Dialog
18
- </span>
22
+ <span class="form-dialog__title"> Dialog </span>
19
23
  </slot>
20
24
  <v-spacer />
21
- <v-btn icon="mdi-close" @click="closeDialog" />
25
+ <v-btn icon="mdi-close" variant="text" @click="closeDialog" />
22
26
  </v-toolbar>
23
27
 
24
- <v-sheet class="flex-grow-1 overflow-y-auto px-3">
28
+ <v-sheet class="flex-grow-1 overflow-y-auto px-4 form-dialog__body">
25
29
  <slot />
26
30
  </v-sheet>
27
31
 
28
- <v-sheet class="flex-shrink-0 px-3 py-2">
32
+ <v-sheet class="flex-shrink-0 px-4 py-3 form-dialog__footer">
29
33
  <slot name="footer" />
30
34
  </v-sheet>
31
35
  </v-card>
@@ -33,11 +37,6 @@
33
37
  </template>
34
38
 
35
39
  <script setup lang="ts">
36
- import { useTheme, useDisplay } from "vuetify";
37
-
38
- const theme = useTheme().global;
39
- const { mdAndUp } = useDisplay();
40
-
41
40
  const props = defineProps<{
42
41
  modelValue: boolean;
43
42
  }>();
@@ -62,4 +61,44 @@ function closeDialog() {
62
61
  :deep(.v-dialog .v-overlay__content) {
63
62
  margin: auto;
64
63
  }
64
+
65
+ .form-dialog__card {
66
+ font-family: var(--font-sans);
67
+ background: var(--card);
68
+ /* `!important` because Vuetify's own `.v-overlay__content > .v-card` rule is
69
+ more specific than a class on the card, and it is what keeps the dialog at
70
+ its factory 4px. */
71
+ border-radius: var(--r-modal) !important;
72
+ box-shadow: var(--shadow-modal);
73
+ /* Never taller than the screen it has to fit inside; the body is what
74
+ scrolls, so the Cancel/Submit footer cannot be pushed out of view. */
75
+ max-height: calc(100vh - 32px);
76
+ overflow: hidden;
77
+ }
78
+
79
+ .form-dialog__head {
80
+ border-bottom: 1px solid var(--border);
81
+ }
82
+
83
+ .form-dialog__title {
84
+ font-size: var(--fs-card-title);
85
+ font-weight: var(--fw-card-title);
86
+ color: var(--text);
87
+ text-transform: capitalize;
88
+ }
89
+
90
+ .form-dialog__body,
91
+ .form-dialog__footer {
92
+ background: var(--card);
93
+ }
94
+
95
+ .form-dialog__footer {
96
+ border-top: 1px solid var(--border);
97
+ }
98
+
99
+ @media (max-width: 599.98px) {
100
+ .form-dialog__card {
101
+ max-height: calc(100dvh - 32px);
102
+ }
103
+ }
65
104
  </style>