@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,20 +1,15 @@
1
1
  <template>
2
- <v-card width="100%">
3
- <v-toolbar>
4
- <v-row no-gutters class="fill-height px-6" align="center">
5
- <span class="font-weight-bold text-h5 text-capitalize">
6
- {{ title }}
7
- </span>
8
- </v-row>
9
- </v-toolbar>
2
+ <v-card width="100%" class="screen-modal">
3
+ <v-card-title class="text-capitalize">{{ title }}</v-card-title>
10
4
 
11
- <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-5">
5
+ <v-card-text class="screen-modal__body pa-5">
12
6
  <v-form ref="formRef" v-model="validForm" :disabled="disable">
13
7
  <v-row no-gutters class="pt-4">
14
8
  <v-col v-if="isCCTV" cols="12">
15
9
  <InputLabel class="text-capitalize" title="Camera Name" required />
16
10
  <v-text-field
17
11
  v-model.trim="camera.name"
12
+ class="filter-field"
18
13
  density="comfortable"
19
14
  :rules="[requiredRule]"
20
15
  placeholder="Enter CCTV camera name"
@@ -24,6 +19,7 @@
24
19
  <InputLabel class="text-capitalize" title="URL" required />
25
20
  <v-text-field
26
21
  v-model.trim="camera.host"
22
+ class="filter-field"
27
23
  density="comfortable"
28
24
  :rules="[requiredRule, hostRule]"
29
25
  placeholder="Enter camera URL"
@@ -35,6 +31,7 @@
35
31
  <v-select
36
32
  v-model="camera.category"
37
33
  :items="anprCategoryOptions"
34
+ class="filter-field"
38
35
  density="comfortable"
39
36
  :rules="[requiredRule]"
40
37
  />
@@ -45,6 +42,7 @@
45
42
  <v-select
46
43
  v-model="camera.direction"
47
44
  :items="anprDirectionOptions"
45
+ class="filter-field"
48
46
  density="comfortable"
49
47
  :rules="[requiredRule]"
50
48
  />
@@ -55,6 +53,7 @@
55
53
  <v-select
56
54
  v-model="camera.guardPost"
57
55
  :items="guardPostOptions"
56
+ class="filter-field"
58
57
  density="comfortable"
59
58
  />
60
59
  </v-col> -->
@@ -63,6 +62,7 @@
63
62
  <InputLabel class="text-capitalize" title="User" required />
64
63
  <v-text-field
65
64
  v-model.trim="camera.username"
65
+ class="filter-field"
66
66
  density="comfortable"
67
67
  :rules="[requiredRule]"
68
68
  placeholder="Enter username"
@@ -74,6 +74,7 @@
74
74
  <v-text-field
75
75
  v-model.trim="camera.password"
76
76
  type="password"
77
+ class="filter-field"
77
78
  density="comfortable"
78
79
  :rules="[requiredRule]"
79
80
  placeholder="Enter password"
@@ -86,10 +87,11 @@
86
87
  v-model="camera.status"
87
88
  hide-details
88
89
  inset
90
+ class="filter-field"
89
91
  density="comfortable"
90
92
  true-value="active"
91
93
  false-value="inactive"
92
- :color="camera.status === 'active' ? 'success' : 'grey'"
94
+ :color="camera.status === 'active' ? 'success' : 'muted'"
93
95
  :label="camera.status === 'active' ? 'Active' : 'Inactive'"
94
96
  ></v-switch>
95
97
  </v-col>
@@ -97,27 +99,24 @@
97
99
  </v-form>
98
100
  </v-card-text>
99
101
 
100
- <v-toolbar density="compact">
102
+ <!-- Was a `v-toolbar`: a grey slab with square (`tile`) buttons and a
103
+ hardcoded `color="black"` primary. The gate on Submit is unchanged. -->
104
+ <v-card-actions class="screen-modal__footer">
101
105
  <v-row no-gutters>
