mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-02-22 23:42:00 +00:00
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m24s
- Updated `auth-actions.ts` to improve user verification notification formatting and date handling. - Modified `layout.tsx` to support dark mode styling for better user experience. - Refactored `signup/page.tsx` to enhance layout and responsiveness. - Introduced a new API route in `route.ts` for sending user verification notifications. - Improved user feedback in `user-payments-table.tsx` by updating the no payment message. - Made minor adjustments in `application-layout.tsx` for consistent padding. - Enhanced `signup-form.tsx` to display error messages for invalid user validation. These changes improve the user verification process, enhance UI consistency, and provide better feedback to users.
191 lines
4.9 KiB
TypeScript
191 lines
4.9 KiB
TypeScript
"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. \n
|
|
USER DETAILS:
|
|
Name: ${parsedData.data.name}
|
|
Address: ${parsedData.data.address}
|
|
ID Card: ${parsedData.data.id_card}
|
|
DOB: ${parsedData.data.dob.toLocaleDateString("en-US", {
|
|
month: "short",
|
|
day: "2-digit",
|
|
year: "numeric",
|
|
})}
|
|
ACC No: ${parsedData.data.accNo}\n\nVerify 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;
|
|
};
|