Repository: bluewave-labs/verifywise
Pull request #1202: joyride pt2
Author: login: salmanja
Created: 2025-04-16T19:12:06Z | Merged: 2025-04-29T16:31:21Z

## Describe your changes

-Initialized useMultipleOnScreen in Dashboard.tsx in order to wait for all tour elements (refs) in Home and Sidebar are visible.
-Saved the ref array using setHomeTourRefs so components like Home and Sidebar can assign refs.
-Initialized the refs only once and in the Dashboard page, the page that renders both the Home and Sidebar component.
-Used VWContext for sharing refs and tour state because Dashboard renders Home via <Outlet /> and cannot pass refs and state down as props. 
-Wrapped VWButton in <div> tag because refs have to be assigned to DOM elements not components. Even with forwardRef, Tooltip  or the Button element are interfering with ref forwarding.

## Write your issue number after "Fixes "

Fixes #1174 

## Please ensure all items are checked off before requesting a review:

- [x] I deployed the code locally.
- [x] I have performed a self-review of my code.
- [x] I have included the issue # in the PR.
- [x] I have labelled the PR correctly.
- [x] The issue I am working on is assigned to me.
- [x] I didn't use any hardcoded values (otherwise it will not scale, and will make it difficult to maintain consistency across the application).
- [x] I made sure font sizes, color choices etc are all referenced from the theme.
- [x] My PR is granular and targeted to one specific feature.
- [x] I took a screenshot or a video and attached to this PR if there is a UI change.


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a guided tour on the Home page to help users navigate key features.
  - Added visibility tracking for Home and Sidebar components to trigger the guided tour when both are visible.
  - Enabled control over UI component visibility and home tour activation through new context state.

- **Bug Fixes**
  - Removed an unnecessary attribute from the popup button to improve UI consistency.

- **Improvements**
  - Enhanced button component documentation with explicit prop type declarations.
  - Removed the previous home tour feature from the Dashboard for a streamlined experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #1174: Home Page Joyride
Implement joyride tour in home page 

Diff:
diff --git a/Clients/src/App.tsx b/Clients/src/App.tsx
index 750665c892..46b8f0cde7 100644
--- a/Clients/src/App.tsx
+++ b/Clients/src/App.tsx
@@ -6,7 +6,7 @@ import light from "./presentation/themes/light";
 import dark from "./presentation/themes/dark";
 import { CssBaseline } from "@mui/material";
 import { VerifyWiseContext } from "./application/contexts/VerifyWise.context";
-import { useMemo, useState } from "react";
+import { useCallback, useMemo, useState } from "react";
 import { Provider } from "react-redux";
 import { PersistGate } from "redux-persist/integration/react";
 import { store, persistor } from "./application/redux/store";
@@ -17,10 +17,11 @@ import { CookiesProvider } from "react-cookie";
 import { createRoutes } from "./application/config/routes";
 import { DashboardState } from "./application/interfaces/appStates";
 import { AppState } from "./application/interfaces/appStates";