102
- <v-col cols="6">
106
+ <v-col cols="6" class="pr-2">
103
107
  <v-btn
104
- tile
105
108
  block
106
- variant="text"
107
- class="text-none"
108
- size="48"
109
+ variant="outlined"
110
+ class="text-none screen-btn-ghost"
109
111
  @click="back"
110
112
  text="Cancel"
111
113
  />
112
114
  </v-col>
113
- <v-col cols="6">
115
+ <v-col cols="6" class="pl-2">
114
116
  <v-btn
115
- tile
116
117
  block
117
118
  variant="flat"
118
- color="black"
119
- class="text-none"
120
- size="48"
119
+ class="text-none screen-btn-primary"
121
120
  :disabled="!validForm || disable || !hasChanges"
122
121
  @click="submit"
123
122
  :loading="disable"
@@ -125,7 +124,7 @@
125
124
  />
126
125
  </v-col>
127
126
  </v-row>
128
- </v-toolbar>
127
+ </v-card-actions>
129
128
  </v-card>
130
129
  </template>
131
130
 
@@ -1,57 +1,45 @@
1
1
  <template>
2
2
  <v-row no-gutters>
3
3
  <v-col cols="12">
4
- <v-card width="100%" variant="outlined" border="thin" rounded="lg">
5
- <v-toolbar density="compact" color="grey-lighten-4 pl-2 pr-4">
6
- <template #prepend>
7
- <v-btn fab icon density="comfortable" @click="getCameraRefresh()">
8
- <v-icon>mdi-refresh</v-icon>
9
- </v-btn>
10
- </template>
11
-
12
- <template #append>
13
- <v-btn
14
- v-if="!prop.readOnly"
15
- variant="flat"
16
- color="primary"
17
- class="text-none"
18
- @click="dialogAdd = true"
19
- >
4
+ <!-- Two `grey-lighten-4` bars - one above the table, one below - are one
5
+ CardToolbar on the card's own surface. The literal grey stayed white
6
+ on the dark theme's card; measured as four 48px white slabs. -->
7
+ <AppCard class="table-card">
8
+ <CardToolbar :count="pageRange">
9
+ <template #left>
10
+ <AppButton
11
+ variant="icon"
12
+ icon="mdi-refresh"
13
+ aria-label="Refresh"
14
+ @click="getCameraRefresh()"
15
+ />
16
+ <AppButton v-if="!prop.readOnly" @click="dialogAdd = true">
20
17
  Add
21
- </v-btn>
18
+ </AppButton>
22
19
  </template>
23
- </v-toolbar>
24
-
25
- <v-card-text class="pa-0 bg-red">
26
- <v-data-table
27
- :headers="computedHeaders"
28
- :items="items"
29
- fixed-header
30
- hide-default-footer
31
- @click:row="handleRowClick"
32
- style="max-height: 300px"
33
- >
34
- <template #item.host="{ value }">
35
- {{ maskHostUrl(value) }}
36
- </template>
37
- </v-data-table>
38
- </v-card-text>
39
20
 
40
- <v-toolbar density="compact" color="grey-lighten-4">
41
- <template #append>
42
- <v-row no-gutters justify="end" align="center">
43
- <span class="mr-2 text-caption text-font gray">
44
- {{ pageRange }}
45
- </span>
46
- <local-pagination
47
- v-model="page"
48
- :length="pages"
49
- @update:value="$emit('update:value', $event)"
50
- />
51
- </v-row>
21
+ <template #right>
22
+ <local-pagination
23
+ v-model="page"
24
+ :length="pages"
25
+ @update:value="$emit('update:value', $event)"
26
+ />
52
27
  </template>
