Skip to content

Commit

Permalink
feat(saas): Add User to waitlist logic
Browse files Browse the repository at this point in the history
  • Loading branch information
alifarooq9 committed May 9, 2024
1 parent b756a6a commit 9d23608
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 12 deletions.
51 changes: 39 additions & 12 deletions starterkits/saas/src/app/waitlist/_components/waitlist-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { type z } from "zod";
import {
FormField,
FormItem,
Expand All @@ -12,10 +12,15 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { waitlistUsersSchema } from "@/server/db/schema";
import { useMutation } from "@tanstack/react-query";
import { addUserToWaitlistMutation } from "@/server/actions/waitlist/mutations";
import { toast } from "sonner";
import { Icons } from "@/components/ui/icons";

const waitformSchema = z.object({
name: z.string().min(2, "Please enter a valid name"),
email: z.string().email("Please enter a valid email address"),
const waitformSchema = waitlistUsersSchema.pick({
name: true,
email: true,
});

type waitformSchemaType = z.infer<typeof waitformSchema>;
Expand All @@ -29,22 +34,39 @@ export function WaitlistForm() {
},
});

const onSubmit = async (data: waitformSchemaType) => {
console.log(data);
const { mutate, isPending } = useMutation({
mutationFn: () => addUserToWaitlistMutation(form.getValues()),
onSuccess: () => {
toast("You have been added to waitlist", {
description: "You will be notified when the waitlist opens",
});
},
onError: () => {
toast.error("Something went wrong", {
description: "Please try again later",
});
},
});

const onSubmit = async () => {
mutate();
};

return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="grid gap-4">
<div className="grid grid-cols-2 gap-2">
<form
onSubmit={form.handleSubmit(onSubmit)}
className="grid w-full max-w-md gap-4"
>
<div className="grid w-full grid-cols-2 gap-2">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
className="h-10 w-full bg-background sm:w-auto"
className="h-10 w-full bg-background"
placeholder="Name"
{...field}
/>
Expand All @@ -62,7 +84,7 @@ export function WaitlistForm() {
<FormItem>
<FormControl>
<Input
className="h-10 w-full bg-background sm:w-auto"
className="h-10 w-full bg-background"
placeholder="Email"
{...field}
/>
Expand All @@ -74,8 +96,13 @@ export function WaitlistForm() {
/>
</div>

<Button type="submit" className="w-full">
Join the waitlist
<Button
disabled={isPending}
type="submit"
className="w-full gap-2"
>
{isPending ? <Icons.loader className="h-4 w-4" /> : null}
<span>Join the waitlist</span>
</Button>
</form>
</Form>
Expand Down
45 changes: 45 additions & 0 deletions starterkits/saas/src/server/actions/waitlist/mutations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use server";
import { waitlistUsers, waitlistUsersSchema } from "@/server/db/schema";
import { type z } from "zod";
import { db } from "@/server/db";

type AddUserToWaitlistMutationProps = z.infer<typeof waitlistUsersSchema>;

export async function addUserToWaitlistMutation({
name,
email,
}: AddUserToWaitlistMutationProps) {
const parseData = await waitlistUsersSchema.safeParseAsync({
name,
email,
});

if (!parseData.success) {
return {
success: false,
error: parseData.error.message,
};
}

const { data } = parseData;

try {
await db
.insert(waitlistUsers)
.values(data)
.onConflictDoUpdate({
target: waitlistUsers.email,
set: { name: data.name },
})
.execute();

return {
success: true,
};
} catch (error) {
return {
success: false,
error: "Something went wrong, please try again later",
};
}
}
15 changes: 15 additions & 0 deletions starterkits/saas/src/server/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,18 @@ export const subscriptionsRelations = relations(subscriptions, ({ one }) => ({
references: [organizations.id],
}),
}));

export const waitlistUsers = createTable("waitlistUser", {
id: varchar("id", { length: 255 })
.notNull()
.primaryKey()
.default(sql`gen_random_uuid()`),
email: varchar("email", { length: 255 }).notNull().unique(),
name: varchar("name", { length: 255 }).notNull(),
createdAt: timestamp("createdAt", { mode: "date" }).notNull().defaultNow(),
});

export const waitlistUsersSchema = createInsertSchema(waitlistUsers, {
email: z.string().email("Email must be a valid email address"),
name: z.string().min(3, "Name must be at least 3 characters long"),
});

0 comments on commit 9d23608

Please sign in to comment.