"use server"; import { signUpFormSchema } from "@/lib/schemas"; import { backendRegister, checkIdOrPhone, checkTempIdOrPhone, } from "@/queries/authentication"; import { handleApiResponse, tryCatch } from "@/utils/tryCatch"; import { redirect } from "next/navigation"; import { z } from "zod"; const formSchema = z.object({ phoneNumber: z .string() .regex(/^[7|9][0-9]{2}-[0-9]{4}$/, "Please enter a valid phone number"), }); export type FilterUserResponse = { ok: boolean; verified: boolean; }; export type FilterTempUserResponse = { ok: boolean; otp_verified: boolean; }; 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 FORMATTED_MOBILE_NUMBER: string = `${phoneNumber.split("-").join("")}`; console.log({ FORMATTED_MOBILE_NUMBER }); const user = await fetch( `${process.env.SARLINK_API_BASE_URL}/api/auth/users/filter/?mobile=${FORMATTED_MOBILE_NUMBER}`, { method: "GET", headers: { "Content-Type": "application/json", }, }, ); const userData = (await user.json()) as FilterUserResponse; console.log({ userData }); if (!userData?.verified) { return redirect(`/auth/signup?phone_number=${phoneNumber}`); } if (!userData.verified) { return { message: "Your account is on pending verification. Please wait for a response from admin or contact shihaam.", status: "error", }; } const sendOTPResponse = await fetch( `${process.env.SARLINK_API_BASE_URL}/auth/mobile/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ mobile: FORMATTED_MOBILE_NUMBER, }), }, ); const otpResponse = await sendOTPResponse.json(); console.log("otpResponse", otpResponse); redirect(`/auth/verify-otp?phone_number=${FORMATTED_MOBILE_NUMBER}`); } export type ActionState = { status?: string; payload?: FormData; errors?: z.typeToFlattenedError< { id_card: string; phone_number: string; name: string; atoll_id: string; island_id: string; address: string; dob: Date; terms: string; policy: string; accNo: string; }, string >; db_error?: string; error?: string; }; 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 console.log("DATA ON SERVER SIDE", data); if (!parsedData.success) { return { message: "Invalid form data", payload: formData, errors: parsedData.error.flatten(), }; } const idCardExists = await checkIdOrPhone({ id_card: parsedData.data.id_card, }); if (idCardExists.ok) { return { message: "ID card already exists.", payload: formData, db_error: "id_card", }; } const phoneNumberExists = await checkIdOrPhone({ phone_number: parsedData.data.phone_number, }); const tempPhoneNumberExists = await checkTempIdOrPhone({ phone_number: parsedData.data.phone_number, }); if (phoneNumberExists.ok || tempPhoneNumberExists.ok) { return { message: "Phone number already exists.", payload: formData, db_error: "phone_number", }; } const [signupError, signupResponse] = await tryCatch( backendRegister({ payload: { firstname: parsedData.data.name.split(" ")[0], lastname: parsedData.data.name.split(" ")[1], 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) { return { message: signupError.message, payload: formData, db_error: "phone_number", }; } console.log("SIGNUP RESPONSE", signupResponse); redirect( `/auth/verify-otp-registration?phone_number=${encodeURIComponent(signupResponse.t_username)}`, ); return { message: "User created successfully", error: "success" }; } 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; }; export async function backendMobileLogin({ mobile }: { mobile: string }) { const response = await fetch( `${process.env.SARLINK_API_BASE_URL}/auth/mobile/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ mobile, }), }, ); return handleApiResponse<{ detail: string }>(response, "backendMobileLogin"); }