53
- </v-toolbar>
54
- </v-card>
28
+ </CardToolbar>
29
+
30
+ <v-data-table
31
+ :headers="computedHeaders"
32
+ :items="items"
33
+ fixed-header
34
+ hide-default-footer
35
+ @click:row="handleRowClick"
36
+ style="max-height: 300px"
37
+ >
38
+ <template #item.host="{ value }">
39
+ {{ maskHostUrl(value) }}
40
+ </template>
41
+ </v-data-table>
42
+ </AppCard>
55
43
  </v-col>
56
44
 
57
45
  <!-- dialog -->
@@ -302,12 +290,25 @@ const computedHeaders = computed(() => {
302
290
  { title: "URL", key: "host" },
303
291
  ]
304
292
  }else if(prop.type === "anpr"){
305
- return [
293
+ return [
306
294
  { title: "URL", key: "host" },
307
295
  { title: "Type", key: "direction" },
308
296
  ]
309
297
  }
310
- // return prop.headers;
298
+ // A THIRD TYPE FELL OFF THE END. Both arms above are early returns and the
299
+ // fallback was commented out, so `computedHeaders` resolved to `undefined`
300
+ // for any `type` that is neither `ip` nor `anpr` - and `:headers="undefined"`
301
+ // does not mean "no table", it means Vuetify derives the columns from the
302
+ // first item's own keys, i.e. a raw dump of every field including `_id`.
303
+ //
304
+ // `prop.headers` is the component's declared escape hatch for exactly this
305
+ // and nothing was reading it, so the prop was dead. Reading it makes the
306
+ // fallback deterministic and gives a caller a way to supply its own columns.
307
+ //
308
+ // The four commented-out entries in that prop's default (Host, Category,
309
+ // Guard House, Actions) are ANOTHER TEAM'S deliberate change (9610a7d,
310
+ // f24fa80) and are left exactly as they are.
311
+ return prop.headers;
311
312
  });
312
313
 
313
314
  const items = ref<Array<TCamera>>([]);
@@ -1,30 +1,32 @@
1
1
  <template>
2
- <v-card width="100%" :disabled="loading" :loading="loading">
3
- <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-5 px-7 text-center">
4
- <span> {{ promptTitle }}</span>
2
+ <v-card class="screen-modal" width="100%" :disabled="loading" :loading="loading">
3
+ <v-card-text class="screen-modal__body pa-5 my-5 px-7 text-center">
4
+ <span class="screen-card-title"> {{ promptTitle }}</span>
5
5
 
6
- <span v-if="message" class="text-error mt-2">
6
+ <!-- `text-error` is Vuetify's own class over `--v-theme-error`,
7
+ which is the design's `--err` in both themes - already a token,
8
+ so it stays. -->
9
+ <!-- A `div`, as in the Dialog/ twin: on an inline `span` the `mt-2`
10
+ does nothing and the warning ran straight into the title with
11
+ no space - "delete this?This removes the record...". -->
12
+ <div v-if="message" class="text-error mt-2">
7
13
  {{ message }} Do you want to delete anyway?
8
- </span>
14
+ </div>
9
15
  </v-card-text>
10
16
 
11
- <v-toolbar class="pa-0" density="compact">
12
- <v-row no-gutters>
13
- <v-col cols="6" class="pa-0">
14
- <v-btn block variant="text" class="text-none" size="large" tile @click="emit('close')"
15
- height="48">
16
- Cancel
17
- </v-btn>
18
- </v-col>
17
+ <!-- The design's footer: two equal-width buttons, ghost then primary,
18
+ on a bordered strip. The handoff draws no destructive variant, so
19
+ the confirming action takes the primary shape like every other
20
+ modal's Submit. -->
21
+ <div class="screen-modal__footer">
22
+ <v-btn class="screen-btn-ghost" variant="outlined" @click="emit('close')">
23
+ Cancel
24
+ </v-btn>
19
25
 
