"use client" import { CheckIcon, Loader2, XIcon } from "lucide-react" import { useCallback, useContext, useEffect, useMemo, useState } from "react" import { useAuthenticate } from "../../hooks/use-authenticate" import { AuthUIContext } from "../../lib/auth-ui-provider" import { cn, getLocalizedError, getSearchParam } from "../../lib/utils" import type { AuthLocalization } from "../../localization/auth-localization" import type { SettingsCardClassNames } from "../settings/shared/settings-card" import { Button } from "../ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card" import { Skeleton } from "../ui/skeleton" import { OrganizationCellView } from "./organization-cell-view" export interface AcceptInvitationCardProps { className?: string classNames?: SettingsCardClassNames localization?: Partial } export function AcceptInvitationCard({ className, classNames, localization: localizationProp }: AcceptInvitationCardProps) { const { localization: contextLocalization, redirectTo, replace, toast } = useContext(AuthUIContext) const localization = useMemo( () => ({ ...contextLocalization, ...localizationProp }), [contextLocalization, localizationProp] ) const { data: sessionData } = useAuthenticate() const [invitationId, setInvitationId] = useState(null) useEffect(() => { const invitationIdParam = getSearchParam("invitationId") if (!invitationIdParam) { toast({ variant: "error", message: localization.INVITATION_NOT_FOUND }) replace(redirectTo) return } setInvitationId(invitationIdParam) }, [localization.INVITATION_NOT_FOUND, toast, replace, redirectTo]) if (!sessionData || !invitationId) { return ( ) } return ( ) } function AcceptInvitationContent({ className, classNames, localization: localizationProp, invitationId }: AcceptInvitationCardProps & { invitationId: string }) { const { authClient, hooks: { useInvitation }, localization: contextLocalization, organization, redirectTo, replace, toast, localizeErrors } = useContext(AuthUIContext) const localization = useMemo( () => ({ ...contextLocalization, ...localizationProp }), [contextLocalization, localizationProp] ) const [isRejecting, setIsRejecting] = useState(false) const [isAccepting, setIsAccepting] = useState(false) const isProcessing = isRejecting || isAccepting const { data: invitation, isPending } = useInvitation({ query: { id: invitationId } }) const getRedirectTo = useCallback( () => getSearchParam("redirectTo") || redirectTo, [redirectTo] ) useEffect(() => { if (isPending || !invitationId) return if (!invitation) { toast({ variant: "error", message: localization.INVITATION_NOT_FOUND }) replace(redirectTo) return } if ( invitation.status !== "pending" || new Date(invitation.expiresAt) < new Date() ) { toast({ variant: "error", message: new Date(invitation.expiresAt) < new Date() ? localization.INVITATION_EXPIRED : localization.INVITATION_NOT_FOUND }) replace(redirectTo) } }, [ invitation, isPending, invitationId, localization, toast, replace, redirectTo ]) const acceptInvitation = async () => { setIsAccepting(true) try { await authClient.organization.acceptInvitation({ invitationId: invitationId, fetchOptions: { throw: true } }) toast({ variant: "success", message: localization.INVITATION_ACCEPTED || "Invitation accepted" }) replace(getRedirectTo()) } catch (error) { toast({ variant: "error", message: getLocalizedError({ error, localization, localizeErrors }) }) setIsAccepting(false) } } const rejectInvitation = async () => { setIsRejecting(true) try { await authClient.organization.rejectInvitation({ invitationId: invitationId, fetchOptions: { throw: true } }) toast({ variant: "success", message: localization.INVITATION_REJECTED }) replace(redirectTo) } catch (error) { toast({ variant: "error", message: getLocalizedError({ error, localization, localizeErrors }) }) setIsRejecting(false) } } const builtInRoles = [ { role: "owner", label: localization.OWNER }, { role: "admin", label: localization.ADMIN }, { role: "member", label: localization.MEMBER } ] const roles = [...builtInRoles, ...(organization?.customRoles || [])] const roleLabel = roles.find((r) => r.role === invitation?.role)?.label || invitation?.role if (!invitation) return ( ) return ( {localization.ACCEPT_INVITATION} {localization.ACCEPT_INVITATION_DESCRIPTION}

{roleLabel}

) } const AcceptInvitationSkeleton = ({ className, classNames, localization }: AcceptInvitationCardProps) => { return (
) }