consolidated signup

This commit is contained in:
2025-02-08 23:28:18 +08:00
parent ce4e90e18d
commit 90ec907cb3
4 changed files with 63 additions and 8 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

@@ -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>