@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
@@ -21,10 +21,8 @@
21
21
  <v-row no-gutters align="center" class="w-100">
22
22
  <v-col cols="auto" v-if="canCreateScheduleTask">
23
23
  <v-btn
24
- class="text-none"
25
- rounded="pill"
26
- variant="tonal"
27
- size="large"
24
+ class="text-none screen-btn-primary"
25
+ variant="flat"
28
26
  @click="openFormDialog"
29
27
  >
30
28
  Create Schedule Task
@@ -33,7 +31,7 @@
33
31
 
34
32
  <v-spacer />
35
33
 
36
- <v-col cols="auto">
34
+ <v-col cols="auto" class="filter-field">
37
35
  <v-text-field
38
36
  v-model="searchInput"
39
37
  density="compact"
@@ -49,28 +47,31 @@
49
47
 
50
48
  <template #item.areas="{ value }">
51
49
  <div v-if="value && value.length > 0">
52
- <v-chip
50
+ <StatusChip
53
51
  v-for="(area, idx) in value.slice(0, 2)"
54
52
  :key="idx"
55
- size="small"
56
53
  class="mr-1 mb-1"
57
- >
58
- {{ area.name }}
59
- </v-chip>
60
- <v-chip v-if="value.length > 2" size="small" class="mb-1">
61
- +{{ value.length - 2 }} more
62
- </v-chip>
54
+ :dot="false"
55
+ tone="neutral"
56
+ :label="area.name"
57
+ />
58
+ <StatusChip
59
+ v-if="value.length > 2"
60
+ class="mb-1"
61
+ :dot="false"
62
+ tone="neutral"
63
+ :label="`+${value.length - 2} more`"
64
+ />
63
65
  </div>
64
66
  <span v-else>N/A</span>
65
67
  </template>
66
68
 
67
69
  <template #item.status="{ value }">
68
- <v-chip
69
- :color="value === 'active' ? 'success' : 'default'"
70
+ <StatusChip
70
71
  class="text-capitalize"
71
- >
72
- {{ value || "N/A" }}
73
- </v-chip>
72
+ :status="value"
73
+ :label="value || 'N/A'"
74
+ />
74
75
  </template>
75
76
  </TableMain>
76
77
 
@@ -270,15 +271,11 @@
270
271
  Status:
271
272
  </v-col>
272
273
  <v-col cols="7" class="text-subtitle-2">
273
- <v-chip
274
- :color="
275
- selectedTask.status === 'active' ? 'success' : 'default'
276
- "
277
- size="small"
274
+ <StatusChip
278
275
  class="text-capitalize"
279
- >
280
- {{ selectedTask.status || "N/A" }}
281
- </v-chip>
276
+ :status="selectedTask.status"
277
+ :label="selectedTask.status || 'N/A'"
278
+ />
282
279
  </v-col>
283
280
  </v-row>
284
281
 
@@ -300,51 +297,41 @@
300
297
  </HygieneUpdateMoreAction>
301
298
  </v-dialog>
302
299
 
303
- <v-dialog v-model="dialogDeleteTask" max-width="450">
304
- <v-card>
305
- <v-toolbar>
306
- <v-row no-gutters class="fill-height px-6" align="center">
307
- <span class="font-weight-bold text-h6 text-capitalize">
308
- Delete {{ selectedTask?.title || "Schedule Task" }}
309
- </span>
310
- </v-row>
311
- </v-toolbar>
312
- <v-card-text>
313
- <span class="text-subtitle-2"
314
- >Are you sure you want to delete this schedule task?</span
315
- >
300
+ <!--
301
+ Was a `v-toolbar` title bar (Vuetify paints that from its own `surface`,
302
+ a grey slab visibly lighter than the card on dark) over a second toolbar
303
+ carrying two block buttons, the confirm one on `color="black"` - not a
304
+ token, so it drew a light-theme fill on the dark theme. It is the shared
305
+ confirmation shape now, the same one every converted screen uses.
306
+ -->
307
+ <v-dialog v-model="dialogDeleteTask" max-width="520">
308
+ <v-card class="screen-modal">
309
+ <v-card-title class="text-capitalize">
310
+ Delete {{ selectedTask?.title || "Schedule Task" }}
311
+ </v-card-title>
312
+
313
+ <v-card-text class="screen-modal__body">
314
+ Are you sure you want to delete this schedule task?
316
315
  </v-card-text>
317
316
 
