-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(navbar): implement landing page navbar
-implement landing page navbar reusable component for both desktop and mobile screens [Delivers #21]
- Loading branch information
Showing
24 changed files
with
5,481 additions
and
2,941 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,27 @@ | ||
import { | ||
createBrowserRouter, | ||
createRoutesFromElements, | ||
Route, | ||
RouterProvider, | ||
} from 'react-router-dom'; | ||
import Home from './pages/Home'; | ||
import Shop from './pages/Shop'; | ||
import About from './pages/About'; | ||
import Contact from './pages/Contact'; | ||
|
||
function App() { | ||
return <p className="text-blue-400">Welcome to Dynamites E-commerce</p>; | ||
const router = createBrowserRouter( | ||
createRoutesFromElements( | ||
<Route path="/"> | ||
<Route index element={<Home />} /> | ||
<Route path="/shop" element={<Shop />} /> | ||
<Route path="/about" element={<About />} /> | ||
<Route path="/contact" element={<Contact />} /> | ||
</Route> | ||
) | ||
); | ||
|
||
return <RouterProvider router={router} />; | ||
} | ||
|
||
export default App; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import { render, screen, fireEvent } from '@testing-library/react'; | ||
import { MemoryRouter } from 'react-router-dom'; | ||
import { describe, it, expect } from 'vitest'; | ||
import Navbar from '@/components/Navbar'; | ||
|
||
describe('Navbar Component', () => { | ||
it('renders Navbar component', () => { | ||
render( | ||
<MemoryRouter> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
const logo = screen.getByAltText(/logo/i); | ||
expect(logo).toBeInTheDocument(); | ||
|
||
const title = screen.getByText(/dynamites/i); | ||
expect(title).toBeInTheDocument(); | ||
|
||
const homeLink = screen.getByText(/Home/i); | ||
expect(homeLink).toBeInTheDocument(); | ||
|
||
const shopLink = screen.getByText(/Shop/i); | ||
expect(shopLink).toBeInTheDocument(); | ||
|
||
const aboutLink = screen.getByText(/About us/i); | ||
expect(aboutLink).toBeInTheDocument(); | ||
|
||
const contactLink = screen.getByText(/Contact/i); | ||
expect(contactLink).toBeInTheDocument(); | ||
|
||
const cartIcon = screen.getByAltText(/cart/i); | ||
expect(cartIcon).toBeInTheDocument(); | ||
|
||
const avatar = screen.getByAltText(/profile/i); | ||
expect(avatar).toBeInTheDocument(); | ||
|
||
const username = screen.getByText(/amanda green/i); | ||
expect(username).toBeInTheDocument(); | ||
}); | ||
|
||
it('highlights the correct navigation link based on the current route', () => { | ||
render( | ||
<MemoryRouter initialEntries={['/shop']}> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
expect(screen.getByText('Shop')).toHaveClass( | ||
'border-b-[2px] border-custom-purple text-custom-purple' | ||
); | ||
}); | ||
|
||
it('toggles menu on hamburger icon click', () => { | ||
render( | ||
<MemoryRouter> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
const hamburgerIcon = screen.getByRole('img', { name: /hamburger/i }); | ||
fireEvent.click(hamburgerIcon); | ||
|
||
// expect(screen.getByAltText(/home/i)).toBeInTheDocument(); | ||
}); | ||
|
||
it('toggles profile menu on avatar click', () => { | ||
render( | ||
<MemoryRouter> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
expect(screen.queryByText(/edit profile/i)).not.toBeInTheDocument(); | ||
|
||
const profileIcon = screen.getAllByRole('img', { name: /down/i })[0]; | ||
fireEvent.click(profileIcon); | ||
|
||
expect(screen.getByText(/edit profile/i)).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders links with correct paths', () => { | ||
render( | ||
<MemoryRouter> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
const homeLink = screen.getByText(/home/i); | ||
expect(homeLink.closest('a')).toHaveAttribute('href', '/'); | ||
|
||
const shopLink = screen.getByText(/shop/i); | ||
expect(shopLink.closest('a')).toHaveAttribute('href', '/shop'); | ||
|
||
const aboutLink = screen.getByText(/about us/i); | ||
expect(aboutLink.closest('a')).toHaveAttribute('href', '/about'); | ||
|
||
const contactLink = screen.getByText(/contact/i); | ||
expect(contactLink.closest('a')).toHaveAttribute('href', '/contact'); | ||
}); | ||
|
||
it('displays cart item count', () => { | ||
render( | ||
<MemoryRouter> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
const cartCount = screen.getByText(/5/i); | ||
expect(cartCount).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders profile options on avatar click', () => { | ||
render( | ||
<MemoryRouter> | ||
<Navbar /> | ||
</MemoryRouter> | ||
); | ||
|
||
const profileIcon = screen.getAllByRole('img', { name: /down/i })[0]; | ||
fireEvent.click(profileIcon); | ||
|
||
const editProfileOption = screen.getByText(/edit profile/i); | ||
expect(editProfileOption).toBeInTheDocument(); | ||
|
||
const preferencesOption = screen.getByText(/preferences/i); | ||
expect(preferencesOption).toBeInTheDocument(); | ||
|
||
const nightModeOption = screen.getByText(/night mode/i); | ||
expect(nightModeOption).toBeInTheDocument(); | ||
|
||
const helpCenterOption = screen.getByText(/help center/i); | ||
expect(helpCenterOption).toBeInTheDocument(); | ||
|
||
const signOutOption = screen.getByText(/sign out/i); | ||
expect(signOutOption).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { Link, useLocation } from 'react-router-dom'; | ||
import { useState } from 'react'; | ||
|
||
function Navbar() { | ||
const location = useLocation(); | ||
const [toggleMenu, setToggleMenu] = useState(false); | ||
const [toggleProfileMenu, setToggleProfileMenu] = useState(false); | ||
return ( | ||
<div className="relative flex items-center justify-between w-full h-16 shadow-sm"> | ||
<img | ||
src="/hamburger.png" | ||
alt="hamburger" | ||
width="20" | ||
height="20" | ||
className="md:hidden ml-8" | ||
onClick={() => setToggleMenu(!toggleMenu)} | ||
/> | ||
<div className="flex items-center gap-2 md:ml-8"> | ||
<img src="/logo.png" alt="logo" /> | ||
<h2 className="text-custom-black font-bold">Dynamites</h2> | ||
</div> | ||
<nav className="xs:hidden md:flex items-center h-full"> | ||
<Link | ||
to="/" | ||
className={`${location.pathname === '/' ? 'border-b-[2px] border-custom-purple text-custom-purple' : 'text-custom-grey'} h-full flex items-center justify-center pl-4 pr-8`} | ||
> | ||
Home | ||
</Link> | ||
<Link | ||
to="/shop" | ||
className={`${location.pathname === '/shop' ? 'border-b-[2px] border-custom-purple text-custom-purple' : 'text-custom-grey'} h-full flex items-center justify-center pl-4 pr-8`} | ||
> | ||
Shop | ||
</Link> | ||
<Link | ||
to="/about" | ||
className={`${location.pathname === '/about' ? 'border-b-[2px] border-custom-purple text-custom-purple' : 'text-custom-grey'} h-full flex items-center justify-center pl-4 pr-8`} | ||
> | ||
About Us | ||
</Link> | ||
<div | ||
className={`${location.pathname === '/contact' ? 'border-b-[2px] border-custom-purple text-custom-purple' : 'text-custom-grey'} flex items-center gap-2 h-full pl-4 pr-8`} | ||
> | ||
<Link | ||
to="/contact" | ||
className="h-full flex items-center justify-center" | ||
> | ||
Contact | ||
</Link> | ||
<img src="/down.png" width="15" height="15" alt="contact" /> | ||
</div> | ||
</nav> | ||
<div className="flex items-center gap-8 mr-8"> | ||
<div className="flex items-center gap-4"> | ||
<div className="relative"> | ||
<img src="/cart.png" alt="cart" /> | ||
<div className="flex items-center justify-center w-4 h-4 rounded-full bg-red-700 text-white absolute right-[-0.3rem] top-[-0.2rem] text-sm"> | ||
5 | ||
</div> | ||
</div> | ||
<img src="/heart.png" alt="heart" /> | ||
</div> | ||
<div className="xs:hidden md:flex items-center gap-2"> | ||
<div className="w-8 h-8 rounded-full overflow-hidden"> | ||
<img | ||
src="/avatar.jpg" | ||
className="w-full h-full object-cover" | ||
alt="profile" | ||
/> | ||
</div> | ||
<h2 className="text-custom-black">Amanda Green</h2> | ||
<img | ||
src="/down.png" | ||
width="15" | ||
height="15" | ||
alt="down" | ||
onClick={() => setToggleProfileMenu(!toggleProfileMenu)} | ||
/> | ||
</div> | ||
</div> | ||
{toggleMenu && ( | ||
<div className="absolute top-16 flex flex-col items-start p-4 w-full gap-4 text-custom-grey shadow-sm border-b border-custom-lightGrey"> | ||
<Link to="/">Home</Link> | ||
<Link to="/shop">Shop</Link> | ||
<Link to="/about">About</Link> | ||
<Link to="contact">Contact</Link> | ||
<div className="flex flex-col w-full gap-2 border-b-[1.5px] border-custom-lightGrey py-2"> | ||
<div className="flex gap-2 w-full items-center"> | ||
<img src="/edit.png" width="20" height="20" alt="edit" /> | ||
<h2>Edit profile</h2> | ||
</div> | ||
<div className="flex gap-2 w-full items-center"> | ||
<img src="/settings.png" width="20" height="20" alt="settings" /> | ||
<h2>Preferences</h2> | ||
</div> | ||
</div> | ||
<div className="flex items-center w-full justify-between pr-2 py-2 border-b-[1.5px] border-custom-lightGrey"> | ||
<div className="flex gap-2 items-center"> | ||
<img src="/moon.png" width="20" height="20" alt="moon" /> | ||
<h2>Night mode</h2> | ||
</div> | ||
<div className="rounded-xl w-9 h-5 bg-custom-purple flex items-center justify-end px-1"> | ||
<div className="bg-white rounded-full w-3 h-3" /> | ||
</div> | ||
</div> | ||
<div className="flex gap-2 w-full items-center pt-1"> | ||
<img src="/help.png" width="20" height="20" alt="help" /> | ||
<h2>Help center</h2> | ||
</div> | ||
<div className="flex gap-2 w-full items-center border-t-[1.5px] border-custom-lightGrey pt-1 mt-8"> | ||
<img src="/signout.png" width="20" height="20" alt="signout" /> | ||
<h2>Sign out</h2> | ||
</div> | ||
</div> | ||
)} | ||
{toggleProfileMenu && ( | ||
<div className="absolute top-16 right-0 flex flex-col items-center w-52 shadow-sm py-2 text-custom-grey rounded-b-md border-l border-b border-custom-lightGrey"> | ||
<div className="flex flex-col w-full gap-2 border-b-[1.5px] border-custom-lightGrey py-2"> | ||
<div className="flex gap-2 w-full items-center px-2"> | ||
<img src="/edit.png" width="20" height="20" alt="edit" /> | ||
<h2>Edit profile</h2> | ||
</div> | ||
<div className="flex gap-2 w-full items-center px-2"> | ||
<img src="/settings.png" width="20" height="20" alt="settings" /> | ||
<h2>Preferences</h2> | ||
</div> | ||
</div> | ||
<div className="flex items-center w-full justify-between pr-2 py-2 border-b-[1.5px] border-custom-lightGrey"> | ||
<div className="flex gap-2 items-center px-2"> | ||
<img src="/moon.png" width="20" height="20" alt="moon" /> | ||
<h2>Night mode</h2> | ||
</div> | ||
<div className="rounded-xl w-9 h-5 bg-custom-purple flex items-center justify-end px-1"> | ||
<div className="bg-white rounded-full w-3 h-3" /> | ||
</div> | ||
</div> | ||
<div className="flex gap-2 w-full items-center px-2 pt-1"> | ||
<img src="/help.png" width="20" height="20" alt="help" /> | ||
<h2>Help center</h2> | ||
</div> | ||
<div className="flex gap-2 w-full items-center px-2 border-t-[1.5px] border-custom-lightGrey pt-1 mt-8"> | ||
<img src="/signout.png" width="20" height="20" alt="signout" /> | ||
<h2>Sign out</h2> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
export default Navbar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Navbar from '@/components/Navbar'; | ||
|
||
function About() { | ||
return <Navbar />; | ||
} | ||
|
||
export default About; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Navbar from '@/components/Navbar'; | ||
|
||
function Contact() { | ||
return <Navbar />; | ||
} | ||
|
||
export default Contact; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Navbar from '@/components/Navbar'; | ||
|
||
function Home() { | ||
return <Navbar />; | ||
} | ||
|
||
export default Home; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Navbar from '@/components/Navbar'; | ||
|
||
function Shop() { | ||
return <Navbar />; | ||
} | ||
|
||
export default Shop; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters