@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.
- package/.changeset/camera-wall-gated-endpoint.md +47 -0
- package/.changeset/camera-wall-plain-english.md +60 -0
- package/.changeset/camera-wall-selection-and-guidance.md +65 -0
- package/.changeset/dark-primary-contrast.md +39 -0
- package/.changeset/dashboard-dark-theme-contrast.md +15 -0
- package/.changeset/notification-preferences.md +17 -0
- package/.changeset/pm-sidebar-grouping-and-list-scaffold.md +27 -0
- package/.changeset/service-provider-invitation-actions.md +28 -0
- package/assets/css/primitives.css +680 -0
- package/assets/css/screens.css +541 -0
- package/assets/css/shell.css +258 -0
- package/assets/css/tokens.css +220 -0
- package/components/AccessCardQrTagging.vue +1 -1
- package/components/AccessManagement.vue +53 -72
- package/components/AppButton.vue +52 -0
- package/components/AppCard.vue +20 -0
- package/components/AppDateField.vue +35 -0
- package/components/AppField.vue +46 -0
- package/components/AppKpiTile.vue +65 -0
- package/components/AppSegmented.vue +38 -0
- package/components/AppSelect.vue +203 -0
- package/components/AreaChecklistHistoryMain.vue +6 -2
- package/components/AreaMain.vue +9 -17
- package/components/AttendanceMain.vue +4 -3
- package/components/Avatar/Main.vue +54 -2
- package/components/BillingMain.vue +26 -30
- package/components/BuildingManagement/buildings.vue +27 -38
- package/components/BuildingManagement/units.vue +26 -42
- package/components/BulletinBoardManagement.vue +23 -10
- package/components/CameraWall.vue +1034 -0
- package/components/CameraWallTile.vue +818 -0
- package/components/CardToolbar.vue +37 -0
- package/components/CleaningScheduleMain.vue +29 -46
- package/components/ClientMain.vue +90 -78
- package/components/DashboardEmptyState.vue +11 -1
- package/components/DashboardMain.vue +349 -275
- package/components/DashboardPanel.vue +1 -1
- package/components/DocumentManagement.vue +129 -93
- package/components/EntryPassInformation.vue +4 -4
- package/components/EntryPassMain.vue +49 -27
- package/components/EquipmentItemMain.vue +4 -6
- package/components/EquipmentManagementMain.vue +9 -7
- package/components/FeedbackMain.vue +42 -56
- package/components/FormDialog.vue +60 -21
- package/components/HidAccessLogDashboard.vue +119 -44
- package/components/HidCameraCaptureDialog.vue +199 -0
- package/components/HidIntercomManagement.vue +825 -202
- package/components/HidQrCodeConfiguration.vue +927 -93
- package/components/HidServiceSettingsPanel.vue +20 -1
- package/components/HidUserEnrollment.vue +454 -106
- package/components/InvitationMain.vue +46 -61
- package/components/Layout/Header.vue +289 -37
- package/components/Layout/NavigationDrawer.vue +340 -30
- package/components/ManageChecklistMain.vue +17 -17
- package/components/MemberMain.vue +79 -60
- package/components/MyAttendanceMain.vue +3 -5
- package/components/NavigationItem.vue +9 -0
- package/components/Nfc/NFCPatrolRouteMain.vue +116 -103
- package/components/NotificationSettings.vue +361 -0
- package/components/OnlineFormConfigurationForm.vue +620 -224
- package/components/OnlineFormFill.vue +36 -8
- package/components/OnlineFormsConfiguration.vue +7 -3
- package/components/PageHeader.vue +43 -0
- package/components/PassInformation.vue +104 -45
- package/components/QrTemplate/CreditCardLandscape.vue +19 -12
- package/components/QrTemplate/PrintDialog.vue +209 -196
- package/components/RolePermissionMain.vue +184 -91
- package/components/ScanVisitorQRCode.vue +35 -7
- package/components/ScheduleAreaMain.vue +15 -49
- package/components/ScheduleTaskMain.vue +23 -26
- package/components/ScheduleTastTicketMain.vue +18 -43
- package/components/ServiceProviderInvitationPrompt.vue +150 -0
- package/components/ServiceProviderMain.vue +346 -157
- package/components/SiteSettings.vue +25 -10
- package/components/SpecificAttr.vue +10 -2
- package/components/StatusChip.vue +93 -0
- package/components/SwitchContext.vue +33 -1
- package/components/TableHygiene.vue +29 -46
- package/components/TableList.vue +1 -1
- package/components/TableListSecondary.vue +1 -1
- package/components/TableMain.vue +161 -77
- package/components/TableV3.vue +61 -66
- package/components/UnitMain.vue +9 -17
- package/components/VehicleManagement.vue +20 -9
- package/components/VisitorForm.vue +294 -78
- package/components/VisitorManagement.vue +221 -71
- package/components/VisitorSocketPopUp.vue +56 -2
- package/components/WorkOrder/Main.vue +42 -51
- package/composables/useComment.ts +3 -3
- package/composables/useHidAmico.ts +151 -0
- package/composables/useHidNavigation.ts +0 -7
- package/composables/useLocalAuth.ts +9 -36
- package/composables/useNotificationPreference.ts +87 -0
- package/composables/useOnlineFormPages.ts +2 -0
- package/composables/useOrg.ts +1 -1
- package/composables/useRole.ts +22 -0
- package/composables/useServiceProviderInvitation.ts +145 -0
- package/composables/useSipWebPhone.ts +336 -0
- package/composables/useSiteSettings.ts +50 -0
- package/composables/useThemePreference.ts +63 -0
- package/composables/useVisitor.ts +6 -1
- package/composables/useVisitorSocket.ts +26 -0
- package/composables/useWebUsb.ts +127 -37
- package/nuxt.config.ts +31 -0
- package/package.json +4 -1
- package/pages/[org]/[site]/access-mgmt/intercom/index.vue +1 -1
- package/pages/notification-settings.vue +19 -0
- package/plugins/secure-member.client.ts +21 -56
- package/plugins/vuetify.ts +68 -9
- package/test/visitor-socket.test.mjs +36 -0
- package/types/org.d.ts +2 -0
- package/types/site.d.ts +71 -0
- package/utils/camera-wall.test.ts +571 -0
- package/utils/camera-wall.ts +926 -0
- package/utils/nav-sections.test.ts +190 -0
- package/utils/nav-sections.ts +151 -0
- package/utils/status.test.ts +77 -0
- package/utils/status.ts +90 -0
- package/utils/theme.test.ts +534 -0
- package/utils/theme.ts +294 -0
- package/components/HidIdentityMapping.vue +0 -975
- package/middleware/member.ts +0 -4
- 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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
<
|
|
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
|
|
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>
|