318
- <v-toolbar class="pa-0" density="compact">
319
- <v-row no-gutters>
320
- <v-col cols="6" class="pa-0">
321
- <v-btn
322
- block
323
- variant="text"
324
- class="text-none"
325
- size="large"
326
- @click="dialogDeleteTask = false"
327
- height="48"
328
- >
329
- Cancel
330
- </v-btn>
331
- </v-col>
332
-
333
- <v-col cols="6" class="pa-0">
334
- <v-btn
335
- block
336
- variant="flat"
337
- color="black"
338
- class="text-none font-weight-bold"
339
- height="48"
340
- :loading="submitting"
341
- @click="_deleteScheduleTask"
342
- >
343
- Delete
344
- </v-btn>
345
- </v-col>
346
- </v-row>
347
- </v-toolbar>
317
+ <div class="screen-modal__footer">
318
+ <v-btn
319
+ class="screen-btn-ghost"
320
+ variant="outlined"
321
+ :disabled="submitting"
322
+ @click="dialogDeleteTask = false"
323
+ >
324
+ Cancel
325
+ </v-btn>
326
+ <v-btn
327
+ class="screen-btn-primary"
328
+ variant="flat"
329
+ :loading="submitting"
330
+ @click="_deleteScheduleTask"
331
+ >
332
+ Delete
333
+ </v-btn>
334
+ </div>
348
335
  </v-card>
349
336
  </v-dialog>
350
337
 
@@ -1,44 +1,35 @@
1
1
  <template>
2
- <v-card width="100%">
3
- <v-toolbar>
4
- <v-row no-gutters>
5
- <v-col cols="12" class="text-h6 font-weight-bold px-3">Vehicle Number ({{ vehicleNumber }})</v-col>
6
- </v-row>
7
- </v-toolbar>
2
+ <v-card width="100%" class="screen-modal search-vehicle-user">
3
+ <v-card-title>Vehicle Number ({{ vehicleNumber }})</v-card-title>
8
4
 
9
- <v-card-text style="max-height: 100vh; overflow-y: auto">
10
- <v-data-table :items="prop.vehicleNumberUsersList" hide-default-footer :headers="headers" density="comfortable"
11
- item-key="_id ">
12
- <template #item.name="{ item }">
13
- <span class="d-flex align-center ga-2">
14
- <span>
15
- <AvatarMain :name="item?.name" :size="20" :id="item?._id" />
5
+ <div class="screen-modal__body search-vehicle-user__body">
6
+ <!-- `table-card` is the shared table card's own class, so the header
7
+ type, the cell padding and the row rule are the design's - without
8
+ TableMain's page toolbar, which a two-row picker inside a dialog
9
+ has nothing to put in. -->
10
+ <AppCard class="table-card">
11
+ <v-data-table :items="prop.vehicleNumberUsersList" hide-default-footer :headers="headers" density="comfortable"
12
+ item-key="_id ">
13
+ <template #item.name="{ item }">
14
+ <span class="d-flex align-center ga-2">
15
+ <span>
16
+ <AvatarMain :name="item?.name" :size="20" :id="item?._id" />
17
+ </span>
18
+ <span class="text-capitalize">{{ item?.name }}</span>
16
19
  </span>
17
- <span class="text-capitalize">{{ item?.name }}</span>
18
- </span>
19
- </template>
20
+ </template>
20
21
 
21
- <template #item.actions="{ item }">
22
- <v-btn text="Select" rounded="md" flat color="blue" density="comfortable" :ripple="false" @click="handleSelectUser(item)" />
23
- </template>
24
- </v-data-table>
25
- </v-card-text>
22
+ <template #item.actions="{ item }">
23
+ <AppButton variant="ghost" @click="handleSelectUser(item)">Select</AppButton>
24
+ </template>
25
+ </v-data-table>
26
+ </AppCard>
27
+ </div>
26
28
 
27
- <v-toolbar class="pa-0" density="compact">
28
- <v-row no-gutters>
29
- <v-col cols="6" class="pa-0">
30
- <v-btn block variant="text" class="text-none" size="large" @click="emit('close')" height="48">
31
- Close
32
- </v-btn>
33
- </v-col>
34
-
35
- <v-col cols="6" class="pa-0">
36
- <v-btn block variant="flat" color="black" class="text-none" height="48" tile @click="emit('close')">
37
- Add Different User
38
- </v-btn>
39
- </v-col>
40
- </v-row>
41
- </v-toolbar>
29
+ <div class="search-vehicle-user__footer">
30
+ <AppButton variant="ghost" @click="emit('close')">Close</AppButton>
31
+ <AppButton @click="emit('close')">Add Different User</AppButton>
32
+ </div>
42
33
  <v-dialog v-model="confirmAction" persistent max-width="450">
43
34
  <DialogReplaceAutofillPrompt @close="confirmAction = false" @proceed="handleUpdateUserDetails"/>
44
35
  </v-dialog>
@@ -89,4 +80,15 @@ onMounted(() => {
89
80
  })
90
81
  </script>
91
82
 
