Skip to content

Worflow UI#45

Merged
Vamsi-o merged 2 commits into
mainfrom
worflow-ui
Jan 2, 2026
Merged

Worflow UI#45
Vamsi-o merged 2 commits into
mainfrom
worflow-ui

Conversation

@TejaBudumuru3

@TejaBudumuru3 TejaBudumuru3 commented Jan 1, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features

    • Added sidebar navigation featuring workflow and credentials management
    • Introduced user profile menu with account logout functionality
    • Enhanced mobile responsiveness across the application
    • Improved Google Sheets integration with enhanced data initialization
  • Bug Fixes

    • Fixed workflow container layout display issue
    • Corrected error message logging
  • Chores

    • Updated UI component library with new interactive components

✏️ Tip: You can customize this high-level summary in your review settings.

…ooltip components and mobile hook

- Implemented `Collapsible`, `CollapsibleTrigger`, and `CollapsibleContent` components for collapsible UI sections.
- Created `DropdownMenu` components including `DropdownMenuPortal`, `DropdownMenuTrigger`, `DropdownMenuContent`, and various item types for enhanced dropdown functionality.
- Added `Separator` component for visual separation in layouts.
- Developed a comprehensive `Sidebar` component with context management, mobile responsiveness, and various subcomponents for structured navigation.
- Introduced `Skeleton` component for loading states.
- Implemented `Tooltip` components for contextual hints and information.
- Added `useIsMobile` hook to detect mobile device state for responsive design.
@TejaBudumuru3 TejaBudumuru3 requested a review from Vamsi-o as a code owner January 1, 2026 20:58
@coderabbitai

coderabbitai Bot commented Jan 1, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces a sidebar-based workflow editor layout with Radix UI components, expands user state management to include email and name, refactors GoogleSheetFormClient to accept initial data, updates the WorkflowSchema by removing UserId, and adds multiple new UI primitives (collapsible, dropdown-menu, separator, tooltip, sidebar system, skeleton, and mobile hook).

Changes

Cohort / File(s) Summary
Backend: Workflow Trigger & Schema Updates
apps/http-backend/src/routes/userRoutes/userRoutes.ts, packages/common/src/index.ts
Fixed "error.meesage" typo; added database update to set isEmpty = false when trigger created; removed UserId field from WorkflowSchema.
State Management: User Profile Data
apps/web/app/store/slices/userSlice.ts, apps/web/app/components/providers.tsx
Added email and name fields to UserSlice state; dispatched setEmail and setUserName in authenticated provider branch.
Frontend: Layout & Sidebar Integration
apps/web/app/components/ui/app-sidebar.tsx, apps/web/app/workflow/page.tsx
New AppSidebar component managing workflows, credentials, and logout; updated workflow page to use SidebarProvider and two-column layout.
Frontend: Node Component Refactoring
apps/web/app/components/nodes/GoogleSheetFormClient.tsx, apps/web/app/components/nodes/CreateWorkFlow.tsx
GoogleSheetFormClient: expanded props with initialData, added useEffect hooks for fetching initial documents/sheets, updated signature; CreateWorkFlow: changed container height to 100%, added fitViewOptions with minZoom.
UI Package: Radix UI Dependencies & Button Updates
packages/ui/package.json, packages/ui/src/components/button.tsx
Added @radix-ui collapsible, dropdown-menu, separator, tooltip dependencies; added icon-sm/icon-lg button sizes, default variant/size values, and data-variant/data-size attributes.
UI Package: New Collapsible & Dropdown Components
packages/ui/src/components/collapsible.tsx, packages/ui/src/components/dropdown-menu.tsx
New Collapsible (root, trigger, content wrappers); new DropdownMenu system (15\+ exported components for menu composition).
UI Package: Separator & Tooltip Components
packages/ui/src/components/separator.tsx, packages/ui/src/components/tooltip.tsx
New Separator component with horizontal/vertical orientation; new Tooltip system (provider, trigger, content with portal and arrow).
UI Package: Comprehensive Sidebar System
packages/ui/src/components/sidebar.tsx
Large new sidebar system: 20\+ exported components (Provider, Trigger, Content, Group, Menu, etc.) with collapsible state, mobile responsiveness via Sheet, keyboard shortcuts, and cookie persistence.
UI Package: Skeleton & Mobile Hook
packages/ui/src/components/skeleton.tsx, packages/ui/src/hooks/use-mobile.ts
New Skeleton loading component; new useIsMobile hook with 768px breakpoint and media query listener.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 A sidebar blooms, with dropdown cheer,
User data stored, credentials near,
Collapsible rows and tooltips bright,
GoogleSheets now initialized right—
Layout flows from top to side,
Workflows managed far and wide!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.69% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Worflow UI' is vague and generic, using broad terms that don't clearly convey the specific changes made in this comprehensive pull request. Provide a more specific title that highlights the primary change, such as 'Add workflow sidebar with credentials management' or 'Implement sidebar layout and user data persistence'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f82cd25 and a2394bc.

