mirror of
				https://github.com/i701/sarlink-portal.git
				synced 2025-11-04 12:36:59 +00:00 
			
		
		
		
	
		
			All checks were successful
		
		
	
	Build and Push Docker Images / Build and Push Docker Images (push) Successful in 12m34s
				
			
		
			
				
	
	
		
			230 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
"use server";
 | 
						|
 | 
						|
import { redirect } from "next/navigation";
 | 
						|
import { z } from "zod";
 | 
						|
import { signUpFormSchema } from "@/lib/schemas";
 | 
						|
import {
 | 
						|
  backendRegister,
 | 
						|
  checkIdOrPhone,
 | 
						|
  checkTempIdOrPhone,
 | 
						|
} from "@/queries/authentication";
 | 
						|
import { handleApiResponse, tryCatch } from "@/utils/tryCatch";
 | 
						|
 | 
						|
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;
 | 
						|
  t_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.ok) {
 | 
						|
    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 age =
 | 
						|
    new Date().getFullYear() - new Date(parsedData.data.dob).getFullYear();
 | 
						|
  if (age < 18) {
 | 
						|
    return {
 | 
						|
      message: "You must be at least 18 years old to register.",
 | 
						|
      payload: formData,
 | 
						|
      db_error: "dob",
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  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(" ").slice(1).join(" "),
 | 
						|
        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");
 | 
						|
}
 |