Skip to content

Commit

Permalink
Merge pull request #15 from wizelineacademy/notifications
Browse files Browse the repository at this point in the history
notifications ui done
  • Loading branch information
pedroalonsoms authored Apr 8, 2024
2 parents 22ba0f9 + 331f5fe commit 91628ff
Show file tree
Hide file tree
Showing 6 changed files with 340 additions and 24 deletions.
159 changes: 136 additions & 23 deletions components/Notifications.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,146 @@
"use client";

import { useState } from "react";
import { Menu, Transition } from "@headlessui/react";
import { Fragment, useEffect, useState } from "react";
import CloseIcon from "./icons/CloseIcon";

const Notifications = () => {
const [isActive, setIsActive] = useState(false);
const notificationsCount = 1;
const [notifications, setNotifications] = useState([
{
id: 1,
title: "RULER",
type: "RULER",
},
{
id: 2,
title: "Sprint Survey",
type: "SPRINT",
},
{
id: 3,
title: "Project Survey",
type: "PROJECT",
},
]);

useEffect(() => {
const onClickOutsideButton = (e: MouseEvent) => {
if (!(e.target as HTMLElement).closest(".group")) {
setIsActive(false);
}
};
document.addEventListener("click", onClickOutsideButton);
return () => document.removeEventListener("click", onClickOutsideButton);
}, []);
const handleClickNotification = (index: number) => {
const newNotifications = [...notifications];
newNotifications.splice(index, 1);
setNotifications(newNotifications);
};

return (
<div
onClick={() => setIsActive(!isActive)}
className={`${isActive ? "bg-primary" : "bg-white"} group rounded-full p-2 drop-shadow-lg hover:bg-primary`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.8}
stroke="currentColor"
className={`${isActive ? "text-white" : "text-primary"} h-6 w-6 group-hover:text-white`}
<Menu as="div" className="relative inline-block text-left">
<Menu.Button
className={`${isActive ? "bg-primary" : "bg-white"} group rounded-full p-2 drop-shadow-lg hover:bg-primary`}
>
<div onClick={() => setIsActive(!isActive)}>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.8}
stroke="currentColor"
className={`${isActive ? "text-white" : "text-primary"} h-6 w-6 group-hover:text-white`}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0"
/>
</svg>
{notifications.length > 0 && (
<span className=" absolute -right-px -top-px flex h-3 w-3 items-center justify-center rounded-full bg-red-700 " />
)}
</div>
</Menu.Button>

<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0"
/>
</svg>
{notificationsCount > 0 && (
<span className=" absolute -right-px -top-px flex h-3 w-3 items-center justify-center rounded-full bg-red-700 " />
)}
</div>
<Menu.Items className="absolute right-0 mt-2 box-content h-72 w-96 origin-top-right divide-y divide-gray-100 rounded-md bg-white px-4 shadow-lg ring-1 ring-black/5 focus:outline-none">
<Menu.Item>
{({ close }) => (
<div className="mt-3 flex flex-row items-center justify-between">
<div className="flex flex-row gap-1">
<p className="text-md font-bold text-black">Notifications</p>
<p className="">({notifications.length})</p>
</div>
<CloseIcon size="h-6 w-6" closeFunction={close} />
</div>
)}
</Menu.Item>
{notifications.length > 0 &&
notifications.map((notification, index) => {
return (
<div
key={notification.id}
className="w-full cursor-pointer py-1"
onClick={() => handleClickNotification(index)}
>
<Menu.Item>
{({ active }) => (
<button
className={`${active ? "bg-gray-200" : ""} flex w-full items-center rounded-t-md border-b-2 border-gray-200 p-2`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className=" h-12 w-12 text-primary"
>
<path
fillRule="evenodd"
d="M4.848 2.771A49.144 49.144 0 0 1 12 2.25c2.43 0 4.817.178 7.152.52 1.978.292 3.348 2.024 3.348 3.97v6.02c0 1.946-1.37 3.678-3.348 3.97a48.901 48.901 0 0 1-3.476.383.39.39 0 0 0-.297.17l-2.755 4.133a.75.75 0 0 1-1.248 0l-2.755-4.133a.39.39 0 0 0-.297-.17 48.9 48.9 0 0 1-3.476-.384c-1.978-.29-3.348-2.024-3.348-3.97V6.741c0-1.946 1.37-3.68 3.348-3.97ZM6.75 8.25a.75.75 0 0 1 .75-.75h9a.75.75 0 0 1 0 1.5h-9a.75.75 0 0 1-.75-.75Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H7.5Z"
clipRule="evenodd"
/>
</svg>
<div className="ms-4 flex w-full flex-col justify-start">
<p className="text-md text-start font-bold">
{notification.type}
</p>
<p className="text-start text-xs">
You have a pending survery.
<strong> Click here </strong>
and answer your
<strong> {notification.type} </strong>
survey{" "}
</p>
</div>
</button>
)}
</Menu.Item>
</div>
);
})}
{notifications.length === 0 && (
<div className="flex h-5/6 w-full items-center justify-center py-1">
<Menu.Item>
<p className="items-center py-2 text-sm">
No tienes ninguna notificación
</p>
</Menu.Item>
</div>
)}
</Menu.Items>
</Transition>
</Menu>
);
};