20
- <v-col cols="6" class="pa-0">
21
- <v-btn block tile variant="flat" class="text-none" size="large" height="48" color="black"
22
- @click="emit('delete')">
23
- Delete
24
- </v-btn>
25
- </v-col>
26
- </v-row>
27
- </v-toolbar>
26
+ <v-btn class="screen-btn-primary" variant="flat" @click="emit('delete')">
27
+ Delete
28
+ </v-btn>
29
+ </div>
28
30
  </v-card>
29
31
  </template>
30
32
 
@@ -48,4 +50,4 @@ const emit = defineEmits(["close", "delete"])
48
50
 
49
51
  </script>
50
52
 
51
- <style scoped></style>
53
+ <style scoped></style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <v-card flat border="sm grey-lighten-2" color="grey-lighten-3" class="w-100">
2
+ <v-card flat class="w-100 member-summary">
3
3
  <v-card-text>
4
4
  <v-row no-gutters>
5
5
  <v-col cols="10" no-gutters>
@@ -13,7 +13,7 @@
13
13
  </v-row>
14
14
  </v-col>
15
15
  <v-col cols="2" class="d-flex align-center justify-center">
16
- <v-btn icon="mdi-trash-outline" size="small" color="red" @click="emit('remove')" />
16
+ <v-btn class="member-summary__remove" icon="mdi-trash-outline" variant="text" size="small" @click="emit('remove')" />
17
17
  </v-col>
18
18
  </v-row>
19
19
  </v-card-text>
