From b63ba3f31640c55abf0a03528d0c8513fedccd5c Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Tue, 13 Feb 2024 17:29:55 +0000 Subject: [PATCH] Added a badge with the amount of pending tickets assigned to the user --- src/components/High/Layout.tsx | 1 + src/components/Sidebar.tsx | 14 +++++++++++++- src/hooks/useTickets.tsx | 8 ++++---- src/hooks/useTicketsListener.tsx | 29 +++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/hooks/useTicketsListener.tsx diff --git a/src/components/High/Layout.tsx b/src/components/High/Layout.tsx index 9feadad1..79eb2d2a 100644 --- a/src/components/High/Layout.tsx +++ b/src/components/High/Layout.tsx @@ -34,6 +34,7 @@ export default function Layout({user, children, className, navDisabled = false, onFocusLayerMouseEnter={onFocusLayerMouseEnter} className="-md:hidden" userType={user.type} + userId={user.id} />
void; className?: string; userType?: Type; + userId?: string; } interface NavProps { @@ -40,6 +42,7 @@ interface NavProps { keyPath: string; disabled?: boolean; isMinimized?: boolean; + badge?: number; } const Nav = ({ @@ -49,7 +52,10 @@ const Nav = ({ keyPath, disabled = false, isMinimized = false, -}: NavProps) => ( + badge, +}: NavProps) => { + const displayBadge = badge && badge > 0 ? true : false; + return ( {!isMinimized && {label}} + {displayBadge &&
{badge}
} ); + } export default function Sidebar({ path, @@ -74,6 +82,7 @@ export default function Sidebar({ userType, onFocusLayerMouseEnter, className, + userId, }: Props) { const router = useRouter(); @@ -82,6 +91,8 @@ export default function Sidebar({ state.toggleSidebarMinimized, ]); + const {totalAssignedTickets } = useTicketsListener(userId); + const logout = async () => { axios.post("/api/logout").finally(() => { setTimeout(() => router.reload(), 500); @@ -177,6 +188,7 @@ export default function Sidebar({ path={path} keyPath="/tickets" isMinimized={isMinimized} + badge={totalAssignedTickets} /> )} {userType === "developer" && ( diff --git a/src/hooks/useTickets.tsx b/src/hooks/useTickets.tsx index c90fd639..9a5ba240 100644 --- a/src/hooks/useTickets.tsx +++ b/src/hooks/useTickets.tsx @@ -1,22 +1,22 @@ import { Ticket } from "@/interfaces/ticket"; import { Code, Group, User } from "@/interfaces/user"; import axios from "axios"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useCallback } from "react"; export default function useTickets() { const [tickets, setTickets] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isError, setIsError] = useState(false); - const getData = () => { + const getData = useCallback(() => { setIsLoading(true); axios .get(`/api/tickets`) .then((response) => setTickets(response.data)) .finally(() => setIsLoading(false)); - }; + }, []); - useEffect(getData, []); + useEffect(getData, [getData]); return { tickets, isLoading, isError, reload: getData }; } diff --git a/src/hooks/useTicketsListener.tsx b/src/hooks/useTicketsListener.tsx new file mode 100644 index 00000000..520ee947 --- /dev/null +++ b/src/hooks/useTicketsListener.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import useTickets from "./useTickets"; + +const useTicketsListener = (userId?: string) => { + const { tickets, reload } = useTickets(); + + React.useEffect(() => { + const intervalId = setInterval(() => { + reload(); + }, 60 * 1000); + + return () => clearInterval(intervalId); + }, [reload]); + + if (userId) { + const assignedTickets = tickets.filter( + (ticket) => ticket.assignedTo === userId && ticket.status === "submitted" + ); + + return { + assignedTickets, + totalAssignedTickets: assignedTickets.length, + }; + } + + return {}; +}; + +export default useTicketsListener;