From 192a613f9cb61ee293948824aafc86246c81eb70 Mon Sep 17 00:00:00 2001 From: Tejashwini Date: Wed, 22 Jul 2026 20:27:47 +0530 Subject: [PATCH 1/2] Fix Settings dropdown z-index overlap and Activity Logs filter panel overflow Signed-off-by: Tejashwini --- frontend/src/components/admin/ActivityLogs.css | 2 +- frontend/src/components/common/NavBar.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/admin/ActivityLogs.css b/frontend/src/components/admin/ActivityLogs.css index d51ee1c..13e2fac 100644 --- a/frontend/src/components/admin/ActivityLogs.css +++ b/frontend/src/components/admin/ActivityLogs.css @@ -75,7 +75,7 @@ .activity-filter-panel { display: grid; - grid-template-columns: minmax(220px, 1.6fr) repeat(6, minmax(120px, 0.7fr)); + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; padding: 12px; border: 1px solid var(--activity-line); diff --git a/frontend/src/components/common/NavBar.jsx b/frontend/src/components/common/NavBar.jsx index 2757127..0a5b4d0 100644 --- a/frontend/src/components/common/NavBar.jsx +++ b/frontend/src/components/common/NavBar.jsx @@ -60,7 +60,7 @@ const NavBar = ({ setSelectedComponent }) => { }; return ( - + Learnhub From 8e951599680097aed6303cb159ccfda44fccacd8 Mon Sep 17 00:00:00 2001 From: Tejashwini Date: Sat, 25 Jul 2026 22:29:22 +0530 Subject: [PATCH 2/2] Add reusable Toast component and replace native alerts in Login.jsx Signed-off-by: Tejashwini --- frontend/src/components/common/Login.jsx | 38 ++++++++++------ frontend/src/components/common/Toast.jsx | 58 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 frontend/src/components/common/Toast.jsx diff --git a/frontend/src/components/common/Login.jsx b/frontend/src/components/common/Login.jsx index e7d3383..5955b45 100644 --- a/frontend/src/components/common/Login.jsx +++ b/frontend/src/components/common/Login.jsx @@ -9,6 +9,7 @@ import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import axiosInstance from './AxiosInstance'; import PublicNavBar from './PublicNavBar'; +import Toast from './Toast'; const Login = () => { const navigate = useNavigate() @@ -20,6 +21,15 @@ const Login = () => { const [forgotEmail, setForgotEmail] = useState(''); const [resetToken, setResetToken] = useState(''); const [newPassword, setNewPassword] = useState(''); + const [toast, setToast] = useState({ message: '', type: 'info' }); + + const showToast = (message, type = 'info') => { + setToast({ message, type }); + }; + + const closeToast = () => { + setToast({ message: '', type: 'info' }); + }; const handleChange = (e) => { const { name, value } = e.target; @@ -30,12 +40,12 @@ const Login = () => { e.preventDefault(); if (!data?.email || !data?.password) { - return alert("Please fill all fields"); + return showToast("Please fill all fields", "error"); } else { axiosInstance.post('/api/user/login', data) .then((res) => { if (res.data.success) { - alert(res.data.message) + showToast(res.data.message, "success"); localStorage.setItem("token", res.data.token); localStorage.setItem("user", JSON.stringify(res.data.userData)); @@ -44,12 +54,12 @@ const Login = () => { window.location.reload() }, 1000) } else { - alert(res.data.message) + showToast(res.data.message, "error"); } }) .catch((err) => { if (err.response && err.response.status === 401) { - alert("User doesn't exist"); + showToast("User doesn't exist", "error"); } navigate("/login"); }); @@ -58,22 +68,22 @@ const Login = () => { const handleForgotSubmit = (e) => { e.preventDefault(); - if (!forgotEmail) return alert("Please enter email"); + if (!forgotEmail) return showToast("Please enter email", "error"); axiosInstance.post('/api/user/forgot-password', { email: forgotEmail }) .then((res) => { - alert(res.data.message); + showToast(res.data.message, "success"); setViewMode('reset'); }) .catch((err) => { console.log(err); - alert("Error sending reset email"); + showToast("Error sending reset email", "error"); }); }; const handleResetSubmit = (e) => { e.preventDefault(); if (!forgotEmail || !resetToken || !newPassword) { - return alert("Please fill all fields"); + return showToast("Please fill all fields", "error"); } axiosInstance.post('/api/user/reset-password', { email: forgotEmail, @@ -82,20 +92,21 @@ const Login = () => { }) .then((res) => { if (res.data.success) { - alert(res.data.message); + showToast(res.data.message, "success"); setViewMode('login'); } else { - alert(res.data.message || "Failed to reset password"); + showToast(res.data.message || "Failed to reset password", "error"); } }) .catch((err) => { console.log(err); - alert("Reset failed. Please verify code and password requirements."); + showToast("Reset failed. Please verify code and password requirements.", "error"); }); }; return ( <> + @@ -238,7 +249,4 @@ const Login = () => { ) } -export default Login - - - +export default Login \ No newline at end of file diff --git a/frontend/src/components/common/Toast.jsx b/frontend/src/components/common/Toast.jsx new file mode 100644 index 0000000..835e8fd --- /dev/null +++ b/frontend/src/components/common/Toast.jsx @@ -0,0 +1,58 @@ +import React, { useEffect } from "react"; + +const Toast = ({ message, type = "info", onClose, duration = 3000 }) => { + useEffect(() => { + if (!message) return; + const timer = setTimeout(() => { + onClose(); + }, duration); + return () => clearTimeout(timer); + }, [message, duration, onClose]); + + if (!message) return null; + + const backgroundColor = + type === "error" ? "#d32f2f" : type === "success" ? "#2e7d32" : "#323232"; + + return ( +
+ {message} + +
+ ); +}; + +export default Toast; \ No newline at end of file