From 7fadcd561fec32c242f95cc1946e57c17e5f5c54 Mon Sep 17 00:00:00 2001 From: i701 Date: Wed, 27 Nov 2024 07:48:16 +0500 Subject: [PATCH] wip --- actions/auth-actions.ts | 84 ++++- app/(auth)/signup/page.tsx | 10 +- app/(auth)/verify-otp/page.tsx | 9 +- app/layout.tsx | 2 +- components/auth/login-form.tsx | 8 +- components/auth/signup-form.tsx | 356 +++++++++++------- components/auth/verify-otp-form.tsx | 12 +- lib/auth.ts | 9 - lib/schemas.ts | 9 +- .../20241125021358_add/migration.sql | 11 + .../20241125021453_add/migration.sql | 2 + .../20241125021534_add/migration.sql | 2 + .../20241125021636_add/migration.sql | 2 + .../20241126142344_test/migration.sql | 30 ++ .../20241126151827_add/migration.sql | 17 + .../20241126160711_add/migration.sql | 39 ++ prisma/schema.prisma | 41 +- 17 files changed, 454 insertions(+), 189 deletions(-) create mode 100644 prisma/migrations/20241125021358_add/migration.sql create mode 100644 prisma/migrations/20241125021453_add/migration.sql create mode 100644 prisma/migrations/20241125021534_add/migration.sql create mode 100644 prisma/migrations/20241125021636_add/migration.sql create mode 100644 prisma/migrations/20241126142344_test/migration.sql create mode 100644 prisma/migrations/20241126151827_add/migration.sql create mode 100644 prisma/migrations/20241126160711_add/migration.sql diff --git a/actions/auth-actions.ts b/actions/auth-actions.ts index 1b16f1f..7957dac 100644 --- a/actions/auth-actions.ts +++ b/actions/auth-actions.ts @@ -2,10 +2,11 @@ import { authClient } from "@/lib/auth-client"; import prisma from "@/lib/db"; -import type { signUpFormSchema } from "@/lib/schemas"; +import { signUpFormSchema } from "@/lib/schemas"; +// import type { User } from "@prisma/client"; import { redirect } from "next/navigation"; import { z } from "zod"; - +import { headers } from "next/headers"; const formSchema = z.object({ phoneNumber: z .string() @@ -13,7 +14,7 @@ const formSchema = z.object({ }); export async function signin( - currentState: { message: string; status: string }, + previousState: ActionState, formData: FormData, ) { const phoneNumber = formData.get("phoneNumber") as string; @@ -46,17 +47,78 @@ export async function signin( await authClient.phoneNumber.sendOtp({ phoneNumber: NUMBER_WITH_COUNTRY_CODE, }); - redirect("/verify-otp"); + redirect(`/verify-otp?phone_number=${encodeURIComponent(phoneNumber)}`); } -export async function signup({ - userData, -}: { userData: z.infer }) { - const newUser = await prisma.user.create({ - data: { ...userData, email: "" }, - }); +type ActionState = { + message: string; + payload?: FormData; +}; - redirect("/login"); +export async function signup( + _actionState: ActionState, + formData: FormData, +) { + const data = Object.fromEntries(formData.entries()); + const parsedData = signUpFormSchema.safeParse(data); + // get phone number from /signup?phone_number=999-1231 + const headersList = await headers() + const referer = headersList.get("referer") + const number = referer?.split("?")[1]?.split("=")[1] + let NUMBER_WITH_COUNTRY_CODE: string + + console.log(data) + + if (!parsedData.success) { + return { + message: "Invalid form data", + payload: formData, + errors: parsedData.error.flatten(), + }; + } + if (parsedData.data.name.includes("a")){ + return { + message: "ID card already exists.", + payload: formData, + db_error: "id_card", + }; + } + + if (number) { + NUMBER_WITH_COUNTRY_CODE = `+960${number.split("-").join("")}` + } else { + NUMBER_WITH_COUNTRY_CODE = `+960${parsedData.data.phone_number.split("-").join("")}`; + } + console.log({NUMBER_WITH_COUNTRY_CODE}) + const idCardExists = await prisma.user.findFirst({ + where: { + id_card: parsedData.data.id_card, + }, + }); + if (idCardExists) { + return { + message: "ID card already exists.", + payload: formData, + db_error: "id_card", + }; + } + // const newUser = await prisma.user.create({ + // data: { + // name: parsedData.data.name, + // islandId: "1", + // atollId: "1", + // house_name: parsedData.data.house_name, + // id_card: parsedData.data.id_card, + // dob: parsedData.data.dob, + // phoneNumber: NUMBER_WITH_COUNTRY_CODE, + // }, + // }); + // await authClient.phoneNumber.sendOtp({ + // phoneNumber: newUser.phoneNumber, + // }); + // redirect(`/verify-otp?phone_number=${encodeURIComponent(newUser.phoneNumber)}`); + + return { message: "Post created" }; } export const sendOtp = async (phoneNumber: string, code: string) => { diff --git a/app/(auth)/signup/page.tsx b/app/(auth)/signup/page.tsx index ea634bd..30268e3 100644 --- a/app/(auth)/signup/page.tsx +++ b/app/(auth)/signup/page.tsx @@ -1,8 +1,14 @@ import SignUpForm from "@/components/auth/signup-form"; +import prisma from "@/lib/db"; import Image from "next/image"; import React from "react"; -export default function LoginPage() { +export default async function LoginPage() { + const atolls = await prisma.atoll.findMany({ + include: { + islands: true + } + }) return
Sar Link Logo @@ -11,7 +17,7 @@ export default function LoginPage() {

SAR Link Portal

Pay for your devices and track your bills.

- +
; } diff --git a/app/(auth)/verify-otp/page.tsx b/app/(auth)/verify-otp/page.tsx index 575cf75..8a53726 100644 --- a/app/(auth)/verify-otp/page.tsx +++ b/app/(auth)/verify-otp/page.tsx @@ -2,7 +2,12 @@ import VerifyOTPForm from "@/components/auth/verify-otp-form"; import Image from "next/image"; import React from "react"; -export default function VerifyOTP() { +export default async function VerifyOTP({ + searchParams, +}: { + searchParams: Promise<{ phone_number: string }> +}) { + const phone_number = (await searchParams).phone_number return
Sar Link Logo @@ -11,7 +16,7 @@ export default function VerifyOTP() {

SAR Link Portal

Pay for your devices and track your bills.

- +
; } diff --git a/app/layout.tsx b/app/layout.tsx index 5358e7c..7d0e3f9 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -25,7 +25,7 @@ export default function RootLayout({ - + -

Login

-
+
: "Request OTP"}
-
+ {/*
Don't have an account?{" "} Sign up -
+
*/}
); diff --git a/components/auth/signup-form.tsx b/components/auth/signup-form.tsx index 12bcfe2..bd4beef 100644 --- a/components/auth/signup-form.tsx +++ b/components/auth/signup-form.tsx @@ -1,167 +1,241 @@ "use client"; import { Button } from "@/components/ui/button"; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@/components/ui/form"; import { Input } from "@/components/ui/input"; -import { signUpFormSchema } from "@/lib/schemas"; -import { zodResolver } from "@hookform/resolvers/zod"; import Link from "next/link"; + +import { signup } from "@/actions/auth-actions"; +import { cn } from "@/lib/utils"; +import { Loader } from "lucide-react"; +import { useActionState } from "react"; import { useSearchParams } from "next/navigation"; +import { Atoll, Island, Prisma } from "@prisma/client"; +import * as React from "react" -import { useForm } from "react-hook-form"; -import { toast } from "sonner"; -import type { z } from "zod"; -import { DatePicker } from "../ui/datepicker"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" -export default function SignUpForm() { - const params = useSearchParams(); - console.log(params); - const phone_number = params.get("phone_number"); - const form = useForm>({ - resolver: zodResolver(signUpFormSchema), - defaultValues: { - phoneNumber: phone_number ?? "", - name: "", - id_card: "", - house_name: "", - island: "F.Dharanboodhoo", - }, - }); - - function onSubmit(values: z.infer) { - console.log(values); +type AtollWithIslands = Prisma.AtollGetPayload<{ + include: { + islands: true; } +}> + +export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) { + const [atoll, setAtoll] = React.useState() + const [island, setIsland] = React.useState() + + + + const [actionState, action, isPending] = useActionState(signup, { + message: "", + }); + const params = useSearchParams(); + const phoneNumberFromUrl = params.get("phone_number"); + const NUMBER_WITHOUT_DASH = phoneNumberFromUrl?.split("-").join("") + return ( -
- -

- Sign up -

-
- +
+
+ + + ( - - Name - - - - - - )} + type="text" + defaultValue={(actionState.payload?.get("name") || "") as string} + placeholder="Full Name" /> - + {actionState.errors?.fieldErrors.name} + + )} +
+
+ + ( - - ID Card - - - - - + type="text" + maxLength={7} + defaultValue={(actionState.payload?.get("id_card") || "") as string} + className={cn( + 'text-base', + actionState.errors?.fieldErrors?.id_card && 'border-2 border-red-500', )} + placeholder="ID Card" /> - ( - - Island - - - - - + {actionState?.errors?.fieldErrors?.id_card?.[0] && ( + + {actionState.errors.fieldErrors.id_card[0]} + + )} + {actionState.db_error === "id_card" && ( + + {actionState.message} + + )} +
+
+ {/* + - + {actionState?.errors?.fieldErrors.island_name} + + )} */} + +
+ + +
+
+ + +
+
+ +
+ + ( - - House Name - - - - - - )} + defaultValue={(actionState.payload?.get("house_name") || "") as string} + type="text" + placeholder="House Name" /> - + {actionState.errors?.fieldErrors?.house_name} + + )} +
+ +
+ + ( - - Date of birth - - - - - - )} + defaultValue={(actionState.payload?.get("dob") || "") as string} + type="date" + placeholder="Date of birth" /> - ( - - Phone number - -
-
- - - -
- -
-
- -
- )} - /> - -
-
- Already have an account?{" "} - - login - + {actionState.errors?.fieldErrors?.dob && ( + + {actionState.errors?.fieldErrors?.dob} + + )}
- - +
+ + +
+ {actionState?.errors?.fieldErrors?.phone_number?.[0] && ( + + {actionState.errors.fieldErrors.phone_number[0]} + + )} + +
+ +
+ Already have an account?{" "} + + login + +
+ + ); } + + + + + + + + diff --git a/components/auth/verify-otp-form.tsx b/components/auth/verify-otp-form.tsx index 4bb3df1..9280727 100644 --- a/components/auth/verify-otp-form.tsx +++ b/components/auth/verify-otp-form.tsx @@ -15,14 +15,13 @@ import { z } from "zod"; const OTPSchema = z.object({ pin: z.string().min(6, { message: "Your one-time password must be 6 characters.", - }), }); -export default function VerifyOTPForm() { +export default function VerifyOTPForm({ phone_number }: { phone_number: string }) { const [isPending, startTransition] = useTransition(); const router = useRouter(); - + console.log("verification in OTP form", phone_number) const { register, handleSubmit, @@ -35,13 +34,13 @@ export default function VerifyOTPForm() { }); const onSubmit: SubmitHandler> = (data) => { - console.log(data); startTransition(async () => { const isVerified = await authClient.phoneNumber.verify({ - phoneNumber: "+9607780588", + phoneNumber: phone_number, code: data.pin, }); + console.log({ isVerified }); if (!isVerified.error) { router.push("/devices"); } else { @@ -53,9 +52,8 @@ export default function VerifyOTPForm() { return (
-

Verify OTP