"use server"; import { authClient } from "@/lib/auth-client"; import prisma from "@/lib/db"; import VerifyUserDetails from "@/lib/person"; import { signUpFormSchema } from "@/lib/schemas"; import { headers } from "next/headers"; // import type { User } from "@prisma/client"; import { redirect } from "next/navigation"; import { z } from "zod"; import { SendUserRejectionDetailSMS } from "./user-actions"; const formSchema = z.object({ phoneNumber: z .string() .regex(/^[7|9][0-9]{2}-[0-9]{4}$/, "Please enter a valid phone number"), }); export async function signin(previousState: ActionState, formData: FormData) { const phoneNumber = formData.get("phoneNumber") as string; const result = formSchema.safeParse({ phoneNumber }); console.log(phoneNumber); if (!result.success) { return { message: result.error.errors[0].message, // Get the error message from Zod status: "error", }; } if (!phoneNumber) { return { message: "Please enter a phone number", status: "error", }; } const NUMBER_WITH_COUNTRY_CODE: string = `+960${phoneNumber.split("-").join("")}`; const userExists = await prisma.user.findUnique({ where: { phoneNumber: NUMBER_WITH_COUNTRY_CODE, }, }); if (!userExists) { return redirect(`/signup?phone_number=${phoneNumber}`); } if (!userExists?.verified) return { message: "Your account is on pending verification. Please wait for a response from admin or contact shihaam.", status: "error", }; await authClient.phoneNumber.sendOtp({ phoneNumber: NUMBER_WITH_COUNTRY_CODE, }); redirect( `/verify-otp?phone_number=${encodeURIComponent(NUMBER_WITH_COUNTRY_CODE)}`, ); } type ActionState = { message: string; payload?: FormData; }; 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 (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 phoneNumberExists = await prisma.user.findFirst({ where: { phoneNumber: NUMBER_WITH_COUNTRY_CODE, }, }); if (phoneNumberExists) { return { message: "Phone number already exists.", payload: 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: NUMBER_WITH_COUNTRY_CODE, }, }); const isValidPerson = await VerifyUserDetails({ user: newUser }); if (!isValidPerson) { await SendUserRejectionDetailSMS({ details: ` A new user has requested for verification. USER DETAILS: Name: ${parsedData.data.name} Address: ${parsedData.data.address} ID Card: ${parsedData.data.id_card} DOB: ${parsedData.data.dob} ACC No: ${parsedData.data.accNo} Verify the user with the folloiwing link: ${process.env.BETTER_AUTH_URL}/users/${newUser.id}/verify `, phoneNumber: process.env.ADMIN_PHONENUMBER ?? "", }); return { message: "Your account has been requested for verification. Please wait for a response from admin.", payload: formData, db_error: "invalidPersonValidation", }; } if (isValidPerson) { await authClient.phoneNumber.sendOtp({ phoneNumber: newUser.phoneNumber, }); } redirect( `/verify-otp?phone_number=${encodeURIComponent(newUser.phoneNumber)}`, ); return { message: "User created successfully" }; } export const sendOtp = async (phoneNumber: string, code: string) => { // Implement sending OTP code via SMS console.log("Send OTP server fn", phoneNumber, code); const respose = await fetch(`${process.env.SMS_API_BASE_URL}/api/sms`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.SMS_API_KEY}`, }, body: JSON.stringify({ check_delivery: false, number: phoneNumber, message: `Your OTP code is ${code}`, }), }); const data = await respose.json(); console.log(data); return data; };