Skip to content

Commit c9f3a31

Browse files
committed
feat: #309 - Add new logout page; restyle admin dropdown; restyle logout button; fix css of mobile nav links; remove login sidenav
1 parent 757e712 commit c9f3a31

File tree

10 files changed

+83
-99
lines changed

10 files changed

+83
-99
lines changed

frontend/src/components/Header/FeatureMenuDropDown.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ export const FeatureMenuDropDown = () => {
44
const location = useLocation();
55
const currentPath = location.pathname;
66
return (
7-
<div className="h-50 absolute top-full mb-2 mt-2 flex flex-row items-center rounded-lg border-2 bg-white font-inter text-sm sm:px-6 md:px-8 lg:px-8 xl:px-6 ">
8-
<div className="mx-3 my-5 ">
7+
<div className="h-50 absolute top-full mb-2 mt-2 flex flex-row items-center rounded-lg border-2 bg-white font-satoshi text-sm">
8+
<div className="">
99
<Link to="/AdminPortal">
1010
<ul className={currentPath === "/AdminPortal" ? "subheader-nav-item subheader-nav-item-selected" : "subheader-nav-item"}>
1111
<span className="font-bold">Manage files</span>
1212

13-
<div className="mt-1 font-satoshi text-sm text-gray-400">
13+
<div className="font-normal mt-1 text-gray-600">
1414
Manage and chat with files
1515
</div>
1616
</ul>
@@ -19,7 +19,7 @@ export const FeatureMenuDropDown = () => {
1919
<ul className={currentPath === "/rulesmanager" ? "subheader-nav-item subheader-nav-item-selected" : "subheader-nav-item"}>
2020
<span className="font-bold">Manage rules</span>
2121

22-
<div className="mt-1 font-satoshi text-sm text-gray-400">
22+
<div className="font-normal mt-1 text-gray-600">
2323
Manage list of rules
2424
</div>
2525
</ul>
@@ -28,7 +28,7 @@ export const FeatureMenuDropDown = () => {
2828
<ul className={currentPath === "/ManageMeds" ? "subheader-nav-item subheader-nav-item-selected" : "subheader-nav-item"}>
2929
<span className="font-bold">Manage meds</span>
3030

31-
<div className="mt-1 font-satoshi text-sm text-gray-400">
31+
<div className="font-normal mt-1 text-gray-600">
3232
Manage list of meds
3333
</div>
3434
</ul>

frontend/src/components/Header/Header.tsx

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
import { useState, useRef, useEffect, Fragment } from "react";
2-
// import { useState, Fragment } from "react";
3-
import accountLogo from "../../assets/account.svg";
1+
import { useState, useRef, useEffect } from "react";
42
import { Link, useNavigate, useLocation } from "react-router-dom";
53
import "../../components/Header/header.css";
64
import Chat from "./Chat";
75
import { FeatureMenuDropDown } from "./FeatureMenuDropDown";
86
import MdNavBar from "./MdNavBar";
9-
import { connect, useDispatch } from "react-redux";
7+
import { connect } from "react-redux";
108
import { RootState } from "../../services/actions/types";
11-
import { logout, AppDispatch } from "../../services/actions/auth";
12-
import { HiChevronDown } from "react-icons/hi";
9+
import { FaChevronDown, FaSignOutAlt } from "react-icons/fa";
1310
import { useGlobalContext } from "../../contexts/GlobalContext.tsx";
1411

1512
interface LoginFormProps {
@@ -23,24 +20,14 @@ const Header: React.FC<LoginFormProps> = ({ isAuthenticated, isSuperuser }) => {
2320
const dropdownRef = useRef(null);
2421
let delayTimeout: number | null = null;
2522
const [showChat, setShowChat] = useState(false);
26-
const [redirect, setRedirect] = useState(false);
2723
const { setShowSummary, setEnterNewPatient, triggerFormReset, setIsEditing } =
2824
useGlobalContext();
2925

30-
const dispatch = useDispatch<AppDispatch>();
31-
32-
const logout_user = () => {
33-
dispatch(logout());
34-
setRedirect(false);
35-
};
36-
3726
const authLinks = () => (
38-
<nav onClick={logout_user} className="flex cursor-pointer items-center">
39-
<img src={accountLogo} alt="logo" className="mr-5 h-5 object-contain " />
40-
<span className=" text-black hover:border-b-2 hover:border-blue-600 hover:text-black hover:no-underline lg:text-sm xl:text-lg">
41-
Sign out
42-
</span>
43-
</nav>
27+
<Link to="/logout" className="font-satoshi flex cursor-pointer items-center text-black hover:text-blue-600">
28+
Sign Out
29+
<FaSignOutAlt className="ml-2 inline-block" />
30+
</Link>
4431
);
4532

4633
const handleMouseEnter = () => {
@@ -201,14 +188,12 @@ const Header: React.FC<LoginFormProps> = ({ isAuthenticated, isSuperuser }) => {
201188
: "absolute ml-1.5 "
202189
}`}
203190
>
204-
<HiChevronDown className="inline-block" />
191+
<FaChevronDown className="inline-block" />
205192
</span>
206193
</span>
207194
{showFeaturesMenu && <FeatureMenuDropDown />}
208195
</div>
209196
)}
210-
211-
{redirect ? navigate("/") : <Fragment></Fragment>}
212197
</>
213198
</nav>
214199
{isAuthenticated && (

frontend/src/components/Header/MdNavBar.tsx

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import Chat from "./Chat";
55
// import logo from "../../assets/balancer.png";
66
import closeLogo from "../../assets/close.svg";
77
import hamburgerLogo from "../../assets/hamburger.svg";
8-
import {useDispatch} from "react-redux";
9-
import {logout, AppDispatch} from "../../services/actions/auth";
108

119
interface LoginFormProps {
1210
isAuthenticated: boolean;
@@ -22,13 +20,6 @@ const MdNavBar = (props: LoginFormProps) => {
2220
setNav(!nav);
2321
};
2422

25-
const dispatch = useDispatch<AppDispatch>();
26-
27-
const logout_user = () => {
28-
dispatch(logout());
29-
};
30-
31-
3223
return (
3324
<div
3425
className={
@@ -131,20 +122,19 @@ const MdNavBar = (props: LoginFormProps) => {
131122
<li className="border-b border-gray-300 p-4">
132123
<a href="https://www.flipcause.com/secure/cause_pdetails/MjMyMTIw"
133124
target="_blank"
134-
className="text-black hover:border-blue-600 hover:text-blue-600 hover:no-underline"
125+
className="mr-9 text-black hover:border-b-2 hover:border-blue-600 hover:text-black hover:no-underline"
135126
>
136127
Donate
137128
</a>
138129
</li>
139130
{isAuthenticated &&
140-
<li className="border-b border-gray-300 p-4">
141-
<a
142-
onClick={logout_user}
143-
className="mr-9 text-black hover:border-b-2 hover:border-blue-600 hover:text-black hover:no-underline"
144-
>
145-
Sign Out
146-
</a>
147-
</li>
131+
<li className="border-b border-gray-300 p-4">
132+
<Link
133+
to="/logout"
134+
className="mr-9 text-black hover:border-b-2 hover:border-blue-600 hover:text-black hover:no-underline"
135+
>Sign Out
136+
</Link>
137+
</li>
148138
}
149139
</ul>
150140
</div>

frontend/src/components/Header/header.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323
}
2424

2525
.header-nav-item {
26-
@apply text-black border-transparent border-b-2 hover:border-blue-600 hover:text-blue-600 hover:border-b-2 hover:border-blue-600;
26+
@apply text-black border-transparent border-b-2 hover:cursor-pointer hover:border-blue-600 hover:text-blue-600 hover:border-b-2 hover:border-blue-600;
2727
}
2828

2929
.header-nav-item.header-nav-item-selected {
3030
@apply text-blue-600;
3131
}
3232

3333
.subheader-nav-item {
34-
@apply cursor-pointer rounded-lg p-3 transition duration-300 hover:bg-gray-100;
34+
@apply cursor-pointer p-3 transition duration-300 hover:bg-gray-200 border-b border-gray-200;
3535
}
3636

3737
.subheader-nav-item.subheader-nav-item-selected {

frontend/src/pages/Layout/Layout.tsx

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// Layout.tsx
2-
import {ReactNode, useState, useEffect} from "react";
2+
import {ReactNode} from "react";
33
import Header from "../../components/Header/Header";
44
import Footer from "../../components/Footer/Footer";
55
import {connect} from "react-redux";
66
import {useAuth} from "./authHooks.ts";
77
import {RootState} from "../../services/actions/types";
8-
import {useLocation} from "react-router-dom";
98

109
interface LayoutProps {
1110
children: ReactNode;
@@ -16,32 +15,8 @@ interface LoginFormProps {
1615
}
1716

1817
export const Layout = ({
19-
children,
20-
isAuthenticated,
21-
}: LayoutProps & LoginFormProps): JSX.Element => {
22-
const [showLoginMenu, setShowLoginMenu] = useState(false);
23-
const location = useLocation();
24-
25-
26-
useEffect(() => {
27-
if (!isAuthenticated) {
28-
if (
29-
location.pathname === "/login" ||
30-
location.pathname === "/resetpassword" ||
31-
location.pathname.includes("password") ||
32-
location.pathname.includes("reset")
33-
) {
34-
setShowLoginMenu(false);
35-
} else {
36-
setShowLoginMenu(true);
37-
}
38-
}
39-
}, [isAuthenticated, location.pathname]);
40-
41-
const handleLoginMenu = () => {
42-
setShowLoginMenu(!showLoginMenu);
43-
};
44-
18+
children
19+
}: LayoutProps & LoginFormProps): JSX.Element => {
4520
useAuth();
4621
return (
4722
<main>

frontend/src/pages/Layout/Layout_V2_Header.tsx

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { useState, useEffect } from "react";
21
import { Link, useLocation } from "react-router-dom";
32
import { useAuth } from "./authHooks.ts";
43
import { useGlobalContext } from "../../../src/contexts/GlobalContext.tsx";
@@ -7,31 +6,12 @@ interface LoginFormProps {
76
isAuthenticated: boolean;
87
}
98

10-
const Header: React.FC<LoginFormProps> = ({ isAuthenticated }) => {
11-
const [showLoginMenu, setShowLoginMenu] = useState(false);
9+
const Header: React.FC<LoginFormProps> = () => {
1210
const location = useLocation();
1311
const { setShowMetaPanel } = useGlobalContext();
1412

1513
const isOnDrugSummaryPage = location.pathname.includes("/drugsummary");
1614

17-
useEffect(() => {
18-
// only show the login menu on non‑auth pages
19-
if (!isAuthenticated) {
20-
const path = location.pathname;
21-
const isAuthPage =
22-
path === "/login" ||
23-
path === "/resetpassword" ||
24-
path.includes("password") ||
25-
path.includes("reset");
26-
27-
setShowLoginMenu(!isAuthPage);
28-
}
29-
}, [isAuthenticated, location.pathname]);
30-
31-
const handleLoginMenu = () => {
32-
setShowLoginMenu((prev) => !prev);
33-
};
34-
3515
useAuth();
3616

3717
return (

frontend/src/pages/Login/LoginForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function LoginForm({ isAuthenticated, loginError }: LoginFormProps) {
7070
<FaExclamationTriangle size={24} />
7171
</div>
7272
<div>
73-
<p className="text-gray-800">This login is for Code for Philly administrators. Providers can use all site features without logging in. <Link to="/" className="underline hover:text-blue-600 hover:no-underline" style={{ 'white-space': 'nowrap' }}>Return to Homepage</Link></p>
73+
<p className="text-gray-800">This login is for Code for Philly administrators. Providers can use all site features without logging in. <Link to="/" className="underline hover:text-blue-600 hover:no-underline" style={{ 'whiteSpace': 'nowrap' }}>Return to Homepage</Link></p>
7474
</div>
7575
</blockquote>
7676
</div>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { useEffect } from 'react';
2+
import { useNavigate } from 'react-router-dom';
3+
import { useDispatch } from "react-redux";
4+
import { logout, AppDispatch } from "../../services/actions/auth";
5+
6+
const LogoutPage = () => {
7+
const navigate = useNavigate();
8+
const dispatch = useDispatch<AppDispatch>();
9+
10+
useEffect(() => {
11+
dispatch(logout());
12+
13+
const timer = setTimeout(() => {
14+
navigate('/');
15+
}, 3000); // Redirect after 3 seconds
16+
17+
// Cleanup the timer on component unmount
18+
return () => clearTimeout(timer);
19+
}, [dispatch, navigate]);
20+
21+
return (
22+
<div className="flex items-center justify-center min-h-screen bg-gray-100 px-4">
23+
<div className="bg-white p-8 rounded shadow-md max-w-md text-center">
24+
<h1 className="text-2xl font-semibold text-gray-800 mb-4">You’ve been logged out</h1>
25+
<div className="w-full h-2 bg-gray-200 overflow-hidden relative rounded-full">
26+
<div className="absolute top-0 left-0 h-2 w-1/3 bg-blue-500 rounded-full animate-loading"></div>
27+
</div>
28+
<p className="text-gray-600 mb-6">
29+
Thank you for using <span className="body_logo">Balancer</span>. You'll be redirected to the homepage shortly.
30+
</p>
31+
<button
32+
onClick={() => navigate('/')}
33+
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition"
34+
>
35+
Go to Homepage Now
36+
</button>
37+
</div>
38+
</div>
39+
);
40+
};
41+
42+
export default LogoutPage;

frontend/src/routes/routes.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import App from "../App";
22
import RouteError from "../pages/404/404.tsx";
33
import LoginForm from "../pages/Login/Login.tsx";
4+
import Logout from "../pages/Logout/Logout.tsx";
45
import AdminPortal from "../pages/AdminPortal/AdminPortal.tsx";
56
import ResetPassword from "../pages/Login/ResetPassword.tsx";
67
import ResetPasswordConfirm from "../pages/Login/ResetPasswordConfirm.tsx";
@@ -50,6 +51,10 @@ const routes = [
5051
path: "login",
5152
element: <LoginForm />,
5253
},
54+
{
55+
path: "logout",
56+
element: <Logout />,
57+
},
5358
{
5459
path: "resetPassword",
5560
element: <ResetPassword />,

frontend/tailwind.config.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,15 @@ export default {
1010
lora: "'Lora', serif",
1111
'quicksand': ['Quicksand', 'sans-serif']
1212
},
13+
keyframes: {
14+
'loading': {
15+
'0%': { left: '-40%' },
16+
'100%': { left: '100%' },
17+
},
18+
},
1319
animation: {
14-
'pulse-bounce': 'pulse-bounce 2s infinite', // Adjust duration and iteration as needed
20+
'pulse-bounce': 'pulse-bounce 2s infinite',
21+
'loading': 'loading 3s infinite',
1522
},
1623
plugins: [],
1724
},

0 commit comments

Comments
 (0)