11import {
2+ ArrowsClockwise ,
23 CheckCircle ,
34 Clock ,
45 EnvelopeOpen ,
56 Prohibit ,
67 SignIn ,
8+ WarningCircle ,
79} from "@phosphor-icons/react" ;
810import { useMutation , useQuery } from "@tanstack/react-query" ;
911import { ClientOnly , createFileRoute } from "@tanstack/react-router" ;
@@ -15,8 +17,6 @@ import {
1517 sharedSecondaryButtonClassName ,
1618 SharedNoteLoading ,
1719 SharedNotePrompt ,
18- SharedNoteTransientError ,
19- SharedNoteUnavailable ,
2020} from "@/components/shared-note-viewer" ;
2121import { fetchUser } from "@/functions/auth" ;
2222import { clearShareRouteContinuation } from "@/functions/share-route-continuation" ;
@@ -48,15 +48,15 @@ export const Route = createFileRoute("/team/invite/$invitationId")({
4848 ] ,
4949 } ) ,
5050 headers : ( ) => privateShareHeaders ,
51- pendingComponent : SharedNoteLoading ,
51+ pendingComponent : WorkspaceInvitationLoading ,
5252 component : Component ,
5353} ) ;
5454
5555function Component ( ) {
5656 const { user } = Route . useLoaderData ( ) ;
5757 const { invitationId } = Route . useParams ( ) ;
5858 return (
59- < ClientOnly fallback = { < SharedNoteLoading /> } >
59+ < ClientOnly fallback = { < WorkspaceInvitationLoading /> } >
6060 < InvitationClient invitationId = { invitationId } signedIn = { Boolean ( user ) } />
6161 </ ClientOnly >
6262 ) ;
@@ -116,12 +116,12 @@ function InvitationClient({
116116 } ) ;
117117
118118 if ( continuation . isPending ) {
119- return < SharedNoteLoading /> ;
119+ return < WorkspaceInvitationLoading /> ;
120120 }
121121
122122 if ( continuation . isError ) {
123123 return (
124- < SharedNoteTransientError
124+ < WorkspaceInvitationTransientError
125125 retry = { ( ) => {
126126 void continuation . retry ( ) ;
127127 } }
@@ -130,7 +130,7 @@ function InvitationClient({
130130 }
131131
132132 if ( ! continuation . token || ! parsedInvitationId ) {
133- return < SharedNoteUnavailable /> ;
133+ return < WorkspaceInvitationUnavailable /> ;
134134 }
135135
136136 if ( ! signedIn ) {
@@ -140,6 +140,7 @@ function InvitationClient({
140140 } ) ;
141141 return (
142142 < SharedNotePrompt
143+ headerLabel = "Team invitation"
143144 icon = { < SignIn className = "size-6" aria-hidden = "true" /> }
144145 title = "Sign in to accept this invitation"
145146 description = "Use the email address this workspace invitation was sent to. Your invitation stays in this browser tab while you sign in."
@@ -156,7 +157,17 @@ function InvitationClient({
156157 }
157158
158159 if ( invitationQuery . isPending ) {
159- return < SharedNoteLoading /> ;
160+ return < WorkspaceInvitationLoading /> ;
161+ }
162+
163+ if ( invitationQuery . isError || invitationQuery . data ?. status === "error" ) {
164+ return (
165+ < WorkspaceInvitationTransientError
166+ retry = { ( ) => {
167+ void invitationQuery . refetch ( ) ;
168+ } }
169+ />
170+ ) ;
160171 }
161172
162173 const invitationFailure = getInvitationRouteFailure ( {
@@ -168,14 +179,15 @@ function InvitationClient({
168179 invitationFailure === "unavailable" ||
169180 invitationQuery . data ?. status !== "ready"
170181 ) {
171- return < SharedNoteUnavailable /> ;
182+ return < WorkspaceInvitationUnavailable /> ;
172183 }
173184
174185 const invitation = invitationQuery . data . invitation ;
175186
176187 if ( invitation . status === "accepted" || acceptMutation . isSuccess ) {
177188 return (
178189 < SharedNotePrompt
190+ headerLabel = "Team invitation"
179191 icon = { < CheckCircle className = "size-6" aria-hidden = "true" /> }
180192 title = { `You've joined ${ invitation . workspaceName } ` }
181193 description = "Open Anarlog on your computer to start collaborating in this workspace."
@@ -191,6 +203,7 @@ function InvitationClient({
191203 if ( invitation . status === "revoked" ) {
192204 return (
193205 < SharedNotePrompt
206+ headerLabel = "Team invitation"
194207 icon = { < Prohibit className = "size-6" aria-hidden = "true" /> }
195208 title = "This invitation was revoked"
196209 description = "Ask a workspace admin to send a new invitation."
@@ -201,6 +214,7 @@ function InvitationClient({
201214 if ( invitation . status === "expired" ) {
202215 return (
203216 < SharedNotePrompt
217+ headerLabel = "Team invitation"
204218 icon = { < Clock className = "size-6" aria-hidden = "true" /> }
205219 title = "This invitation has expired"
206220 description = "Ask a workspace admin to send a new invitation."
@@ -210,6 +224,7 @@ function InvitationClient({
210224
211225 return (
212226 < SharedNotePrompt
227+ headerLabel = "Team invitation"
213228 icon = { < EnvelopeOpen className = "size-6" aria-hidden = "true" /> }
214229 title = { `Join ${ invitation . workspaceName } ` }
215230 description = "Accept the invitation to become a member of this Anarlog workspace."
@@ -245,6 +260,47 @@ function InvitationClient({
245260 ) ;
246261}
247262
263+ function WorkspaceInvitationLoading ( ) {
264+ return (
265+ < SharedNoteLoading
266+ headerLabel = "Team invitation"
267+ loadingLabel = "Loading team invitation"
268+ />
269+ ) ;
270+ }
271+
272+ function WorkspaceInvitationUnavailable ( ) {
273+ return (
274+ < SharedNotePrompt
275+ headerLabel = "Team invitation"
276+ icon = { < WarningCircle className = "size-6" aria-hidden = "true" /> }
277+ title = "This team invitation isn’t available"
278+ description = "Sign in with the email address that received this invitation, or ask the workspace admin for a new invitation."
279+ />
280+ ) ;
281+ }
282+
283+ function WorkspaceInvitationTransientError ( { retry } : { retry : ( ) => void } ) {
284+ return (
285+ < SharedNotePrompt
286+ headerLabel = "Team invitation"
287+ icon = { < WarningCircle className = "size-6" aria-hidden = "true" /> }
288+ title = "We couldn’t load this team invitation"
289+ description = "Anarlog had a temporary problem loading the invitation. Please try again."
290+ actions = {
291+ < button
292+ type = "button"
293+ className = { sharedPrimaryButtonClassName }
294+ onClick = { retry }
295+ >
296+ < ArrowsClockwise className = "mr-2 size-4" aria-hidden = "true" />
297+ Try again
298+ </ button >
299+ }
300+ />
301+ ) ;
302+ }
303+
248304async function clearInvitationContinuation ( pathname : string ) {
249305 clearShareRouteToken ( pathname ) ;
250306 await clearShareRouteContinuation ( { data : pathname } ) . catch ( ( ) => undefined ) ;
0 commit comments