Expand Down
2 changes: 1 addition & 1 deletion components/UserProfileButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const UserProfileButton = ({
const isActive = false;
return (
<button
className={`${className} ${isActive ? "bg-primary" : "bg-white"} group rounded-full p-2 drop-shadow-lg hover:bg-primary`}
className={`${className} ${isActive ? "bg-primary" : "bg-white"} group rounded-full p-2 drop-shadow-lg`}
>
{photoUrl ? (
<Image
Expand Down
23 changes: 23 additions & 0 deletions components/icons/CloseIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
interface CloseIconInterface {
size: string;
closeFunction: () => void;
}
const CloseIcon = ({ size, closeFunction }: CloseIconInterface) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className={size}
onClick={closeFunction}
>
<path
fillRule="evenodd"
d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z"
clipRule="evenodd"
/>
</svg>
);
};

export default CloseIcon;
31 changes: 31 additions & 0 deletions components/icons/DashboardIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Link from "next/link";

interface DashboardIconInterface {
path: string;
currentPath: string;
}
const DashboardIcon = ({ path, currentPath }: DashboardIconInterface) => {
const isActive = currentPath === path;
return (
<Link
href={path}
className={`${isActive ? "bg-primary" : "bg-white transition-all delay-0 hover:scale-[1.175]"} group rounded-full p-2 drop-shadow-lg`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={`${isActive ? "text-white" : "text-primary"} h-6 w-6`}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z"
/>
</svg>
</Link>
);
};
export default DashboardIcon;
32 changes: 32 additions & 0 deletions components/icons/PIPIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Link from "next/link";

interface PIPIconInterface {
path: string;
currentPath: string;
}
const PIPIcon = ({ path, currentPath }: PIPIconInterface) => {
const isActive = currentPath === path;
return (
<Link
href={path}
className={`${isActive ? "bg-primary" : "bg-white transition-all delay-0 hover:scale-[1.175]"} group rounded-full p-2 drop-shadow-lg`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={`${isActive ? "text-white" : "text-primary"} h-6 w-6`}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z"
/>
</svg>
</Link>
);
};

export default PIPIcon;
117 changes: 117 additions & 0 deletions components/icons/UserIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"use client";
import { Menu, Transition } from "@headlessui/react";
import Link from "next/link";
import { Fragment, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useClerk } from "@clerk/nextjs";

interface UserIconInterface {
path: string;
currentPath: string;
}
const UserIcon = ({ path, currentPath }: UserIconInterface) => {
const onSite = currentPath === path;
const [isClicked, setIsClicked] = useState<boolean>(false);
const { signOut } = useClerk();
const router = useRouter();
const handleSignOut = () => {
signOut(() => router.push("/sign-in"));
};

useEffect(() => {
const onCLickOutsideButton = (e: MouseEvent) => {
if (!(e.target as HTMLElement).closest(".group")) {
setIsClicked(false);
}
};
document.addEventListener("click", onCLickOutsideButton);
return () => document.removeEventListener("click", onCLickOutsideButton);
}, []);

return (
<Menu as="div" className="relative inline-block text-left">
<Menu.Button
onClick={() => setIsClicked(!isClicked)}
className={`${onSite || isClicked ? "bg-primary" : "bg-white transition-all delay-0 hover:scale-[1.175]"} group rounded-full p-2 drop-shadow-lg`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={`${onSite || isClicked ? "text-white" : "text-primary"} h-6 w-6 `}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
/>
</svg>
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 mt-2 w-56 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black/5 focus:outline-none">
<div className="px-1 py-1 ">
<Menu.Item>
<p className="mx-auto items-center px-2 py-2 text-sm">
Hola José Carlos!
</p>
</Menu.Item>
</div>
<div className="flex flex-col gap-1 px-1 py-1">
<Menu.Item disabled={onSite}>
{({ active }) => (
<Link
href="/profile"
className={`${
active
? "bg-primary/75 text-white"
: onSite
? "bg-primary text-white"
: "text-gray-900"
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
Ir a perfil
</Link>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<button
className={`${
active ? "bg-primary/75 text-white" : "text-gray-900"
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
Cambiar tema
</button>
)}
</Menu.Item>
</div>
<div className="px-1 py-1" onClick={handleSignOut}>
{" "}
<Menu.Item>
{({ active }) => (
<button
className={`${
active ? "bg-red-700 text-white" : "text-gray-900"
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
Cerrar sesión
</button>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
);
};
export default UserIcon;

0 comments on commit 91628ff

Please sign in to comment.