diff --git a/AceJobAgency.client/package.json b/AceJobAgency.client/package.json
index 8afc590..8e1cf2a 100644
--- a/AceJobAgency.client/package.json
+++ b/AceJobAgency.client/package.json
@@ -20,7 +20,8 @@
"lodash": "^4.17.21",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-router-dom": "^6.29.0"
+ "react-router-dom": "^6.29.0",
+ "react-toastify": "^11.0.3"
},
"devDependencies": {
"@tauri-apps/cli": "^2.2.7",
diff --git a/AceJobAgency.client/pnpm-lock.yaml b/AceJobAgency.client/pnpm-lock.yaml
index 96e5e8a..b552fc7 100644
--- a/AceJobAgency.client/pnpm-lock.yaml
+++ b/AceJobAgency.client/pnpm-lock.yaml
@@ -41,6 +41,9 @@ importers:
react-router-dom:
specifier: ^6.29.0
version: 6.29.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-toastify:
+ specifier: ^11.0.3
+ version: 11.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
devDependencies:
'@tauri-apps/cli':
specifier: ^2.2.7
@@ -2185,6 +2188,12 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-toastify@11.0.3:
+ resolution: {integrity: sha512-cbPtHJPfc0sGqVwozBwaTrTu1ogB9+BLLjd4dDXd863qYLj7DGrQ2sg5RAChjFUB4yc3w8iXOtWcJqPK/6xqRQ==}
+ peerDependencies:
+ react: ^18 || ^19
+ react-dom: ^18 || ^19
+
react@18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
@@ -5316,6 +5325,12 @@ snapshots:
transitivePeerDependencies:
- '@types/react'
+ react-toastify@11.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ clsx: 2.1.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
react@18.3.1:
dependencies:
loose-envify: 1.4.0
diff --git a/AceJobAgency.client/src/components/SignupView.tsx b/AceJobAgency.client/src/components/SignupView.tsx
index f5aeba4..9d383f3 100644
--- a/AceJobAgency.client/src/components/SignupView.tsx
+++ b/AceJobAgency.client/src/components/SignupView.tsx
@@ -1,6 +1,7 @@
import { Input, Button, Link, Select, SelectItem } from "@heroui/react";
import { IconMail, IconLock } from "@tabler/icons-react";
import { useState } from "react";
+import { toast } from "react-toastify";
import http from "../http";
import { useNavigate } from "react-router-dom";
@@ -16,13 +17,47 @@ export default function SignupView({
const [lastName, setLastName] = useState("");
const [nric, setNric] = useState("");
const [gender, setGender] = useState("0");
- const dateOfBirthInput = document.getElementById("dateOfBirthInput");
+ const [dateOfBirth, setDateOfBirth] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const navigate = useNavigate();
+ const validatePassword = (password: string): boolean => {
+ const passwordComplexityRegex =
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{12,}$/;
+ return passwordComplexityRegex.test(password);
+ };
+
+ const validateFields = () => {
+ if (
+ !firstName ||
+ !lastName ||
+ !emailValue ||
+ !nric ||
+ !dateOfBirth ||
+ !password ||
+ !confirmPassword
+ ) {
+ toast.error("All fields are required.");
+ return false;
+ }
+ if (password !== confirmPassword) {
+ toast.error("Passwords do not match.");
+ return false;
+ }
+ if (!validatePassword(password)) {
+ toast.error(
+ "Password must be at least 12 characters long and include uppercase, lowercase, number, and special character."
+ );
+ return false;
+ }
+ return true;
+ };
+
const handleSubmit = async () => {
+ if (!validateFields()) return;
+
const user = {
id: "",
firstName,
@@ -31,7 +66,7 @@ export default function SignupView({
nationalRegistrationIdentityCardNumber: nric,
email: emailValue,
password,
- dateOfBirth: new Date((dateOfBirthInput as any).value),
+ dateOfBirth: new Date(dateOfBirth),
resumeName: "",
whoAmI: "",
};
@@ -39,14 +74,14 @@ export default function SignupView({
try {
const response = await http.post("/User/register", user);
- if (response.status != 200) {
+ if (response.status !== 200) {
throw new Error("Failed to sign up");
}
- // Handle successful signup (e.g., show a message, redirect, etc.)
- console.log("User signed up successfully");
+ toast.success("User signed up successfully");
+ navigate("/");
} catch (error) {
- console.error("Error during signup:", error);
+ toast.error((error as any).response?.data || "Error during signup");
}
};
@@ -91,7 +126,8 @@ export default function SignupView({
setDateOfBirth(e.target.value)}
/>
{
event.preventDefault();
@@ -15,6 +17,7 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
+