@7365admin1/layer-common 3.2.1 → 3.2.2-staging.100

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 (123) hide show
  1. package/.changeset/camera-wall-gated-endpoint.md +47 -0
  2. package/.changeset/camera-wall-plain-english.md +60 -0
  3. package/.changeset/camera-wall-selection-and-guidance.md +65 -0
  4. package/.changeset/dark-primary-contrast.md +39 -0
  5. package/.changeset/dashboard-dark-theme-contrast.md +15 -0
  6. package/.changeset/notification-preferences.md +17 -0
  7. package/.changeset/pm-sidebar-grouping-and-list-scaffold.md +27 -0
  8. package/.changeset/service-provider-invitation-actions.md +28 -0
  9. package/assets/css/primitives.css +680 -0
  10. package/assets/css/screens.css +541 -0
  11. package/assets/css/shell.css +258 -0
  12. package/assets/css/tokens.css +220 -0
  13. package/components/AccessCardQrTagging.vue +1 -1
  14. package/components/AccessManagement.vue +53 -72
  15. package/components/AppButton.vue +52 -0
  16. package/components/AppCard.vue +20 -0
  17. package/components/AppDateField.vue +35 -0
  18. package/components/AppField.vue +46 -0
  19. package/components/AppKpiTile.vue +65 -0
  20. package/components/AppSegmented.vue +38 -0
  21. package/components/AppSelect.vue +203 -0
  22. package/components/AreaChecklistHistoryMain.vue +6 -2
  23. package/components/AreaMain.vue +9 -17
  24. package/components/AttendanceMain.vue +4 -3
  25. package/components/Avatar/Main.vue +54 -2
  26. package/components/BillingMain.vue +26 -30
  27. package/components/BuildingManagement/buildings.vue +27 -38
  28. package/components/BuildingManagement/units.vue +26 -42
  29. package/components/BulletinBoardManagement.vue +23 -10
  30. package/components/CameraWall.vue +1034 -0
  31. package/components/CameraWallTile.vue +818 -0
  32. package/components/CardToolbar.vue +37 -0
  33. package/components/CleaningScheduleMain.vue +29 -46
  34. package/components/ClientMain.vue +90 -78
  35. package/components/DashboardEmptyState.vue +11 -1
  36. package/components/DashboardMain.vue +349 -275
  37. package/components/DashboardPanel.vue +1 -1
  38. package/components/DocumentManagement.vue +129 -93
  39. package/components/EntryPassInformation.vue +4 -4
  40. package/components/EntryPassMain.vue +49 -27
  41. package/components/EquipmentItemMain.vue +4 -6
  42. package/components/EquipmentManagementMain.vue +9 -7
  43. package/components/FeedbackMain.vue +42 -56
  44. package/components/FormDialog.vue +60 -21
  45. package/components/HidAccessLogDashboard.vue +119 -44
  46. package/components/HidCameraCaptureDialog.vue +199 -0
  47. package/components/HidIntercomManagement.vue +825 -202
  48. package/components/HidQrCodeConfiguration.vue +927 -93
  49. package/components/HidServiceSettingsPanel.vue +20 -1
  50. package/components/HidUserEnrollment.vue +454 -106
  51. package/components/InvitationMain.vue +46 -61
  52. package/components/Layout/Header.vue +289 -37
  53. package/components/Layout/NavigationDrawer.vue +340 -30
  54. package/components/ManageChecklistMain.vue +17 -17
  55. package/components/MemberMain.vue +79 -60
  56. package/components/MyAttendanceMain.vue +3 -5
  57. package/components/NavigationItem.vue +9 -0
  58. package/components/Nfc/NFCPatrolRouteMain.vue +116 -103
  59. package/components/NotificationSettings.vue +361 -0
  60. package/components/OnlineFormConfigurationForm.vue +620 -224
  61. package/components/OnlineFormFill.vue +36 -8
  62. package/components/OnlineFormsConfiguration.vue +7 -3
  63. package/components/PageHeader.vue +43 -0
  64. package/components/PassInformation.vue +104 -45
  65. package/components/QrTemplate/CreditCardLandscape.vue +19 -12
  66. package/components/QrTemplate/PrintDialog.vue +209 -196
  67. package/components/RolePermissionMain.vue +184 -91
  68. package/components/ScanVisitorQRCode.vue +35 -7
  69. package/components/ScheduleAreaMain.vue +15 -49
  70. package/components/ScheduleTaskMain.vue +23 -26
  71. package/components/ScheduleTastTicketMain.vue +18 -43
  72. package/components/ServiceProviderInvitationPrompt.vue +150 -0
  73. package/components/ServiceProviderMain.vue +346 -157
  74. package/components/SiteSettings.vue +25 -10
  75. package/components/SpecificAttr.vue +10 -2
  76. package/components/StatusChip.vue +93 -0
  77. package/components/SwitchContext.vue +33 -1
  78. package/components/TableHygiene.vue +29 -46
  79. package/components/TableList.vue +1 -1
  80. package/components/TableListSecondary.vue +1 -1
  81. package/components/TableMain.vue +161 -77
  82. package/components/TableV3.vue +61 -66
  83. package/components/UnitMain.vue +9 -17
  84. package/components/VehicleManagement.vue +20 -9
  85. package/components/VisitorForm.vue +294 -78
  86. package/components/VisitorManagement.vue +221 -71
  87. package/components/VisitorSocketPopUp.vue +56 -2
  88. package/components/WorkOrder/Main.vue +42 -51
  89. package/composables/useComment.ts +3 -3
  90. package/composables/useHidAmico.ts +151 -0
  91. package/composables/useHidNavigation.ts +0 -7
  92. package/composables/useLocalAuth.ts +9 -36
  93. package/composables/useNotificationPreference.ts +87 -0
  94. package/composables/useOnlineFormPages.ts +2 -0
  95. package/composables/useOrg.ts +1 -1
  96. package/composables/useRole.ts +22 -0
  97. package/composables/useServiceProviderInvitation.ts +145 -0
  98. package/composables/useSipWebPhone.ts +336 -0
  99. package/composables/useSiteSettings.ts +50 -0
  100. package/composables/useThemePreference.ts +63 -0
  101. package/composables/useVisitor.ts +6 -1
  102. package/composables/useVisitorSocket.ts +26 -0
  103. package/composables/useWebUsb.ts +127 -37
  104. package/nuxt.config.ts +31 -0
  105. package/package.json +4 -1
  106. package/pages/[org]/[site]/access-mgmt/intercom/index.vue +1 -1
  107. package/pages/notification-settings.vue +19 -0
  108. package/plugins/secure-member.client.ts +21 -56
  109. package/plugins/vuetify.ts +68 -9
  110. package/test/visitor-socket.test.mjs +36 -0
  111. package/types/org.d.ts +2 -0
  112. package/types/site.d.ts +71 -0
  113. package/utils/camera-wall.test.ts +571 -0
  114. package/utils/camera-wall.ts +926 -0
  115. package/utils/nav-sections.test.ts +190 -0
  116. package/utils/nav-sections.ts +151 -0
  117. package/utils/status.test.ts +77 -0
  118. package/utils/status.ts +90 -0
  119. package/utils/theme.test.ts +534 -0
  120. package/utils/theme.ts +294 -0
  121. package/components/HidIdentityMapping.vue +0 -975
  122. package/middleware/member.ts +0 -4
  123. package/pages/[org]/[site]/access-mgmt/identity-mapping/index.vue +0 -23
