registration verification WIP
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m40s

This commit is contained in:
i701 2025-04-17 14:04:22 +05:00
parent 0f9d1107de
commit 470e8452b5
3 changed files with 83 additions and 44 deletions

View File

@ -76,8 +76,9 @@ export async function signin(previousState: ActionState, formData: FormData) {
redirect(`/auth/verify-otp?phone_number=${FORMATTED_MOBILE_NUMBER}`); redirect(`/auth/verify-otp?phone_number=${FORMATTED_MOBILE_NUMBER}`);
} }
type ActionState = { export type ActionState = {
message: string; message: string;
status: string;
payload?: FormData; payload?: FormData;
}; };

View File

@ -3,58 +3,30 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { VerifyRegistrationOTP } from "@/queries/authentication";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { Loader2 } from "lucide-react"; import { Loader2 } from "lucide-react";
import { signIn } from "next-auth/react"; import { signIn } from "next-auth/react";
import Link from "next/link"; import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation"; import { redirect, useRouter, useSearchParams } from "next/navigation";
import { useTransition } from "react"; import { useActionState } 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({ export default function VerifyRegistrationOTPForm({
phone_number, phone_number,
}: { phone_number: string }) { }: { phone_number: string }) {
const [isPending, startTransition] = useTransition();
const router = useRouter();
console.log("verification in OTP form", phone_number); console.log("verification in OTP form", phone_number);
const {
register,
handleSubmit,
formState: { errors },
} = useForm<z.infer<typeof OTPSchema>>({
defaultValues: {
pin: "",
},
resolver: zodResolver(OTPSchema),
});
const searchParams = useSearchParams();
const callbackUrl = searchParams.get("callbackUrl") || "/dashboard";
const onSubmit: SubmitHandler<z.infer<typeof OTPSchema>> = (data) => { const searchParams = useSearchParams();
startTransition(async () => { const mobile = searchParams.get("phone_number");
const nextAuth = await signIn("credentials", { if (!mobile) redirect("/auth/login");
pin: data.pin, const [state, formAction, isPending] = useActionState(VerifyRegistrationOTP, {
callbackUrl, message: "",
redirect: false, status: "",
}); });
if (!nextAuth?.error) {
router.push("/devices");
} else {
toast.error(JSON.parse(nextAuth?.error ?? "").message);
}
});
};
return ( return (
<form <form
onSubmit={handleSubmit(onSubmit)} action={formAction}
className="w-full max-w-xs bg-white dark:bg-sarLinkOrange/10 title-bg border rounded-lg shadow my-4" className="w-full max-w-xs bg-white dark:bg-sarLinkOrange/10 title-bg border rounded-lg shadow my-4"
> >
<div className="grid pb-4 pt-4 gap-4 px-4"> <div className="grid pb-4 pt-4 gap-4 px-4">
@ -66,16 +38,24 @@ export default function VerifyRegistrationOTPForm({
<Label htmlFor="otp-number" className="sr-only text-gray-500"> <Label htmlFor="otp-number" className="sr-only text-gray-500">
Enter the OTP Enter the OTP
</Label> </Label>
<input
type="number"
name="mobile"
defaultValue={phone_number}
value={phone_number}
hidden
/>
<Input <Input
disabled={isPending} disabled={isPending}
id="otp-number" id="otp-number"
{...register("pin")} name="otp"
type="text" maxLength={6}
type="number"
placeholder="Enter OTP" placeholder="Enter OTP"
className="bg-white text-black" className="bg-white text-black"
/> />
{errors.pin && ( {state?.status === "error" && (
<p className="text-red-500 text-sm">{errors.pin.message}</p> <p className="text-red-500 text-sm">{state.message}</p>
)} )}
</div> </div>
<Button className="w-full" disabled={isPending} type="submit"> <Button className="w-full" disabled={isPending} type="submit">

View File

@ -1,7 +1,9 @@
"use server"; "use server";
import type { ActionState } from "@/actions/auth-actions";
import type { TAuthUser, User } from "@/lib/types/user"; import type { TAuthUser, User } from "@/lib/types/user";
import axiosInstance from "@/utils/axiosInstance"; import axiosInstance from "@/utils/axiosInstance";
import { handleApiResponse } from "@/utils/tryCatch"; import { handleApiResponse } from "@/utils/tryCatch";
import { z } from "zod";
export async function login({ export async function login({
password, password,
@ -92,3 +94,59 @@ export async function backendRegister({ payload }: { payload: TSignupUser }) {
console.log("backendRegister response", response); console.log("backendRegister response", response);
return handleApiResponse<{ t_username: string }>(response, "backendRegister"); return handleApiResponse<{ t_username: string }>(response, "backendRegister");
} }
const formSchema = z.object({
mobile: z.string().regex(/^[79]\d{6}$/, "Please enter a valid phone number"),
otp: z
.string()
.min(6, {
message: "OTP is required.",
})
.max(6, {
message: "OTP is required.",
}),
});
export async function VerifyRegistrationOTP(
_actionState: ActionState,
formData: FormData,
) {
const formValues = Object.fromEntries(formData.entries());
const result = formSchema.safeParse(formValues);
console.log("formValues", formValues);
if (!result.success) {
return {
message: result.error.errors[0].message, // Get the error message from Zod
status: "error",
};
}
if (formValues.otp === "") {
return {
message: "OTP is required.",
status: "error",
};
}
const { mobile, otp } = formValues;
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/auth/register/verify/`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mobile: mobile,
otp: Number.parseInt(otp as string),
}),
},
);
const data = (await response.json()) as { message: string };
return {
message: data.message,
status: response.status === 200 ? "success" : "error",
};
}