diff --git a/Frontend/src/components/Message.jsx b/Frontend/src/components/Message.jsx
index eb8d0d8..cc18762 100644
--- a/Frontend/src/components/Message.jsx
+++ b/Frontend/src/components/Message.jsx
@@ -1,12 +1,18 @@
import React from "react";
-const Message = ({ message }) => {
+const Message = ({ message, type = "error" }) => {
const date = new Date();
+
+ const background =
+ type === "error"
+ ? "bg-red-100 border border-red-400 text-red-700"
+ : "bg-gray-100 border border-gray-300 text-gray-800";
+
return (
-
-
{message}
-
- {date.getDate()}/{date.getMonth()}/{date.getFullYear()}{" "}
+
+
{message}
+
+ {date.getDate()}/{date.getMonth() + 1}/{date.getFullYear()}{" "}
{date.toLocaleTimeString()}
diff --git a/Frontend/src/pages/Login/SignupPage.jsx b/Frontend/src/pages/Login/SignupPage.jsx
index ee38806..894d9b2 100644
--- a/Frontend/src/pages/Login/SignupPage.jsx
+++ b/Frontend/src/pages/Login/SignupPage.jsx
@@ -1,8 +1,9 @@
-import React, { useRef } from "react";
+import React, { useRef, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { BACKEND_URL } from "../../constants";
import { t } from "../../service/translation";
import { useOutletContext } from "react-router-dom";
+import { isPasswordPwned } from "../../utils/passwordUtils";
const SignupPage = (props) => {
const outletContext = useOutletContext?.();
@@ -12,41 +13,72 @@ const SignupPage = (props) => {
const firstNameElement = useRef();
const lastNameElement = useRef();
const emailElement = useRef();
- const roleElement = useRef();
const passwordElement = useRef();
+ const [error, setError] = useState("");
const navigate = useNavigate();
const handleRegisteration = async (event) => {
event.preventDefault();
+ setError("");
+
+ const password = passwordElement.current.value;
+
+ const strongPasswordRegex =
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/;
+
+ if (!strongPasswordRegex.test(password)) {
+ setError(
+ "Password must be at least 8 characters long and include uppercase, lowercase, number, and special character."
+ );
+ return;
+ }
+
+ try {
+ const pwned = await isPasswordPwned(password);
+ if (pwned) {
+ setError("This password previously appeared in a data breach. Please use a new password.");
+ return;
+ }
+ } catch (err) {
+ console.error("Password breach check failed:", err);
+ setError("Something went wrong while checking password security. Try again.");
+ return;
+ }
const user = {
name:
firstNameElement.current.value + " " + lastNameElement.current.value,
email: emailElement.current.value,
- password: passwordElement.current.value,
+ password: password,
};
- event.preventDefault();
+ try {
+ const response = await fetch(`${BACKEND_URL}/api/v1/register`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(user),
+ credentials: "include",
+ });
- const responce = await fetch(`${BACKEND_URL}/api/v1/register`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(user),
- credentials: "include",
- });
- const data = await responce.json();
+ const data = await response.json();
+
+ if (data.success === true) {
+ navigate("/user/login");
+ } else {
+ setError(data.message || "Registration failed. Please try again.");
+ }
+ } catch (err) {
+ console.error("Registration error:", err);
+ setError("Something went wrong on the server. Please try again later.");
+ }
firstNameElement.current.value = "";
lastNameElement.current.value = "";
emailElement.current.value = "";
passwordElement.current.value = "";
-
- if (data.success == true) {
- navigate("/user/login");
- }
};
return (
@@ -57,39 +89,31 @@ const SignupPage = (props) => {
{t("signup_register_heading", language)}
{t("signup_welcome", language)}
-
- {t("signup_subtitle", language)}
-
-