import { useEffect, useState } from 'react'; import { zodResolver } from '@hookform/resolvers/zod'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { Loader } from 'lucide-react'; import { useForm } from 'react-hook-form'; import { useRevalidator } from 'react-router'; import { z } from 'zod'; import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app'; import { trpc } from '@documenso/trpc/react'; import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; import { Button } from '@documenso/ui/primitives/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@documenso/ui/primitives/select'; import { useToast } from '@documenso/ui/primitives/use-toast'; export type TeamTransferDialogProps = { teamId: number; teamName: string; ownerUserId: number; trigger?: React.ReactNode; }; export const TeamTransferDialog = ({ trigger, teamId, teamName, ownerUserId, }: TeamTransferDialogProps) => { const [open, setOpen] = useState(false); const { _ } = useLingui(); const { toast } = useToast(); const { revalidate } = useRevalidator(); const { mutateAsync: requestTeamOwnershipTransfer } = trpc.team.requestTeamOwnershipTransfer.useMutation(); const { data, refetch: refetchTeamMembers, isPending: loadingTeamMembers, isLoadingError: loadingTeamMembersError, } = trpc.team.getTeamMembers.useQuery({ teamId, }); const confirmTransferMessage = _(msg`transfer ${teamName}`); const ZTransferTeamFormSchema = z.object({ teamName: z.literal(confirmTransferMessage, { errorMap: () => ({ message: `You must enter '${confirmTransferMessage}' to proceed` }), }), newOwnerUserId: z.string(), clearPaymentMethods: z.boolean(), }); const form = useForm>({ resolver: zodResolver(ZTransferTeamFormSchema), defaultValues: { teamName: '', clearPaymentMethods: false, }, }); const onFormSubmit = async ({ newOwnerUserId, clearPaymentMethods, }: z.infer) => { try { await requestTeamOwnershipTransfer({ teamId, newOwnerUserId: Number.parseInt(newOwnerUserId), clearPaymentMethods, }); await revalidate(); toast({ title: _(msg`Success`), description: _(msg`An email requesting the transfer of this team has been sent.`), duration: 5000, }); setOpen(false); } catch (err) { toast({ title: _(msg`An unknown error occurred`), description: _( msg`We encountered an unknown error while attempting to request a transfer of this team. Please try again later.`, ), variant: 'destructive', duration: 10000, }); } }; useEffect(() => { if (!open) { form.reset(); } }, [open, form]); useEffect(() => { if (open && loadingTeamMembersError) { void refetchTeamMembers(); } }, [open, loadingTeamMembersError, refetchTeamMembers]); const teamMembers = data ? data.filter((teamMember) => teamMember.userId !== ownerUserId) : undefined; return ( !form.formState.isSubmitting && setOpen(value)}> {trigger ?? ( )} {teamMembers && teamMembers.length > 0 ? ( Transfer team Transfer ownership of this team to a selected team member.
( New team owner )} /> ( Confirm by typing{' '} {confirmTransferMessage} )} />
    {IS_BILLING_ENABLED() && (
  • Any payment methods attached to this team will remain attached to this team. Please contact us if you need to update this information.
  • )}
  • The selected team member will receive an email which they must accept before the team is transferred
) : ( {loadingTeamMembers ? ( ) : (

{loadingTeamMembersError ? ( An error occurred while loading team members. Please try again later. ) : ( You must have at least one other team member to transfer ownership. )}

)}
)}
); };