From 48764d6370954ae6013f70f1f4850a8b075c4e49 Mon Sep 17 00:00:00 2001
From: Sean Hatfield <seanhatfield5@gmail.com>
Date: Tue, 5 Dec 2023 15:58:57 -0800
Subject: [PATCH] Gear icon appear on hover for workspace (#410)

* gear icon appear on hover for workspace

* put back user role check for default

* wrap in callback

---------

Co-authored-by: timothycarambat <rambat1010@gmail.com>
---
 .../Sidebar/ActiveWorkspaces/index.jsx        | 39 +++++++++++++++----
 .../ChatContainer/ChatHistory/index.jsx       |  2 +-
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx b/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx
index 4e423a6dd..fe14bf9f2 100644
--- a/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx
+++ b/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { useState, useEffect, useCallback } from "react";
 import * as Skeleton from "react-loading-skeleton";
 import "react-loading-skeleton/dist/skeleton.css";
 import Workspace from "../../../models/workspace";
@@ -14,9 +14,10 @@ import useUser from "../../../hooks/useUser";
 export default function ActiveWorkspaces() {
   const { slug } = useParams();
   const [loading, setLoading] = useState(true);
-  const [settingHover, setSettingHover] = useState(false);
+  const [settingHover, setSettingHover] = useState({});
   const [workspaces, setWorkspaces] = useState([]);
   const [selectedWs, setSelectedWs] = useState(null);
+  const [hoverStates, setHoverStates] = useState({});
   const { showing, showModal, hideModal } = useManageWorkspaceModal();
   const { user } = useUser();
 
@@ -29,6 +30,22 @@ export default function ActiveWorkspaces() {
     getWorkspaces();
   }, []);
 
+  const handleMouseEnter = useCallback((workspaceId) => {
+    setHoverStates((prev) => ({ ...prev, [workspaceId]: true }));
+  }, []);
+
+  const handleMouseLeave = useCallback((workspaceId) => {
+    setHoverStates((prev) => ({ ...prev, [workspaceId]: false }));
+  }, []);
+
+  const handleGearMouseEnter = useCallback((workspaceId) => {
+    setSettingHover((prev) => ({ ...prev, [workspaceId]: true }));
+  }, []);
+
+  const handleGearMouseLeave = useCallback((workspaceId) => {
+    setSettingHover((prev) => ({ ...prev, [workspaceId]: false }));
+  }, []);
+
   if (loading) {
     return (
       <>
@@ -48,10 +65,14 @@ export default function ActiveWorkspaces() {
     <>
       {workspaces.map((workspace) => {
         const isActive = workspace.slug === slug;
+        const isHovered = hoverStates[workspace.id];
+        const isGearHovered = settingHover[workspace.id];
         return (
           <div
             key={workspace.id}
             className="flex gap-x-2 items-center justify-between"
+            onMouseEnter={() => handleMouseEnter(workspace.id)}
+            onMouseLeave={() => handleMouseLeave(workspace.id)}
           >
             <a
               href={isActive ? null : paths.workspace.chat(workspace.slug)}
@@ -82,17 +103,21 @@ export default function ActiveWorkspaces() {
                   </p>
                 </div>
                 <button
-                  onMouseEnter={() => setSettingHover(true)}
-                  onMouseLeave={() => setSettingHover(false)}
-                  onClick={() => {
+                  type="button"
+                  onClick={(e) => {
+                    e.preventDefault();
                     setSelectedWs(workspace);
                     showModal();
                   }}
+                  onMouseEnter={() => handleGearMouseEnter(workspace.id)}
+                  onMouseLeave={() => handleGearMouseLeave(workspace.id)}
                   className="rounded-md flex items-center justify-center text-white ml-auto"
                 >
                   <GearSix
-                    weight={settingHover ? "fill" : "regular"}
-                    hidden={!isActive || user?.role === "default"}
+                    weight={isGearHovered ? "fill" : "regular"}
+                    hidden={
+                      (!isActive && !isHovered) || user?.role === "default"
+                    }
                     className="h-[20px] w-[20px] transition-all duration-300"
                   />
                 </button>
diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx
index 036bb0389..1de2504b7 100644
--- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx
+++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx
@@ -26,7 +26,7 @@ export default function ChatHistory({ history = [], workspace }) {
   const debouncedScroll = debounce(handleScroll, 100);
 
   useEffect(() => {
-    if(!chatHistoryRef.current) return null;
+    if (!chatHistoryRef.current) return null;
     const chatHistoryElement = chatHistoryRef.current;
     chatHistoryElement.addEventListener("scroll", debouncedScroll);
 
-- 
GitLab