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(
+