@@ -45,4 +45,29 @@ const displayFields: Record<keyof TMemberInfo, string> = {
45
45
 
46
46
  </script>
47
47
 
48
- <style scoped></style>
48
+ <style scoped>
49
+ /*
50
+ * Was `border="sm grey-lighten-2" color="grey-lighten-3"` - two LITERAL light
51
+ * greys, i.e. a pale slab with a pale frame drawn straight across the dark
52
+ * theme. The design draws an added-member row as an inset on the card it sits
53
+ * in, so it takes `--hover` (the neutral wash the chips and avatars use) on
54
+ * `--border`, at the inner radius.
55
+ *
56
+ * The remove action was `color="red"` - not a token, and a solid red circle the
57
+ * design never draws. It is the `--err` glyph the rest of the layer uses.
58
+ */
59
+ .member-summary {
60
+ background: var(--hover);
61
+ border: 1px solid var(--border);
62
+ border-radius: var(--r-inner);
63
+ color: var(--text);
64
+ }
65
+
66
+ .member-summary :deep(.v-card-text) {
67
+ font-size: var(--fs-cell);
68
+ }
69
+
70
+ .member-summary__remove {
71
+ color: var(--err);
72
+ }
73
+ </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <v-card flat border="md black">
2
+ <v-card flat class="screen-card toggle-card">
3
3
  <v-card-text class="d-flex justify-space-between align-center py-0">
4
- <p>{{ label }}</p>
4
+ <p class="toggle-card__label">{{ label }}</p>
5
5
  <v-switch v-model="toggle" :color="toggleColor" hide-details />
6
6
  </v-card-text>
7
7
  </v-card>
@@ -22,4 +22,16 @@ defineProps({
22
22
  const toggle = defineModel({default: false})
23
23
  </script>
24
24
 
25
- <style scoped></style>
25
+ <style scoped>
26
+ /*
27
+ * Was `border="md black"` - a 2px LITERAL black frame, which is a black box
28
+ * drawn across the dark theme. The design draws a settings row as the ordinary
29
+ * 1px card, so this is `.screen-card` plus the design's cell type on the label
30
+ * (Vuetify's `<p>` inherits the body size, not the design's).
31
+ */
32
+ .toggle-card__label {
33
+ font-size: var(--fs-cell);
34
+ color: var(--text);
35
+ margin: 0;
36
+ }
37
+ </style>
@@ -0,0 +1,37 @@
1
+ <!--
2
+ THE IN-CARD TOP ROW.
3
+
4
+ The design does NOT put a screen's tabs above its card - they are the card's
5
+ own first row, with the pagination on the opposite end of that same line, and
6
+ the tab underline meets the card's rule. Today those tabs sit in a
7
+ `v-toolbar`'s extension slot, which stacks them BELOW a separate bar and
8
+ costs a whole row of height.
9
+
10
+ Two shapes, both from the handoff: with tabs (`0 20px`, the tabs supply the
11
+ vertical padding) and without (`10px 14px`, a refresh button on the left).
12
+ This component only places things - the tabs, the count and the pager are
13
+ passed in and keep their own behaviour.
14
+ -->
15
+ <template>
16
+ <div class="app-toolbar" :class="{ 'app-toolbar--plain': !$slots.tabs }">
17
+ <div v-if="$slots.tabs" class="app-tabs" role="tablist">
18
+ <slot name="tabs" />
19
+ </div>
20
+
21
+ <slot name="left" />
22
+
23
+ <div class="app-toolbar__spacer" />
24
+
25
+ <div class="app-toolbar__right">
26
+ <span v-if="count" class="app-toolbar__count">{{ count }}</span>
27
+ <slot name="right" />
28
+ </div>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ defineProps({
34
+ /** The design's `1-1 of 1` range, printed as the screen already computes it. */
35
+ count: { type: String, default: "" },
36
+ });
37
+ </script>
@@ -22,9 +22,7 @@
22
22
 
23
23
  <div class="edit-btn mb-5" v-if="imgEditable">
24
24
  <v-btn
25
- color="primary"
26
- height="42px"
27
- width="100px"
25
+ class="screen-btn-primary"
28
26
  @click.stop="onMediaEdit(item.url, idx)"
29
27
  >
30
28
  Edit
@@ -32,14 +30,9 @@
32
30
  </div>
33
31
 
34
32
  <div class="delete-btn mb-3" v-if="imgDelete">
35
- <v-btn
36
- color="red"
37
- height="42px"
38
- width="100px"
39
- @click.stop="onMediaDelete(item.url)"
40
- >
33
+ <AppButton variant="err" @click.stop="onMediaDelete(item.url)">
41
34
  Delete
42
- </v-btn>
35
+ </AppButton>
43
36
  </div>
44
37
  </v-carousel-item>
45
38
 
@@ -53,20 +46,15 @@
53
46
  <source :src="item.url" />
54
47
  </video>
55
48
  <div class="play-overlay">
56
- <v-btn class="play-btn" icon size="55" color="primary">
49
+ <v-btn class="play-btn" icon size="55">
57
50
  <v-icon icon="mdi-play" size="40" />
58
51
  </v-btn>
59
52
  </div>
60
53
 
61
54
  <div class="delete-btn pb-4" v-if="imgDelete">
62
- <v-btn
63
- color="red"
64
- height="42px"
65
- width="100px"
66
- @click.stop="onMediaDelete(item.url)"
67
- >
55
+ <AppButton variant="err" @click.stop="onMediaDelete(item.url)">
68
56
  Delete
69
- </v-btn>
57
+ </AppButton>
70
58
  </div>
71
59
  </div>
72
60
  </v-carousel-item>
@@ -82,19 +70,16 @@
82
70
  <v-icon
83
71
  :icon="getFileIcon(item.type)"
84
72
  size="150"
85
- :color="getFileIconColor(getFileIcon(item.type))"
73
+ :class="getFileIconTone(getFileIcon(item.type))"
86
74
  />
87
- <div class="text-h6 text-center text-wrap mt-2">{{ item.name }}</div>
75
+ <div class="screen-card-title text-center text-wrap mt-2">
76
+ {{ item.name }}
77
+ </div>
88
78
 
89
79
  <div class="delete-btn pb-4" v-if="imgDelete">
90
- <v-btn
91
- color="red"
92
- height="42px"
93
- width="100px"
94
- @click.stop="onMediaDelete(item.url)"
95
- >
80
+ <AppButton variant="err" @click.stop="onMediaDelete(item.url)">
96
81
  Delete
97
- </v-btn>
82
+ </AppButton>
98
83
  </div>
99
84
  </div>
100
85
  </v-carousel-item>
@@ -105,7 +90,7 @@
105
90
 
106
91
  <!-- Dialog for fullscreen view -->
107
92
  <v-dialog v-model="isDialogOpen" max-width="700">
108
- <v-card>
93
+ <v-card class="screen-modal">
109
94
  <v-btn icon class="close-btn" @click="isDialogOpen = false">
110
95
  <v-icon icon="mdi-close" size="40" />
111
96
  </v-btn>
@@ -346,14 +331,21 @@ const getFileIcon = (type: string) => {
346
331
  return iconMap[type] || "mdi-file-outline";
347
332
  };
348
333
 
349
- function getFileIconColor(icon?: string) {
350
- if (icon === "mdi-file-pdf-box") return "#F44336"; // Red
351
- if (icon === "mdi-file-word-box") return "#2196F3"; // Blue
334
+ /**
335
+ * The file-type tone. The handoff draws no file-type icon palette at all, so
336
+ * the six distinctions this screen already made are kept and simply said in the
337
+ * tokens that carry those tones - the same reading `AttachmentsViewer` took.
338
+ * The one exception is the archive icon, which was purple: there is no purple
339
+ * token, so it falls in with the generic files on `--muted`. That IS a change
340
+ * of meaning and is recorded rather than papered over.
341
+ */
342
+ function getFileIconTone(icon?: string) {
343
+ if (icon === "mdi-file-pdf-box") return "tone-err";
344
+ if (icon === "mdi-file-word-box") return "tone-info";
352
345
  if (icon === "mdi-file-excel-box" || icon === "mdi-file-delimited-outline")
353
- return "#4CAF50"; // Green
354
- if (icon === "mdi-file-powerpoint-box") return "#FF9800"; // Orange
355
- if (icon === "mdi-zip-box-outline") return "#9C27B0"; // Purple
356
- return "grey";
346
+ return "tone-ok";
347
+ if (icon === "mdi-file-powerpoint-box") return "tone-warn";
348
+ return "tone-muted";
357
349
  }
358
350
 
359
351
  const message = ref("");
@@ -419,6 +411,13 @@ async function downloadFile({
419
411
  right: 5%;
420
412
  }
421
413
 
414
+ /**
415
+ * DELIBERATELY NOT `.screen-modal__close`. This close sits ON the picture, not
416
+ * on a card, so the design's borderless muted glyph would be unreadable over a
417
+ * bright photo in light theme and over a dark one in dark theme. The existing
418
+ * dark chip is legible on both, and the handoff draws no media lightbox at all
419
+ * - parity with a readable control wins over a primitive that would disappear.
420
+ */
422
421
  .close-btn {
423
422
  position: absolute;
424
423
  top: 10px;
@@ -440,8 +439,29 @@ async function downloadFile({
440
439
  pointer-events: auto;
441
440
  }
442
441
 
442
+ /* Was `color="primary"`, i.e. the FOREGROUND token used as a fill. The button
443
+ the design fills is `--accent-strong` with `--on-accent-strong` ink. */
443
444
  .play-btn {
444
- border-radius: 9999px;
445
+ border-radius: var(--r-pill);
446
+ background: var(--accent-strong);
447
+ color: var(--on-accent-strong);
448
+ }
449
+
450
+ /* The file-type tones, on tokens instead of six hard-coded hexes. */
451
+ .tone-err {
452
+ color: var(--err);
453
+ }
454
+ .tone-info {
455
+ color: var(--info);
456
+ }
457
+ .tone-ok {
458
+ color: var(--ok);
459
+ }
460
+ .tone-warn {
461
+ color: var(--warn);
462
+ }
463
+ .tone-muted {
464
+ color: var(--muted);
445
465
  }
446
466
 
447
467
  .dialog-video-container {
@@ -1,36 +1,32 @@
1
1
  <template>
2
- <v-card class="mb-2 pa-4 rounded-lg" width="400" elevation="2">
2
+ <v-card class="chat-bubble screen-card mb-2 pa-4" width="400" elevation="0">
3
3
  <v-row no-gutters align="center">
4
4
  <v-col cols="auto" class="mr-3">
5
- <v-avatar color="surface-variant" size="35">
5
+ <v-avatar class="chat-bubble__avatar" size="35">
6
6
  <v-img v-if="currentUser?.profile" width="15" height="15" />
7
- <span v-else class="text-h5">{{ getNameInitials(senderName) }}</span>
7
+ <span v-else>{{ getNameInitials(senderName) }}</span>
8
8
  </v-avatar>
9
9
  </v-col>
10
10
 
11
11
  <v-col class="d-flex flex-column">
12
- <span class="text-body-2 font-weight-medium">{{ senderName }}</span>
13
- <span class="text-caption text-grey">{{ role }}</span>
12
+ <span class="chat-bubble__sender">{{ senderName }}</span>
13
+ <span class="chat-bubble__sub">{{ role }}</span>
14
14
  </v-col>
15
15
  </v-row>
16
16
 
17
17
  <v-row no-gutters class="mt-1">
18
18
  <v-col>
19
- <span class="py-2">{{ message }}</span>
19
+ <span class="chat-bubble__text py-2">{{ message }}</span>
20
20
 
21
21
  <v-row no-gutters justify="space-between" align="center" class="mt-1">
22
22
  <v-col cols="auto">
23
- <span class="text-caption">{{ timestamp }}</span>
23
+ <span class="chat-bubble__sub">{{ timestamp }}</span>
24
24
  </v-col>
25
- <v-col
26
- v-if="isCurrentUser"
27
- cols="auto"
28
- class="d-flex align-center bg-grey-200"
29
- >
30
- <v-icon size="16" class="mr-1 text--secondary"
25
+ <v-col v-if="isCurrentUser" cols="auto" class="d-flex align-center">
26
+ <v-icon size="16" class="chat-bubble__sub mr-1"
31
27
  >mdi-eye-outline</v-icon
32
28
  >
33
- <span class="text-caption text--secondary">{{ seenLabel }}</span>
29
+ <span class="chat-bubble__sub">{{ seenLabel }}</span>
34
30
  </v-col>
35
31
  </v-row>
36
32
  </v-col>
@@ -51,3 +47,36 @@ defineProps<{
51
47
  const { currentUser } = useLocalAuth();
52
48
  const { getNameInitials } = useUtils();
53
49
  </script>
50
+
51
+ <style scoped>
52
+ .chat-bubble {
53
+ font-family: var(--font-sans);
54
+ color: var(--text);
55
+ }
56
+
57
+ /* Was `color="surface-variant"` with the initials at `text-h5`, i.e. a 24px
58
+ pair of letters in a 35px circle. The design's avatar is the tone wash with
59
+ the accent ink, and the initials fit inside it. */
60
+ .chat-bubble__avatar {
61
+ background: var(--hover);
62
+ color: var(--text2);
63
+ font-size: 13px;
64
+ font-weight: 700;
65
+ }
66
+
67
+ .chat-bubble__sender {
68
+ font-size: var(--fs-cell);
69
+ font-weight: 600;
70
+ }
71
+
72
+ .chat-bubble__text {
73
+ font-size: var(--fs-cell);
74
+ }
75
+
76
+ /* The role, the timestamp and the seen label were `text-grey`, `text-caption`
77
+ and `text--secondary` - three different greys for one sub-line. One tone. */
78
+ .chat-bubble__sub {
79
+ font-size: var(--fs-chip);
80
+ color: var(--muted);
81
+ }
82
+ </style>