92
- <style scoped></style>
83
+ <style scoped>
84
+ .search-vehicle-user__body {
85
+ padding: 4px 20px 0;
86
+ }
87
+
88
+ .search-vehicle-user__footer {
89
+ display: flex;
90
+ justify-content: flex-end;
91
+ gap: 8px;
92
+ padding: 16px 20px 20px;
93
+ }
94
+ </style>
@@ -1,21 +1,29 @@
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">
6
- {{ props.title }}
7
- </span>
8
- </v-row>
9
- </v-toolbar>
10
- <v-card-text style="max-height: 100vh; overflow-y: auto">
2
+ <!--
3
+ A dialog card, so it wears `.screen-modal` (16px corner, the modal shadow,
4
+ the `--card` surface) rather than Vuetify's 4px factory card. The two
5
+ `v-toolbar`s this used to have were grey slabs standing in for a title row
6
+ and a footer; a `v-card-title` and a `v-card-actions` are those two rows
7
+ without the slab, and they follow the theme instead of staying grey in dark.
8
+ -->
9
+ <v-card width="100%" class="screen-modal">
10
+ <v-card-title>{{ props.title }}</v-card-title>
11
+
12
+ <v-card-text class="screen-modal__body">
11
13
  <v-form v-model="validForm" :disabled="disable">
12
14
  <v-row no-gutters>
13
15
  <v-col cols="12" class="mt-2">
14
16
  <v-row no-gutters>
15
17
  <InputLabel class="text-capitalize" title="Email" required />
16
18
  <v-col cols="12">
19
+ <!-- Still a `v-text-field`, not an `AppField`: the Submit
20
+ button is gated on `validForm`, which only exists because
21
+ these `:rules` run. `.filter-field` is the established way
22
+ to give a Vuetify input the design's 40px/10px/13.5px shape
23
+ without taking its validation away. -->
17
24
  <v-text-field
18
25
  v-model="email"
26
+ class="filter-field"
19
27
  density="comfortable"
20
28
  :rules="[requiredRule, emailRule]"
21
29
  ></v-text-field>
@@ -38,27 +46,28 @@
38
46
  </v-form>
39
47
  </v-card-text>
40
48
 
41
- <v-toolbar>
42
- <v-row class="px-6">
43
- <v-col cols="6">
49
+ <!-- The two-across, full-width footer is kept: the handoff draws no modal,
50
+ so its layout is not specified and changing it would be invention.
51
+ What changes is the chrome - `color="black"` was a hardcoded fill that
52
+ ignored the theme, and the bare text Cancel had no shape at all. -->
53
+ <v-card-actions class="screen-modal__footer">
54
+ <v-row class="px-4" no-gutters>
55
+ <v-col cols="6" class="pr-2">
44
56
  <v-btn
45
57
  block
46
- variant="text"
47
- class="text-none"
48
- size="large"
58
+ variant="outlined"
59
+ class="text-none screen-btn-ghost"
49
60
  @click="cancel"
50
61
  >
51
62
  Cancel
52
63
  </v-btn>
53
64
  </v-col>
54
65
 
55
- <v-col cols="6">
66
+ <v-col cols="6" class="pl-2">
56
67
  <v-btn
57
68
  block
58
69
  variant="flat"
59
- color="black"
60
- class="text-none"
61
- size="large"
70
+ class="text-none screen-btn-primary"
62
71
  :disabled="!validForm"
63
72
  @click="submit"
64
73
  >
@@ -66,7 +75,7 @@
66
75
  </v-btn>
67
76
  </v-col>
68
77
  </v-row>
69
- </v-toolbar>
78
+ </v-card-actions>
70
79
  </v-card>
71
80
  </template>
72
81
 
