consolidated signup
This commit is contained in:
@@ -20,7 +20,8 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^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": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2.2.7",
|
"@tauri-apps/cli": "^2.2.7",
|
||||||
|
|||||||
15
AceJobAgency.client/pnpm-lock.yaml
generated
15
AceJobAgency.client/pnpm-lock.yaml
generated
@@ -41,6 +41,9 @@ importers:
|
|||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^6.29.0
|
specifier: ^6.29.0
|
||||||
version: 6.29.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
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:
|
devDependencies:
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
specifier: ^2.2.7
|
specifier: ^2.2.7
|
||||||
@@ -2185,6 +2188,12 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
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:
|
react@18.3.1:
|
||||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -5316,6 +5325,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/react'
|
- '@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:
|
react@18.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Input, Button, Link, Select, SelectItem } from "@heroui/react";
|
import { Input, Button, Link, Select, SelectItem } from "@heroui/react";
|
||||||
import { IconMail, IconLock } from "@tabler/icons-react";
|
import { IconMail, IconLock } from "@tabler/icons-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
import http from "../http";
|
import http from "../http";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
@@ -16,13 +17,47 @@ export default function SignupView({
|
|||||||
const [lastName, setLastName] = useState("");
|
const [lastName, setLastName] = useState("");
|
||||||
const [nric, setNric] = useState("");
|
const [nric, setNric] = useState("");
|
||||||
const [gender, setGender] = useState("0");
|
const [gender, setGender] = useState("0");
|
||||||
const dateOfBirthInput = document.getElementById("dateOfBirthInput");
|
const [dateOfBirth, setDateOfBirth] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [confirmPassword, setConfirmPassword] = useState("");
|
const [confirmPassword, setConfirmPassword] = useState("");
|
||||||
|
|
||||||
const navigate = useNavigate();
|
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 () => {
|
const handleSubmit = async () => {
|
||||||
|
if (!validateFields()) return;
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: "",
|
id: "",
|
||||||
firstName,
|
firstName,
|
||||||
@@ -31,7 +66,7 @@ export default function SignupView({
|
|||||||
nationalRegistrationIdentityCardNumber: nric,
|
nationalRegistrationIdentityCardNumber: nric,
|
||||||
email: emailValue,
|
email: emailValue,
|
||||||
password,
|
password,
|
||||||
dateOfBirth: new Date((dateOfBirthInput as any).value),
|
dateOfBirth: new Date(dateOfBirth),
|
||||||
resumeName: "",
|
resumeName: "",
|
||||||
whoAmI: "",
|
whoAmI: "",
|
||||||
};
|
};
|
||||||
@@ -39,14 +74,14 @@ export default function SignupView({
|
|||||||
try {
|
try {
|
||||||
const response = await http.post("/User/register", user);
|
const response = await http.post("/User/register", user);
|
||||||
|
|
||||||
if (response.status != 200) {
|
if (response.status !== 200) {
|
||||||
throw new Error("Failed to sign up");
|
throw new Error("Failed to sign up");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle successful signup (e.g., show a message, redirect, etc.)
|
toast.success("User signed up successfully");
|
||||||
console.log("User signed up successfully");
|
navigate("/");
|
||||||
} catch (error) {
|
} 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({
|
|||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
className="rounded-xl px-4 transition-colors dark:bg-neutral-800 dark:hover:bg-neutral-700"
|
className="rounded-xl px-4 transition-colors dark:bg-neutral-800 dark:hover:bg-neutral-700"
|
||||||
id="dateOfBirthInput"
|
value={dateOfBirth}
|
||||||
|
onChange={(e) => setDateOfBirth(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { HeroUIProvider } from "@heroui/react";
|
|||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import App from "./App.tsx";
|
import App from "./App.tsx";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
import { ToastContainer } from "react-toastify";
|
||||||
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
|
|
||||||
document.addEventListener("contextmenu", (event) => {
|
document.addEventListener("contextmenu", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -15,6 +17,7 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|||||||
<HeroUIProvider>
|
<HeroUIProvider>
|
||||||
<main>
|
<main>
|
||||||
<App />
|
<App />
|
||||||
|
<ToastContainer />
|
||||||
</main>
|
</main>
|
||||||
</HeroUIProvider>
|
</HeroUIProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
Reference in New Issue
Block a user