Skip to content

Commit a3ea880

Browse files
Merge pull request #21 from cherryontech/feat/footer_navbar
Feat/footer-and-navbar
2 parents 0aead5c + a996240 commit a3ea880

4 files changed

Lines changed: 316 additions & 90 deletions

File tree

src/components/Footer.jsx

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { Link } from 'react-router-dom';
33

4-
const links = [
4+
// Links logged out grid
5+
const loggedOutLinks = [
56
{ id: 'home', text: 'Home', href: '/' },
67
{ id: 'dashboard', text: 'Dashboard', href: '/dashboard' },
78
{ id: 'privacy-policy', text: 'Privacy Policy', href: '/privacy-policy' },
@@ -11,70 +12,122 @@ const links = [
1112
text: 'Terms of Service',
1213
href: '/terms-of-service',
1314
},
14-
{ id: 'onboarding', text: 'Onboarding', href: '/onboarding' },
15+
16+
];
17+
18+
// Links logged in
19+
const loggedInLinks = [
20+
{ id: 'home', text: 'Home', href: '/' },
21+
{ id: 'privacy-policy', text: 'Privacy Policy', href: '/privacy-policy' },
22+
{
23+
id: 'terms-of-service',
24+
text: 'Terms of Service',
25+
href: '/terms-of-service',
26+
},
1527
];
1628

1729
const Footer = () => {
18-
const getLinkGridClasses = (id) => {
30+
const [isLoggedIn, setIsLoggedIn] = useState(
31+
!!localStorage.getItem('authToken')
32+
);
33+
34+
useEffect(() => {
35+
const checkAuth = () => {
36+
setIsLoggedIn(!!localStorage.getItem('authToken'));
37+
};
38+
39+
window.addEventListener('storage', checkAuth);
40+
checkAuth();
41+
42+
return () => {
43+
window.removeEventListener('storage', checkAuth);
44+
};
45+
}, []);
46+
47+
const getLinkClasses = (isLoggedIn) =>
48+
`focus:outline-none focus-visible:ring-2 rounded-lg px-2 py-1 transition-colors whitespace-nowrap ${
49+
isLoggedIn
50+
? `font-[Poppins] text-xl font-medium text-[#1E1E1E] leading-normal hover:font-bold focus:ring-persianblue `
51+
: 'font-medium text-xl text-[#1e1e1e] hover:font-bold focus:ring-persianblue'
52+
}`;
53+
54+
// Grid logged out state
55+
const getLoggedOutGridClasses = (id) => {
1956
switch (id) {
2057
case 'home':
21-
return 'row-start-1 col-start-1';
58+
return 'lg:row-start-1 lg:col-start-1';
2259
case 'dashboard':
23-
return 'row-start-1 col-start-2';
60+
return 'lg:row-start-1 lg:col-start-2';
2461
case 'privacy-policy':
25-
return 'row-start-2 col-start-1';
62+
return 'lg:row-start-2 lg:col-start-1';
2663
case 'sign-up':
27-
return 'row-start-2 col-start-2';
64+
return 'lg:row-start-2 lg:col-start-2';
2865
case 'terms-of-service':
29-
return 'row-start-3 col-start-1';
66+
return 'lg:row-start-3 lg:col-start-1';
3067
default:
3168
return '';
3269
}
3370
};
3471

3572
return (
36-
<footer className="w-full relative bg-[linear-gradient(180deg,rgba(225,255,228,1)_0%,rgba(187,253,255,1)_100%)]">
37-
{/*Responsive Navigation Container */}
38-
<nav
39-
className="
40-
// Mobile Styles
41-
flex flex-col items-center py-5 px-2 space-y-4
73+
<footer
74+
className={`w-full relative bg-[linear-gradient(180deg,rgba(225,255,228,1)_0%,rgba(187,253,255,1)_100%)] font-poppins`}
75+
>
76+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
77+
{isLoggedIn ? (
78+
/* Footer for authenticated user */
79+
<nav
80+
className="flex flex-col items-center justify-center py-4 h-auto md:flex-row md:h-[100px] space-y-3 md:space-y-0 "
81+
aria-label="Logged-in Footer navigation"
82+
>
83+
{loggedInLinks.map((link) => (
84+
<Link
85+
key={link.id}
86+
to={link.href}
87+
className={`
88+
mx-6 sm:mx-8 md:mx-12 lg:mx-[135px]
89+
${getLinkClasses(true)}
90+
`}
91+
>
92+
{link.text}
93+
</Link>
94+
))}
95+
</nav>
96+
) : (
97+
/* Footer for NON-authenticated user */
98+
<nav
99+
className="
100+
// Mobile Styles: Centered column
101+
flex flex-col items-center py-5 px-2 space-y-4
42102
43-
// Desktop Styles
44-
lg:grid
45-
lg:grid-cols-2
46-
lg:grid-rows-3
47-
48-
49-
lg:gap-x-[184px] lg:gap-y-4
50-
51-
lg:px-[104px]
52-
lg:py-[40px]
53-
lg:h-[250px]
54-
lg:mx-auto
55-
lg:max-w-[1440px]
56-
lg:w-full
57-
"
58-
aria-label="Footer navigation"
59-
>
60-
{links.map((link) => (
61-
<Link
62-
key={link.id}
63-
to={link.href}
64-
className={`
65-
relative h-[30px] font-medium text-[#1e1e1e] text-xl tracking-[0] leading-[normal]
66-
focus:outline-none focus:ring-2 focus:ring-persianblue rounded-[5px] px-5
67-
68-
69-
// Grid Placement for Desktop
70-
lg:text-left lg:h-auto
71-
${getLinkGridClasses(link.id)}
72-
`}
103+
// Desktop Styles: 2-column Grid
104+
lg:grid
105+
lg:grid-cols-2
106+
lg:grid-rows-3
107+
lg:gap-x-40 lg:gap-y-4
108+
lg:px-10
109+
lg:py-10
110+
lg:max-w-[1000px]
111+
lg:mx-auto
112+
"
113+
aria-label="Logged-out Footer navigation"
73114
>
74-
{link.text}
75-
</Link>
76-
))}
77-
</nav>
115+
{loggedOutLinks.map((link) => (
116+
<Link
117+
key={link.id}
118+
to={link.href}
119+
className={`
120+
text-center relative h-auto ${getLinkClasses(false)}
121+
// Grid Placement for Desktop
122+
lg:text-left ${getLoggedOutGridClasses(link.id)}
123+
`}
124+
>
125+
{link.text}
126+
</Link>
127+
))}
128+
</nav>
129+
)}
130+
</div>
78131
</footer>
79132
);
80133
};

src/components/MobileMenu.jsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// react
2+
import React from 'react';
3+
import { Link } from 'react-router-dom';
4+
import { AiOutlineClose } from 'react-icons/ai';
5+
import { RiLayoutHorizontalFill, RiUser3Fill } from 'react-icons/ri';
6+
import { PiListBulletsFill } from 'react-icons/pi';
7+
8+
const MobileMenu = ({ isOpen, toggleMenu }) => {
9+
const navLinks = [
10+
{ name: 'Dashboard', href: '/dashboard', icon: PiListBulletsFill },
11+
{
12+
name: 'Detox Challenge',
13+
href: '/detoxChallenge',
14+
icon: RiLayoutHorizontalFill,
15+
},
16+
{ name: 'Profile', href: '/profile', icon: RiUser3Fill },
17+
];
18+
19+
return (
20+
<>
21+
{/* Side Menu*/}
22+
<div
23+
className={`fixed top-0 left-0 h-full w-full bg-white shadow-xl p-2 transform transition-transform duration-300 ease-in-out z-50 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}
24+
role="dialog"
25+
aria-modal="true"
26+
aria-label="Main Navigation Menu"
27+
id="mobile-menu"
28+
>
29+
{/* Close Button */}
30+
<button
31+
onClick={toggleMenu}
32+
className="text-stone-900 text-3xl mt-8 mb-2 ml-8 rounded-full p-1"
33+
aria-label="Close Menu"
34+
>
35+
<AiOutlineClose />
36+
</button>
37+
38+
{/* Links with Icons */}
39+
<nav>
40+
<ul className="flex flex-col space-y-3 ml-10 ">
41+
{navLinks.map((link) => (
42+
<li key={link.name} className="mb-4">
43+
<Link
44+
to={link.href}
45+
className="flex items-center text-stone-900 text-lg font-poppins font-semibold transition-colors hover:font-bold focus:outline-none focus:ring-2focus:outline-none focus-visible:ring-2 focus-visible:ring-persianblue rounded-[5px]"
46+
onClick={toggleMenu}
47+
>
48+
<link.icon
49+
className="mr-2 text-2xl text-black w-5 h-6 "
50+
aria-hidden="true"
51+
/>
52+
{link.name}
53+
</Link>
54+
</li>
55+
))}
56+
</ul>
57+
</nav>
58+
</div>
59+
</>
60+
);
61+
};
62+
63+
export default MobileMenu;

0 commit comments

Comments
 (0)