Skip to content

Commit

Permalink
Finishes the notification task
Browse files Browse the repository at this point in the history
  • Loading branch information
Favor-star committed Jul 9, 2024
1 parent ea71b18 commit 487d23e
Show file tree
Hide file tree
Showing 6 changed files with 398 additions and 17 deletions.
64 changes: 48 additions & 16 deletions src/components/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import React, { useState, useEffect } from 'react';
import { NavLink, useNavigate } from 'react-router-dom';
import React, { useRef, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { DesktopNav, PopularCategory } from '../../containers/nav/NavbarComponents';
import WishNav from './wishNav/WishNav';
import CartNav from './cartNav/CartNav';
import { LuBell } from 'react-icons/lu';
import Notifications from './notifications/Notifications';
import { cn } from '../../utils';

const Navbar: React.FC = () => {
const [cartOpen, setCartOpen] = useState(false);
const [notificationOpen, setNotificationOpen] = useState<boolean>(false);
const navbarRef = useRef<HTMLDivElement>(null);
const [navbarHeight, setNavbarHeight] = useState<number>(20);
const [cartOpen, SetCartOpen] = useState(false);
const [wish, setWish] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const navigate = useNavigate();
Expand Down Expand Up @@ -34,7 +40,6 @@ const Navbar: React.FC = () => {
container?.classList.remove('-translate-x-full');
hideScrollbar();
});

overlay?.addEventListener('click', e => {
if (e.target !== e.currentTarget) {
return;
Expand All @@ -45,21 +50,34 @@ const Navbar: React.FC = () => {
});
}, []);

const handleSearch = (e: React.FormEvent) => {
useEffect(() => {
const updateNavbarHeight = () => {
setNavbarHeight(navbarRef.current?.offsetHeight as number);
};
updateNavbarHeight();
// setTimeout(updateNavbarHeight, 0);
window.addEventListener('resize', updateNavbarHeight);
return () => {
window.removeEventListener('resize', updateNavbarHeight);
};
}, []);

const handleSearch = (e: any) => {
e.preventDefault();
navigate(`/search?searchQuery=${searchQuery}`);
};

return (
<>
{(wish || cartOpen) && (
{(wish || cartOpen || notificationOpen) && (
<div
onClick={e => {
if (e.target !== e.currentTarget) {
return;
}
setWish(false);
setCartOpen(false);
SetCartOpen(false);
setNotificationOpen(false);
}}
className='absolute bg-[#00000000] top-0 w-full border h-full'
style={{ zIndex: 10 }}
Expand All @@ -70,7 +88,10 @@ const Navbar: React.FC = () => {
wish || cartOpen ? 'sticky' : ''
} z-10`}
>
<div className='flex justify-between gap-2 flex-wrap p-3 md:p-4 xl:px-10 2xl:w-[1440px] relative'>
<div
className='flex justify-between gap-2 flex-wrap p-3 md:p-4 xl:px-10 2xl:w-[1440px] relative'
ref={navbarRef}
>
<div className='flex items-center gap-3 order-1'>
<div
id='humbergurBtn'
Expand Down Expand Up @@ -131,11 +152,12 @@ const Navbar: React.FC = () => {
</div>
)}
</div>
<NavLink
to='shoppingcart'
className='rounded-full transition-all ease-in-out delay-100 hover:bg-grayColor active:bg-greenColor p-1 active:text-blackColor hover:text-blackColor relative'
{/* Favorite */}
<a
className='rounded-full transition-all ease-in-out delay-100 hover:bg-grayColor active:bg-greenColor p-1 active:text-blackColor hover:text-blackColor relative'
onClick={() => setNotificationOpen(!notificationOpen)}
>
<svg
{/* <svg
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 24'
Expand All @@ -148,11 +170,12 @@ const Navbar: React.FC = () => {
strokeLinejoin='round'
d='M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z'
/>
</svg>
</svg> */}
<LuBell strokeWidth={1} stroke='currentColor' className='size-6 md:size-8' />
<span className='absolute top-1 right-1 w-2 h-2 rounded-full bg-redColor'></span>
</NavLink>
</a>
<div
onClick={() => setCartOpen(state => !state)}
onClick={() => SetCartOpen(state => !state)}
className='rounded-full transition-all ease-in-out delay-100 hover:bg-grayColor active:bg-greenColor active:text-blackColor hover:text-blackColor p-1 select-none'
>
<div className='relative'>
Expand All @@ -178,7 +201,7 @@ const Navbar: React.FC = () => {
<div
onClick={e => {
if (e.target !== e.currentTarget) {
setCartOpen(false);
SetCartOpen(false);
return;
}
}}
Expand Down Expand Up @@ -253,6 +276,15 @@ const Navbar: React.FC = () => {
</div>
</div>
</div>
<div
className={cn(
'max-w-[500px] w-11/12 absolute right-2 z-[100] transition-all',
!notificationOpen ? 'h-0 scale-0 origin-top' : 'h-fit scale-100 origin-top'
)}
style={{ top: `${navbarHeight}px` }}
>
<Notifications />
</div>
</div>
</>
);
Expand Down
122 changes: 122 additions & 0 deletions src/components/navbar/notifications/NotificationComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { BiDotsVertical } from 'react-icons/bi';
import { cn } from '../../../utils';
import { useEffect, useRef, useState } from 'react';
import {
useMarkNotificationAsReadMutation,
useDeleteSingleNotificationsMutation,
} from '../../../services/notificationsAPI';
import { FaSpinner } from 'react-icons/fa6';

interface NotificationProps {
id: string;
message: string;
time: string;
date: string;
isRead: boolean;
onDelete: (id: string) => void;
onReadChange: (isRead: boolean) => void;
}
const NotificationComponent = ({
message,
time,
date,
isRead: initialIsRead,
id,
onDelete,
onReadChange,
}: NotificationProps) => {
const [isMenuClicked, setIsMenuClicked] = useState(false);
const [isRead, setIsRead] = useState(initialIsRead);
const menubarRef = useRef<HTMLDivElement>(null);
const [markNotificationAsRead, { isLoading }] = useMarkNotificationAsReadMutation();
const [deleteNotification, { isLoading: isDeleting }] = useDeleteSingleNotificationsMutation();
const markAsRead = async () => {
const { data } = await markNotificationAsRead({ isRead: !isRead, id });
setIsRead(data.data.isRead);
onReadChange(data.data.isRead);
};
const notificationDelete = () => {
deleteNotification(id);
onDelete(id);
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (menubarRef.current && !menubarRef.current.contains(event.target as Node)) {
setIsMenuClicked(false);
}
};

if (isMenuClicked) {
document.addEventListener('mousedown', handleClickOutside);
} else {
document.removeEventListener('mousedown', handleClickOutside);
}

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isMenuClicked]);

return (
<div
className={cn(
'w-full gap-2 flex items-center relative p-2',
isRead
? 'bg-blackColor md:bg-grayColor md:text-blackColor text-whiteColor text-opacity-50 md:text-opacity-40 '
: 'bg-blackColor md:bg-grayColor md:text-blackColor text-whiteColor'
)}
key={id}
>
<span className='w-full'>
<span className='flex justify-between'>
<p className='text-sm'>{message}</p>
<p
className={cn('text-xs font-medium italic text-skyBlueText hidden', isRead ? 'hidden' : 'hidden md:block')}
>
Unread
</p>
<div
className={cn('w-3 h-3 rounded-full bg-skyBlueText md:hidden', isRead ? 'hidden' : 'block md:hidden')}
></div>
</span>
<span className='w-full text-xs flex justify-between items-center italic'>
<p className='italic font-light'>{date} </p>
<p className='italic font-light'>{time}</p>
</span>
</span>
<button
onClick={e => {
e.preventDefault();
setIsMenuClicked(!isMenuClicked);
}}
>
<BiDotsVertical className=' aspect-square max-w-8 w-20 ' />
</button>
{isMenuClicked && (
<div
ref={menubarRef}
className={cn(
'absolute top-10 right-0 bg-white shadow-customShadow border text-sm text-greenColor font-medium flex flex-col gap-2 items-start rounded-xl transition-all z-20 bg-whiteColor overflow-hidden',
isMenuClicked ? 'scale-1 origin-top' : 'h-0 scale-0 origin-top'
)}
>
<button
onClick={notificationDelete}
className=' hover:bg-greenColor hover:text-whiteColor bg-whiteColor text-greenColor p-2 w-full text-left'
>
<FaSpinner className={cn('w-3 h-3 ', isDeleting ? 'block animate-spin ' : 'hidden')} /> Delete
</button>
<button
onClick={markAsRead}
className=' hover:bg-greenColor hover:text-whiteColor bg-whiteColor text-greenColor p-2 w-full text-left'
>
<FaSpinner className={cn('w-3 h-3 ', isLoading ? 'block animate-spin ' : 'hidden')} />{' '}
{isRead ? 'Mark as Unread' : 'Mark as Read'}
</button>
</div>
)}
</div>
);
};

export default NotificationComponent;
Loading

0 comments on commit 487d23e

Please sign in to comment.