@@ -32,13 +32,18 @@
32
32
  </template>
33
33
 
34
34
  <template #item.createdBy="{ item }">
35
- <v-avatar
36
- size="32"
37
- class="mr-2"
38
- :color="getAvatarColor(item.createdBy)"
39
- >
40
- <span class="white--text">{{ getInitials(item.createdBy) }}</span>
41
- </v-avatar>
35
+ <!--
36
+ THE 3.12:1 `HS` CHIP.
37
+
38
+ This was a hand-rolled copy of `AvatarMain` with two problems: its
39
+ fill was Vuetify's MATERIAL `blue`/`purple`/`grey` (not a theme
40
+ token, so no `on-*` pair applied to it) and its `white--text` is
41
+ Vuetify 2 syntax that does nothing in Vuetify 3 - leaving Vuetify to
42
+ derive WHITE, which reads 3.12:1 on that blue in BOTH themes.
43
+ `AvatarMain` draws the same circle with the same initials and now
44
+ guarantees its label clears 4.5:1.
45
+ -->
46
+ <AvatarMain :name="item.createdBy" :size="32" class="mr-2" />
42
47
  {{ item.createdBy || "N/A" }}
43
48
  </template>
44
49
 
@@ -47,13 +52,7 @@
47
52
  </template>
48
53
 
49
54
  <template #item.status="{ value }">
50
- <v-chip
51
- :color="getStatusColor(value)"
52
- class="font-weight-bold"
53
- style="background: #ffe6c2; color: #ff9800"
54
- >
55
- {{ value || "To-Do" }}
56
- </v-chip>
55
+ <StatusChip :status="value || 'To-Do'" :label="value || 'To-Do'" />
57
56
  </template>
58
57
  <!-- Completion Date/Time -->
59
58
  <template #item.completionDate="{ value }">
@@ -61,7 +60,11 @@
61
60
  </template>
62
61
  <!-- Action (Accept button) -->
63
62
  <template #item.action="{ item }">
64
- <v-btn outlined class="accept-btn" @click.stop="acceptTask(item)">
63
+ <v-btn
64
+ variant="outlined"
65
+ class="text-none screen-btn-ghost"
66
+ @click.stop="acceptTask(item)"
67
+ >
65
68
  Accept
66
69
  </v-btn>
67
70
  </template>
@@ -133,24 +136,6 @@ const headers = [
133
136
 
134
137
  const { formatDate } = useUtils();
135
138
 
136
- function getInitials(name: string) {
137
- if (!name) return "";
138
- return name
139
- .split(" ")
140
- .map((n) => n[0])
141
- .join("")
142
- .toUpperCase();
143
- }
144
- function getAvatarColor(name: string) {
145
- if (name === "Demo Smith") return "purple";
146
- if (name === "Hygiene SP") return "blue";
147
- return "grey";
148
- }
149
- function getStatusColor(status: string) {
150
- if (status === "To-Do") return "orange";
151
- if (status === "Completed") return "green";
152
- return "grey";
153
- }
154
139
  function acceptTask(item: any) {
155
140
  selectedTask.value = item;
156
141
  showAcceptDialog.value = true;
@@ -170,13 +155,3 @@ function onRowClick(data: any) {
170
155
  }
171
156
  }
172
157
  </script>
173
-
174
- <style scoped>
175
- .accept-btn {
176
- border: 1px solid #333;
177
- background: #fff;
178
- border-radius: 4px;
179
- cursor: pointer;
180
- min-width: 80px;
181
- }
182
- </style>
@@ -0,0 +1,150 @@
1
+ <template>
2
+ <v-card
3
+ v-if="invitation"
4
+ width="100%"
5
+ rounded="lg"
6
+ variant="outlined"
7
+ border="thin"
8
+ class="sp-invite-prompt"
9
+ >
10
+ <v-card-item>
11
+ <template #prepend>
12
+ <v-avatar color="primary" variant="tonal" size="44">
13
+ <v-icon>mdi-office-building-marker-outline</v-icon>
14
+ </v-avatar>
15
+ </template>
16
+ <v-card-title class="text-wrap sp-invite-prompt-title">
17
+ {{ invitation.orgName }} has invited you to {{ invitation.siteName }}
18
+ </v-card-title>
19
+ <v-card-subtitle class="text-wrap">
20
+ Approved by Seven365 · {{ expiryLine }}
21
+ </v-card-subtitle>
22
+ </v-card-item>
23
+
24
+ <v-card-text class="text-body-2">
25
+ {{ invitation.orgName }} would like your company to provide services at
26
+ <strong>{{ invitation.siteName }}</strong
27
+ >. If you accept, this site will be added to your list of sites.
28
+ </v-card-text>
29
+
30
+ <v-card-actions class="px-4 pb-4">
31
+ <v-btn
32
+ variant="flat"
33
+ color="primary"
34
+ class="text-none"
35
+ :loading="working === 'accept'"
36
+ :disabled="Boolean(working) || !open"
37
+ @click="accept"
38
+ >
39
+ Accept
40
+ </v-btn>
41
+ <v-btn
42
+ variant="outlined"
43
+ class="text-none ml-2"
44
+ :loading="working === 'decline'"
45
+ :disabled="Boolean(working) || !open"
46
+ @click="decline"
47
+ >
48
+ Decline
49
+ </v-btn>
50
+ <v-spacer />
51
+ <v-chip
52
+ v-if="!open"
53
+ size="small"
54
+ variant="tonal"
55
+ class="text-none"
56
+ :color="invitation.status === 'complete' ? 'success' : undefined"
57
+ >
58
+ {{ invitation.statusLabel }}
59
+ </v-chip>
60
+ </v-card-actions>
61
+ </v-card>
62
+
63
+ <v-card v-else-if="error" width="100%" rounded="lg" variant="outlined" border="thin">
64
+ <v-card-text class="text-body-2">{{ error }}</v-card-text>
65
+ </v-card>
66
+ </template>
67
+
68
+ <script setup lang="ts">
69
+ /**
70
+ * The invitation as the service provider sees it — inside the app they already
71
+ * use, from the session they already have.
72
+ *
73
+ * There is deliberately no sign-up and no one-time code anywhere on this
74
+ * screen: a company that already exists on iService365 never creates a second
75
+ * account. The email they receive only carries them here.
76
+ *
77
+ * An invitation that has not been approved by Seven365 is not readable at all —
78
+ * the server answers "not found" — so this component cannot show one.
79
+ */
80
+ const props = defineProps({
81
+ invitationId: { type: String, required: true },
82
+ });
83
+
84
+ const emit = defineEmits<{ (e: "answered", status: string): void }>();
85
+
86
+ const { getInvitation, declineInvitation } = useServiceProviderInvitation();
87
+ const { addViaInvite } = useCustomerSite();
88
+
89
+ const invitation = ref<any>(null);
90
+ const error = ref("");
91
+ const working = ref("");
92
+
93
+ const open = computed(() => invitation.value?.status === "pending");
94
+
95
+ const expiryLine = computed(() => {
96
+ const expires = invitation.value?.expireAt;
97
+ if (!expires) return "";
98
+ const days = Math.max(
99
+ 0,
100
+ Math.ceil((new Date(expires).getTime() - Date.now()) / 86400000),
101
+ );
102
+ if (!open.value) return "no longer waiting for an answer";
103
+ return days <= 1 ? "expires within a day" : `expires in ${days} days`;
104
+ });
105
+
106
+ async function load() {
107
+ try {
108
+ invitation.value = await getInvitation(props.invitationId);
109
+ } catch (err: any) {
110
+ error.value =
111
+ err?.data?.message || "This invitation is no longer available.";
112
+ }
113
+ }
114
+
115
+ async function accept() {
116
+ working.value = "accept";
117
+ try {
118
+ await addViaInvite(props.invitationId);
119
+ await load();
120
+ emit("answered", "complete");
121
+ } catch (err: any) {
122
+ error.value = err?.data?.message || "Could not accept this invitation.";
123
+ } finally {
124
+ working.value = "";
125
+ }
126
+ }
127
+
128
+ async function decline() {
129
+ working.value = "decline";
130
+ try {
131
+ await declineInvitation(props.invitationId);
132
+ await load();
133
+ emit("answered", "declined");
134
+ } catch (err: any) {
135
+ error.value = err?.data?.message || "Could not decline this invitation.";
136
+ } finally {
137
+ working.value = "";
138
+ }
139
+ }
140
+
141
+ await load();
142
+ </script>
143
+
144
+ <style scoped>
145
+ .sp-invite-prompt-title {
146
+ font-size: 1.05rem;
147
+ font-weight: 600;
148
+ line-height: 1.35;
149
+ }
150
+ </style>