feat(login): improve error handling and show rate limit message

- Display meaningful error messages on login failure, including rate limiting (429)
- Added fallback for unexpected JSON responses from the server
- Integrated `Message` component for error display
- Cleaned up form value clearing and error state management
This commit is contained in:
K
2025-07-18 02:12:46 +05:30
parent aaf88fda56
commit 9c3feca6a7
+40 -20
View File
@@ -1,25 +1,27 @@
import React, { useRef } from "react";
import React, { useRef, useState } from "react";
import { useDispatch } from "react-redux";
import { Link, useNavigate, useOutletContext } from "react-router-dom";
import { userSliceActions } from "../../store/userSlice";
import { BACKEND_URL } from "../../constants";
import { t } from "../../service/translation"; // Adjust path as needed
import { t } from "../../service/translation";
import Message from "../../components/Message"; // Import Message component
const LoginPage = () => {
// Get language from outlet context
const { language } = useOutletContext();
console.log("LoginPage language:", language);
const emailElement = useRef();
const passwordElement = useRef();
const [error, setError] = useState(""); // For showing errors
const navigate = useNavigate();
const dispatch = useDispatch();
const handleLogin = async (event) => {
event.preventDefault();
const responce = await fetch(`${BACKEND_URL}/api/v1/login`, {
setError(""); // Clear previous error
try {
const response = await fetch(`${BACKEND_URL}/api/v1/login`, {
method: "POST",
credentials: "include",
headers: {
@@ -31,15 +33,31 @@ const LoginPage = () => {
}),
});
const user = await responce.json();
if (response.status === 429) {
setError("Too many login attempts. Please try again after 15 minutes.");
return;
}
dispatch(userSliceActions.addUser(user.data));
let data;
try {
data = await response.json();
} catch (jsonError) {
setError("Unexpected server response. Please try again.");
return;
}
if (data.success === true) {
dispatch(userSliceActions.addUser(data.data));
navigate("/");
} else {
setError(data.message || "Login failed. Please check your credentials.");
}
emailElement.current.value = "";
passwordElement.current.value = "";
if (user.success === true) {
navigate("/");
} catch (err) {
console.error("Login error:", err);
setError("Something went wrong. Please try again.");
}
};
@@ -55,9 +73,15 @@ const LoginPage = () => {
</div>
<div className="backdrop-blur-md bg-gradient-to-tr from-slate-300/10 to-slate-200/30 rounded-lg shadow-md lg:p-36">
<h1 className="text-2xl font-bold text-gray-50 mb-4">{t("login_title", language)}</h1>
<p className="text-gray-100 mb-6">
{t("login_subtitle", language)}
</p>
<p className="text-gray-100 mb-6">{t("login_subtitle", language)}</p>
{/* Show error message */}
{error && (
<div className="my-4">
<Message message={error} type="error" />
</div>
)}
<form className="space-y-6" onSubmit={handleLogin}>
<div>
<label
@@ -123,10 +147,7 @@ const LoginPage = () => {
</div>
<p className="text-gray-100 text-center mt-4">
{t("login_new_user", language)}{" "}
<Link
to={"/user/signup"}
className="text-blue-600 hover:underline"
>
<Link to={"/user/signup"} className="text-blue-600 hover:underline">
{t("login_signup", language)}
</Link>
</p>
@@ -138,4 +159,3 @@ const LoginPage = () => {
};
export default LoginPage;