sarlink-portal/queries/authentication.ts
i701 a4ffb1e34a
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m49s
feat: implement AuthLayout component and streamline OTP verification forms with enhanced messaging
2025-04-19 10:22:42 +05:00

208 lines
5.0 KiB
TypeScript

"use server";
import {
type ActionState,
type FilterTempUserResponse,
type FilterUserResponse,
backendMobileLogin,
} from "@/actions/auth-actions";
import type { TAuthUser, User } from "@/lib/types/user";
import axiosInstance from "@/utils/axiosInstance";
import { handleApiResponse, tryCatch } from "@/utils/tryCatch";
import { redirect } from "next/navigation";
import { z } from "zod";
export async function login({
password,
username,
}: {
username: string;
password: string;
}): Promise<TAuthUser> {
const response = await axiosInstance
.post("/auth/login/", {
username: username,
password: password,
})
.then((res) => {
console.log(res);
return res.data; // Return the data from the response
})
.catch((err) => {
console.log(err.response);
throw err; // Throw the error to maintain the Promise rejection
});
return response;
}
export async function logout({ token }: { token: string }) {
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/auth/logout/`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${token}`, // Include the token for authentication
},
},
);
if (response.status !== 204) {
throw new Error("Failed to log out from the backend");
}
console.log("logout res in backend", response);
// Since the API endpoint returns 204 No Content on success, we don't need to parse JSON
return null; // Return null to indicate a successful logout with no content
}
export async function checkIdOrPhone({
id_card,
phone_number,
}: { id_card?: string; phone_number?: string }) {
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/auth/users/filter/?id_card=${id_card}&mobile=${phone_number}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
},
);
const data = (await response.json()) as FilterUserResponse;
return data;
}
export async function checkTempIdOrPhone({
id_card,
phone_number,
}: { id_card?: string; phone_number?: string }) {
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/auth/users/temp/filter/?id_card=${id_card}&mobile=${phone_number}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
},
);
const data = (await response.json()) as FilterTempUserResponse;
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");
}
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 };
const [error, userVerified] = await tryCatch(
checkIdOrPhone({ phone_number: mobile as string }),
);
if (error) {
return {
message:
"There was an error fetching your account information. Please contact support.",
status: "user_check_error",
};
}
if (userVerified.verified) {
return {
message:
"Your account has been successfully verified! You may login now.",
status: "verify_success",
};
// const [mobileLoginError, mobileLoginResponse] = await tryCatch(
// backendMobileLogin({ mobile: mobile as string }),
// );
// if (mobileLoginError) {
// return {
// message: "Login Failed. Please contact support.",
// status: "login_error",
// };
// }
// if (mobileLoginResponse) {
// redirect(`/auth/verify-otp?phone_number=${mobile}`);
// }
}
return {
message:
data.message ||
"Your account could not be verified. Please contact support.",
status: "verify_error",
};
}