📒 Files selected for processing (2)
  • apps/http-backend/src/routes/userRoutes/userRoutes.ts
  • apps/web/app/components/nodes/CreateWorkFlow.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/http-backend/src/routes/userRoutes/userRoutes.ts
  • apps/web/app/components/nodes/CreateWorkFlow.tsx

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/web/app/components/nodes/CreateWorkFlow.tsx (1)

123-151: Dead code: getEmptyWorkflowID is defined but never called.

The function getEmptyWorkflowID (lines 124-138) is defined but the call on line 149 is commented out. Consider removing the dead code or uncommenting if the functionality is needed.

  useEffect(()=>{
-   async function getEmptyWorkflowID(){
-     const workflow = await getEmptyWorkflow()
-     
-     if(workflow){
-       const {id, isEmpty} = workflow
-       dispatch(workflowActions.setWorkflowId(id))
-       dispatch(workflowActions.setWorkflowStatus(isEmpty))
-     }
-     else{
-       if (!userId) return
-       const newWorkflow = await createWorkflow()
-       dispatch(workflowActions.setWorkflowId(newWorkflow.id))
-       dispatch(workflowActions.setWorkflowStatus(newWorkflow.isEmpty))
-     }
-   }
    async function getWorkflowData(){
      if(!workflowId) return
      const workflow = await getworkflowData(workflowId)
      if(workflow.success){
        dispatch(workflowActions.setWorkflowStatus(false))
        dispatch(workflowActions.setWorkflowNodes(workflow.data.nodes))
        dispatch(workflowActions.setWorkflowTrigger(workflow.data.Trigger))
      }
    }
-   // if(!workflowId) getEmptyWorkflowID()
    getWorkflowData();
  },[dispatch, userId, workflowId])
apps/web/app/components/nodes/GoogleSheetFormClient.tsx (2)

150-154: Potential runtime error: unsafe property access.

data.files.length will throw if data.files is undefined. The initial fetch effect (line 76) uses optional chaining (data.files?.length), but this handler doesn't.

      const data = await response.json();
     
-     if (data.files.length >0) {
+     if (data.files?.length > 0) {
        setDocuments(data.files || []);
      }

177-180: Potential runtime error: unsafe nested property access.

data.files.data.length will throw if data.files or data.files.data is undefined.

      const data = await response.json();
-     if (data.files.data.length > 0) {
+     if (data.files?.data?.length > 0) {
        setSheets(data.files.data || []);
      }
🧹 Nitpick comments (9)
packages/ui/src/components/skeleton.tsx (1)

3-11: Consider adding accessibility attributes for loading states.

Skeleton components represent loading placeholders and should communicate this state to assistive technologies. Adding aria-busy="true" or aria-hidden="true" improves the experience for screen reader users.

🔎 Proposed enhancement
 function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
   return (
     <div
       data-slot="skeleton"
       className={cn("bg-accent animate-pulse rounded-md", className)}
+      aria-busy="true"
+      role="status"
       {...props}
     />
   )
 }

Alternatively, use aria-hidden="true" if the skeleton should be completely hidden from screen readers.

packages/ui/src/hooks/use-mobile.ts (1)

8-16: Reorder initial state update to avoid potential race condition.

The current implementation adds the event listener (line 13) before setting the initial state (line 14). While unlikely in practice, this creates a theoretical race condition where a viewport change could occur between these two operations, potentially causing the state to be overwritten incorrectly.

🔎 Recommended ordering
  React.useEffect(() => {
    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
    const onChange = () => {
      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    }
-    mql.addEventListener("change", onChange)
    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
+    mql.addEventListener("change", onChange)
    return () => mql.removeEventListener("change", onChange)
  }, [])
apps/web/app/components/ui/app-sidebar.tsx (4)

46-59: Potential stale data and unnecessary fetches due to useEffect dependency.

The effect depends on selectedWorkflow, but internally it only runs fetches when !creds or !workflow is truthy. This means:

  1. Changing selectedWorkflow won't refetch data if it's already loaded
  2. The dependency doesn't match actual intent

Consider removing selectedWorkflow from deps if refetch isn't intended, or refetch unconditionally if fresh data is needed on workflow change.

  useEffect(()=>{
    async function getWorkflows(){
        const flows = await getAllWorkflows();
        if(flows) setWorkflow(flows)
    }

    async function getCreds(){
        const credentials = await getAllCredentials();
        if(credentials) setCreds(credentials)
    }

-   if(!creds) getCreds()
-   if(!workflow) getWorkflows()
- },[selectedWorkflow])
+   getCreds()
+   getWorkflows()
+ },[]) // Run once on mount, or add proper refetch trigger

