2024-06-04
In this blog we will be displaying a thank you message after the invite is accepted successfully
Blog post by MF Mabala
Displaying a thank you message after and Invitation has been accepted.
This blog is a continuation of my two previous blogs. here are the two links you can access the blogs from. https://madinku.dev/post/displaying-user-details-in-a-shadcn-datatable and https://madinku.dev/post/accepting-an-invitation-with-a-graphql-mutation
In this blog we will be focusing a lot more on adding a thank you message after the form has been sent and the invite accepted. I will then add a link on the message so that the user can click and be able to login to the website . Accepting the invitation means accepting to become a member of the organization or company in question. Continuing from the previous post in the accept-inivitation.tsx file we will add a use state for submitted and add it to the return function as well
import { useAcceptInvitationMutation } from '@gen/graphql';
import * as z from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { useCallback, useState} from 'react';
import { useForm } from 'react-hook-form';
const formSchema = z.object({
firstName: z.string().min(2),
lastName: z.string().min(2),
});
interface UseAcceptInvitationProps {
onCompleted: () => void;
firstName: string;
lastName: string;
id: string;
}
export function useAcceptInvitation({
onCompleted,
firstName,
lastName,
id,
}): UseAcceptInvitationProps {
const [acceptInvitation] = useAcceptInvitationMutation();
const [isDisabled, setIsDisabled] = useState(false);
const [submitted, setSubmitted] = useState(false);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
firstName,
lastName,
email,
},
});
const onSubmit = useCallback(
(values: z.infer<typeof formSchema>) => {
setIsDisabled(true),
acceptInvitation({
variables: {
id,
firstName: values.firstName,
lastName: values.lastName,
},
setSubmitted(true),
onCompleted,
},
});
},
[acceptInvitation, id, onCompleted]
);
return {
onSubmit,
form,
loading,
formFields: ['firstName', 'lastName', 'email'] as const,
submitted,
};
}
We are saying that if the invitation is accepted setSubmitted to true. Then return submitted. We will add the submitted to the AcceptInvite.tsx as well.
import { Invitation} from '@gen/graphql';
import { useRouter, usePathname } from 'next/navigation';
import { useAcceptInvitation} from '../hooks';
import { AcceptInviteDialog } from './acceptInviteDialog';
const InviteTypes = {
Member: {
role: UserRole.Member,
title: 'Accept Invitation',
description: "Edit your details and click accept when you're done.",
},
} as const;
export function AcceptInvite({
type,
id,
email,
firstName,
lastName,
}: AcceptInviteProps) {
const { title, description } = InviteTypes[type];
const router = useRouter();
const pathname = usePathname();
const {
form,
onSubmit,
formFields,
loading: loadingAccepting,
submitted,
isDisabled,
} = useAcceptInvitation({
id,
email,
firstName,
lastName,
onCompleted: () => {
const route = '/invitation';
if (pathname === route) {
// client-side has no reload function that works
return window.location.reload();
}
return router.push(route);
},
});
return (
<AcceptInviteDialog
title={title}
description={description}
form={form}
onSubmit={onSubmit}
formFields={formFields}
loading={loadingAccepting}
isDisabled,
submitted={submitted}
/>
);
}
interface AcceptInviteProps {
type: 'Member';
firstName: string;
lastName: string;
email: string;
id: string;
}
The real work will be added in the dialog. Remember we have a file named AcceptInviteDialog.tsx we will be working the magic in there. Go to that file and add submitted. Go through the file and see where submitted is used.
import Link from 'next/link';
import { FieldValues, UseFormReturn } from 'react-hook-form';
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
Button,
Input,
DialogFooter,
Form,
FormField,
FormItem,
FormLabel,
FormControl,
FormMessage,
} from '~/components/ui';
import { camelToTitleCase } from '~/lib/utils';
export function AcceptInviteDialog<T extends FieldValues>({
title,
description,
form,
formFields,
onSubmit,
isDisabled,
loading,
submitted,
}: AcceptInviteDialogProps<T>) {
return (
<div>
<Dialog>
<DialogTrigger>
<Button variant="default" rounded="full">
{title}
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
{submitted ? (
<div className="flex flex-col max-w-2xl px-10 py-10 mx-auto my-10 text-white bg-green-500">
<h3 className="text-xl font-bold">Your response has been submitted!</h3>
<Link href={'/login'}> <u>Click here to go to the login page</u></Link>
</div>
) : (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col w-full gap-8">
<div className="flex flex-col gap-2 w-full">
{formFields.map((key: any) => (
<FormField
key={key}
control={form.control}
name={key}
render={({ field }) => {
return (
<FormItem>
<FormLabel>{camelToTitleCase(key)}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
);
}}
/>
))}
</div>
<DialogFooter>
<Button type="submit" disabled={isDisabled || loading}>
{loading ? 'Submitting..' : 'Accept Invite'}
</Button>
</DialogFooter>
</form>
</Form>
)}
</div>
</DialogContent>
</Dialog>
</div>
);
}
interface AcceptInviteDialogProps<T extends FieldValues> {
title: string;
description: string;
loading: boolean;
form: UseFormReturn<T>;
formFields: readonly (keyof T)[];
onSubmit: (value: T) => void;
isDisabled: boolean;
submitted: boolean;
}
Explanation
Firstly we add submitted to our props and give it a type of boolean. The form is either submitted or not. Secondly we add submitted just under loading in the function. This will allow us to use submitted in our function for the purpose that we intent to use it for.
Take a look at the picture below
When you look at the code above we are saying if the form is submitted or submitted is true we want to show a 'Thank you For accepting the invite'. Now I want the user to click a link after accepting the invite . The link will take them to the login in page . You will choose which page you want them to go to.
Here is how the message will look like.