diff --git a/actions/auth-actions.ts b/actions/auth-actions.ts index 9541682..728eed1 100644 --- a/actions/auth-actions.ts +++ b/actions/auth-actions.ts @@ -1,7 +1,8 @@ "use server"; import { signUpFormSchema } from "@/lib/schemas"; -import { checkIdOrPhone } from "@/queries/authentication"; +import { backendRegister, checkIdOrPhone } from "@/queries/authentication"; +import { tryCatch } from "@/utils/tryCatch"; import { redirect } from "next/navigation"; import { z } from "zod"; const formSchema = z.object({ @@ -117,22 +118,28 @@ export async function signup(_actionState: ActionState, formData: FormData) { db_error: "phone_number", }; } - - // const newUser = await prisma.user.create({ - // data: { - // name: parsedData.data.name, - // islandId: parsedData.data.island_id, - // atollId: parsedData.data.atoll_id, - // address: parsedData.data.address, - // id_card: parsedData.data.id_card, - // dob: new Date(parsedData.data.dob), - // role: "USER", - // accNo: parsedData.data.accNo, - // phoneNumber: parsedData.data.phone_number, - // }, - // }); - // const isValidPerson = await VerifyUserDetails({ user: newUser }); - + const [signupError, signupResponse] = await tryCatch( + backendRegister({ + payload: { + firstname: parsedData.data.name, + lastname: parsedData.data.name, + username: parsedData.data.phone_number, + address: parsedData.data.address, + id_card: parsedData.data.id_card, + dob: new Date(parsedData.data.dob).toISOString().split("T")[0], + mobile: parsedData.data.phone_number, + island: Number.parseInt(parsedData.data.island_id), + atoll: Number.parseInt(parsedData.data.atoll_id), + acc_no: parsedData.data.accNo, + terms_accepted: parsedData.data.terms, + policy_accepted: parsedData.data.policy, + }, + }), + ); + if (signupError) { + throw new Error(signupError.message); + } + console.log("SIGNUP RESPONSE", signupResponse); // if (!isValidPerson) { // await SendUserRejectionDetailSMS({ // details: ` @@ -162,9 +169,9 @@ export async function signup(_actionState: ActionState, formData: FormData) { // phoneNumber: newUser.phoneNumber, // }); // } - // redirect( - // `/verify-otp?phone_number=${encodeURIComponent(newUser.phoneNumber)}`, - // ); + redirect( + `/auth/verify-otp-registration?phone_number=${encodeURIComponent(signupResponse.t_username)}`, + ); return { message: "User created successfully" }; } diff --git a/app/(auth)/auth/verify-otp-registration/page.tsx b/app/(auth)/auth/verify-otp-registration/page.tsx new file mode 100644 index 0000000..d93a136 --- /dev/null +++ b/app/(auth)/auth/verify-otp-registration/page.tsx @@ -0,0 +1,34 @@ +import VerifyRegistrationOTPForm from "@/components/auth/verify-registration-otp-form"; +import Image from "next/image"; +import { redirect } from "next/navigation"; +import React from "react"; + +export default async function VerifyRegistrationOTP({ + searchParams, +}: { + searchParams: Promise<{ phone_number: string }>; +}) { + const phone_number = (await searchParams).phone_number; + if (!phone_number) { + return redirect("/login"); + } + console.log( + "phone number from server page params (verify otp page)", + phone_number, + ); + + return ( +
+
+ Sar Link Logo +
+

SAR Link Portal

+

+ Pay for your devices and track your bills. +

+
+ +
+
+ ); +} diff --git a/components/auth/login-form.tsx b/components/auth/login-form.tsx index 4bdb163..d3cd64b 100644 --- a/components/auth/login-form.tsx +++ b/components/auth/login-form.tsx @@ -33,15 +33,9 @@ export default function LoginForm() {

{state.message}

)} - {/*
- Don't have an account?{" "} - - Sign up - -
*/} ); diff --git a/components/auth/verify-registration-otp-form.tsx b/components/auth/verify-registration-otp-form.tsx new file mode 100644 index 0000000..d60d739 --- /dev/null +++ b/components/auth/verify-registration-otp-form.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { Loader2 } from "lucide-react"; +import { signIn } from "next-auth/react"; +import Link from "next/link"; +import { useRouter, useSearchParams } from "next/navigation"; +import { useTransition } from "react"; +import { type SubmitHandler, useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; +const OTPSchema = z.object({ + pin: z.string().min(6, { + message: "OTP is required.", + }), +}); + +export default function VerifyRegistrationOTPForm({ + phone_number, +}: { phone_number: string }) { + const [isPending, startTransition] = useTransition(); + const router = useRouter(); + console.log("verification in OTP form", phone_number); + const { + register, + handleSubmit, + formState: { errors }, + } = useForm>({ + defaultValues: { + pin: "", + }, + resolver: zodResolver(OTPSchema), + }); + const searchParams = useSearchParams(); + const callbackUrl = searchParams.get("callbackUrl") || "/dashboard"; + + const onSubmit: SubmitHandler> = (data) => { + startTransition(async () => { + const nextAuth = await signIn("credentials", { + pin: data.pin, + callbackUrl, + redirect: false, + }); + if (!nextAuth?.error) { + router.push("/devices"); + } else { + toast.error(JSON.parse(nextAuth?.error ?? "").message); + } + }); + }; + + return ( +
+
+
+

+ Please enter the OTP sent to your mobile number [{phone_number}] to + verify and complete your registration +

+ + + {errors.pin && ( +

{errors.pin.message}

+ )} +
+ +
+
+ Go back to{" "} + + login + +
+
+ ); +} diff --git a/queries/authentication.ts b/queries/authentication.ts index 73e0bd8..5eb07e2 100644 --- a/queries/authentication.ts +++ b/queries/authentication.ts @@ -1,6 +1,7 @@ "use server"; -import type { TAuthUser } from "@/lib/types/user"; +import type { TAuthUser, User } from "@/lib/types/user"; import axiosInstance from "@/utils/axiosInstance"; +import { handleApiResponse } from "@/utils/tryCatch"; export async function login({ password, @@ -51,7 +52,6 @@ export async function checkIdOrPhone({ id_card, phone_number, }: { id_card?: string; phone_number?: string }) { - console.log("id_card and phone_number", { id_card, phone_number }); const response = await fetch( `${process.env.SARLINK_API_BASE_URL}/api/auth/users/filter/?id_card=${id_card}&mobile=${phone_number}`, { @@ -64,3 +64,31 @@ export async function checkIdOrPhone({ const data = await response.json(); return data; } + +type TSignupUser = Pick< + User, + "username" | "address" | "mobile" | "id_card" | "dob" +> & { + firstname: string; + lastname: string; + atoll: number; + island: number; + acc_no: string; + terms_accepted: boolean; + policy_accepted: boolean; +}; +export async function backendRegister({ payload }: { payload: TSignupUser }) { + console.log("backendRegister payload", payload); + const response = await fetch( + `${process.env.SARLINK_API_BASE_URL}/api/auth/register/`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }, + ); + console.log("backendRegister response", response); + return handleApiResponse<{ t_username: string }>(response, "backendRegister"); +}