@@ -0,0 +1,155 @@
1
+ <template>
2
+ <!-- `AppCard` is the design's card - 14px radius, a 1px `--border` rule and
3
+ the one-pixel shadow on `--card`. The `v-card rounded="lg"
4
+ variant="outlined"` it replaced was Vuetify's own card at its own
5
+ radius and border weight. -->
6
+ <AppCard v-if="invitation" class="sp-invite-prompt">
7
+ <div class="d-flex align-start ga-3 pa-4">
8
+ <v-avatar color="primary" variant="tonal" size="44">
9
+ <v-icon>mdi-office-building-marker-outline</v-icon>
10
+ </v-avatar>
11
+ <div class="flex-grow-1">
12
+ <div class="screen-card-title">
13
+ {{ invitation.orgName }} has invited you to {{ invitation.siteName }}
14
+ </div>
15
+ <div class="screen-hint sp-invite-prompt__sub">
16
+ Approved by Seven365 · {{ expiryLine }}
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ <div class="px-4 sp-invite-prompt__body">
22
+ {{ invitation.orgName }} would like your company to provide services at
23
+ <strong>{{ invitation.siteName }}</strong
24
+ >. If you accept, this site will be added to your list of sites.
25
+ </div>
26
+
27
+ <div class="d-flex align-center ga-2 px-4 py-4">
28
+ <!-- Both stay `v-btn`s: `loading` is the only signal that an accept or a
29
+ decline is in flight, and `AppButton` has no equivalent. They take
30
+ the design's two button classes instead. -->
31
+ <v-btn
32
+ variant="flat"
33
+ class="screen-btn-primary"
34
+ :loading="working === 'accept'"
35
+ :disabled="Boolean(working) || !open"
36
+ @click="accept"
37
+ >
38
+ Accept
39
+ </v-btn>
40
+ <v-btn
41
+ variant="outlined"
42
+ class="screen-btn-ghost"
43
+ :loading="working === 'decline'"
44
+ :disabled="Boolean(working) || !open"
45
+ @click="decline"
46
+ >
47
+ Decline
48
+ </v-btn>
49
+ <v-spacer />
50
+ <!-- Was a raw `v-chip` on Vuetify's fixed `success` green, or no colour
51
+ at all for every other outcome. `StatusChip` maps the status WORD
52
+ through the shared `utils/status.ts` tones, so "complete" and
53
+ "declined" come out the same colours they do everywhere else. -->
54
+ <StatusChip
55
+ v-if="!open"
56
+ :status="invitation.status"
57
+ :label="invitation.statusLabel"
58
+ />
59
+ </div>
60
+ </AppCard>
61
+
62
+ <AppCard v-else-if="error">
63
+ <div class="pa-4 sp-invite-prompt__body">{{ error }}</div>
64
+ </AppCard>
65
+ </template>
66
+
67
+ <script setup lang="ts">
68
+ /**
69
+ * The invitation as the service provider sees it — inside the app they already
70
+ * use, from the session they already have.
71
+ *
72
+ * There is deliberately no sign-up and no one-time code anywhere on this
73
+ * screen: a company that already exists on iService365 never creates a second
74
+ * account. The email they receive only carries them here.
75
+ *
76
+ * An invitation that has not been approved by Seven365 is not readable at all —
77
+ * the server answers "not found" — so this component cannot show one.
78
+ */
79
+ const props = defineProps({
80
+ invitationId: { type: String, required: true },
81
+ });
82
+
83
+ const emit = defineEmits<{ (e: "answered", status: string): void }>();
84
+
85
+ const { getInvitation, declineInvitation } = useServiceProviderInvitation();
86
+ const { addViaInvite } = useCustomerSite();
87
+
88
+ const invitation = ref<any>(null);
89
+ const error = ref("");
90
+ const working = ref("");
91
+
92
+ const open = computed(() => invitation.value?.status === "pending");
93
+
94
+ const expiryLine = computed(() => {
95
+ const expires = invitation.value?.expireAt;
96
+ if (!expires) return "";
97
+ const days = Math.max(
98
+ 0,
99
+ Math.ceil((new Date(expires).getTime() - Date.now()) / 86400000),
100
+ );
101
+ if (!open.value) return "no longer waiting for an answer";
102
+ return days <= 1 ? "expires within a day" : `expires in ${days} days`;
103
+ });
104
+
105
+ async function load() {
106
+ try {
107
+ invitation.value = await getInvitation(props.invitationId);
108
+ } catch (err: any) {
109
+ error.value =
110
+ err?.data?.message || "This invitation is no longer available.";
111
+ }
112
+ }
113
+
114
+ async function accept() {
115
+ working.value = "accept";
116
+ try {
117
+ await addViaInvite(props.invitationId);
118
+ await load();
119
+ emit("answered", "complete");
120
+ } catch (err: any) {
121
+ error.value = err?.data?.message || "Could not accept this invitation.";
122
+ } finally {
123
+ working.value = "";
124
+ }
125
+ }
126
+
127
+ async function decline() {
128
+ working.value = "decline";
129
+ try {
130
+ await declineInvitation(props.invitationId);
131
+ await load();
132
+ emit("answered", "declined");
133
+ } catch (err: any) {
134
+ error.value = err?.data?.message || "Could not decline this invitation.";
135
+ } finally {
136
+ working.value = "";
137
+ }
138
+ }
139
+
140
+ await load();
141
+ </script>
142
+
143
+ <style scoped>
144
+ /* The title was a hand-set 1.05rem/600; `.screen-card-title` is the design's
145
+ 15.5px/800, so only the wrap and the leading are left here. */
146
+ .sp-invite-prompt :deep(.screen-card-title) {
147
+ display: block;
148
+ line-height: 1.35;
149
+ }
150
+
151
+ .sp-invite-prompt__sub,
152
+ .sp-invite-prompt__body {
153
+ font-size: var(--fs-cell);
154
+ }
155
+ </style>