@burdenoff/microfe-organization 2026.624.2 → 2026.625.2
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/dist/organization-management/modules/members/components/BulkInviteForm.js.map +1 -1
- package/dist/organization-management/modules/members/pages/InviteMemberPage.js +58 -52
- package/dist/organization-management/modules/members/pages/InviteMemberPage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/InvitePeoplePage.js +41 -39
- package/dist/organization-management/modules/members/pages/InvitePeoplePage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/MemberDetailPage.js +70 -68
- package/dist/organization-management/modules/members/pages/MemberDetailPage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/MembersListPage.js +232 -203
- package/dist/organization-management/modules/members/pages/MembersListPage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/MyInvitesPage.js +38 -37
- package/dist/organization-management/modules/members/pages/MyInvitesPage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js +134 -132
- package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js.map +1 -1
- package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js +38 -36
- package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js.map +1 -1
- package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +163 -166
- package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js +48 -46
- package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js.map +1 -1
- package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js +257 -229
- package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js.map +1 -1
- package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js +43 -50
- package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js.map +1 -1
- package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js +39 -37
- package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js.map +1 -1
- package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js +146 -145
- package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js.map +1 -1
- package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js +46 -44
- package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js.map +1 -1
- package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js +115 -72
- package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js.map +1 -1
- package/package.json +2 -2
package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js
CHANGED
|
@@ -5,11 +5,11 @@ import { useTr as a } from "../../../shared/hooks/useTr.js";
|
|
|
5
5
|
import { useOrganizationPageView as o } from "../../../hooks/useOrganizationPageView.js";
|
|
6
6
|
import { useState as s } from "react";
|
|
7
7
|
import { AlertTriangle as c, Ban as l, Building2 as u, CheckCircle as d, Clock as f, Home as p, Loader2 as m, Mail as h, XCircle as g } from "lucide-react";
|
|
8
|
-
import { Badge as _ } from "@burdenoff/fe-libs/ui";
|
|
9
|
-
import { jsx as
|
|
10
|
-
import { useParams as
|
|
8
|
+
import { Badge as _, EmphasisPanel as v, GlassCard as y } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
import { jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
10
|
+
import { useParams as S } from "react-router-dom";
|
|
11
11
|
//#region src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx
|
|
12
|
-
function
|
|
12
|
+
function C(e) {
|
|
13
13
|
if (!e) return null;
|
|
14
14
|
let t = new Date(e);
|
|
15
15
|
return Number.isNaN(t.getTime()) ? null : t.toLocaleDateString("en-US", {
|
|
@@ -20,268 +20,270 @@ function x(e) {
|
|
|
20
20
|
minute: "2-digit"
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
function
|
|
24
|
-
return /* @__PURE__ */
|
|
23
|
+
function w({ children: e }) {
|
|
24
|
+
return /* @__PURE__ */ b("div", {
|
|
25
25
|
className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-10 sm:px-6",
|
|
26
|
-
children: /* @__PURE__ */
|
|
26
|
+
children: /* @__PURE__ */ b("div", {
|
|
27
27
|
className: "mx-auto max-w-2xl",
|
|
28
28
|
children: e
|
|
29
29
|
})
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
return /* @__PURE__ */
|
|
34
|
-
|
|
32
|
+
function T({ icon: e, iconClass: t, title: n, description: r, email: i, primaryLabel: a, onPrimary: o }) {
|
|
33
|
+
return /* @__PURE__ */ b(w, { children: /* @__PURE__ */ x(y, {
|
|
34
|
+
treatment: "plain",
|
|
35
|
+
className: "border-border-seam p-8 text-center",
|
|
35
36
|
children: [
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ b("div", {
|
|
37
38
|
className: `mx-auto mb-4 flex size-14 items-center justify-center rounded-2xl ${t}`,
|
|
38
|
-
children: /* @__PURE__ */
|
|
39
|
+
children: /* @__PURE__ */ b(e, { size: 28 })
|
|
39
40
|
}),
|
|
40
|
-
/* @__PURE__ */
|
|
41
|
+
/* @__PURE__ */ b("h1", {
|
|
41
42
|
className: "text-2xl font-bold text-[var(--color-text-primary)]",
|
|
42
43
|
children: n
|
|
43
44
|
}),
|
|
44
|
-
/* @__PURE__ */
|
|
45
|
+
/* @__PURE__ */ b("p", {
|
|
45
46
|
className: "mt-2 text-[var(--color-text-secondary)]",
|
|
46
47
|
children: r
|
|
47
48
|
}),
|
|
48
|
-
i ? /* @__PURE__ */
|
|
49
|
+
i ? /* @__PURE__ */ b("p", {
|
|
49
50
|
className: "mt-1 break-all text-sm text-[var(--color-text-muted)]",
|
|
50
51
|
children: i
|
|
51
52
|
}) : null,
|
|
52
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ x("button", {
|
|
53
54
|
type: "button",
|
|
54
55
|
onClick: o,
|
|
55
56
|
className: "mt-6 inline-flex items-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90",
|
|
56
|
-
children: [/* @__PURE__ */
|
|
57
|
+
children: [/* @__PURE__ */ b(p, { size: 16 }), a]
|
|
57
58
|
})
|
|
58
59
|
]
|
|
59
60
|
}) });
|
|
60
61
|
}
|
|
61
|
-
function
|
|
62
|
+
function E() {
|
|
62
63
|
o("organizations.invite-acceptance");
|
|
63
|
-
let
|
|
64
|
-
if (
|
|
65
|
-
|
|
64
|
+
let E = a(), { inviteId: D = "" } = S(), { basePath: O = "/organizations", navigate: k, currentUser: A, authToken: j } = e(), M = !!(j || A?.email), { invite: N, loading: P, error: F, refetch: I } = n(D, M), { acceptInvite: L } = t(), { rejectInvite: R } = r(), [z, B] = s(null), [V, H] = s(null), U = () => k(`${O}/invites/organizations`), W = async () => {
|
|
65
|
+
if (D) try {
|
|
66
|
+
B("accept"), H(null), await L(D), k(N?.organizationId ? `${O}/${N.organizationId}` : O);
|
|
66
67
|
} catch (e) {
|
|
67
|
-
|
|
68
|
+
H(e instanceof Error ? e.message : E("members.inviteAcceptance.acceptFailed", "Failed to accept invitation"));
|
|
68
69
|
} finally {
|
|
69
|
-
|
|
70
|
+
B(null);
|
|
70
71
|
}
|
|
71
|
-
},
|
|
72
|
-
if (
|
|
73
|
-
|
|
72
|
+
}, G = async () => {
|
|
73
|
+
if (D) try {
|
|
74
|
+
B("reject"), H(null), await R(D), U();
|
|
74
75
|
} catch (e) {
|
|
75
|
-
|
|
76
|
+
H(e instanceof Error ? e.message : E("members.inviteAcceptance.rejectFailed", "Failed to reject invitation"));
|
|
76
77
|
} finally {
|
|
77
|
-
|
|
78
|
+
B(null);
|
|
78
79
|
}
|
|
79
80
|
};
|
|
80
|
-
if (!
|
|
81
|
-
let e = encodeURIComponent(`${
|
|
82
|
-
return /* @__PURE__ */
|
|
83
|
-
|
|
81
|
+
if (!M) {
|
|
82
|
+
let e = encodeURIComponent(`${O}/invite/${D}`);
|
|
83
|
+
return /* @__PURE__ */ b(w, { children: /* @__PURE__ */ x(y, {
|
|
84
|
+
treatment: "plain",
|
|
85
|
+
className: "border-border-seam p-8",
|
|
84
86
|
children: [
|
|
85
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ x("div", {
|
|
86
88
|
className: "mb-4 flex items-center gap-3",
|
|
87
|
-
children: [/* @__PURE__ */
|
|
89
|
+
children: [/* @__PURE__ */ b("div", {
|
|
88
90
|
className: "rounded-xl bg-[var(--color-bg-subtle)] p-3",
|
|
89
|
-
children: /* @__PURE__ */
|
|
91
|
+
children: /* @__PURE__ */ b(h, {
|
|
90
92
|
size: 24,
|
|
91
93
|
className: "text-[var(--color-text-primary)]"
|
|
92
94
|
})
|
|
93
|
-
}), /* @__PURE__ */
|
|
95
|
+
}), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h1", {
|
|
94
96
|
className: "text-2xl font-bold text-[var(--color-text-primary)]",
|
|
95
|
-
children:
|
|
96
|
-
}), /* @__PURE__ */
|
|
97
|
+
children: E("members.inviteAcceptance.signInRequired", "Sign in to view your invitation")
|
|
98
|
+
}), /* @__PURE__ */ b("p", {
|
|
97
99
|
className: "text-[var(--color-text-secondary)]",
|
|
98
|
-
children:
|
|
100
|
+
children: E("members.inviteAcceptance.signInDescription", "Organization invitations require an authenticated account before you can review or accept them.")
|
|
99
101
|
})] })]
|
|
100
102
|
}),
|
|
101
|
-
/* @__PURE__ */
|
|
103
|
+
/* @__PURE__ */ b("p", {
|
|
102
104
|
className: "mb-6 text-sm text-[var(--color-text-muted)]",
|
|
103
|
-
children:
|
|
105
|
+
children: E("members.inviteAcceptance.signInHint", "Use the same email address that received the invitation, then come back here to accept or decline it.")
|
|
104
106
|
}),
|
|
105
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ x("div", {
|
|
106
108
|
className: "flex flex-col gap-3 sm:flex-row",
|
|
107
|
-
children: [/* @__PURE__ */
|
|
109
|
+
children: [/* @__PURE__ */ b("a", {
|
|
108
110
|
href: `/auth/login?returnTo=${e}`,
|
|
109
111
|
className: "inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90",
|
|
110
|
-
children:
|
|
111
|
-
}), /* @__PURE__ */
|
|
112
|
+
children: E("members.inviteAcceptance.signInButton", "Sign In")
|
|
113
|
+
}), /* @__PURE__ */ x("button", {
|
|
112
114
|
type: "button",
|
|
113
|
-
onClick: () =>
|
|
115
|
+
onClick: () => k(O),
|
|
114
116
|
className: "inline-flex items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]",
|
|
115
|
-
children: [/* @__PURE__ */
|
|
117
|
+
children: [/* @__PURE__ */ b(p, { size: 16 }), E("members.inviteAcceptance.backToOrganizations", "Back to Organizations")]
|
|
116
118
|
})]
|
|
117
119
|
})
|
|
118
120
|
]
|
|
119
121
|
}) });
|
|
120
122
|
}
|
|
121
|
-
if (
|
|
123
|
+
if (P) return /* @__PURE__ */ b(w, { children: /* @__PURE__ */ b("div", {
|
|
122
124
|
className: "flex min-h-[300px] items-center justify-center rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]",
|
|
123
|
-
children: /* @__PURE__ */
|
|
125
|
+
children: /* @__PURE__ */ b(m, {
|
|
124
126
|
size: 28,
|
|
125
127
|
className: "animate-spin text-[var(--color-text-muted)]"
|
|
126
128
|
})
|
|
127
129
|
}) });
|
|
128
|
-
if (
|
|
130
|
+
if (F) return /* @__PURE__ */ b(T, {
|
|
129
131
|
icon: c,
|
|
130
132
|
iconClass: "bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]",
|
|
131
|
-
title:
|
|
132
|
-
description:
|
|
133
|
-
primaryLabel:
|
|
133
|
+
title: E("members.inviteAcceptance.errorTitle", "Error Loading Invitation"),
|
|
134
|
+
description: F.message,
|
|
135
|
+
primaryLabel: E("members.inviteAcceptance.tryAgain", "Try Again"),
|
|
134
136
|
onPrimary: () => {
|
|
135
|
-
|
|
137
|
+
I();
|
|
136
138
|
}
|
|
137
139
|
});
|
|
138
|
-
if (!
|
|
140
|
+
if (!N) return /* @__PURE__ */ b(T, {
|
|
139
141
|
icon: c,
|
|
140
142
|
iconClass: "bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]",
|
|
141
|
-
title:
|
|
142
|
-
description:
|
|
143
|
-
primaryLabel:
|
|
144
|
-
onPrimary: () =>
|
|
143
|
+
title: E("members.inviteAcceptance.notFoundTitle", "Invitation Not Found"),
|
|
144
|
+
description: E("members.inviteAcceptance.notFoundDescription", "This invitation link is invalid, has been removed, or was addressed to a different account."),
|
|
145
|
+
primaryLabel: E("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
|
|
146
|
+
onPrimary: () => k(O)
|
|
145
147
|
});
|
|
146
|
-
let
|
|
147
|
-
if (
|
|
148
|
+
let K = N.expiresAt && new Date(N.expiresAt) < /* @__PURE__ */ new Date(), q = N.status === i.Pending && K ? i.Expired : N.status;
|
|
149
|
+
if (q === i.Accepted) return /* @__PURE__ */ b(T, {
|
|
148
150
|
icon: d,
|
|
149
151
|
iconClass: "bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]",
|
|
150
|
-
title:
|
|
151
|
-
description:
|
|
152
|
-
email:
|
|
153
|
-
primaryLabel:
|
|
154
|
-
onPrimary: () =>
|
|
152
|
+
title: E("members.inviteAcceptance.alreadyAcceptedTitle", "Invitation Already Accepted"),
|
|
153
|
+
description: E("members.inviteAcceptance.alreadyAcceptedDescription", "You have already accepted this invitation."),
|
|
154
|
+
email: N.email,
|
|
155
|
+
primaryLabel: E("members.inviteAcceptance.goToOrganization", "Go to Organization"),
|
|
156
|
+
onPrimary: () => k(`${O}/${N.organizationId}`)
|
|
155
157
|
});
|
|
156
|
-
if (
|
|
158
|
+
if (q === i.Rejected) return /* @__PURE__ */ b(T, {
|
|
157
159
|
icon: g,
|
|
158
160
|
iconClass: "bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]",
|
|
159
|
-
title:
|
|
160
|
-
description:
|
|
161
|
-
email:
|
|
162
|
-
primaryLabel:
|
|
163
|
-
onPrimary: () =>
|
|
161
|
+
title: E("members.inviteAcceptance.rejectedTitle", "Invitation Declined"),
|
|
162
|
+
description: E("members.inviteAcceptance.rejectedDescription", "This invitation was previously declined."),
|
|
163
|
+
email: N.email,
|
|
164
|
+
primaryLabel: E("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
|
|
165
|
+
onPrimary: () => k(O)
|
|
164
166
|
});
|
|
165
|
-
if (
|
|
167
|
+
if (q === i.Expired) return /* @__PURE__ */ b(T, {
|
|
166
168
|
icon: f,
|
|
167
169
|
iconClass: "bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)]",
|
|
168
|
-
title:
|
|
169
|
-
description:
|
|
170
|
-
email:
|
|
171
|
-
primaryLabel:
|
|
172
|
-
onPrimary: () =>
|
|
170
|
+
title: E("members.inviteAcceptance.expiredTitle", "Invitation Expired"),
|
|
171
|
+
description: E("members.inviteAcceptance.expiredDescription", "This invitation has expired. Please contact an organization admin for a new one."),
|
|
172
|
+
email: N.email,
|
|
173
|
+
primaryLabel: E("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
|
|
174
|
+
onPrimary: () => k(O)
|
|
173
175
|
});
|
|
174
|
-
if (
|
|
176
|
+
if (q === i.Cancelled) return /* @__PURE__ */ b(T, {
|
|
175
177
|
icon: l,
|
|
176
178
|
iconClass: "bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]",
|
|
177
|
-
title:
|
|
178
|
-
description:
|
|
179
|
-
email:
|
|
180
|
-
primaryLabel:
|
|
181
|
-
onPrimary: () =>
|
|
179
|
+
title: E("members.inviteAcceptance.cancelledTitle", "Invitation Cancelled"),
|
|
180
|
+
description: E("members.inviteAcceptance.cancelledDescription", "This invitation was cancelled by the sender and is no longer valid."),
|
|
181
|
+
email: N.email,
|
|
182
|
+
primaryLabel: E("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
|
|
183
|
+
onPrimary: () => k(O)
|
|
182
184
|
});
|
|
183
|
-
let
|
|
184
|
-
return /* @__PURE__ */
|
|
185
|
-
className: "
|
|
185
|
+
let J = N.organization?.name ?? N.organizationId, Y = C(N.expiresAt), X = z !== null;
|
|
186
|
+
return /* @__PURE__ */ b(w, { children: /* @__PURE__ */ x(v, {
|
|
187
|
+
className: "p-8",
|
|
186
188
|
children: [
|
|
187
|
-
/* @__PURE__ */
|
|
189
|
+
/* @__PURE__ */ x("div", {
|
|
188
190
|
className: "mb-6 flex items-center gap-3",
|
|
189
|
-
children: [/* @__PURE__ */
|
|
191
|
+
children: [/* @__PURE__ */ b("div", {
|
|
190
192
|
className: "rounded-xl bg-[var(--color-bg-subtle)] p-3",
|
|
191
|
-
children: /* @__PURE__ */
|
|
193
|
+
children: /* @__PURE__ */ b(u, {
|
|
192
194
|
size: 24,
|
|
193
195
|
className: "text-[var(--color-text-primary)]"
|
|
194
196
|
})
|
|
195
|
-
}), /* @__PURE__ */
|
|
197
|
+
}), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h1", {
|
|
196
198
|
className: "text-2xl font-bold text-[var(--color-text-primary)]",
|
|
197
|
-
children:
|
|
198
|
-
}), /* @__PURE__ */
|
|
199
|
+
children: E("members.inviteAcceptance.pageTitle", "Organization Invitation")
|
|
200
|
+
}), /* @__PURE__ */ x("p", {
|
|
199
201
|
className: "text-[var(--color-text-secondary)]",
|
|
200
202
|
children: [
|
|
201
|
-
|
|
203
|
+
E("members.inviteAcceptance.pageSubtitle", "You've been invited to join"),
|
|
202
204
|
" ",
|
|
203
|
-
/* @__PURE__ */
|
|
205
|
+
/* @__PURE__ */ b("span", {
|
|
204
206
|
className: "font-medium text-[var(--color-text-primary)]",
|
|
205
|
-
children:
|
|
207
|
+
children: J
|
|
206
208
|
})
|
|
207
209
|
]
|
|
208
210
|
})] })]
|
|
209
211
|
}),
|
|
210
|
-
/* @__PURE__ */
|
|
212
|
+
/* @__PURE__ */ x("dl", {
|
|
211
213
|
className: "space-y-4 rounded-xl bg-[var(--color-bg-subtle)] p-5",
|
|
212
214
|
children: [
|
|
213
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
214
216
|
className: "text-sm font-medium text-[var(--color-text-muted)]",
|
|
215
|
-
children:
|
|
216
|
-
}), /* @__PURE__ */
|
|
217
|
+
children: E("members.inviteAcceptance.emailLabel", "Email Address")
|
|
218
|
+
}), /* @__PURE__ */ b("dd", {
|
|
217
219
|
className: "mt-1 break-all text-[var(--color-text-primary)]",
|
|
218
|
-
children:
|
|
220
|
+
children: N.email
|
|
219
221
|
})] }),
|
|
220
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ x("div", {
|
|
221
223
|
className: "flex flex-wrap items-center gap-2",
|
|
222
|
-
children: [/* @__PURE__ */
|
|
224
|
+
children: [/* @__PURE__ */ b("dt", {
|
|
223
225
|
className: "text-sm font-medium text-[var(--color-text-muted)]",
|
|
224
|
-
children:
|
|
225
|
-
}), /* @__PURE__ */
|
|
226
|
+
children: E("members.inviteAcceptance.roleLabel", "Role")
|
|
227
|
+
}), /* @__PURE__ */ b("dd", { children: /* @__PURE__ */ b(_, {
|
|
226
228
|
variant: "secondary",
|
|
227
|
-
children:
|
|
229
|
+
children: N.role
|
|
228
230
|
}) })]
|
|
229
231
|
}),
|
|
230
|
-
|
|
232
|
+
Y ? /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
231
233
|
className: "text-sm font-medium text-[var(--color-text-muted)]",
|
|
232
|
-
children:
|
|
233
|
-
}), /* @__PURE__ */
|
|
234
|
+
children: E("members.inviteAcceptance.expiresLabel", "Expires")
|
|
235
|
+
}), /* @__PURE__ */ x("dd", {
|
|
234
236
|
className: "mt-1 flex items-center gap-2 text-[var(--color-text-primary)]",
|
|
235
|
-
children: [/* @__PURE__ */
|
|
237
|
+
children: [/* @__PURE__ */ b(f, {
|
|
236
238
|
size: 16,
|
|
237
239
|
className: "text-[var(--color-text-muted)]"
|
|
238
|
-
}),
|
|
240
|
+
}), Y]
|
|
239
241
|
})] }) : null,
|
|
240
|
-
|
|
242
|
+
N.message ? /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
241
243
|
className: "text-sm font-medium text-[var(--color-text-muted)]",
|
|
242
|
-
children:
|
|
243
|
-
}), /* @__PURE__ */
|
|
244
|
+
children: E("members.inviteAcceptance.messageLabel", "Message")
|
|
245
|
+
}), /* @__PURE__ */ b("dd", {
|
|
244
246
|
className: "mt-1 text-[var(--color-text-secondary)]",
|
|
245
|
-
children:
|
|
247
|
+
children: N.message
|
|
246
248
|
})] }) : null
|
|
247
249
|
]
|
|
248
250
|
}),
|
|
249
|
-
|
|
251
|
+
V ? /* @__PURE__ */ x("div", {
|
|
250
252
|
className: "mt-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ b(c, {
|
|
252
254
|
size: 16,
|
|
253
255
|
className: "shrink-0 text-[var(--color-status-error-text)]"
|
|
254
|
-
}), /* @__PURE__ */
|
|
256
|
+
}), /* @__PURE__ */ b("p", {
|
|
255
257
|
className: "text-sm text-[var(--color-status-error-text)]",
|
|
256
|
-
children:
|
|
258
|
+
children: V
|
|
257
259
|
})]
|
|
258
260
|
}) : null,
|
|
259
|
-
/* @__PURE__ */
|
|
260
|
-
className: "mt-6 flex flex-col gap-3 border-t border-[var(--color-border-
|
|
261
|
-
children: [/* @__PURE__ */
|
|
261
|
+
/* @__PURE__ */ x("div", {
|
|
262
|
+
className: "mt-6 flex flex-col gap-3 border-t border-[var(--color-border-seam)] pt-6 sm:flex-row",
|
|
263
|
+
children: [/* @__PURE__ */ x("button", {
|
|
262
264
|
type: "button",
|
|
263
|
-
onClick: () => void
|
|
264
|
-
disabled:
|
|
265
|
+
onClick: () => void W(),
|
|
266
|
+
disabled: X,
|
|
265
267
|
className: "inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-[var(--color-status-success-bg)] px-6 py-3 font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50",
|
|
266
|
-
children: [
|
|
268
|
+
children: [z === "accept" ? /* @__PURE__ */ b(m, {
|
|
267
269
|
size: 16,
|
|
268
270
|
className: "animate-spin"
|
|
269
|
-
}) : /* @__PURE__ */
|
|
270
|
-
}), /* @__PURE__ */
|
|
271
|
+
}) : /* @__PURE__ */ b(d, { size: 16 }), E("members.inviteAcceptance.acceptButton", "Accept Invitation")]
|
|
272
|
+
}), /* @__PURE__ */ x("button", {
|
|
271
273
|
type: "button",
|
|
272
|
-
onClick: () => void
|
|
273
|
-
disabled:
|
|
274
|
+
onClick: () => void G(),
|
|
275
|
+
disabled: X,
|
|
274
276
|
className: "inline-flex flex-1 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-3 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50",
|
|
275
|
-
children: [
|
|
277
|
+
children: [z === "reject" ? /* @__PURE__ */ b(m, {
|
|
276
278
|
size: 16,
|
|
277
279
|
className: "animate-spin"
|
|
278
|
-
}) : /* @__PURE__ */
|
|
280
|
+
}) : /* @__PURE__ */ b(g, { size: 16 }), E("members.inviteAcceptance.declineButton", "Decline")]
|
|
279
281
|
})]
|
|
280
282
|
})
|
|
281
283
|
]
|
|
282
284
|
}) });
|
|
283
285
|
}
|
|
284
286
|
//#endregion
|
|
285
|
-
export {
|
|
287
|
+
export { E as OrganizationInviteAcceptancePage };
|
|
286
288
|
|
|
287
289
|
//# sourceMappingURL=OrganizationInviteAcceptancePage.js.map
|
package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrganizationInviteAcceptancePage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n Mail,\n Loader2,\n CheckCircle,\n XCircle,\n Clock,\n AlertTriangle,\n Ban,\n Home,\n Building2,\n} from 'lucide-react';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { useOrganizationInvite, useAcceptInvite, useRejectInvite } from '../hooks/useInvites';\nimport { InviteStatus } from '../../../../generated/global-types';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\n\n/**\n * OrganizationInviteAcceptancePage\n *\n * Per-invite acceptance page reached from the organization invite email link\n * (`/organizations/invite/:inviteId`). Mirrors the workspace invite-acceptance\n * flow: loads the single invite by id, renders the appropriate state machine\n * (PENDING → accept/reject, ACCEPTED/REJECTED/EXPIRED/CANCELLED), and gates the\n * unauthenticated case behind a sign-in CTA that returns the user here.\n *\n * The previous behaviour dropped the recipient on `/organizations/invites`\n * (the workspace-invites list tab) with no invite context, which rendered as\n * an empty page. The email now deep-links here with the invite id.\n */\nfunction formatDate(value?: string | null): string | null {\n if (!value) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n return date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction PageShell({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-10 sm:px-6\">\n <div className=\"mx-auto max-w-2xl\">{children}</div>\n </div>\n );\n}\n\ninterface StatusViewProps {\n icon: typeof CheckCircle;\n iconClass: string;\n title: string;\n description: string;\n email?: string;\n primaryLabel: string;\n onPrimary: () => void;\n}\n\nfunction StatusView({\n icon: Icon,\n iconClass,\n title,\n description,\n email,\n primaryLabel,\n onPrimary,\n}: StatusViewProps) {\n return (\n <PageShell>\n <div className=\"rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-8 text-center\">\n <div\n className={`mx-auto mb-4 flex size-14 items-center justify-center rounded-2xl ${iconClass}`}\n >\n <Icon size={28} />\n </div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">{title}</h1>\n <p className=\"mt-2 text-[var(--color-text-secondary)]\">{description}</p>\n {email ? (\n <p className=\"mt-1 break-all text-sm text-[var(--color-text-muted)]\">{email}</p>\n ) : null}\n <button\n type=\"button\"\n onClick={onPrimary}\n className=\"mt-6 inline-flex items-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n <Home size={16} />\n {primaryLabel}\n </button>\n </div>\n </PageShell>\n );\n}\n\nexport function OrganizationInviteAcceptancePage() {\n useOrganizationPageView('organizations.invite-acceptance');\n const tr = useTr();\n const { inviteId = '' } = useParams<{ inviteId: string }>();\n const { basePath = '/organizations', navigate, currentUser, authToken } = useOrgConsole();\n\n const isAuthenticated = Boolean(authToken || currentUser?.email);\n const { invite, loading, error, refetch } = useOrganizationInvite(inviteId, isAuthenticated);\n const { acceptInvite } = useAcceptInvite();\n const { rejectInvite } = useRejectInvite();\n\n const [processing, setProcessing] = useState<'accept' | 'reject' | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n const goToInvitesList = () => navigate(`${basePath}/invites/organizations`);\n\n const handleAccept = async () => {\n if (!inviteId) return;\n try {\n setProcessing('accept');\n setActionError(null);\n await acceptInvite(inviteId);\n navigate(invite?.organizationId ? `${basePath}/${invite.organizationId}` : basePath);\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.acceptFailed', 'Failed to accept invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n const handleReject = async () => {\n if (!inviteId) return;\n try {\n setProcessing('reject');\n setActionError(null);\n await rejectInvite(inviteId);\n goToInvitesList();\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.rejectFailed', 'Failed to reject invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n // Unauthenticated — invitees must sign in with the invited email first.\n if (!isAuthenticated) {\n const returnTo = encodeURIComponent(`${basePath}/invite/${inviteId}`);\n return (\n <PageShell>\n <div className=\"rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-8\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.signInRequired', 'Sign in to view your invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n 'members.inviteAcceptance.signInDescription',\n 'Organization invitations require an authenticated account before you can review or accept them.'\n )}\n </p>\n </div>\n </div>\n <p className=\"mb-6 text-sm text-[var(--color-text-muted)]\">\n {tr(\n 'members.inviteAcceptance.signInHint',\n 'Use the same email address that received the invitation, then come back here to accept or decline it.'\n )}\n </p>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <a\n href={`/auth/login?returnTo=${returnTo}`}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n {tr('members.inviteAcceptance.signInButton', 'Sign In')}\n </a>\n <button\n type=\"button\"\n onClick={() => navigate(basePath)}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Home size={16} />\n {tr('members.inviteAcceptance.backToOrganizations', 'Back to Organizations')}\n </button>\n </div>\n </div>\n </PageShell>\n );\n }\n\n if (loading) {\n return (\n <PageShell>\n <div className=\"flex min-h-[300px] items-center justify-center rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={28} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </PageShell>\n );\n }\n\n if (error) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.errorTitle', 'Error Loading Invitation')}\n description={error.message}\n primaryLabel={tr('members.inviteAcceptance.tryAgain', 'Try Again')}\n onPrimary={() => {\n void refetch();\n }}\n />\n );\n }\n\n if (!invite) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.notFoundTitle', 'Invitation Not Found')}\n description={tr(\n 'members.inviteAcceptance.notFoundDescription',\n 'This invitation link is invalid, has been removed, or was addressed to a different account.'\n )}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n const isExpiredByDate = invite.expiresAt && new Date(invite.expiresAt) < new Date();\n const effectiveStatus =\n invite.status === InviteStatus.Pending && isExpiredByDate\n ? InviteStatus.Expired\n : invite.status;\n\n if (effectiveStatus === InviteStatus.Accepted) {\n return (\n <StatusView\n icon={CheckCircle}\n iconClass=\"bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]\"\n title={tr('members.inviteAcceptance.alreadyAcceptedTitle', 'Invitation Already Accepted')}\n description={tr(\n 'members.inviteAcceptance.alreadyAcceptedDescription',\n 'You have already accepted this invitation.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganization', 'Go to Organization')}\n onPrimary={() => navigate(`${basePath}/${invite.organizationId}`)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Rejected) {\n return (\n <StatusView\n icon={XCircle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.rejectedTitle', 'Invitation Declined')}\n description={tr(\n 'members.inviteAcceptance.rejectedDescription',\n 'This invitation was previously declined.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Expired) {\n return (\n <StatusView\n icon={Clock}\n iconClass=\"bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)]\"\n title={tr('members.inviteAcceptance.expiredTitle', 'Invitation Expired')}\n description={tr(\n 'members.inviteAcceptance.expiredDescription',\n 'This invitation has expired. Please contact an organization admin for a new one.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Cancelled) {\n return (\n <StatusView\n icon={Ban}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.cancelledTitle', 'Invitation Cancelled')}\n description={tr(\n 'members.inviteAcceptance.cancelledDescription',\n 'This invitation was cancelled by the sender and is no longer valid.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n // PENDING — show the acceptance UI.\n const organizationName = invite.organization?.name ?? invite.organizationId;\n const expiresLabel = formatDate(invite.expiresAt);\n const busy = processing !== null;\n\n return (\n <PageShell>\n <div className=\"rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-8\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Building2 size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.pageTitle', 'Organization Invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr('members.inviteAcceptance.pageSubtitle', \"You've been invited to join\")}{' '}\n <span className=\"font-medium text-[var(--color-text-primary)]\">\n {organizationName}\n </span>\n </p>\n </div>\n </div>\n\n <dl className=\"space-y-4 rounded-xl bg-[var(--color-bg-subtle)] p-5\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.emailLabel', 'Email Address')}\n </dt>\n <dd className=\"mt-1 break-all text-[var(--color-text-primary)]\">{invite.email}</dd>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.roleLabel', 'Role')}\n </dt>\n <dd>\n <Badge variant=\"secondary\">{invite.role}</Badge>\n </dd>\n </div>\n {expiresLabel ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.expiresLabel', 'Expires')}\n </dt>\n <dd className=\"mt-1 flex items-center gap-2 text-[var(--color-text-primary)]\">\n <Clock size={16} className=\"text-[var(--color-text-muted)]\" />\n {expiresLabel}\n </dd>\n </div>\n ) : null}\n {invite.message ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.messageLabel', 'Message')}\n </dt>\n <dd className=\"mt-1 text-[var(--color-text-secondary)]\">{invite.message}</dd>\n </div>\n ) : null}\n </dl>\n\n {actionError ? (\n <div className=\"mt-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3\">\n <AlertTriangle size={16} className=\"shrink-0 text-[var(--color-status-error-text)]\" />\n <p className=\"text-sm text-[var(--color-status-error-text)]\">{actionError}</p>\n </div>\n ) : null}\n\n <div className=\"mt-6 flex flex-col gap-3 border-t border-[var(--color-border-default)] pt-6 sm:flex-row\">\n <button\n type=\"button\"\n onClick={() => void handleAccept()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-[var(--color-status-success-bg)] px-6 py-3 font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'accept' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <CheckCircle size={16} />\n )}\n {tr('members.inviteAcceptance.acceptButton', 'Accept Invitation')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleReject()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-3 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'reject' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <XCircle size={16} />\n )}\n {tr('members.inviteAcceptance.declineButton', 'Decline')}\n </button>\n </div>\n </div>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrganizationInviteAcceptancePage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n Mail,\n Loader2,\n CheckCircle,\n XCircle,\n Clock,\n AlertTriangle,\n Ban,\n Home,\n Building2,\n} from 'lucide-react';\nimport { Badge, EmphasisPanel, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { useOrganizationInvite, useAcceptInvite, useRejectInvite } from '../hooks/useInvites';\nimport { InviteStatus } from '../../../../generated/global-types';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\n\n/**\n * OrganizationInviteAcceptancePage\n *\n * Per-invite acceptance page reached from the organization invite email link\n * (`/organizations/invite/:inviteId`). Mirrors the workspace invite-acceptance\n * flow: loads the single invite by id, renders the appropriate state machine\n * (PENDING → accept/reject, ACCEPTED/REJECTED/EXPIRED/CANCELLED), and gates the\n * unauthenticated case behind a sign-in CTA that returns the user here.\n *\n * The previous behaviour dropped the recipient on `/organizations/invites`\n * (the workspace-invites list tab) with no invite context, which rendered as\n * an empty page. The email now deep-links here with the invite id.\n */\nfunction formatDate(value?: string | null): string | null {\n if (!value) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n return date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction PageShell({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-10 sm:px-6\">\n <div className=\"mx-auto max-w-2xl\">{children}</div>\n </div>\n );\n}\n\ninterface StatusViewProps {\n icon: typeof CheckCircle;\n iconClass: string;\n title: string;\n description: string;\n email?: string;\n primaryLabel: string;\n onPrimary: () => void;\n}\n\nfunction StatusView({\n icon: Icon,\n iconClass,\n title,\n description,\n email,\n primaryLabel,\n onPrimary,\n}: StatusViewProps) {\n return (\n <PageShell>\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8 text-center\">\n <div\n className={`mx-auto mb-4 flex size-14 items-center justify-center rounded-2xl ${iconClass}`}\n >\n <Icon size={28} />\n </div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">{title}</h1>\n <p className=\"mt-2 text-[var(--color-text-secondary)]\">{description}</p>\n {email ? (\n <p className=\"mt-1 break-all text-sm text-[var(--color-text-muted)]\">{email}</p>\n ) : null}\n <button\n type=\"button\"\n onClick={onPrimary}\n className=\"mt-6 inline-flex items-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n <Home size={16} />\n {primaryLabel}\n </button>\n </GlassCard>\n </PageShell>\n );\n}\n\nexport function OrganizationInviteAcceptancePage() {\n useOrganizationPageView('organizations.invite-acceptance');\n const tr = useTr();\n const { inviteId = '' } = useParams<{ inviteId: string }>();\n const { basePath = '/organizations', navigate, currentUser, authToken } = useOrgConsole();\n\n const isAuthenticated = Boolean(authToken || currentUser?.email);\n const { invite, loading, error, refetch } = useOrganizationInvite(inviteId, isAuthenticated);\n const { acceptInvite } = useAcceptInvite();\n const { rejectInvite } = useRejectInvite();\n\n const [processing, setProcessing] = useState<'accept' | 'reject' | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n const goToInvitesList = () => navigate(`${basePath}/invites/organizations`);\n\n const handleAccept = async () => {\n if (!inviteId) return;\n try {\n setProcessing('accept');\n setActionError(null);\n await acceptInvite(inviteId);\n navigate(invite?.organizationId ? `${basePath}/${invite.organizationId}` : basePath);\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.acceptFailed', 'Failed to accept invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n const handleReject = async () => {\n if (!inviteId) return;\n try {\n setProcessing('reject');\n setActionError(null);\n await rejectInvite(inviteId);\n goToInvitesList();\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.rejectFailed', 'Failed to reject invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n // Unauthenticated — invitees must sign in with the invited email first.\n if (!isAuthenticated) {\n const returnTo = encodeURIComponent(`${basePath}/invite/${inviteId}`);\n return (\n <PageShell>\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.signInRequired', 'Sign in to view your invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n 'members.inviteAcceptance.signInDescription',\n 'Organization invitations require an authenticated account before you can review or accept them.'\n )}\n </p>\n </div>\n </div>\n <p className=\"mb-6 text-sm text-[var(--color-text-muted)]\">\n {tr(\n 'members.inviteAcceptance.signInHint',\n 'Use the same email address that received the invitation, then come back here to accept or decline it.'\n )}\n </p>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <a\n href={`/auth/login?returnTo=${returnTo}`}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n {tr('members.inviteAcceptance.signInButton', 'Sign In')}\n </a>\n <button\n type=\"button\"\n onClick={() => navigate(basePath)}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Home size={16} />\n {tr('members.inviteAcceptance.backToOrganizations', 'Back to Organizations')}\n </button>\n </div>\n </GlassCard>\n </PageShell>\n );\n }\n\n if (loading) {\n return (\n <PageShell>\n <div className=\"flex min-h-[300px] items-center justify-center rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={28} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </PageShell>\n );\n }\n\n if (error) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.errorTitle', 'Error Loading Invitation')}\n description={error.message}\n primaryLabel={tr('members.inviteAcceptance.tryAgain', 'Try Again')}\n onPrimary={() => {\n void refetch();\n }}\n />\n );\n }\n\n if (!invite) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.notFoundTitle', 'Invitation Not Found')}\n description={tr(\n 'members.inviteAcceptance.notFoundDescription',\n 'This invitation link is invalid, has been removed, or was addressed to a different account.'\n )}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n const isExpiredByDate = invite.expiresAt && new Date(invite.expiresAt) < new Date();\n const effectiveStatus =\n invite.status === InviteStatus.Pending && isExpiredByDate\n ? InviteStatus.Expired\n : invite.status;\n\n if (effectiveStatus === InviteStatus.Accepted) {\n return (\n <StatusView\n icon={CheckCircle}\n iconClass=\"bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]\"\n title={tr('members.inviteAcceptance.alreadyAcceptedTitle', 'Invitation Already Accepted')}\n description={tr(\n 'members.inviteAcceptance.alreadyAcceptedDescription',\n 'You have already accepted this invitation.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganization', 'Go to Organization')}\n onPrimary={() => navigate(`${basePath}/${invite.organizationId}`)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Rejected) {\n return (\n <StatusView\n icon={XCircle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.rejectedTitle', 'Invitation Declined')}\n description={tr(\n 'members.inviteAcceptance.rejectedDescription',\n 'This invitation was previously declined.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Expired) {\n return (\n <StatusView\n icon={Clock}\n iconClass=\"bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)]\"\n title={tr('members.inviteAcceptance.expiredTitle', 'Invitation Expired')}\n description={tr(\n 'members.inviteAcceptance.expiredDescription',\n 'This invitation has expired. Please contact an organization admin for a new one.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Cancelled) {\n return (\n <StatusView\n icon={Ban}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.cancelledTitle', 'Invitation Cancelled')}\n description={tr(\n 'members.inviteAcceptance.cancelledDescription',\n 'This invitation was cancelled by the sender and is no longer valid.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n // PENDING — show the acceptance UI.\n const organizationName = invite.organization?.name ?? invite.organizationId;\n const expiresLabel = formatDate(invite.expiresAt);\n const busy = processing !== null;\n\n return (\n <PageShell>\n <EmphasisPanel className=\"p-8\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Building2 size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.pageTitle', 'Organization Invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr('members.inviteAcceptance.pageSubtitle', \"You've been invited to join\")}{' '}\n <span className=\"font-medium text-[var(--color-text-primary)]\">\n {organizationName}\n </span>\n </p>\n </div>\n </div>\n\n <dl className=\"space-y-4 rounded-xl bg-[var(--color-bg-subtle)] p-5\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.emailLabel', 'Email Address')}\n </dt>\n <dd className=\"mt-1 break-all text-[var(--color-text-primary)]\">{invite.email}</dd>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.roleLabel', 'Role')}\n </dt>\n <dd>\n <Badge variant=\"secondary\">{invite.role}</Badge>\n </dd>\n </div>\n {expiresLabel ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.expiresLabel', 'Expires')}\n </dt>\n <dd className=\"mt-1 flex items-center gap-2 text-[var(--color-text-primary)]\">\n <Clock size={16} className=\"text-[var(--color-text-muted)]\" />\n {expiresLabel}\n </dd>\n </div>\n ) : null}\n {invite.message ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.messageLabel', 'Message')}\n </dt>\n <dd className=\"mt-1 text-[var(--color-text-secondary)]\">{invite.message}</dd>\n </div>\n ) : null}\n </dl>\n\n {actionError ? (\n <div className=\"mt-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3\">\n <AlertTriangle size={16} className=\"shrink-0 text-[var(--color-status-error-text)]\" />\n <p className=\"text-sm text-[var(--color-status-error-text)]\">{actionError}</p>\n </div>\n ) : null}\n\n <div className=\"mt-6 flex flex-col gap-3 border-t border-[var(--color-border-seam)] pt-6 sm:flex-row\">\n <button\n type=\"button\"\n onClick={() => void handleAccept()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-[var(--color-status-success-bg)] px-6 py-3 font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'accept' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <CheckCircle size={16} />\n )}\n {tr('members.inviteAcceptance.acceptButton', 'Accept Invitation')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleReject()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-3 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'reject' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <XCircle size={16} />\n )}\n {tr('members.inviteAcceptance.declineButton', 'Decline')}\n </button>\n </div>\n </EmphasisPanel>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|