diff --git a/starterkits/saas/src/app/waitlist/_components/waitlist-form.tsx b/starterkits/saas/src/app/waitlist/_components/waitlist-form.tsx index ab2b10e..6b07654 100644 --- a/starterkits/saas/src/app/waitlist/_components/waitlist-form.tsx +++ b/starterkits/saas/src/app/waitlist/_components/waitlist-form.tsx @@ -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, @@ -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; @@ -29,14 +34,31 @@ 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 (
- -
+ +
@@ -62,7 +84,7 @@ export function WaitlistForm() { @@ -74,8 +96,13 @@ export function WaitlistForm() { />
- diff --git a/starterkits/saas/src/server/actions/waitlist/mutations.ts b/starterkits/saas/src/server/actions/waitlist/mutations.ts new file mode 100644 index 0000000..e19a9f1 --- /dev/null +++ b/starterkits/saas/src/server/actions/waitlist/mutations.ts @@ -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; + +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", + }; + } +} diff --git a/starterkits/saas/src/server/db/schema.ts b/starterkits/saas/src/server/db/schema.ts index d03e61b..a0cf57a 100644 --- a/starterkits/saas/src/server/db/schema.ts +++ b/starterkits/saas/src/server/db/schema.ts @@ -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"), +});