64-67: Empty handler function.

credHandler is defined but does nothing. Either implement the intended behavior or remove it to avoid confusion.


76-93: Missing error handling in createNewWorkflow.

If createWorkflow() throws, the error is unhandled and could cause a poor UX. Consider wrapping in try/catch with appropriate user feedback.

🔎 Suggested improvement
  const createNewWorkflow = async()=>{
+   try {
      const workflow = await getEmptyWorkflow()
          
      if(workflow){
        const {id, isEmpty} = workflow
        dispatch(workflowActions.setWorkflowId(id))
        dispatch(workflowActions.setWorkflowStatus(isEmpty))
        toast.info("You are in empty workflow")
      }
      else{
        const newWorkflow = await createWorkflow()
        dispatch(workflowActions.clearWorkflow())
        setSelectedWorkflow(null)
        dispatch(workflowActions.setWorkflowId(newWorkflow.id))
        dispatch(workflowActions.setWorkflowStatus(newWorkflow.isEmpty))
        toast.success("Workflow created")
      }
+   } catch (error) {
+     console.error("Failed to create workflow:", error)
+     toast.error("Failed to create workflow")
+   }
  }

44-45: Consider clearer variable naming.

workflow (line 44) stores an array of workflows, which can be confusing alongside flow (single workflow from Redux). Consider renaming to workflows for clarity.

- const [workflow, setWorkflow] = useState<Array<any>>()
+ const [workflows, setWorkflows] = useState<Array<any>>([])
packages/ui/src/components/tooltip.tsx (1)

21-29: Each Tooltip creates its own TooltipProvider.

Wrapping each Tooltip instance in its own TooltipProvider works, but can be inefficient with many tooltips. Radix recommends a single provider at the app root. However, this pattern does ensure each tooltip is self-contained.

If many tooltips will be used, consider having consumers wrap with a single TooltipProvider at a higher level, and having Tooltip just use TooltipPrimitive.Root directly.

apps/web/app/components/nodes/GoogleSheetFormClient.tsx (1)

63-113: Shared loading state between two async effects can cause UI inconsistency.

Both fetchInitialDocuments and fetchInitialSheets set/clear the same loading state independently. If both run simultaneously, the first to finish will set loading = false while the other is still fetching.

Consider using separate loading states or a counter-based approach.

🔎 Suggested approach
+ const [loadingDocuments, setLoadingDocuments] = useState(false);
+ const [loadingSheets, setLoadingSheets] = useState(false);
+ const loading = loadingDocuments || loadingSheets;

  useEffect(() => {
    const fetchInitialDocuments = async () => {
      if (!initialData?.credentialId) return;
      
-     setLoading(true);
+     setLoadingDocuments(true);
      try {
        // ...fetch logic
      } finally {
-       setLoading(false);
+       setLoadingDocuments(false);
      }
    };
    fetchInitialDocuments();
  }, [initialData?.credentialId]);
packages/ui/src/components/sidebar.tsx (1)

85-86: Cookie missing SameSite attribute.

Modern browsers default to SameSite=Lax, but explicitly setting it is a best practice for clarity and cross-browser consistency.

- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}; SameSite=Lax`
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0feada and f82cd25.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (18)
  • apps/http-backend/src/routes/userRoutes/userRoutes.ts
  • apps/web/app/components/nodes/CreateWorkFlow.tsx
  • apps/web/app/components/nodes/GoogleSheetFormClient.tsx
  • apps/web/app/components/providers.tsx
  • apps/web/app/components/ui/app-sidebar.tsx
  • apps/web/app/workflow/lib/config.ts
  • apps/web/app/workflow/page.tsx
  • apps/web/store/slices/userSlice.ts
  • packages/common/src/index.ts
  • packages/ui/package.json
  • packages/ui/src/components/button.tsx
  • packages/ui/src/components/collapsible.tsx
  • packages/ui/src/components/dropdown-menu.tsx
  • packages/ui/src/components/separator.tsx
  • packages/ui/src/components/sidebar.tsx
  • packages/ui/src/components/skeleton.tsx
  • packages/ui/src/components/tooltip.tsx
  • packages/ui/src/hooks/use-mobile.ts
💤 Files with no reviewable changes (1)
  • packages/common/src/index.ts
🧰 Additional context used
🧬 Code graph analysis (9)
packages/ui/src/components/collapsible.tsx (3)
packages/ui/src/components/label.tsx (1)
  • Label (8-22)
packages/ui/src/components/sheet.tsx (3)
  • Sheet (9-11)
  • SheetTrigger (13-17)
  • SheetTitle (104-115)
packages/ui/src/components/select.tsx (4)
  • SelectScrollUpButton (140-156)
  • SelectTrigger (27-51)
  • Select (9-13)
  • SelectScrollDownButton (158-174)
packages/ui/src/components/tooltip.tsx (4)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
packages/ui/src/components/select.tsx (1)
  • SelectTrigger (27-51)
packages/ui/src/components/sheet.tsx (2)
  • SheetOverlay (31-45)
  • Sheet (9-11)
packages/ui/src/components/label.tsx (1)
  • Label (8-22)
apps/web/store/slices/userSlice.ts (2)
apps/web/app/login/page.tsx (2)
  • email (11-110)
  • e (83-83)
apps/web/store/slices/workflowSlice.ts (1)
  • WorkflowSlice (19-24)
apps/web/app/workflow/lib/config.ts (3)
packages/nodes/src/common/google-oauth-service.ts (2)
  • getAllCredentials (103-117)
  • getCredentials (77-101)
packages/common/src/index.ts (1)
  • BACKEND_URL (4-4)
apps/hooks/src/index.ts (1)
  • req (7-53)
apps/web/app/components/providers.tsx (1)
apps/web/store/slices/userSlice.ts (1)
  • userAction (41-41)
packages/ui/src/components/dropdown-menu.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/web/app/components/nodes/CreateWorkFlow.tsx (4)
apps/web/app/hooks/redux.ts (1)
  • useAppSelector (7-7)
apps/web/app/workflow/lib/config.ts (1)
  • createWorkflow (78-100)
apps/web/app/types/workflow.types.ts (1)
  • NodeType (1-11)
apps/web/app/components/nodes/GoogleSheetFormClient.tsx (1)
  • GoogleSheetFormClient (29-371)
packages/ui/src/components/separator.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/http-backend/src/routes/userRoutes/userRoutes.ts (2)
apps/http-backend/src/routes/userRoutes/userMiddleware.ts (2)
  • userMiddleware (18-42)
  • AuthRequest (8-10)
packages/db/src/index.ts (1)
  • prismaClient (17-18)
🔇 Additional comments (20)
packages/ui/src/components/skeleton.tsx (1)

13-13: LGTM!

The export follows standard conventions for the UI component library.

apps/http-backend/src/routes/userRoutes/userRoutes.ts (1)

369-369: Good catch on the typo fix!

Correcting error.meesage to error.message fixes a potential bug where the error message would be undefined.

packages/ui/src/hooks/use-mobile.ts (1)

5-19: Consider SSR hydration implications of initial undefined state.

The hook initializes isMobile as undefined (line 6) and returns !!isMobile (line 18), which coerces undefined to false on the initial render. This means:

  1. Server-side: Always returns false (since useEffect doesn't run on server)
  2. Client first render: Returns false (before effect runs)
  3. After effect: Returns actual viewport state

This pattern is intentional for SSR safety but can cause:

  • Potential hydration mismatch warnings if server renders assuming desktop
  • Brief layout shift when the effect updates the state post-hydration

If this is intentional, consider documenting this behavior. Alternatively, you could return undefined explicitly until the effect runs, allowing consumers to handle the loading state.

Alternative approach (explicit undefined)
-  return !!isMobile
+  return isMobile

This would return false | true | undefined, allowing consumers to distinguish between "checked and is desktop" vs "not yet checked". Update the return type accordingly:

export function useIsMobile(): boolean | undefined {
apps/web/app/workflow/lib/config.ts (1)

48-61: LGTM!

The getAllCredentials function follows the established patterns in this file with proper error handling and consistent structure.

packages/ui/src/components/button.tsx (1)

7-60: LGTM! Well-structured button enhancements.

The changes improve the button component:

  1. New size variants (icon-sm, icon-lg) provide more granular icon button sizing options
  2. Explicit default values in props destructuring improve code clarity
  3. Data attributes (data-variant, data-size) enable better debugging, testing, and CSS targeting
  4. Styling refinements to hover states appear intentional and consistent

All changes follow established patterns and maintain backward compatibility.

apps/web/app/components/providers.tsx (1)

19-22: LGTM! Consistent extension of user state management.

The additions of setEmail and setUserName dispatches follow the same pattern as the existing setUserId dispatch, with appropriate optional chaining and null fallbacks. Removing the debug console.log also cleans up the code.

apps/web/app/workflow/page.tsx (1)

13-20: Verify SidebarProvider scope.

SidebarProvider typically should wrap both the sidebar and main content area to enable proper state sharing (e.g., collapse/expand state, responsive behavior). Currently, it only wraps AppSidebar, which may limit functionality.

Consider this structure instead:

🔎 Suggested restructure
-    <div className=" w-auto h-full text-black">
-      <SidebarProvider>
-      <AppSidebar />
-      
-        {/* {children} */}
-      </SidebarProvider>
-    </div>
-    <div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">
-      <CreateWorkFlow/>
-    </div>
+    <SidebarProvider>
+      <div className="w-auto h-full text-black">
+        <AppSidebar />
+      </div>
+      <div className="flex-col h-[95vh] w-full items-center justify-center bg-[#0f0f1a]">
+        <CreateWorkFlow/>
+      </div>
+    </SidebarProvider>
packages/ui/src/components/separator.tsx (1)

1-28: LGTM!

The Separator component is well-implemented and follows the established pattern in the codebase for wrapping Radix UI primitives. The use of sensible defaults (orientation="horizontal", decorative=true), proper prop forwarding, and responsive className logic via data attributes is appropriate.

apps/web/store/slices/userSlice.ts (1)

7-8: LGTM!

The additions to the UserSlice interface and reducers are well-implemented. The new email and name fields with their corresponding setEmail and setUserName reducers follow the existing pattern, maintain type consistency (string | null), and integrate properly with the clearUser reducer.

Also applies to: 14-15, 28-33

packages/ui/src/components/collapsible.tsx (1)

1-33: LGTM!

The Collapsible component wrappers are well-implemented and follow the established pattern in the codebase for wrapping Radix UI primitives (as seen in similar components like Sheet, Select, and Label). All three components (Collapsible, CollapsibleTrigger, CollapsibleContent) properly add data-slot attributes and use correct TypeScript typing via React.ComponentProps.

packages/ui/package.json (1)

10-17: Package versions verified and secure.

All specified Radix UI packages (@radix-ui/react-collapsible@1.1.12, @radix-ui/react-dialog@1.1.15, @radix-ui/react-dropdown-menu@2.1.16, @radix-ui/react-label@2.1.8, @radix-ui/react-select@2.2.6, @radix-ui/react-separator@1.1.8, @radix-ui/react-slot@1.2.3, and @radix-ui/react-tooltip@1.2.8) exist on the npm registry and have no known security vulnerabilities.

packages/ui/src/components/tooltip.tsx (1)

1-61: LGTM!

The Tooltip component implementation follows established patterns in the UI package (data-slot attributes, cn utility for className composition). The animation classes and Portal usage are correctly applied.

apps/web/app/components/nodes/CreateWorkFlow.tsx (3)

343-343: Position calculation may be incorrect for editing existing nodes.

position={existingNodes.length + 1} always calculates position based on total nodes count. When editing an existing node, this should probably use the node's actual position, not append position.

Verify that the position prop is used correctly in GoogleSheetFormClient and whether it represents the node's ordinal position or is used for new node placement only.


153-220: LGTM on workflow graph rebuilding logic.

The guard condition correctly prevents rebuilding when there's no stored data, and the node/edge generation logic properly handles triggers, actions, and placeholder positioning.


344-349: The current implementation is correct and does not need changes.

The code properly reads from selectedNodeConfig.spreadsheetId (lowercase 's') from the backend and assigns it to spreadSheetId (uppercase 'S') as expected by GoogleSheetFormClient. The backend config (per actions.ts) returns the property with lowercase 's', and the component interface (per GoogleSheetFormClient.tsx line 24) expects uppercase 'S' for the initialData prop. The mapping on line 348 of CreateWorkFlow.tsx correctly bridges this difference.

Changing to selectedNodeConfig.spreadSheetId would result in undefined being passed to the component, breaking initial data population instead of fixing it.

apps/web/app/components/nodes/GoogleSheetFormClient.tsx (1)

29-40: LGTM on state initialization from initialData.

The state variables are correctly initialized with values from initialData when present, with appropriate fallbacks.

packages/ui/src/components/dropdown-menu.tsx (1)

1-257: LGTM!

The DropdownMenu component set is well-implemented following established UI package patterns:

  • Consistent use of data-slot attributes for styling hooks
  • Proper className composition with cn utility
  • Correct use of Portal for main content
  • Appropriate animation and styling classes

The implementation aligns with other Radix UI wrapper components in the package.

packages/ui/src/components/sidebar.tsx (3)

47-54: Good practice: Context with error boundary.

The useSidebar hook correctly throws a descriptive error when used outside a SidebarProvider, making debugging easier.


183-206: Good accessibility: Mobile sidebar uses Sheet with sr-only header.

The mobile implementation correctly includes visually hidden but screen-reader accessible title and description via SheetHeader with sr-only class.


1-726: LGTM overall!

This is a comprehensive, well-structured sidebar component library with:

  • Proper controlled/uncontrolled state management
  • Cookie persistence for user preferences
  • Keyboard shortcut support (Ctrl/Cmd+B)
  • Mobile-responsive design with Sheet fallback
  • Tooltip integration for collapsed state
  • Extensive composable subcomponents

The implementation follows established patterns and provides good accessibility features.

Comment thread apps/http-backend/src/routes/userRoutes/userRoutes.ts Outdated
Comment on lines +401 to +406
await prismaClient.workflow.update({
where:{ id: dataSafe.data.WorkflowId },
data:{
isEmpty: false
}
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for workflow update.

The workflow update operation at lines 401-406 lacks error handling. If this update fails after the trigger has been successfully created, it would leave the system in an inconsistent state where:

  • The trigger exists in the database
  • The workflow's isEmpty flag remains true (incorrect)

This could lead to unexpected behavior in the UI or other parts of the system that rely on the isEmpty flag.

🔎 Proposed fix
      })
-      await prismaClient.workflow.update({
-        where:{ id: dataSafe.data.WorkflowId },
-        data:{
-          isEmpty: false
-        }
-      })
+      try {
+        await prismaClient.workflow.update({
+          where:{ id: dataSafe.data.WorkflowId },
+          data:{
+            isEmpty: false
+          }
+        })
+      } catch (updateError) {
+        console.log("Warning: Failed to update workflow isEmpty flag:", updateError);
+        // Note: trigger was created successfully but isEmpty flag may be stale
+      }

      if(createdTrigger){
📝 Committable suggestion

‼️ 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.

Suggested change
await prismaClient.workflow.update({
where:{ id: dataSafe.data.WorkflowId },
data:{
isEmpty: false
}
})
try {
await prismaClient.workflow.update({
where:{ id: dataSafe.data.WorkflowId },
data:{
isEmpty: false
}
})
} catch (updateError) {
console.log("Warning: Failed to update workflow isEmpty flag:", updateError);
// Note: trigger was created successfully but isEmpty flag may be stale
}
🤖 Prompt for AI Agents
In apps/http-backend/src/routes/userRoutes/userRoutes.ts around lines 401-406,
the prismaClient.workflow.update call has no error handling which can leave a
created trigger in DB while the workflow.isEmpty stays true; wrap the update in
error handling or (preferably) perform the trigger creation and workflow update
inside a prisma transaction so both succeed or both rollback; if you cannot
convert to a transaction, catch errors from the update, delete the newly created
trigger to rollback the partial change, log the failure with context, and
rethrow or return an appropriate error response.

Comment on lines +42 to +46
console.log('initial data: ', initialData)
console.log('initial document: ', selectedDocument)
console.log('initial sheet: ', selectedSheet)
console.log('initial range: ', range)
console.log("initial operation: ",operation)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove debug console.log statements.

Multiple debug logs should be removed before merging to production.

- console.log('initial data: ', initialData)
- console.log('initial document: ', selectedDocument)
- console.log('initial sheet: ', selectedSheet)
- console.log('initial range: ', range)
- console.log("initial operation: ",operation)
📝 Committable suggestion

‼️ 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.

Suggested change
console.log('initial data: ', initialData)
console.log('initial document: ', selectedDocument)
console.log('initial sheet: ', selectedSheet)
console.log('initial range: ', range)
console.log("initial operation: ",operation)
🤖 Prompt for AI Agents
In apps/web/app/components/nodes/GoogleSheetFormClient.tsx around lines 42 to
46, remove the five debug console.log statements (console.log('initial data...',
selectedDocument, selectedSheet, range, operation)) so no debug output is left
in production; if you need runtime inspection, replace them with a proper logger
behind a development-only check or use the existing debug/log utility, otherwise
simply delete these console.log lines.

{creds ? (creds.length === 0 ?
(<SidebarMenuSubItem key={0}>
<SidebarMenuSubButton>
<span>No credentials avaliable</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo in user-facing text.

"avaliable" should be "available".

-                                   <span>No credentials avaliable</span>
+                                   <span>No credentials available</span>
📝 Committable suggestion

‼️ 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.

Suggested change
<span>No credentials avaliable</span>
<span>No credentials available</span>
🤖 Prompt for AI Agents
In apps/web/app/components/ui/app-sidebar.tsx around line 157, there's a typo in
the user-facing string "No credentials avaliable"; update the text to "No
credentials available" to fix the misspelling, keeping casing and spacing
consistent with surrounding UI copy.

Comment thread apps/web/app/workflow/lib/config.ts Outdated
import { BACKEND_URL } from "@repo/common/zod";
import { GoogleSheetsNodeExecutor } from "@repo/nodes";
import axios from "axios"
const date = new Date()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Move date instantiation inside createWorkflow function.

The date constant is declared at the module level (line 4), which means it's evaluated once when the module loads, not when createWorkflow is called. This causes all workflows created in the same session to receive identical timestamps in their names (line 82: workflow-${date.getTime()}), defeating the purpose of using timestamps for uniqueness.

🔎 Proposed fix
-const date = new Date()
 export const getAvailableTriggers = async () => {

And in createWorkflow:

 export const createWorkflow = async()=>{
     try{
+      const date = new Date()
       const response = await axios.post(`${BACKEND_URL}/user/create/workflow`,
         {
           Name:`workflow-${date.getTime()}`,

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/web/app/workflow/lib/config.ts around line 4 (and referenced at line
82), the module-level const date = new Date() causes the same timestamp to be
reused for every workflow; move the Date instantiation inside createWorkflow so
a fresh new Date() (or Date.now()) is created during each call and replace
usages of the module-level date (e.g., workflow-${date.getTime()}) with the
locally constructed timestamp to ensure unique, per-call names.

Comment thread apps/web/app/workflow/lib/config.ts Outdated
Comment on lines +64 to +76
export const getAllWorkflows = async()=>{
try{
const res = await axios.get(`${BACKEND_URL}/user/workflows`,{
withCredentials: true
})
const data = res.data.Data
console.log("workflows: ",data)
return data
}catch(e){
console.error("Error fetching credentials:", e);
throw e;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix copy-paste error in error message.

Line 73 logs "Error fetching credentials" but this function is getAllWorkflows. The error message should reference workflows, not credentials.

🔎 Proposed fix
  }catch(e){
-    console.error("Error fetching credentials:", e);
+    console.error("Error fetching workflows:", e);
    throw e;
  }
📝 Committable suggestion

‼️ 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.

Suggested change
export const getAllWorkflows = async()=>{
try{
const res = await axios.get(`${BACKEND_URL}/user/workflows`,{
withCredentials: true
})
const data = res.data.Data
console.log("workflows: ",data)
return data
}catch(e){
console.error("Error fetching credentials:", e);
throw e;
}
}
export const getAllWorkflows = async()=>{
try{
const res = await axios.get(`${BACKEND_URL}/user/workflows`,{
withCredentials: true
})
const data = res.data.Data
console.log("workflows: ",data)
return data
}catch(e){
console.error("Error fetching workflows:", e);
throw e;
}
}
🤖 Prompt for AI Agents
In apps/web/app/workflow/lib/config.ts around lines 64 to 76, the catch block
logs "Error fetching credentials" which is a copy-paste mistake for
getAllWorkflows; change the console.error call to reference workflows (e.g.,
"Error fetching workflows:" or "Error fetching all workflows:") and keep passing
the caught error object so the log shows details, then rethrow the error as
currently implemented.

@@ -1,15 +1,27 @@
"use client";

import { SidebarProvider, SidebarTrigger } from "@workspace/ui/components/sidebar";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unused import.

SidebarTrigger is imported but never used in the component.

🔎 Proposed fix
-import { SidebarProvider, SidebarTrigger } from "@workspace/ui/components/sidebar";
+import { SidebarProvider } from "@workspace/ui/components/sidebar";
📝 Committable suggestion

‼️ 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.

Suggested change
import { SidebarProvider, SidebarTrigger } from "@workspace/ui/components/sidebar";
import { SidebarProvider } from "@workspace/ui/components/sidebar";
🤖 Prompt for AI Agents
In apps/web/app/workflow/page.tsx around line 3, the import statement brings in
SidebarTrigger which is not used; remove SidebarTrigger from the import so only
SidebarProvider is imported (or delete the entire import if SidebarProvider is
also unused), and run a quick search to ensure there are no remaining references
to SidebarTrigger before committing.

{/* {children} */}
</SidebarProvider>
</div>
<div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix CSS class typos.

The className string contains two typos:

  • fitems-center should be items-center
  • flex -col should be flex-col
🔎 Proposed fix
-    <div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">
+    <div className="flex flex-col h-[95vh] w-full items-center justify-center bg-[#0f0f1a]">
📝 Committable suggestion

‼️ 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.

Suggested change
<div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">
<div className="flex flex-col h-[95vh] w-full items-center justify-center bg-[#0f0f1a]">
🤖 Prompt for AI Agents
In apps/web/app/workflow/page.tsx around line 21 the className has typos:
replace "flex -col" with "flex-col" and "fitems-center" with "items-center" so
the final className uses "flex-col items-center justify-center" (keeping the
other utility classes and spacing intact).

@@ -0,0 +1,13 @@
import { cn } from "@workspace/ui/lib/utils"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add missing React type import.

The component uses React.ComponentProps<"div"> on line 3, but React types are not imported. This will cause a TypeScript compilation error: "Cannot find namespace 'React'."

🔎 Proposed fix
+import type React from "react"
 import { cn } from "@workspace/ui/lib/utils"
📝 Committable suggestion

‼️ 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.

Suggested change
import { cn } from "@workspace/ui/lib/utils"
import type React from "react"
import { cn } from "@workspace/ui/lib/utils"
🤖 Prompt for AI Agents
packages/ui/src/components/skeleton.tsx around line 1: the file uses
React.ComponentProps<"div"> but doesn't import React, causing a TS error; add a
React type import at the top (for example a type-only import like `import type *
as React from "react"` or a regular `import React from "react"`) so the React
namespace/types are available for ComponentProps; keep existing imports and
ensure the import is placed before any usage of React types.

Vamsi-o
Vamsi-o previously approved these changes Jan 2, 2026

@Vamsi-o Vamsi-o left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work , Just move the Date inside to try catch in createWorkflow

@TejaBudumuru3 TejaBudumuru3 dismissed Vamsi-o’s stale review January 2, 2026 07:58

The merge-base changed after approval.

@Vamsi-o Vamsi-o merged commit 2970b61 into main Jan 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants