import { useIsLoggedIn, useParams } from 'common' import Link from 'next/link' import { useRouter } from 'next/router' import type { ReactNode } from 'react' import { toast } from 'sonner' import { Button, Card, CardContent } from 'ui' import { Admonition, ShimmeringLoader } from 'ui-patterns' import { getOrganizationInviteContent, getOrganizationInviteStatus, } from './OrganizationInvite.utils' import { OrganizationInviteError } from './OrganizationInviteError' import { InterstitialAccountRow, InterstitialLayout, BrivenLogo, } from '@/components/layouts/InterstitialLayout' import { useOrganizationAcceptInvitationMutation } from '@/data/organization-members/organization-invitation-accept-mutation' import { useOrganizationInvitationTokenQuery } from '@/data/organization-members/organization-invitation-token-query' import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled' import { useProfile, useProfileNameAndPicture } from '@/lib/profile' export const OrganizationInvite = () => { const router = useRouter() const isLoggedIn = useIsLoggedIn() const { profile, isLoading: isLoadingProfile } = useProfile() const { username, avatarUrl, primaryEmail } = useProfileNameAndPicture() const { slug, token } = useParams() const isSignUpEnabled = useIsFeatureEnabled('dashboard_auth:sign_up') const { data, error, isSuccess: isSuccessInvitation, isError: isErrorInvitation, isPending: isLoadingInvitation, } = useOrganizationInvitationTokenQuery( { slug, token }, { retry: false, refetchOnWindowFocus: false, enabled: !!profile && !!slug && !!token, } ) const inviteStatus = getOrganizationInviteStatus({ data, error, isErrorInvitation, isLoadingInvitation, isLoadingProfile, isLoggedIn, isRouterReady: router.isReady, isSuccessInvitation, profileExists: !!profile, }) const isSignedOut = inviteStatus === 'signed-out' const isInvitationLoading = inviteStatus === 'loading' const inviteContent = getOrganizationInviteContent({ data, isSignUpEnabled, status: inviteStatus, }) const hasError = ['wrong-account', 'expired', 'invalid', 'error'].includes(inviteStatus) const loginRedirectLink = `/sign-in?returnTo=${encodeURIComponent(`/join?token=${token}&slug=${slug}`)}` const signupRedirectLink = `/sign-up?returnTo=${encodeURIComponent(`/join?token=${token}&slug=${slug}`)}` const { mutate: joinOrganization, isPending: isJoining } = useOrganizationAcceptInvitationMutation({ onSuccess: () => { router.push('/organizations') }, onError: (error) => { toast.error(`Failed to join organization: ${error.message}`) }, }) async function handleJoinOrganization() { if (!slug) return console.error('Slug is required') if (!token) return console.error('Token is required') joinOrganization({ slug, token }) } const withLayout = (children: ReactNode) => ( } title={ isInvitationLoading ? ( ) : inviteContent.title ? ( inviteContent.title ) : undefined } description={ isInvitationLoading ? ( ) : inviteContent.description ? ( inviteContent.description ) : undefined } titleClassName="text-xl" >
{children}
) if (isSignedOut) { return withLayout(
{isSignUpEnabled && ( )}
) } if (isInvitationLoading) { return withLayout(
) } if (inviteStatus === 'no-longer-valid') { return withLayout(
) } if (hasError) { return withLayout( ) } return withLayout(
) }