+import { ComponentVisible } from "./application/interfaces/ComponentVisible";
 
 function App() {
   const mode = useSelector((state: AppState) => state.ui?.mode || "light");
-  const token = useSelector((state: AppState) => state.auth?.authToken);
+  const token = useSelector((state: AppState) => state.auth?.authToken); 
 
   const [uiValues, setUiValues] = useState<unknown | undefined>({});
   const [authValues, setAuthValues] = useState<unknown | undefined>({});
@@ -43,6 +44,18 @@ function App() {
   } = useProjectStatus({ userId });
 
   const [currentProjectId, setCurrentProjectId] = useState<string | null>("");
+const [componentsVisible, setComponentsVisible] = useState<ComponentVisible>({
+  home: false,
+  sidebar: false,
+})
+const changeComponentVisibility = useCallback(
+  (component: keyof ComponentVisible, value: boolean) => {
+    setComponentsVisible((prev) => ({
+      ...prev,
+      [component]: value,
+    }));
+  }, []
+);
 
   const contextValues = useMemo(
     () => ({
@@ -63,6 +76,8 @@ function App() {
       userId,
       projects,
       setProjects,
+      componentsVisible,
+      changeComponentVisibility,
     }),
     [
       uiValues,
@@ -82,6 +97,8 @@ function App() {
       userId,
       projects,
       setProjects,
+      componentsVisible,
+      changeComponentVisibility,
     ]
   );
 
diff --git a/Clients/src/application/contexts/VerifyWise.context.ts b/Clients/src/application/contexts/VerifyWise.context.ts
index f93cb2b738..21fdac42a0 100644
--- a/Clients/src/application/contexts/VerifyWise.context.ts
+++ b/Clients/src/application/contexts/VerifyWise.context.ts
@@ -1,6 +1,7 @@
 import React, { createContext } from "react";
 import { defaultProjectStatus, ProjectStatus } from "../hooks/useProjectStatus";
 import { Project } from "../../domain/Project";
+import { ComponentVisible } from "../../application/interfaces/ComponentVisible";
 
 interface VerifyWiseContextProps {
   uiValues: any;
@@ -20,6 +21,8 @@ interface VerifyWiseContextProps {
   userId: string;
   projects: Project[];
   setProjects: React.Dispatch<React.SetStateAction<Project[]>>;
+  componentsVisible: ComponentVisible;
+  changeComponentVisibility: (component: keyof ComponentVisible, value:boolean) => void;
 }
 
 const VerifyWiseContext = createContext<VerifyWiseContextProps>({
@@ -40,6 +43,8 @@ const VerifyWiseContext = createContext<VerifyWiseContextProps>({
   userId: "",
   projects: [],
   setProjects: () => {},
+  componentsVisible: {home:false, sidebar:false},
+  changeComponentVisibility: () => {},
 });
 
 export { VerifyWiseContext };
diff --git a/Clients/src/application/interfaces/ComponentVisible.ts b/Clients/src/application/interfaces/ComponentVisible.ts
new file mode 100644
index 0000000000..97c59b9657
--- /dev/null
+++ b/Clients/src/application/interfaces/ComponentVisible.ts
@@ -0,0 +1,4 @@
+export interface ComponentVisible {
+  home: boolean;
+  sidebar: boolean;
+}
diff --git a/Clients/src/presentation/components/Popup/index.tsx b/Clients/src/presentation/components/Popup/index.tsx
index 7826e8dba6..8e3ef34b95 100644
--- a/Clients/src/presentation/components/Popup/index.tsx
+++ b/Clients/src/presentation/components/Popup/index.tsx
@@ -84,7 +84,6 @@ const Popup: FC<PopupProps> = ({
         onClick={handleOpenOrClose}
         sx={styles.openPopupButton}
         disableRipple={theme.components?.MuiButton?.defaultProps?.disableRipple}
-        data-joyride-id="new-project-button"
       >
         {openPopupButtonName}
       </Button>
diff --git a/Clients/src/presentation/components/Sidebar/index.tsx b/Clients/src/presentation/components/Sidebar/index.tsx
index c2b2f9f4b9..086c7c8632 100644
--- a/Clients/src/presentation/components/Sidebar/index.tsx
+++ b/Clients/src/presentation/components/Sidebar/index.tsx
@@ -44,6 +44,7 @@ import { Link as MuiLink } from "@mui/material";
 import { User } from "../../../application/hooks/useUsers";
 import { ROLES } from "../../../application/constants/roles";
 import useLogout from "../../../application/hooks/useLogout";
+import useMultipleOnScreen from "../../../application/hooks/useMultipleOnScreen";
 import ReadyToSubscribeBox from "../ReadyToSubscribeBox/ReadyToSubscribeBox";
 
 const menu = [
@@ -112,10 +113,14 @@ const Sidebar = ({ projects }: { projects: any }) => {
   const [selectedProjectId, setSelectedProjectId] = useState("");
   const logout = useLogout();
 
-  const { dashboardValues, setDashboardValues, setCurrentProjectId, userId } =
+  const { dashboardValues, setDashboardValues, setCurrentProjectId, userId, changeComponentVisibility} =
     useContext(VerifyWiseContext);
   const { users } = dashboardValues;
 
+const { refs, allVisible } = useMultipleOnScreen<HTMLElement>({
+  countToTrigger: 1,
+});
+
   const user: User = users
     ? users.find((user: User) => user.id === userId)
     : DEFAULT_USER;
@@ -163,6 +168,12 @@ const Sidebar = ({ projects }: { projects: any }) => {
     }
   };
 
+useEffect(() => {
+  if (allVisible) {
+   changeComponentVisibility("sidebar", true);
+  }
+}, [allVisible]);
+
   useEffect(() => {
     if (projects.length === 0) {
       setSelectedProjectId("");
@@ -277,6 +288,7 @@ const Sidebar = ({ projects }: { projects: any }) => {
             width: "fit-content",
           }}
           data-joyride-id="select-project"
+          ref={refs[0]}
         >
           {projects.length > 0 ? (
             <Select
@@ -312,6 +324,7 @@ const Sidebar = ({ projects }: { projects: any }) => {
         disablePadding
         sx={{ px: theme.spacing(8) }}
         data-joyride-id="dashboard-navigation"
+        ref={refs[1]}
       >
         {/* Items of the menu */}
         {menu.map((item) =>
diff --git a/Clients/src/presentation/containers/Dashboard/index.tsx b/Clients/src/presentation/containers/Dashboard/index.tsx
index 629c0ee7cc..e9e3293d81 100644
--- a/Clients/src/presentation/containers/Dashboard/index.tsx
+++ b/Clients/src/presentation/containers/Dashboard/index.tsx
@@ -2,14 +2,12 @@ import { Stack } from "@mui/material";
 import "./index.css";
 import Sidebar from "../../components/Sidebar";
 import { Outlet, useLocation } from "react-router";
-import { useContext, useEffect, useState, FC } from "react";
+import { useContext, useEffect, FC } from "react";
 import { VerifyWiseContext } from "../../../application/contexts/VerifyWise.context";
 import {
   getEntityById,
   getAllEntities,
 } from "../../../application/repository/entity.repository";
-import PageTour from "../../components/PageTour";
-import CustomStep from "../../components/PageTour/CustomStep";
 import DemoAppBanner from "../../components/DemoBanner/DemoAppBanner";
 
 interface DashboardProps {
@@ -17,41 +15,13 @@ interface DashboardProps {
 }
 
 const Dashboard: FC<DashboardProps> = ({ reloadTrigger }) => {
-  const { token, setDashboardValues, projects, setProjects } =
-    useContext(VerifyWiseContext);
+  const {
+    token,
+    setDashboardValues,
+    projects,
+    setProjects,
+  } = useContext(VerifyWiseContext);
   const location = useLocation();
-  const [runHomeTour, setRunHomeTour] = useState(false);
-  //joyride steps
-  const homeSteps = [
-    // Sidebar steps
-    {
-      target: '[data-joyride-id="new-project-button"]',
-      content: (
-        <CustomStep
-          header="Create your first project"
-          body="Each project corresponds to an AI activity in your company."
-        />
-      ),
-    },
-    {
-      target: '[data-joyride-id="select-project"]',
-      content: (
-        <CustomStep
-          header="Select a project"
-          body="Once created, you can select it here."
-        />
-      ),
-    },
-    {
-      target: '[data-joyride-id="dashboard-navigation"]',
-      content: (
-        <CustomStep
-          header="Fill in compliance,assessments, risks and vendors"
-          body="Each project has its own set of questions and documents where you can fill in here."
-        />
-      ),
-    },
-  ];
 
   useEffect(() => {
     const fetchProjects = async () => {
@@ -84,24 +54,6 @@ const Dashboard: FC<DashboardProps> = ({ reloadTrigger }) => {
 
     fetchProjects();
     fetchUsers();
-
-    //check if required DOM elements are ready
-    const checkTourElements = () => {
-      const newProjectButton = document.querySelector(
-        '[data-joyride-id="new-project-button"]'
-      );
-      const dashboardNav = document.querySelector(
-        '[data-joyride-id="dashboard-navigation"]'
-      );
-
-      if (location.pathname === "/" && newProjectButton && dashboardNav) {
-        setRunHomeTour(true);
-      } else {
-        setRunHomeTour(false);
-      }
-    };
-    const timeout = setTimeout(checkTourElements, 1000);
-    return () => clearTimeout(timeout);
   }, [setDashboardValues, reloadTrigger, location.pathname]);
 
   const mappedProjects =
@@ -123,16 +75,6 @@ const Dashboard: FC<DashboardProps> = ({ reloadTrigger }) => {
       <Sidebar projects={mappedProjects} />
       <Stack spacing={3}>      
         <DemoAppBanner />                      
-
-        {/* Joyride */}
-        {runHomeTour && (
-          <PageTour
-          steps={homeSteps}
-          run={runHomeTour}
-          onFinish={() => setRunHomeTour(false)}
-          tourKey="home-tour"
-          />
-        )}
         <Outlet />
       </Stack>
     </Stack>
diff --git a/Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx b/Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx
new file mode 100644
index 0000000000..e08730625b
--- /dev/null
+++ b/Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx
@@ -0,0 +1,34 @@
+import { PageTourStep } from "../../../components/PageTour";
+import CustomStep from "../../../components/PageTour/CustomStep";
+
+const HomeSteps: PageTourStep[] = [
+ {
+       target: '[data-joyride-id="new-project-button"]',
+       content: (
+         <CustomStep
+           header="Create your first project"
+           body="Each project corresponds to an AI activity in your company."
+         />
+       ),
+     },
+     {
+       target: '[data-joyride-id="select-project"]',
+       content: (
+         <CustomStep
+           header="Select a project"
+           body="Once created, you can select it here."
+         />
+       ),
+     },
+     {
+       target: '[data-joyride-id="dashboard-navigation"]',
+       content: (
+         <CustomStep
+           header="Fill in compliance,assessments, risks and vendors"
+           body="Each project has its own set of questions and documents where you can fill in here."
+         />
+       ),
+     },
+];
+
+export default HomeSteps;
diff --git a/Clients/src/presentation/pages/Home/1.0Home/index.tsx b/Clients/src/presentation/pages/Home/1.0Home/index.tsx
index ee1f25c410..156689ff46 100644
--- a/Clients/src/presentation/pages/Home/1.0Home/index.tsx
+++ b/Clients/src/presentation/pages/Home/1.0Home/index.tsx
@@ -30,10 +30,16 @@ import {
 import { useProjectData } from "../../../../application/hooks/useFetchProjects";
 import { AlertState } from "../../../../application/interfaces/appStates";
 import { fetchData } from "../../../../application/hooks/fetchDataHook";
-
+import PageTour from "../../../components/PageTour";
+import HomeSteps from "./HomeSteps";
+import useMultipleOnScreen from "../../../../application/hooks/useMultipleOnScreen";
+        
 const VWHome = () => {
-  const { setDashboardValues } = useContext(VerifyWiseContext);
-
+  const {
+    setDashboardValues,
+    componentsVisible,
+    changeComponentVisibility
+  } = useContext(VerifyWiseContext);
   const [complianceProgressData, setComplianceProgressData] =
     useState<ComplianceProgress>();
   const [assessmentProgressData, setAssessmentProgressData] =
@@ -48,6 +54,22 @@ const VWHome = () => {
 
   const { projects, loading: projectLoading, fetchProjects } = useProjectData();
 
+   const [runHomeTour, setRunHomeTour] = useState(false);
+  const { refs, allVisible } = useMultipleOnScreen<HTMLElement>({
+    countToTrigger: 1,
+  });
+  useEffect(() => {
+    if (allVisible) {
+      changeComponentVisibility("home", true);
+    }
+  }, [allVisible]);
+
+  useEffect(() => {
+    if (componentsVisible.home && componentsVisible.sidebar) {
+      setRunHomeTour(true);
+    }
+  }, [componentsVisible]);
+
   useEffect(() => {
     const fetchProgressData = async () => {
       await fetchData("/users", (data) => {
@@ -207,18 +229,19 @@ const VWHome = () => {
                 onClick={() => handleGenerateDemoDataClick()}
               />
             )}
-
-            <VWButton
-              variant="contained"
-              text="New project"
-              sx={{
-                backgroundColor: "#13715B",
-                border: "1px solid #13715B",
-                gap: 2,
-              }}
-              icon={<AddCircleOutlineIcon />}
-              onClick={() => setIsProjectFormModalOpen(true)}
-            />
+            <div data-joyride-id="new-project-button" ref={refs[0]}>
+              <VWButton
+                variant="contained"
+                text="New project"
+                sx={{
+                  backgroundColor: "#13715B",
+                  border: "1px solid #13715B",
+                  gap: 2,
+                }}
+                icon={<AddCircleOutlineIcon />}
+                onClick={() => setIsProjectFormModalOpen(true)}
+              />
+            </div>
           </Stack>
         </Stack>
         <Stack className="vwhome-body-projects" sx={vwhomeBodyProjects}>
@@ -266,6 +289,14 @@ const VWHome = () => {
           <VWProjectForm onClose={handleProjectFormModalClose} />
         </Box>
       </Modal>
+      <PageTour
+        steps={HomeSteps}
+        run={runHomeTour}
+        onFinish={() => {
+          setRunHomeTour(false);
+        }}
+        tourKey="home-tour"
+      />
     </Stack>
   );
 };
diff --git a/Clients/src/presentation/vw-v2-components/Buttons/index.tsx b/Clients/src/presentation/vw-v2-components/Buttons/index.tsx
index ee050702a5..aa69ee2119 100644
--- a/Clients/src/presentation/vw-v2-components/Buttons/index.tsx
+++ b/Clients/src/presentation/vw-v2-components/Buttons/index.tsx
@@ -32,7 +32,6 @@
 import { Button } from "@mui/material";
 import PropTypes from "prop-types";
 import { ButtonProps } from "@mui/material/Button";
-
 import singleTheme from "../../themes/v1SingleTheme";
 
 interface VWButtonProps {
@@ -47,35 +46,38 @@ interface VWButtonProps {
   icon?: any;
 }
 
-const VWButton: React.FC<VWButtonProps> = ({
-  variant = "contained",
-  size = "medium",
-  isDisabled = false,
-  isLink = false,
-  color = "primary",
-  onClick,
-  sx,
-  text = "VWButton",
-  icon,
-}) => {
-  const appearance = singleTheme.buttons[color][variant];
+const VWButton: React.FC< VWButtonProps> = (
+  (
+    {
+      variant = "contained",
+      size = "medium",
+      isDisabled = false,
+      isLink = false,
+      color = "primary",
+      onClick,
+      sx,
+      text = "VWButton",
+      icon,
+    }) => {
+    const appearance = singleTheme.buttons[color][variant];
 
-  return (
-    <Button
-      disableRipple
-      variant={variant as ButtonProps["variant"]}
-      size={size as ButtonProps["size"]}
-      disabled={isDisabled}
-      color={color as ButtonProps["color"]}
-      onClick={onClick}
-      sx={{ ...appearance, ...sx }}
-      disableElevation={variant === "contained" && !isLink}
-    >
-      {icon}
-      {text}
-    </Button>
-  );
-};
+    return (
+      <Button
+        disableRipple
+        variant={variant as ButtonProps["variant"]}
+        size={size as ButtonProps["size"]}
+        disabled={isDisabled}
+        color={color as ButtonProps["color"]}
+        onClick={onClick}
+        sx={{ ...appearance, ...sx }}
+        disableElevation={variant === "contained" && !isLink}
+      >
+        {icon}
+        {text}
+      </Button>
+    );
+  }
+);
 
 VWButton.propTypes = {
   variant: PropTypes.oneOf(["contained", "outlined", "text"]),
@@ -92,6 +94,8 @@ VWButton.propTypes = {
   ]),
   onClick: PropTypes.func,
   sx: PropTypes.object,
+  text: PropTypes.string,
+  icon: PropTypes.node,
 };
 
-export default VWButton;
+export default VWButton;
\ No newline at end of file


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>Clients/src/presentation/vw-v2-components/Buttons/index.tsx (1)</summary><blockquote>

`49-80`: **Simplify function declaration structure.**

The nested arrow function with double parentheses is unconventional and potentially confusing.


Consider using a more standard pattern:

```diff
-const VWButton: React.FC< VWButtonProps> = (
-  (
-    {
-      variant = "contained",
-      size = "medium",
-      isDisabled = false,
-      isLink = false,
-      color = "primary",
-      onClick,
-      sx,
-      text = "VWButton",
-      icon,
-    }) => {
+const VWButton: React.FC<VWButtonProps> = ({
+  variant = "contained",
+  size = "medium",
+  isDisabled = false,
+  isLink = false,
+  color = "primary",
+  onClick,
+  sx,
+  text = "VWButton",
+  icon,
+}) => {
```

</blockquote></details>
<details>
<summary>Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx (1)</summary><blockquote>

`27-27`: **Minor formatting issue.**

There's a missing space after the comma in "compliance,assessments".


```diff
-          header="Fill in compliance,assessments, risks and vendors"
+          header="Fill in compliance, assessments, risks and vendors"
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 79d36bbb1b3e7a3c17bf658baa4646d5c2fdb89e and b8e5b0a5135028d0dd99d40fe167db69038b13b1.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `Clients/src/App.tsx` (5 hunks)
* `Clients/src/application/contexts/VerifyWise.context.ts` (3 hunks)
* `Clients/src/application/interfaces/ComponentVisible.ts` (1 hunks)
* `Clients/src/presentation/components/Popup/index.tsx` (0 hunks)
* `Clients/src/presentation/components/Sidebar/index.tsx` (5 hunks)
* `Clients/src/presentation/containers/Dashboard/index.tsx` (1 hunks)
* `Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx` (1 hunks)
* `Clients/src/presentation/pages/Home/1.0Home/index.tsx` (4 hunks)
* `Clients/src/presentation/vw-v2-components/Buttons/index.tsx` (2 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* Clients/src/presentation/components/Popup/index.tsx

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (3)</summary>

<details>
<summary>Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx (1)</summary><blockquote>

<details>
<summary>Clients/src/presentation/components/PageTour/index.tsx (1)</summary>

* `PageTourStep` (11-15)

</details>

</blockquote></details>
<details>
<summary>Clients/src/application/contexts/VerifyWise.context.ts (1)</summary><blockquote>

<details>
<summary>Clients/src/application/interfaces/ComponentVisible.ts (1)</summary>

* `ComponentVisible` (1-4)

</details>

</blockquote></details>
<details>
<summary>Clients/src/App.tsx (1)</summary><blockquote>

<details>
<summary>Clients/src/application/interfaces/ComponentVisible.ts (1)</summary>

* `ComponentVisible` (1-4)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (22)</summary><blockquote>

<details>
<summary>Clients/src/application/interfaces/ComponentVisible.ts (1)</summary>

`1-4`: **Clean interface definition!**

The interface is concise, well-named, and clearly captures the visibility state needed for the tour functionality.

</details>
<details>
<summary>Clients/src/presentation/vw-v2-components/Buttons/index.tsx (1)</summary>

`97-98`: **Good addition of PropTypes!**

The explicit PropTypes for text and icon improve component documentation and type validation.

</details>
<details>
<summary>Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx (1)</summary>

`1-34`: **Well-structured tour steps definition!**

The tour steps are clearly defined with appropriate targets and content.

</details>
<details>
<summary>Clients/src/presentation/components/Sidebar/index.tsx (2)</summary>

`119-121`: **Good implementation of visibility tracking!**

Using the `useMultipleOnScreen` hook to track visibility of key sidebar elements is a clean approach.

---

`293-293`: **Good ref forwarding to track tour-relevant elements!**

The refs are correctly assigned to the elements that need to be tracked for the tour functionality.



Also applies to: 329-329

</details>
<details>
<summary>Clients/src/presentation/containers/Dashboard/index.tsx (2)</summary>

`5-5`: **Imports streamlined to match current component needs**

The import statement has been updated to remove PageTour-related imports that are no longer needed in this component, since the tour functionality has been moved elsewhere.

---

`17-22`: **Context usage simplified after tour functionality extraction**

The destructured context values have been reduced to only those that are still needed in this component. The removal of tour-related state aligns with the PR objective of centralizing the tour functionality and state management.

</details>
<details>
<summary>Clients/src/presentation/pages/Home/1.0Home/index.tsx (6)</summary>

`26-28`: **Tour-related imports added to Home component**

These imports support the tour functionality that was moved from Dashboard into the Home component, aligning with the PR objectives to improve the tour implementation.

---

`31-37`: **Context state for tour functionality integrated**

The Home component now properly consumes the tour-related context values that were added to the VerifyWiseContext. This enables the component to control tour execution and visibility states.

---

`51-61`: **Visibility tracking logic implemented with custom hook**

The `useMultipleOnScreen` hook is used to detect when tour elements become visible, updating the component visibility state in the shared context. This implementation follows the PR objective of ensuring elements are visible before proceeding with the tour.

---

`63-67`: **Tour trigger logic based on component visibility**

This effect properly triggers the home tour when both the home and sidebar components are visible, addressing the requirement to ensure all tour elements are on screen before starting the tour.

---

`258-270`: **Button wrapped in div for proper ref assignment**

The VWButton component is now wrapped in a div with a ref assignment and data-joyride-id, making it properly targetable for the tour. This matches the stated PR objective of enabling ref assignment to DOM elements when components like buttons may interfere with ref forwarding.

---

`351-358`: **Tour component added with proper configuration**

The PageTour component is correctly configured with the imported steps, controlled by the runHomeTour state, and includes proper cleanup on finish. This completes the implementation of the tour functionality in the Home component.

</details>
<details>
<summary>Clients/src/App.tsx (6)</summary>

`9-9`: **Import updated to include useCallback**

The additional hook is needed for the new component visibility change function.

---

`20-20`: **ComponentVisible interface imported**

Good practice to use a proper typed interface for the component visibility state.

---

`48-52`: **Tour state and component visibility state added**

These state variables provide centralized management for the tour functionality and component visibility tracking, which is key to the PR objectives. The initial state correctly sets both components as not visible.

---

`53-60`: **Component visibility updater callback implemented**

Using useCallback for the visibility change function is appropriate as it will be passed down through context. The function is well-designed to handle updates for any component type in the ComponentVisible interface.

---

`81-85`: **New state and functions added to context values**

The tour state, visibility state, and updater functions are properly included in the context values, making them accessible to all components that need them.

---

`105-109`: **Dependency array updated to include new state and functions**

The useMemo dependency array is properly updated to include all the new values, ensuring the context is recalculated when any of these dependencies change.

</details>
<details>
<summary>Clients/src/application/contexts/VerifyWise.context.ts (3)</summary>

`4-4`: **ComponentVisible interface imported**

The import ensures proper typing for the component visibility state in the context.

---

`24-28`: **Context interface extended with tour-related properties**

The VerifyWiseContextProps interface properly defines the types for the new tour state, visibility state, and updater functions. Using React.Dispatch with the appropriate state type for setters is good practice.

---

`49-53`: **Default context values provided for new properties**

The default context object is properly updated with initial values for the new properties, matching their types in the interface.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-22T18:23:09Z
user: login: samuel-coutinho
body: There are a few small changes to make and we should be good.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T16:48:16Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T16:48:53Z
user: login: samuel-coutinho
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T17:15:09Z
user: login: salmanja
body: reviewed changes
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-26T01:19:45Z
user: login: samuel-coutinho
body: LGTM, thanks @salmanja 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T16:31:09Z

Review comments:
diff_hunk: @@ -162,6 +167,15 @@ const Sidebar = ({ projects }: { projects: any }) => {
     }
   };
 
+useEffect(() => {
+  if (allVisible) {
+    setComponentsVisible((prev) => ({
+      ...prev,
+      sidebar: true,
+    }));
+  }
+}, [allVisible]);
path: Clients/src/presentation/components/Sidebar/index.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Consider handling visibility changes in both directions.**

The current implementation updates the context when elements become visible, but doesn't handle the case where they become invisible again.


```diff
useEffect(() => {
-  if (allVisible) {
-    setComponentsVisible((prev) => ({
-      ...prev,
-      sidebar: true,
-    }));
-  }
+  setComponentsVisible((prev) => ({
+    ...prev,
+    sidebar: allVisible,
+  }));
}, [allVisible, setComponentsVisible]);
```

This ensures the sidebar state accurately reflects the current visibility and includes the setter function in the dependency array.


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
useEffect(() => {
  setComponentsVisible((prev) => ({
    ...prev,
    sidebar: allVisible,
  }));
}, [allVisible, setComponentsVisible]);
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-22T18:23:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -162,6 +167,15 @@ const Sidebar = ({ projects }: { projects: any }) => {
     }
   };
 
+useEffect(() => {
+  if (allVisible) {
+    setComponentsVisible((prev) => ({
+      ...prev,
+      sidebar: true,
+    }));
+  }
+}, [allVisible]);
path: Clients/src/presentation/components/Sidebar/index.tsx
user: login: samuel-coutinho
body: Instead of using `setComponentsVisible` directly here, we could use the function created for this purpose: `changeComponentVisibility`. So, in this case, it would be something like:

```
useEffect(() => {
  if (allvisible) {
    changeComponentVisibility("sideBar", true);
  }
}, [allvisible]);
```
created_at: 2025-04-23T16:40:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,6 +56,24 @@ const VWHome = () => {
 
   const { projects, loading: projectLoading, fetchProjects } = useProjectData();
 
+  const { refs, allVisible } = useMultipleOnScreen<HTMLElement>({
+    countToTrigger: 1,
+  });
+  useEffect(() => {
+    if (allVisible) {
+      setComponentsVisible((prev) => ({
+        ...prev,
+        home: true,
+      }));
+    }
+  }, [allVisible]);
path: Clients/src/presentation/pages/Home/1.0Home/index.tsx
user: login: samuel-coutinho
body: The same idea here:
```
useEffect(() => {
  if (allVisible) {
    changeComponentVisibility("home", true);
  }
}, [allVisible]);

```
created_at: 2025-04-23T16:45:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -162,6 +167,15 @@ const Sidebar = ({ projects }: { projects: any }) => {
     }
   };
 
+useEffect(() => {
+  if (allVisible) {
+    setComponentsVisible((prev) => ({
+      ...prev,
+      sidebar: true,
+    }));
+  }
+}, [allVisible]);
path: Clients/src/presentation/components/Sidebar/index.tsx
user: login: coderabbitai[bot]
body: @samuel-coutinho You're right, using the dedicated `changeComponentVisibility` function would be more appropriate here. However, I notice that it's not currently being destructured from the context in this component. Here's the corrected implementation:

```jsx
// Update the context destructuring
const { dashboardValues, setDashboardValues, setCurrentProjectId, userId, setComponentsVisible, changeComponentVisibility } =
    useContext(VerifyWiseContext);

// Update the useEffect hook
useEffect(() => {
  if (allVisible) {
    changeComponentVisibility("sidebar", true);
  }
}, [allVisible, changeComponentVisibility]);
```

This follows your suggestion while ensuring the property name is lowercase (`sidebar`) and adding the function to the dependency array.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: samuel-coutinho
PR: bluewave-labs/verifywise#1202
File: Clients/src/presentation/components/Sidebar/index.tsx:170-177
Timestamp: 2025-04-23T16:48:51.752Z
Learning: In the VerifyWise application, prefer using the dedicated `changeComponentVisibility` function from VerifyWiseContext when updating component visibility states instead of using `setComponentsVisible` directly, as it was specifically created for this purpose.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>




<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@samuel-coutinho You're right, using the dedicated `changeComponentVisibility` function would be more appropriate here. However, I notice that it's not currently being destructured from the context in this component. Here's the corrected implementation:

```jsx
// Update the context destructuring
const { dashboardValues, setDashboardValues, setCurrentProjectId, userId, setComponentsVisible, changeComponentVisibility } =
    useContext(VerifyWiseContext);

// Update the useEffect hook
useEffect(() => {
  if (allVisible) {
    changeComponentVisibility("sidebar", true);
  }
}, [allVisible, changeComponentVisibility]);
```

This follows your suggestion while ensuring the property name is lowercase (`sidebar`) and adding the function to the dependency array.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: samuel-coutinho
PR: bluewave-labs/verifywise#1202
File: Clients/src/presentation/components/Sidebar/index.tsx:170-177
Timestamp: 2025-04-23T16:48:51.752Z
Learning: In the VerifyWise application, prefer using the dedicated `changeComponentVisibility` function from VerifyWiseContext when updating component visibility states instead of using `setComponentsVisible` directly, as it was specifically created for this purpose.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-23T16:48:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -44,6 +45,20 @@ function App() {
 
   const [currentProjectId, setCurrentProjectId] = useState<string | null>("");
 
+  const [runHomeTour, setRunHomeTour] = useState(false);
path: Clients/src/App.tsx
user: login: samuel-coutinho
body: Since `runHomeTour` and  `setRunHomeTour` are used only in `VWHome`, I don't see a reason for this state to be defined here and added to the context. This state could instead be defined in `VWHome`.
created_at: 2025-04-23T17:14:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-16T19:12:12Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

The changes introduce a guided tour ("joyride") feature for the Home page. New state management for component visibility is added to the app context and the `App` component. The Sidebar and Home page components track their visibility using a custom hook and update the shared context accordingly. When both the home and sidebar components are visible, the tour is triggered. The tour steps are defined in a new module and integrated into the Home page via a `PageTour` component. Related code is removed from the Dashboard, and context interfaces are updated to support the new feature.

## Changes

| File(s)                                                                                   | Change Summary                                                                                                  |
|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| Clients/src/App.tsx                                                                       | Added state for `componentsVisible` and a callback to manage component visibility. Exposed these in context.    |
| Clients/src/application/contexts/VerifyWise.context.ts                                    | Extended context interface and default values to include new visibility state and toggle function.              |
| Clients/src/application/interfaces/ComponentVisible.ts                                    | Introduced new `ComponentVisible` interface for tracking home and sidebar visibility.                           |
| Clients/src/presentation/pages/Home/1.0Home/index.tsx                                    | Integrated guided tour logic: triggers tour when both home and sidebar are visible, uses new context state.      |
| Clients/src/presentation/pages/Home/1.0Home/HomeSteps.tsx                                | Added new module exporting the guided tour steps for the Home page.                                             |
| Clients/src/presentation/components/Sidebar/index.tsx                                    | Uses custom hook to track sidebar element visibility and updates context state when visible.                     |
| Clients/src/presentation/containers/Dashboard/index.tsx                                  | Removed previous home tour logic and related imports from Dashboard.                                             |
| Clients/src/presentation/components/Popup/index.tsx                                      | Removed `data-joyride-id` attribute from the popup trigger button.                                              |
| Clients/src/presentation/vw-v2-components/Buttons/index.tsx                              | Reformatted component declaration and added PropTypes for `text` and `icon` props.                              |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant App
    participant VerifyWiseContext
    participant Sidebar
    participant HomePage
    participant PageTour

    App->>VerifyWiseContext: Provide componentsVisible and changeComponentVisibility
    Sidebar->>VerifyWiseContext: setComponentsVisible({ sidebar: true }) when sidebar visible
    HomePage->>VerifyWiseContext: setComponentsVisible({ home: true }) when home visible
    HomePage->>HomePage: set runHomeTour = true when home & sidebar visible
    HomePage->>PageTour: Render PageTour when runHomeTour is true
    PageTour-->>HomePage: On finish, set runHomeTour = false
```

## Assessment against linked issues

| Objective (Issue #)                | Addressed | Explanation |
|----------------------------------|-----------|-------------|
| Implement joyride tour in home page (#1174) | ✅        |             |

## Poem

> A hop and a skip through the Home page anew,  
> With a joyride to guide you, the steps clear and true.  
> Sidebar and home now know when they're seen,  
> And the tour pops to life—what a wonderful scene!  
> So here's to new journeys, with context in tow,  
> The rabbit approves—let the onboarding flow! 🐇✨

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 596a25654a501474a0091245e2bfd1e493add666 and afa1a7b3338ce17769ee0149fc97340e63f9841b.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `Clients/src/presentation/containers/Dashboard/index.tsx` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* Clients/src/presentation/containers/Dashboard/index.tsx

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=bluewave-labs/verifywise&utm_content=1202):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: salmanja
created_at: 2025-04-22T18:27:14Z
body: https://github.com/user-attachments/assets/6a43262b-1f15-4dd2-9d93-0e148131ea72

@samuel-coutinho @MuhammadKhalilzadeh @gorkemcetin 
author_association: CONTRIBUTOR
user: login: gorkem-bwl
created_at: 2025-04-22T18:55:32Z
body: > trim.E45DEBCE-051A-462F-A256-51751B97F80C.MOV 
> @samuel-coutinho @MuhammadKhalilzadeh @gorkemcetin

Are there 3 steps or 2 steps in this dashboard? It says 'step 1 of 3' but I see 2 steps in the video.
author_association: CONTRIBUTOR
user: login: salmanja
created_at: 2025-04-22T19:22:55Z
body: 
https://github.com/user-attachments/assets/f5eb61d4-fdc4-440d-be26-cfd127db3913


author_association: CONTRIBUTOR