Skip to content

Feature/UI #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed

Feature/UI #152

wants to merge 8 commits into from

Conversation

Neo-Neooo
Copy link
Contributor

@Neo-Neooo Neo-Neooo commented Jun 1, 2025

User description

🫰 Thanks for your Pull Request! Here are some helpful tips:

👀 Purpose and Importance of this PR:

  • My code conforms to the coding style of this project.
  • My code requires changes to the documentation.
  • I have updated the documentation accordingly.
  • All tests have passed.

🅰 Fixes for Issues:

Fixes #

📝 Notes for the Reviewer:

🎯 How to Verify this PR:

📑 Additional Documentation, e.g., KEPs (Telepace Enhancement Proposals), Usage Docs, etc.:


Description

  • Introduced a new AppSidebar component to enhance navigation structure.
  • Refactored MainLayout to integrate AppSidebar and manage state with SidebarProvider.
  • Added comprehensive tests for both AppSidebar and updated MainLayout tests.
  • Updated various UI components for consistency and improved user experience.

Changes walkthrough 📝

Relevant files
Enhancement
5 files
AppSidebar.tsx
New AppSidebar Component for Navigation                                   

frontend/components/layout/AppSidebar.tsx

  • Introduced AppSidebar component for improved navigation.
  • Integrated main and secondary navigation items with icons.
  • Added user information display with dropdown for logout.
  • +176/-0 
    MainLayout.tsx
    Refactor MainLayout to Use AppSidebar                                       

    frontend/components/layout/MainLayout.tsx

  • Replaced Sidebar with AppSidebar for better structure.
  • Wrapped layout in SidebarProvider for state management.
  • Adjusted layout styles for sidebar integration.
  • +43/-52 
    button.tsx
    Refactor Button Component Styles                                                 

    frontend/components/ui/button.tsx

  • Adjusted button styles for better visual feedback.
  • Updated variant definitions for consistency.
  • +12/-15 
    sheet.tsx
    Refactor Sheet Component                                                                 

    frontend/components/ui/sheet.tsx

  • Simplified sheet component structure.
  • Removed unnecessary comments for clarity.
  • +19/-53 
    tooltip.tsx
    Refactor Tooltip Component                                                             

    frontend/components/ui/tooltip.tsx

  • Cleaned up tooltip component code.
  • Improved readability and consistency.
  • +10/-22 
    Tests
    3 files
    AppSidebar.test.tsx
    Tests for AppSidebar Component                                                     

    frontend/tests/components/layout/AppSidebar.test.tsx

  • Added tests for AppSidebar component functionality.
  • Verified rendering of navigation links and user info.
  • Ensured correct behavior of sidebar trigger.
  • +117/-0 
    MainLayout.test.tsx
    Update Tests for MainLayout with AppSidebar                           

    frontend/tests/components/layout/MainLayout.test.tsx

  • Updated tests to reflect changes in MainLayout.
  • Verified rendering of AppSidebar and its functionality.
  • +140/-0 
    TopNavigation.test.tsx
    Update Tests for TopNavigation                                                     

    frontend/tests/components/layout/TopNavigation.test.tsx

  • Updated tests for TopNavigation to reflect UI changes.
  • Verified presence of new settings button.
  • +3/-24   
    Dependencies
    1 files
    package.json
    Update Dependencies for Icons                                                       

    frontend/package.json

    • Added @tabler/icons-react dependency for icon usage.
    +2/-2     

    💡 Penify usage:
    Comment /help on the PR to get a list of all available Penify tools and their descriptions

    Summary by CodeRabbit

    • New Features

      • Introduced a new collapsible sidebar navigation component with integrated user info, navigation links, and quick actions.
      • Added a custom hook to detect mobile viewports for responsive layouts.
    • Refactor

      • Replaced the previous sidebar and top navigation system with a unified sidebar provider and new sidebar component.
      • Simplified and updated layout and UI components for consistency and improved accessibility.
      • Updated button and input styles for clearer error states and better focus handling.
      • Adjusted vertical spacing and visual emphasis in the content library.
    • Bug Fixes

      • Ensured proper accessibility and error indication for form inputs.
    • Chores

      • Updated authentication and setup flows to redirect users to the content library instead of the dashboard.
      • Upgraded and reordered dependencies, including a new icon library.
    • Tests

      • Added comprehensive tests for the new sidebar and main layout components.
      • Removed outdated sidebar tests and updated navigation tests to reflect UI changes.
    • Style

      • Unified code style by removing trailing semicolons, comments, and standardizing formatting across UI components.
      • Enhanced global CSS for dark mode support and consistent base styling.

    Neo-Neooo added 7 commits June 1, 2025 09:30
    - 更新了按钮、输入框、分隔符、侧边栏等组件的代码格式,统一了引入方式。
    - 在全局样式中添加了自定义变体和基础样式。
    - 改进了侧边栏的状态管理和样式,增强了用户体验。
    - 修复了多个组件中的小错误,确保更好的兼容性和可用性。
    这些更改提升了代码的可读性和维护性,同时改善了用户界面的整体表现。
    - 将Sidebar组件重命名为AppSidebar,并整合SidebarProvider以管理状态。
    - 更新了MainLayout以使用新的AppSidebar结构,移除不必要的状态管理。
    - 改进了TopNavigation组件,移除了搜索框相关代码,简化了结构。
    - 更新了Sidebar和TopNavigation的测试用例,确保功能正常。
    这些更改提升了组件的可维护性和用户体验。
    - 将 searchParams 类型从对象更改为 Promise,以支持异步处理。
    - 在 PromptForm 中,更新了输入框的错误状态处理,使用 aria-invalid 属性和动态类名来提升可访问性。
    这些更改增强了组件的可维护性和用户体验。
    - 将原Sidebar组件重命名为AppSidebar,整合了导航项和用户信息的展示。
    - 新增了NavMain、NavQuickCreate、NavSecondary和NavUser组件,提升了代码的模块化和可维护性。
    - 更新了MainLayout以使用新的AppSidebar结构,简化了状态管理。
    - 移除了旧的Sidebar测试用例,并新增了针对AppSidebar的测试,确保功能正常。
    这些更改提升了组件的可读性和用户体验。
    - 引入新的导航项和用户信息展示,提升了组件的可读性和可维护性。
    - 移除了旧的Sidebar相关组件,整合了功能到AppSidebar中。
    - 更新了测试用例,确保新结构的功能正常。
    这些更改改善了用户体验并简化了代码结构。
    - 在多个组件中修改重定向路径,确保用户在完成设置或登录后能够正确访问内容库。
    - 更新了相关测试用例,确保新重定向逻辑的有效性。
    这些更改提升了用户体验,确保用户能够顺利访问内容库。
    @Neo-Neooo Neo-Neooo requested review from cubxxw and kubbot as code owners June 1, 2025 14:28
    @github-project-automation github-project-automation bot moved this to Backlog in nexus Jun 1, 2025
    Copy link
    Contributor

    coderabbitai bot commented Jun 1, 2025

    ## Walkthrough
    
    This update introduces a new `AppSidebar` component and replaces the previous sidebar and top navigation system with a provider-based sidebar architecture. The layout and UI are streamlined, with several redirects and UI elements updated to use `/content-library` instead of `/dashboard`. Related tests are refactored, removed, or added accordingly.
    
    ## Changes
    
    | File(s)                                                                                     | Change Summary                                                                                     |
    |---------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|
    | frontend/components/layout/AppSidebar.tsx, frontend/hooks/use-mobile.ts                     | New `AppSidebar` component and mobile detection hook introduced.                                  |
    | frontend/components/layout/MainLayout.tsx, frontend/components/layout/TopNavigation.tsx, frontend/components/layout/Sidebar.tsx | Sidebar and top navigation refactored: old components removed or replaced by `AppSidebar`.        |
    | frontend/__tests__/components/layout/AppSidebar.test.tsx, frontend/__tests__/components/layout/MainLayout.test.tsx | New/updated tests for `AppSidebar` and `MainLayout`.                                             |
    | frontend/__tests__/components/layout/Sidebar.test.tsx                                       | Old sidebar test removed.                                                                         |
    | frontend/__tests__/components/layout/TopNavigation.test.tsx                                 | TopNavigation tests updated for refactored component.                                           |
    | frontend/app/content-library/page.tsx, frontend/app/setup/page.tsx, frontend/app/password-recovery/confirm/page.tsx, frontend/app/prompts/page.tsx, frontend/app/prompts/_components/PromptForm.tsx | UI and logic updated for new navigation, redirect, and input error handling.                     |
    | frontend/components/actions/google-auth-action.ts, frontend/components/actions/items-action.ts, frontend/components/actions/login-action.ts, frontend/components/setup/SetupContent.tsx, frontend/hooks/useAuthRedirect.ts, frontend/middleware.ts | Redirects and middleware logic updated to use `/content-library` instead of `/dashboard`.         |
    | frontend/components/ui/button.tsx, frontend/components/ui/input.tsx, frontend/components/ui/separator.tsx, frontend/components/ui/sheet.tsx, frontend/components/ui/sidebar.tsx, frontend/components/ui/skeleton.tsx, frontend/components/ui/tooltip.tsx | UI components refactored for style, accessibility, and code consistency; input component simplified. |
    | frontend/app/globals.css                                                                    | Dark mode and base style enhancements.                                                          |
    | frontend/package.json                                                                       | Dependencies reordered/updated; new icon package added.                                          |
    | Makefile                                                                                   | Frontend lint target modified to set DEBUG environment variable to empty before linting.         |
    
    ## Sequence Diagram(s)
    
    ```mermaid
    sequenceDiagram
        participant User
        participant AppSidebar
        participant SidebarProvider
        participant AuthContext
        participant Router
    
        User->>AppSidebar: Interacts (e.g., click "Upload Content")
        AppSidebar->>SidebarProvider: Uses context for sidebar state
        AppSidebar->>AuthContext: Retrieves user info for display
        AppSidebar->>Router: Navigates via sidebar links
        AppSidebar-->>User: Updates UI and triggers callbacks

    Possibly related PRs

    Suggested reviewers

    • kubbot

    Poem

    A sidebar hops in, fresh and bright,
    With menus tucked in left and right.
    The dashboard's gone, content leads the way,
    New icons sparkle, styles in play.
    Tests abound, the code feels light—
    A rabbit's cheer for changes right!
    🐇✨

    
    <!-- walkthrough_end -->
    <!-- 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=telepace/nexus&utm_content=152):
    
    - Review comments: Directly reply to a review comment made by CodeRabbit. Example:
      - `I pushed a fix in commit <commit_id>, please review it.`
      - `Explain this complex logic.`
      - `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 explain this code block.`
      -	`@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 explain its main purpose.`
      - `@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.`
    
    ### Support
    
    Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.
    
    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 -->
    

    @penify-dev penify-dev bot added enhancement New feature or request Tests labels Jun 1, 2025
    Copy link

    qodo-merge-pro bot commented Jun 1, 2025

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Potential Memory Leak

    The useIsMobile hook adds an event listener but might not properly clean up if the component unmounts before the effect runs. Consider adding a check to ensure the component is still mounted before setting state.

    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)
      return () => mql.removeEventListener("change", onChange)
    }, [])
    Accessibility Issue

    The SidebarTrigger component uses a button with an icon but doesn't provide adequate accessibility support beyond a screen reader text. Consider adding aria-expanded and aria-controls attributes to improve accessibility.

    function SidebarTrigger({
      className,
      onClick,
      ...props
    }: React.ComponentProps<typeof Button>) {
      const { toggleSidebar } = useSidebar()
    
      return (
        <Button
          data-sidebar="trigger"
          data-slot="sidebar-trigger"
          variant="ghost"
          size="icon"
          className={cn("size-7", className)}
          onClick={(event) => {
            onClick?.(event)
            toggleSidebar()
          }}
          {...props}
        >
          <PanelLeftIcon />
          <span className="sr-only">Toggle Sidebar</span>
        </Button>
      )
    

    Copy link
    Contributor

    penify-dev bot commented Jun 1, 2025

    PR Review 🔍

    ⏱️ Estimated effort to review [1-5]

    4, because the PR introduces a significant new component (AppSidebar) along with extensive test coverage. The changes span multiple files, including tests and layout components, which may require careful review to ensure integration and functionality.

    🧪 Relevant tests

    Yes

    ⚡ Possible issues

    Potential UI Overlap: The new sidebar may overlap with existing components if not styled correctly.

    Navigation Logic: Ensure that the navigation logic correctly reflects the intended user flow, especially with the changes in routing.

    🔒 Security concerns

    No

    Copy link

    qodo-merge-pro bot commented Jun 1, 2025

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix media query inconsistency

    The onChange function uses window.innerWidth which doesn't match the media query
    logic. This can cause inconsistencies when the browser's reported width differs
    from the media query evaluation. Use the matches property from the media query
    list instead.

    frontend/hooks/use-mobile.ts [8-16]

     import * as React from "react"
     
     const MOBILE_BREAKPOINT = 768
     
     export function useIsMobile() {
       const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
     
       React.useEffect(() => {
         const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
         const onChange = () => {
    -      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    +      setIsMobile(mql.matches)
         }
         mql.addEventListener("change", onChange)
    -    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    +    setIsMobile(mql.matches)
         return () => mql.removeEventListener("change", onChange)
       }, [])
     
       return !!isMobile
     }

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly identifies an inconsistency between the media query (max-width: 767px) and the logic window.innerWidth < 768. Using mql.matches ensures consistent behavior and fixes a potential bug.

    Medium
    Remove duplicate variant definition

    There's a duplicate dark variant definition with @custom-variant and @variant.
    The @custom-variant directive is incorrect and should be removed as Tailwind v4
    uses @variant for custom variants.

    frontend/app/globals.css [4-7]

    -@custom-variant dark (&:is(.dark *));
    -
     /* Tailwind v4 自定义变体 */
     @variant dark (&:is(.dark *));
    • Apply / Chat
    Suggestion importance[1-10]: 6

    __

    Why: The suggestion correctly identifies duplicate dark variant definitions where @custom-variant should be removed as Tailwind v4 uses @variant. This is a valid cleanup that prevents potential configuration conflicts.

    Low
    General
    Maintain consistent language in comments

    The test contains a comment in Chinese which is inconsistent with the English
    used throughout the codebase. For better maintainability and consistency,
    translate the comment to English.

    frontend/tests/components/layout/AppSidebar.test.tsx [84-86]

     it("renders upload content section", () => {
       renderSidebar();
       
    -  // 测试Upload Content按钮存在
    +  // Test that Upload Content button exists
       const uploadContentButtons = screen.getAllByText("Upload Content");
       expect(uploadContentButtons.length).toBeGreaterThan(0);
     });

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 3

    __

    Why: The suggestion correctly identifies a Chinese comment that should be translated to English for codebase consistency. However, this is a minor style issue with low impact on functionality.

    Low
    • Update

    Copy link
    Contributor

    penify-dev bot commented Jun 1, 2025

    PR Code Suggestions ✨

    CategorySuggestion                                                                                                                                    Score
    Possible bug
    Check for the existence of the user object before accessing its properties to prevent null reference errors

    Ensure that the user object is defined before accessing its properties to avoid potential
    null reference errors.

    frontend/components/layout/TopNavigation.tsx [87-88]

    -<p className="font-medium">{user?.full_name || "用户"}</p>
    +<p className="font-medium">{user && user.full_name ? user.full_name : "用户"}</p>
     
    Suggestion importance[1-10]: 9

    Why: Checking for the existence of the user object before accessing its properties is crucial to prevent null reference errors, making this a high-priority suggestion.

    9
    Validate the click handler props to ensure they are functions before calling them

    Ensure that the onAddContentClick and onSettingsClick props are validated to be functions
    before invoking them to prevent runtime errors.

    frontend/components/layout/TopNavigation.tsx [33]

    -onClick={onAddContentClick}
    +onClick={() => typeof onAddContentClick === 'function' && onAddContentClick()}
     
    Suggestion importance[1-10]: 8

    Why: Validating the props before invoking them helps prevent potential runtime errors, enhancing the robustness of the component.

    8
    Maintainability
    Use a CSS class for sidebar styles instead of inline styles for better maintainability

    Remove the inline style for --sidebar-width and --sidebar-width-icon and consider using a
    CSS class or a CSS-in-JS solution for better maintainability and separation of concerns.

    frontend/components/layout/MainLayout.tsx [29-34]

    -style={
    -  {
    -    "--sidebar-width": "240px",
    -    "--sidebar-width-icon": "4rem",
    -  } as React.CSSProperties
    -}
    +className="sidebar-custom-styles"
     
    Suggestion importance[1-10]: 8

    Why: This suggestion addresses maintainability by advocating for the use of CSS classes instead of inline styles, which is a good practice in React development.

    8
    Ensure the className prop is always defined to prevent styling issues

    Ensure that the className prop is always passed to the SheetOverlay component to avoid
    potential styling issues when the className is not defined.

    frontend/components/ui/sheet.tsx [38-40]

     className={cn(
       "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
    -  className
    +  className || ""
     )}
     
    Suggestion importance[1-10]: 7

    Why: The suggestion correctly identifies a potential issue with the className prop, but the proposed change of using className || "" is not necessary since the existing code already handles it correctly.

    7
    Improve error handling to provide clearer feedback on token sending failures

    Ensure that the error handling for the token sending process is robust enough to handle
    different error types and provide meaningful feedback to the user.

    frontend/components/setup/SetupContent.tsx [336-338]

    -+          console.error("[SetupContent] Error sending Token to extension:", error);
    ++          console.error("[SetupContent] Error sending Token to extension:", error instanceof Error ? error.message : "Unknown error");
     
    Suggestion importance[1-10]: 7

    Why: This suggestion improves error handling by providing clearer feedback on token sending failures, which is important for maintainability and user experience.

    7
    Confirm the necessity of new dependencies to prevent package bloat

    Ensure that the new dependencies are necessary for the project to avoid bloating the
    package size.

    frontend/package.json [48]

    -"@tabler/icons-react": "^3.33.0",
    +"@tabler/icons-react": "^3.33.0", // Confirm necessity of this dependency
     
    Suggestion importance[1-10]: 7

    Why: This suggestion is valid as it promotes maintainability, but it lacks specificity regarding which dependencies may be unnecessary.

    7
    Use a more descriptive class name for the separator to enhance code clarity

    Consider using a more descriptive class name for the Separator component to improve
    maintainability and readability.

    frontend/components/layout/TopNavigation.tsx [40-42]

     <Separator
       orientation="vertical"
    -  className="mx-2 data-[orientation=vertical]:h-4"
    +  className="mx-2 custom-separator-class"
     />
     
    Suggestion importance[1-10]: 5

    Why: While using a more descriptive class name can improve clarity, the current class name is functional and does not pose a significant issue.

    5
    Standardize the padding style for the CardContent component to maintain visual consistency

    Ensure that the CardContent component in the empty state of the content library has a
    consistent padding style to maintain visual consistency.

    frontend/app/content-library/page.tsx [234]

    -<CardContent className="py-6">
    +<CardContent className="p-6">
     
    Suggestion importance[1-10]: 5

    Why: While the suggestion aims to standardize padding for visual consistency, the existing padding of py-6 is already reasonable, making this change more of a stylistic preference than a necessity.

    5
    Testing
    Run tests to ensure functionality after adding new dependencies

    Consider running tests after adding new dependencies to ensure that everything functions
    as expected.

    frontend/package.json [54]

    -"crypto-js": "^4.2.0",
    +"crypto-js": "^4.2.0", // Run tests to ensure functionality after adding this dependency
     
    Suggestion importance[1-10]: 8

    Why: Running tests after adding dependencies is crucial for ensuring functionality, making this a strong suggestion for maintaining code quality.

    8
    Accessibility
    Improve accessibility by providing more descriptive aria-labels for buttons

    Consider using a more specific aria-label for the buttons to enhance accessibility for
    screen readers.

    frontend/components/layout/TopNavigation.tsx [49]

    -aria-label="设置"
    +aria-label="Open settings menu"
     
    Suggestion importance[1-10]: 7

    Why: Providing more descriptive aria-labels improves accessibility, which is important, but the current labels are still functional.

    7
    Best practice
    Set a default value for the side prop to ensure it always has a valid value

    Consider using a default value for the side prop in SheetContent to ensure it always has a
    valid value, which can prevent rendering issues.

    frontend/components/ui/sheet.tsx [50-53]

    -side = "right",
    +side = "right" as "top" | "right" | "bottom" | "left",
     
    Suggestion importance[1-10]: 6

    Why: The suggestion is valid as it promotes better practices, but the existing default value is already set correctly, making the suggestion less impactful.

    6
    Ensure the size prop has a default value to maintain consistent button styling

    Consider adding a default value for the size prop in the buttonVariants function to ensure
    consistent styling across buttons.

    frontend/components/ui/button.tsx [33]

    -+        size: "default",
    ++        size: size || "default",
     
    Suggestion importance[1-10]: 5

    Why: The suggestion is valid as it promotes best practices for default values, but the current implementation already provides a default value, making this change somewhat redundant.

    5
    Compatibility
    Verify compatibility of new package versions with existing dependencies

    Consider verifying the compatibility of the new versions of the added packages with the
    existing dependencies to avoid potential conflicts.

    frontend/package.json [48]

    -"@tabler/icons-react": "^3.33.0",
    +"@tabler/icons-react": "^3.33.0", // Ensure compatibility with existing dependencies
     
    Suggestion importance[1-10]: 6

    Why: While it's important to verify compatibility, the suggestion does not provide a specific action to take and lacks urgency regarding potential conflicts.

    6
    Check for breaking changes in the removed version of a dependency

    It may be beneficial to check if the removed version of class-variance-authority has any
    breaking changes that could affect the application.

    frontend/package.json [51]

    -"class-variance-authority": "^0.7.1",
    +"class-variance-authority": "^0.7.1", // Check for breaking changes from previous version
     
    Suggestion importance[1-10]: 5

    Why: This suggestion is relevant but does not address any immediate issues since the current version is already in use; it could be more actionable.

    5
    Possible issue
    Validate the type prop to ensure it defaults to a supported input type

    Ensure that the type prop is validated to prevent potential issues with unsupported input
    types.

    frontend/components/ui/input.tsx [8]

    -+      type={type}
    ++      type={type || "text"}
     
    Suggestion importance[1-10]: 4

    Why: While validating the type prop is a good practice, the suggested change does not account for the fact that the type prop is already being passed directly, which may lead to unexpected behavior if the prop is not provided.

    4
    Ensure the delayDuration prop is handled correctly to avoid potential undefined values

    Ensure that the TooltipProvider component is properly handling the delayDuration prop and
    passing it down to the TooltipPrimitive.Root component, as it may affect the tooltip's
    display timing.

    frontend/components/ui/tooltip.tsx [15]

    -+        delayDuration={delayDuration}
    ++        delayDuration={delayDuration || 0}
     
    Suggestion importance[1-10]: 3

    Why: The suggestion addresses a potential issue with the delayDuration prop, but the proposed change does not significantly improve the code's functionality since the prop is already being passed correctly.

    3

    Copy link

    qodo-merge-pro bot commented Jun 1, 2025

    CI Feedback 🧐

    (Feedback updated until commit 19f2f98)

    A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

    Action: all-green-playwright

    Failed stage: Decide whether the needed jobs succeeded or failed [❌]

    Failed test name: test-playwright

    Failure summary:

    The action failed because the required job "test-playwright" failed. The log shows that this job
    resulted in a failure status (line 63-64: "test-playwright": { "result": "failure" }), and it was
    marked as "required to succeed or be skipped" (line 76).

    Relevant error logs:
    1:  ##[group]Runner Image Provisioner
    2:  Hosted Compute Agent
    ...
    
    59:  �[36;1mEOM�[0m
    60:  �[36;1m)" \�[0m
    61:  �[36;1m"$(cat << EOM�[0m
    62:  �[36;1m  {�[0m
    63:  �[36;1m  "test-playwright": {�[0m
    64:  �[36;1m    "result": "failure",�[0m
    65:  �[36;1m    "outputs": {}�[0m
    66:  �[36;1m  }�[0m
    67:  �[36;1m}�[0m
    68:  �[36;1mEOM�[0m
    69:  �[36;1m)"�[0m
    70:  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
    71:  env:
    72:  PYTHONPATH: /home/runner/work/_actions/re-actors/alls-green/release/v1/src
    73:  ##[endgroup]
    74:  # ❌ Some of the required to succeed jobs failed 😢😢😢
    75:  📝 Job statuses:
    76:  📝 test-playwright → ❌ failure [required to succeed or be skipped]
    77:  ##[error]Process completed with exit code 1.
    78:  Cleaning up orphan processes
    

    Copy link
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 8

    🔭 Outside diff range comments (1)
    frontend/components/actions/items-action.ts (1)

    248-363: 💡 Verification agent

    🧩 Analysis chain

    Verify no remaining dashboard references in the codebase.

    The systematic route changes look correct, but let's ensure no "/dashboard" references remain that could cause broken navigation.


    🏁 Script executed:

    #!/bin/bash
    # Description: Search for any remaining references to "/dashboard" route that might need updating
    # Expected: No or minimal results that are intentionally kept (like old route handlers for redirects)
    
    echo "Searching for '/dashboard' references in the codebase..."
    rg -g '!node_modules' -g '!.git' -g '!dist' -g '!build' '"/dashboard"' --type ts --type tsx --type js --type jsx -A 2 -B 2
    
    echo -e "\nSearching for 'dashboard' in route definitions..."
    rg -g '!node_modules' -g '!.git' -g '!dist' -g '!build' "route.*dashboard|dashboard.*route" --type ts --type tsx --type js --type jsx -A 2 -B 2

    Length of output: 576


    To work around ripgrep’s unsupported TSX file type in this environment, let’s switch to grep across all relevant extensions:


    🏁 Script executed:

    #!/bin/bash
    # Search for any "/dashboard" string in TS/JS files (including TSX/JSX)
    echo "Searching for '/dashboard' references in codebase..."
    grep -R '"/dashboard"' . \
      --exclude-dir={node_modules,dist,build} \
      --include='*.ts' \
      --include='*.tsx' \
      --include='*.js' \
      --include='*.jsx' -n || true
    
    # Search for occurrences of "dashboard" in route definitions
    echo -e "\nSearching for 'dashboard' in route definitions..."
    grep -R -E 'route.*dashboard|dashboard.*route' . \
      --exclude-dir={node_modules,dist,build} \
      --include='*.ts' \
      --include='*.tsx' \
      --include='*.js' \
      --include='*.jsx' -n || true

    Length of output: 1367


    Update Remaining “/dashboard” Route References

    The route migration to remove “/dashboard” isn’t complete—there are still live code and test references that need updating to the new path (e.g., /content-library or your chosen landing route).

    Please update or remove these occurrences:

    • frontend/app/login/google/callback/page.tsx:57
      router.push("/dashboard");
    • frontend/app/password-recovery/page.tsx:54
      router.push("/dashboard");
    • frontend/app/page.tsx:54
      <Link href="/dashboard"></Link>
    • frontend/components/layout/AppSidebar.tsx:45
      url: "/dashboard",
    • Tests mocking usePathname in:
      • frontend/tests/app/dashboard/PromptNavigation.test.tsx:21
        usePathname: () => "/dashboard",
      • frontend/tests/components/layout/AppSidebar.test.tsx:8
        usePathname: () => "/dashboard",
      • frontend/tests/components/layout/MainLayout.test.tsx:45
        (usePathname as jest.Mock).mockReturnValue("/dashboard");

    Ensure each reference points to the correct new route or is removed if obsolete.

    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 283-284: Change to an optional chain.

    Unsafe fix: Change to an optional chain.

    (lint/complexity/useOptionalChain)


    [error] 293-297: Change to an optional chain.

    Unsafe fix: Change to an optional chain.

    (lint/complexity/useOptionalChain)

    🧹 Nitpick comments (10)
    frontend/hooks/use-mobile.ts (1)

    18-18: Improve return type consistency.

    Using !!isMobile converts undefined to false, but it would be clearer to handle the undefined case explicitly or use a more predictable type.

    -  return !!isMobile
    +  return isMobile ?? false
    frontend/components/layout/AppSidebar.tsx (2)

    10-10: Consider consolidating icon imports for better maintainability.

    The line imports many icons from @tabler/icons-react in a single line, which can become unwieldy as more icons are added. Consider importing them individually or grouping related icons.

    -import { IconCirclePlusFilled,IconHome,IconDashboard,IconTags,IconMessageChatbot,IconInnerShadowTop,IconUser } from "@tabler/icons-react";
    +import { 
    +  IconCirclePlusFilled,
    +  IconHome,
    +  IconDashboard,
    +  IconTags,
    +  IconMessageChatbot,
    +  IconInnerShadowTop,
    +  IconUser 
    +} from "@tabler/icons-react";

    36-66: Extract navigation data to a configuration file.

    The navigation data is hardcoded within the component, making it less maintainable. Consider extracting it to a separate configuration file or constant.

    Create a new file @/config/navigation.ts:

    export const navigationConfig = {
      navMain: [
        {
          title: "Content Library",
          url: "/content-library",
          icon: IconHome,
        },
        // ... other items
      ],
      navSecondary: [
        {
          title: "Settings",
          icon: Settings,
        },
      ],
    };

    Then import and use it in the component:

    +import { navigationConfig } from "@/config/navigation";
    
    -const data = {
    -  navMain: [
    -    // ... navigation items
    -  ],
    -  navSecondary: [
    -    // ... secondary items  
    -  ],
    -};
    +const data = navigationConfig;
    frontend/__tests__/components/layout/AppSidebar.test.tsx (7)

    6-20: Consider making the route mock more flexible for comprehensive testing.

    The hardcoded /dashboard path limits testing different route scenarios. Consider parameterizing this for better test coverage.

    -// Mock Next.js router
    -jest.mock("next/navigation", () => ({
    -  usePathname: () => "/dashboard",
    -}));
    +// Mock Next.js router
    +const mockPathname = jest.fn(() => "/dashboard");
    +jest.mock("next/navigation", () => ({
    +  usePathname: mockPathname,
    +}));

    This would allow you to test different active states by calling mockPathname.mockReturnValue("/content-library") in individual tests.


    51-58: Comprehensive navigation links testing.

    Good coverage of all expected navigation items. Consider adding href attribute verification for better link testing.

      it("renders all navigation links", () => {
        renderSidebar();
        
    -    expect(screen.getByText("Dashboard")).toBeInTheDocument();
    -    expect(screen.getByText("Favorites")).toBeInTheDocument();
    -    expect(screen.getByText("Prompts")).toBeInTheDocument();
    -    expect(screen.getByText("Content Library")).toBeInTheDocument();
    +    expect(screen.getByRole("link", { name: "Dashboard" })).toBeInTheDocument();
    +    expect(screen.getByRole("link", { name: "Favorites" })).toBeInTheDocument();
    +    expect(screen.getByRole("link", { name: "Prompts" })).toBeInTheDocument();
    +    expect(screen.getByRole("link", { name: "Content Library" })).toBeInTheDocument();
      });

    60-65: Good active state testing, but could be more comprehensive.

    The test correctly verifies the active state for the current route. Consider testing multiple routes to ensure the active state logic works correctly for all navigation items.


    67-72: Consider consolidating or removing redundant logo test.

    This test duplicates the branding verification already covered in the first test. Consider consolidating or making this test more specific to logo functionality.


    95-103: Good interaction testing, but missing settings click test.

    This test properly verifies the upload content click handler. Consider adding a similar test for the settings click handler.

    it("calls onSettingsClick when Settings button is clicked", () => {
      const { mockOnSettingsClick } = renderSidebar();
      
      const settingsButton = screen.getByRole("button", { name: "Settings" });
      fireEvent.click(settingsButton);
      
      expect(mockOnSettingsClick).toHaveBeenCalledTimes(1);
    });

    105-116: Simplify complex button selection logic.

    The current approach to find the trigger button is overly complex. Consider using more specific selectors or test IDs.

      it("renders sidebar trigger button", () => {
        renderSidebar();
        
    -    // Find all buttons with "Toggle Sidebar" name and filter for the one with data-sidebar="trigger"
    -    const triggerButtons = screen.getAllByRole("button", { name: /toggle sidebar/i });
    -    const headerTrigger = triggerButtons.find(button => 
    -      button.getAttribute("data-sidebar") === "trigger"
    -    );
    -    
    -    expect(headerTrigger).toBeInTheDocument();
    -    expect(headerTrigger).toHaveAttribute("data-sidebar", "trigger");
    +    const triggerButton = screen.getByRole("button", { name: /toggle sidebar/i });
    +    expect(triggerButton).toBeInTheDocument();
    +    expect(triggerButton).toHaveAttribute("data-sidebar", "trigger");
      });

    45-117: Consider adding tests for edge cases and accessibility.

    The current test suite covers the happy path well but could benefit from additional test cases:

    1. Different route active states: Test that other navigation items become active when the route changes
    2. User without avatar: Test the display when avatar_url is null
    3. Accessibility: Test keyboard navigation and ARIA attributes
    4. Error states: Test behavior when auth hook returns no user

    Would you like me to help generate additional test cases for these scenarios?

    📜 Review details

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

    📥 Commits

    Reviewing files that changed from the base of the PR and between 631a6ec and 5867968.

    ⛔ Files ignored due to path filters (1)
    • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
    📒 Files selected for processing (29)
    • frontend/__tests__/components/layout/AppSidebar.test.tsx (1 hunks)
    • frontend/__tests__/components/layout/MainLayout.test.tsx (1 hunks)
    • frontend/__tests__/components/layout/Sidebar.test.tsx (0 hunks)
    • frontend/__tests__/components/layout/TopNavigation.test.tsx (1 hunks)
    • frontend/app/content-library/page.tsx (3 hunks)
    • frontend/app/globals.css (2 hunks)
    • frontend/app/password-recovery/confirm/page.tsx (1 hunks)
    • frontend/app/prompts/_components/PromptForm.tsx (1 hunks)
    • frontend/app/prompts/page.tsx (2 hunks)
    • frontend/app/setup/page.tsx (2 hunks)
    • frontend/components/actions/google-auth-action.ts (1 hunks)
    • frontend/components/actions/items-action.ts (3 hunks)
    • frontend/components/actions/login-action.ts (1 hunks)
    • frontend/components/layout/AppSidebar.tsx (1 hunks)
    • frontend/components/layout/MainLayout.tsx (2 hunks)
    • frontend/components/layout/Sidebar.tsx (0 hunks)
    • frontend/components/layout/TopNavigation.tsx (6 hunks)
    • frontend/components/setup/SetupContent.tsx (3 hunks)
    • frontend/components/ui/button.tsx (3 hunks)
    • frontend/components/ui/input.tsx (1 hunks)
    • frontend/components/ui/separator.tsx (2 hunks)
    • frontend/components/ui/sheet.tsx (7 hunks)
    • frontend/components/ui/sidebar.tsx (32 hunks)
    • frontend/components/ui/skeleton.tsx (1 hunks)
    • frontend/components/ui/tooltip.tsx (3 hunks)
    • frontend/hooks/use-mobile.ts (1 hunks)
    • frontend/hooks/useAuthRedirect.ts (2 hunks)
    • frontend/middleware.ts (2 hunks)
    • frontend/package.json (1 hunks)
    💤 Files with no reviewable changes (2)
    • frontend/tests/components/layout/Sidebar.test.tsx
    • frontend/components/layout/Sidebar.tsx
    🧰 Additional context used
    🧬 Code Graph Analysis (5)
    frontend/components/ui/skeleton.tsx (1)
    frontend/lib/utils.ts (1)
    • cn (7-9)
    frontend/components/ui/separator.tsx (1)
    frontend/lib/utils.ts (1)
    • cn (7-9)
    frontend/components/ui/button.tsx (1)
    frontend/lib/utils.ts (1)
    • cn (7-9)
    frontend/components/ui/sheet.tsx (1)
    frontend/lib/utils.ts (1)
    • cn (7-9)
    frontend/components/ui/input.tsx (1)
    frontend/lib/utils.ts (1)
    • cn (7-9)
    ⏰ Context from checks skipped due to timeout of 90000ms (7)
    • GitHub Check: test-playwright (4, 4)
    • GitHub Check: test-playwright (3, 4)
    • GitHub Check: test-playwright (1, 4)
    • GitHub Check: test-playwright (2, 4)
    • GitHub Check: Complete CI/CD Pipeline
    • GitHub Check: test-backend
    • GitHub Check: test-docker-compose
    🔇 Additional comments (44)
    frontend/components/ui/skeleton.tsx (1)

    1-1: Approve stylistic changes
    The removal of trailing semicolons and JSDoc comments aligns with the project’s semicolon-free style. No functional or API changes were introduced.

    Also applies to: 10-10, 13-13

    frontend/components/ui/tooltip.tsx (1)

    1-1: Approve formatting adjustments
    All edits are purely stylistic (removing semicolons, JSDoc comments, and reformatting JSX returns). Component logic and props remain unchanged.

    Also applies to: 3-4, 6-6, 18-18, 28-28, 34-34, 50-50, 58-58, 61-61

    frontend/components/ui/sheet.tsx (1)

    1-140: Approve formatting unification
    This file has only had semicolons and comments removed and minor JSX reformatting. No behavior or prop signatures were altered.

    frontend/components/ui/separator.tsx (1)

    1-29: Approve slot rename & formatting
    The data-slot attribute is updated to "separator" for consistency with other UI components, and trailing semicolons/comments were removed. Ensure that any references or selectors for the old separator-root are updated accordingly.

    frontend/components/ui/sidebar.tsx (1)

    1-727: Approve styling overhaul
    All changes in this file standardize the semicolon-free, comment-free formatting across the Sidebar components. There are no changes to logic, hooks, or public APIs.

    frontend/components/actions/login-action.ts (1)

    93-94: LGTM! Post-login redirect updated correctly.

    The redirect destination has been appropriately updated from "/dashboard" to "/content-library" with a corresponding comment update. This aligns with the broader navigation refactoring.

    frontend/components/actions/google-auth-action.ts (1)

    47-48: LGTM! Google OAuth redirect aligned with login flow.

    The redirect destination has been consistently updated to "/content-library", maintaining uniformity across all authentication methods.

    frontend/app/password-recovery/confirm/page.tsx (1)

    29-32: LGTM! User redirect updated for consistency.

    The redirect for already authenticated users has been correctly updated to "/content-library", maintaining consistency with the new primary landing page.

    frontend/components/actions/items-action.ts (3)

    248-248: LGTM! Cache revalidation path updated correctly.

    The revalidatePath call has been updated to "/content-library" to ensure proper cache invalidation for the new route.


    346-346: LGTM! Cache revalidation path updated consistently.

    The revalidatePath call maintains consistency with the removeItem function, ensuring proper cache invalidation.


    362-363: LGTM! Post-addition redirect updated appropriately.

    The redirect destination and comment have been updated to reflect the new primary content page location.

    frontend/__tests__/components/layout/TopNavigation.test.tsx (1)

    25-26: LGTM! Test updated to match component refactoring.

    The test assertion has been updated to check for the "设置" (Settings) button, which aligns with the TopNavigation component simplification mentioned in the AI summary.

    frontend/hooks/useAuthRedirect.ts (1)

    10-10: LGTM! Consistent redirection path update.

    The changes correctly update the default post-authentication redirection from "/dashboard" to "/content-library" in both documentation and implementation. The logic flow remains intact.

    Also applies to: 40-42

    frontend/app/prompts/_components/PromptForm.tsx (1)

    188-189: Excellent accessibility improvement!

    The refactoring from a custom state prop to standard aria-invalid attribute and conditional CSS classes is a great improvement. This approach:

    • Follows web accessibility standards (WCAG)
    • Uses semantic HTML attributes for screen readers
    • Maintains visual error indication through conditional styling
    • Aligns with modern React form practices
    frontend/components/setup/SetupContent.tsx (1)

    185-185: LGTM! Consistent redirection updates throughout setup flow.

    The changes properly update all references to the post-setup redirection destination:

    • Documentation comments updated to reflect "/content-library" target
    • Console logging updated for debugging consistency
    • Router navigation updated to new destination

    The core setup logic and error handling remain intact. These changes align with the broader navigation structure updates.

    Also applies to: 239-239, 339-339, 344-345

    frontend/app/setup/page.tsx (1)

    10-10: LGTM! Completes the coordinated navigation update.

    The changes correctly update the setup page redirection logic:

    • JSDoc documentation reflects the new destination
    • Inline comments accurately describe the updated flow
    • Redirect call properly routes to "/content-library"

    The authentication logic remains sound and this completes the consistent navigation structure update across the application.

    Also applies to: 22-22, 26-26

    frontend/hooks/use-mobile.ts (2)

    9-11: ⚠️ Potential issue

    Fix inconsistent breakpoint logic.

    There's an inconsistency between the media query breakpoint and the onChange handler:

    • Media query uses max-width: ${MOBILE_BREAKPOINT - 1}px (767px)
    • onChange uses window.innerWidth < MOBILE_BREAKPOINT (768px)

    This could cause the media query listener and the direct width check to have different results.

    -    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
    +    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
         const onChange = () => {
    -      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    +      setIsMobile(window.innerWidth <= MOBILE_BREAKPOINT - 1)
         }

    Likely an incorrect or invalid review comment.


    6-6: 🛠️ Refactor suggestion

    Consider SSR-compatible initial state.

    The initial state of undefined may cause hydration mismatches in SSR environments since the server can't determine the viewport size.

    -  const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
    +  const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
    +    typeof window !== 'undefined' ? window.innerWidth < MOBILE_BREAKPOINT : undefined
    +  )

    Likely an incorrect or invalid review comment.

    frontend/app/content-library/page.tsx (2)

    234-234: LGTM! Improved spacing and visual consistency.

    The padding changes from pt-6 to py-6 provide better vertical balance, and the addition of py-6 to the preview card maintains consistent spacing throughout the component.

    Also applies to: 259-259, 299-299


    254-254: LGTM! More subtle selection indicator.

    Reducing the ring thickness from ring-2 to ring-1 creates a more subtle selection indicator that's less visually aggressive while still clearly indicating the selected state.

    frontend/package.json (1)

    48-48: LGTM! Appropriate dependency updates.

    The addition of @tabler/icons-react and the patch update to class-variance-authority support the new UI components introduced in this PR. The reorganization of crypto-js doesn't affect functionality.

    Also applies to: 51-51, 54-54

    frontend/middleware.ts (2)

    61-63: LGTM: Redirect destination updated correctly.

    The redirect logic from setup page to content-library is properly implemented and aligns with the broader UI navigation restructuring.


    81-81: LGTM: Matcher configuration updated appropriately.

    Adding "/content-library/:path*" to the matcher list is necessary to enable middleware interception for the new navigation structure.

    frontend/app/prompts/page.tsx (3)

    120-125: LGTM: SearchParams type updated for async handling.

    The type change from optional object to optional Promise is correct for Next.js App Router compatibility.


    187-192: LGTM: Consistent type update in PromptsContent.

    The searchParams type is consistently updated to handle async resolution.


    199-201: LGTM: Proper async searchParams handling.

    The implementation correctly awaits the searchParams Promise and provides a safe fallback to an empty object. This prevents potential issues with accessing unresolved Promises.

    frontend/components/layout/MainLayout.tsx (3)

    4-5: LGTM: Appropriate imports for new sidebar architecture.

    The imports correctly bring in the new AppSidebar component and sidebar provider components.


    27-35: LGTM: Well-configured SidebarProvider with custom dimensions.

    The custom CSS variables provide sensible sidebar widths that are more compact than defaults. The inline styles approach is acceptable for component-specific customization.


    36-70:

    ❓ Verification inconclusive

    Verify that page title functionality is properly handled.

    The layout restructure looks clean and follows React patterns well. However, I notice that the pageTitle prop is no longer used in the header structure - it's only used for the isFullscreen determination.

    Please verify that page titles are now handled by individual pages or the AppSidebar component, since they've been removed from the main layout header.


    🏁 Script executed:

    #!/bin/bash
    # Description: Check how page titles are handled in the new structure
    # Expected: Find page title usage in AppSidebar or individual pages
    
    echo "=== Searching for page title usage in AppSidebar ==="
    ast-grep --pattern 'pageTitle'
    
    echo "=== Searching for document.title or metadata usage ==="
    rg -A 3 "document\.title|metadata.*title"
    
    echo "=== Checking if pages set their own titles ==="
    rg -A 2 "title.*:" --type tsx

    Length of output: 66591


    Ensure Page Title Display Is Handled Elsewhere

    Our verification didn’t find any rendering of pageTitle beyond the isFullscreen check in MainLayout:

    • No references to pageTitle in AppSidebar or page‐level components
    • No document.title assignments, React Helmet usage, or similar hooks
    • Tests still expect a data-page-title attribute on MainLayout

    Please confirm that:

    1. Individual pages set their own titles (e.g., via React Helmet or Next.js metadata).
    2. AppSidebar or another component is responsible for displaying the current title.
    3. The now-unused pageTitle prop and any related test assertions are removed or updated.
    frontend/components/layout/TopNavigation.tsx (5)

    3-3: LGTM: Cleaned up unused imports.

    Removing imports for the eliminated search and logo functionality keeps the code clean.


    30-31: LGTM: Improved semantic structure.

    Using a semantic header element instead of a generic div is a good accessibility and HTML semantics improvement.


    40-43: LGTM: Visual separators enhance UI hierarchy.

    The vertical separators between action buttons improve visual grouping and spacing.

    Also applies to: 54-57


    46-46: LGTM: Consistent button variant updates.

    Changing from "ghost" to "outline" variants provides better visual consistency and likely aligns with the updated design system.

    Also applies to: 62-62


    88-88: LGTM: Updated color classes for design consistency.

    The color changes from gray to neutral classes likely align with an updated design system or theme structure.

    Also applies to: 106-106

    frontend/components/layout/AppSidebar.tsx (1)

    73-176: The component implementation looks good overall.

    The AppSidebar component is well-structured with proper use of React hooks, conditional rendering, and accessibility features. The collapsible functionality and user profile integration are implemented correctly.

    frontend/components/ui/button.tsx (1)

    1-1: LGTM! Good styling refinements and code cleanup.

    The changes improve the button component with:

    • Standardized import formatting
    • Refined shadow and focus-visible styles for better visual consistency
    • Added dark mode support for destructive variant
    • Code style cleanup removing trailing punctuation

    These are solid improvements that maintain backward compatibility while enhancing the visual design.

    Also applies to: 5-5, 13-13, 15-15, 35-36, 46-47, 56-57, 59-59

    frontend/__tests__/components/layout/MainLayout.test.tsx (1)

    1-140: Overall test structure and coverage is excellent.

    The test suite provides comprehensive coverage of the MainLayout component with proper mocking strategies and good scenario coverage including fullscreen mode, active navigation, and sidebar provider integration.

    frontend/components/ui/input.tsx (1)

    10-15: Good consolidation of input styling with accessibility support.

    The new implementation consolidates all styling into a single, comprehensive class string with proper focus-visible and aria-invalid support. The styling approach is more direct and includes good accessibility features.

    frontend/__tests__/components/layout/AppSidebar.test.tsx (6)

    1-5: LGTM: Clean imports and proper testing setup.

    The imports are well-structured and include all necessary testing utilities and component dependencies.


    21-25: LGTM: Appropriate logout action mocking.

    The logout action mock is simple and suitable for testing component behavior.


    27-43: Well-designed helper function with good reusability.

    The renderSidebar function follows good testing patterns by:

    • Providing sensible defaults
    • Returning both render result and mocks for verification
    • Encapsulating the provider setup

    46-49: LGTM: Basic rendering test covers core functionality.

    Simple and effective test to ensure the component renders successfully.


    74-79: LGTM: Proper user information display testing.

    Good verification that user data from the auth mock is correctly displayed in the UI.


    89-93: LGTM: Settings button test is appropriate.

    Simple and effective verification of the settings button presence.

    Comment on lines +491 to +498
    @layer base {
    * {
    @apply border-border outline-ring/50;
    }
    body {
    @apply bg-background text-foreground;
    }
    }
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    ⚠️ Potential issue

    Consolidate duplicate @layer base declarations.

    This creates a second @layer base block that duplicates and potentially conflicts with the existing one (lines 283-308). The body styles are already defined in the first @layer base block with @apply bg-background text-foreground font-sans antialiased.

    Consider consolidating these styles into the existing @layer base block to avoid specificity conflicts and maintain a single source of truth.

    -@layer base {
    -  * {
    -    @apply border-border outline-ring/50;
    -  }
    -  body {
    -    @apply bg-background text-foreground;
    -  }
    -}

    Add the border-border outline-ring/50 styles to the existing * selector in the first @layer base block instead.

    📝 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
    @layer base {
    * {
    @apply border-border outline-ring/50;
    }
    body {
    @apply bg-background text-foreground;
    }
    }
    🤖 Prompt for AI Agents
    In frontend/app/globals.css around lines 491 to 498, there is a duplicate @layer
    base block that conflicts with the existing one at lines 283-308. To fix this,
    remove the second @layer base block entirely and add the styles `border-border
    outline-ring/50` to the existing `*` selector inside the first @layer base
    block. This consolidates all base styles in one place and prevents specificity
    conflicts.
    

    @@ -1,6 +1,8 @@
    /* stylelint-disable at-rule-no-unknown */
    @import "tailwindcss";

    @custom-variant dark (&:is(.dark *));
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Remove duplicate dark variant declaration.

    The @custom-variant dark declaration duplicates the existing @variant dark declaration on line 7. This redundancy could cause confusion and maintenance issues.

    -@custom-variant dark (&:is(.dark *));
    📝 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
    @custom-variant dark (&:is(.dark *));
    🤖 Prompt for AI Agents
    In frontend/app/globals.css at line 4, remove the duplicate `@custom-variant
    dark (&:is(.dark *));` declaration because it duplicates the existing `@variant
    dark` declaration on line 7. Keeping only the `@variant dark` declaration will
    avoid redundancy and improve maintainability.
    

    import { useAuth } from "@/lib/auth";
    import { logout } from "@/components/actions/logout-action";

    // 主要导航数据
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Replace Chinese comments with English for better internationalization.

    The codebase contains Chinese comments which may not be accessible to all team members. Consider using English comments for better collaboration in international teams.

    -// 主要导航数据
    +// Main navigation data
    
    -          {/* 左侧:Logo和品牌名称 - 在折叠状态下隐藏 */}
    +          {/* Left: Logo and brand name - hidden in collapsed state */}
    
    -          {/* 右侧:Sidebar Trigger - 在折叠状态下居中 */}
    +          {/* Right: Sidebar Trigger - centered in collapsed state */}
    
    -        {/* 快速创建 - 采用参考示例样式 */}
    +        {/* Quick create - using reference example styles */}
    
    -        {/* 主要导航 */}
    +        {/* Main navigation */}
    
    -        {/* 次要导航 */}
    +        {/* Secondary navigation */}

    Also applies to: 81-81, 86-86, 92-92, 111-111, 133-133

    🤖 Prompt for AI Agents
    In frontend/components/layout/AppSidebar.tsx at lines 35, 81, 86, 92, 111, and
    133, replace all Chinese comments with English comments to improve code
    accessibility and collaboration for international team members. Translate the
    existing Chinese comments accurately into clear English equivalents while
    preserving their original meaning.
    

    Comment on lines +60 to +66
    navSecondary: [
    {
    title: "Settings",
    icon: Settings,
    },
    ],
    };
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Remove unused navigation data or implement it in the UI.

    The navSecondary data is defined but never used in the sidebar UI. Either remove it or implement the secondary navigation section.

    If you want to implement the secondary navigation, update lines 134-138:

             <SidebarGroup className="mt-auto !px-4">
               <SidebarGroupContent>
    -            
    +            <SidebarMenu>
    +              {data.navSecondary.map((item) => (
    +                <SidebarMenuItem key={item.title}>
    +                  <SidebarMenuButton onClick={onSettingsClick} tooltip={item.title}>
    +                    <item.icon />
    +                    <span>{item.title}</span>
    +                  </SidebarMenuButton>
    +                </SidebarMenuItem>
    +              ))}
    +            </SidebarMenu>
               </SidebarGroupContent>
             </SidebarGroup>

    Or if not needed, remove the unused data:

    -  navSecondary: [
    -    {
    -      title: "Settings",
    -      icon: Settings,
    -    },
    -  ],
    📝 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
    navSecondary: [
    {
    title: "Settings",
    icon: Settings,
    },
    ],
    };
    <SidebarGroup className="mt-auto !px-4">
    <SidebarGroupContent>
    <SidebarMenu>
    {data.navSecondary.map((item) => (
    <SidebarMenuItem key={item.title}>
    <SidebarMenuButton onClick={onSettingsClick} tooltip={item.title}>
    <item.icon />
    <span>{item.title}</span>
    </SidebarMenuButton>
    </SidebarMenuItem>
    ))}
    </SidebarMenu>
    </SidebarGroupContent>
    </SidebarGroup>
    🤖 Prompt for AI Agents
    In frontend/components/layout/AppSidebar.tsx around lines 60 to 66, the
    navSecondary navigation data is defined but not used in the sidebar UI. To fix
    this, either remove the entire navSecondary array if it is unnecessary, or
    implement a secondary navigation section in the sidebar component by adding UI
    code to render navSecondary items, similar to the primary navigation rendering
    around lines 134 to 138.
    

    (usePathname as jest.Mock).mockReturnValue("/dashboard");
    });

    it("应该正确渲染MainLayout和所有子组件", () => {
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Consider using English for test descriptions to improve international collaboration.

    The test descriptions are written in Chinese, which may not be accessible to all team members. Consider using English for better collaboration in international teams.

    -  it("应该正确渲染MainLayout和所有子组件", () => {
    +  it("should correctly render MainLayout and all child components", () => {
    
    -  it("应该在fullscreen模式下正确渲染", () => {
    +  it("should correctly render in fullscreen mode", () => {
    
    -  it("应该正确显示当前激活的导航项", () => {
    +  it("should correctly highlight the current active navigation item", () => {
    
    -  it("应该包含SidebarProvider并正确管理sidebar状态", () => {
    +  it("should include SidebarProvider and correctly manage sidebar state", () => {
    
    -  it("应该正确处理没有pageTitle的情况", () => {
    +  it("should correctly handle cases without pageTitle", () => {

    Also applies to: 70-70, 87-87, 111-111, 127-127

    🤖 Prompt for AI Agents
    In frontend/__tests__/components/layout/MainLayout.test.tsx at lines 48, 70, 87,
    111, and 127, the test descriptions are currently written in Chinese. To improve
    international collaboration and accessibility, rewrite these test descriptions
    in English while preserving their original meaning.
    

    Comment on lines +56 to +58
    expect(screen.getByAltText("Nexus Logo")).toBeInTheDocument();
    expect(screen.getByText("Nexus")).toBeInTheDocument();
    expect(screen.getByText("Dashboard")).toBeInTheDocument();
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    💡 Verification agent

    🧩 Analysis chain

    Fix branding inconsistency between tests and component.

    The tests reference "Nexus" branding, but the AppSidebar component uses "Telepace". This inconsistency suggests the tests may be outdated or testing the wrong component.

    Run this script to verify the current branding used in the MainLayout and AppSidebar components:

    Also applies to: 78-78


    🏁 Script executed:

    #!/bin/bash
    # Description: Check branding consistency between MainLayout, AppSidebar and tests
    echo "=== Checking for Nexus references ==="
    rg -i "nexus" frontend/components/layout/
    echo "=== Checking for Telepace references ==="  
    rg -i "telepace" frontend/components/layout/
    echo "=== Checking test expectations ==="
    rg "Nexus" frontend/__tests__/components/layout/MainLayout.test.tsx

    Length of output: 706


    🏁 Script executed:

    #!/bin/bash
    # Inspect MainLayout for branding and alt text
    echo "=== Searching for Telepace in MainLayout ==="
    rg -n "Telepace" frontend/components/layout/MainLayout.tsx
    echo "=== Searching for alt attributes in MainLayout ==="
    rg -n "alt=" frontend/components/layout/MainLayout.tsx
    echo "=== Inspecting AppSidebar img tags for logos ==="
    rg -n "<img" frontend/components/layout/AppSidebar.tsx

    Length of output: 487


    Update MainLayout tests to reflect Telepace branding

    The MainLayout tests still reference “Nexus” even though the AppSidebar and layout now use “Telepace.” Update the assertions in frontend/tests/components/layout/MainLayout.test.tsx to match the current branding.

    • File: frontend/tests/components/layout/MainLayout.test.tsx
    Replace all occurrences of “Nexus” with “Telepace” in the following assertions:

    - expect(screen.getByAltText("Nexus Logo")).toBeInTheDocument();
    - expect(screen.getByText("Nexus")).toBeInTheDocument();
    - expect(screen.getByText("Nexus")).toBeInTheDocument();
    + expect(screen.getByAltText("Telepace Logo")).toBeInTheDocument();
    + expect(screen.getByText("Telepace")).toBeInTheDocument();
    + expect(screen.getByText("Telepace")).toBeInTheDocument();
    🤖 Prompt for AI Agents
    In frontend/__tests__/components/layout/MainLayout.test.tsx around lines 56 to
    58 and line 78, update the test assertions to replace all occurrences of "Nexus"
    with "Telepace" to match the current branding used in the MainLayout and
    AppSidebar components. This includes changing the alt text and any text content
    assertions referencing "Nexus" to "Telepace" to ensure the tests reflect the
    actual UI branding.
    

    Comment on lines +5 to +19
    function Input({ className, type, ...props }: React.ComponentProps<"input">) {
    return (
    <input
    type={type}
    data-slot="input"
    className={cn(
    "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
    "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
    "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
    className
    )}
    {...props}
    />
    )
    }
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    💡 Verification agent

    🧩 Analysis chain

    Verify that the Input component simplification doesn't break existing usage.

    The component has been significantly simplified by removing:

    • forwardRef functionality
    • Variant-based styling with state prop
    • Custom interface extending VariantProps

    This is a breaking change that may affect existing usage throughout the codebase.

    Run this script to verify existing Input component usage:


    🏁 Script executed:

    #!/bin/bash
    # Description: Check for Input component usage that might be affected by the simplification
    
    echo "=== Checking for Input component imports and usage ==="
    rg -A 3 -B 1 "import.*Input" frontend/
    
    echo "=== Checking for state prop usage ==="
    rg "state=" frontend/ --type tsx --type ts
    
    echo "=== Checking for forwardRef usage with Input ==="
    rg -A 5 -B 5 "ref.*Input|Input.*ref" frontend/
    
    echo "=== Checking for Input with custom props ==="
    ast-grep --pattern '<Input $$$state=$_ $$$>'

    Length of output: 65742


    Let’s broaden the search to catch any JSX usage and imports of the Input component in TS/TSX files:

    This will help confirm whether removing the variant API truly has no downstream impact.


    🏁 Script executed:

    #!/bin/bash
    # Search for JSX usage of <Input> in TSX files
    echo "=== JSX usage of <Input> ==="
    rg "<Input" frontend/ --type tsx -n
    
    # Search for any import of Input in TS/TSX
    echo -e "\n=== import statements for Input ==="
    rg "import.*\bInput\b" frontend/ --type tsx --type ts -n

    Length of output: 306


    Let’s re-run using file globs instead of --type:


    🏁 Script executed:

    #!/bin/bash
    echo "=== JSX usage of <Input> in TSX files ==="
    rg '<Input\b' -g '*.tsx' frontend/ -n
    
    echo -e "\n=== import statements for Input ==="
    rg 'import.*\bInput\b' -g '*.ts*' frontend/ -n

    Length of output: 5177


    Action Required: Restore ref forwarding and review variant API removal in Input

    The Input component is imported and used in dozens of places across the frontend (e.g. SettingsPanel.tsx, PromptForm.tsx, TagForm.tsx, login/page.tsx, etc.). By stripping out forwardRef, any refs passed via form libraries like React Hook Form (e.g. {...field}) or direct ref props will no longer attach to the underlying <input>, breaking focus, validation, and uncontrolled use-cases.

    Additionally, although no direct state prop usage was found, removing the variant-based styling API may impact error/invalid state styling for components that previously relied on state="error" or similar.

    Please update the Input implementation to:

    • Wrap in forwardRef<HTMLInputElement, React.ComponentProps<'input'>>
    • Attach ref to the actual <input>
    • (Optional) Reintroduce or adapt the variant/state prop if error-state styling is needed

    Suggested diff:

    -import function Input({ className, type, ...props }: React.ComponentProps<"input">) {
    -  return <input type={type} className={cn(/*…*/)} {...props} />
    -}
    +import { forwardRef } from "react"
    +
    +export const Input = forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
    +  ({ className, type, ...props }, ref) => (
    +    <input
    +      ref={ref}
    +      type={type}
    +      data-slot="input"
    +      className={cn(/* existing class list */, className)}
    +      {...props}
    +    />
    +  )
    +)
    +
    +Input.displayName = "Input"

    – After restoring forwardRef, verify all form integrations and error-state styles continue to work.
    – If you intend to permanently drop the variant/state API, ensure no components depend on it or update them to use the new styling approach.

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

    🤖 Prompt for AI Agents
    In frontend/components/ui/input.tsx around lines 5 to 19, the Input component
    was simplified by removing forwardRef and the variant/state prop, which breaks
    ref forwarding and potentially error-state styling. To fix this, wrap the Input
    function with React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>,
    pass the ref to the underlying <input> element, and optionally reintroduce or
    adapt the variant/state prop if error-state styling is needed. After these
    changes, verify that all form integrations and error-state styles continue to
    work correctly.
    

    Comment on lines +81 to +87
    it("renders upload content section", () => {
    renderSidebar();

    // 测试Upload Content按钮存在
    const uploadContentButtons = screen.getAllByText("Upload Content");
    expect(uploadContentButtons.length).toBeGreaterThan(0);
    });
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Address language consistency and improve test specificity.

    Two issues to address:

    1. Chinese comment in English codebase
    2. Vague assertion using length > 0
      it("renders upload content section", () => {
        renderSidebar();
        
    -    // 测试Upload Content按钮存在
    -    const uploadContentButtons = screen.getAllByText("Upload Content");
    -    expect(uploadContentButtons.length).toBeGreaterThan(0);
    +    // Test Upload Content button exists
    +    expect(screen.getByRole("button", { name: "Upload Content" })).toBeInTheDocument();
      });
    📝 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
    it("renders upload content section", () => {
    renderSidebar();
    // 测试Upload Content按钮存在
    const uploadContentButtons = screen.getAllByText("Upload Content");
    expect(uploadContentButtons.length).toBeGreaterThan(0);
    });
    it("renders upload content section", () => {
    renderSidebar();
    // Test Upload Content button exists
    expect(screen.getByRole("button", { name: "Upload Content" })).toBeInTheDocument();
    });
    🤖 Prompt for AI Agents
    In frontend/__tests__/components/layout/AppSidebar.test.tsx around lines 81 to
    87, replace the Chinese comment with an English one for language consistency and
    improve the test assertion by checking for a more specific condition, such as
    verifying that exactly one "Upload Content" button is rendered or that the
    button is visible, instead of just asserting the length is greater than zero.
    

    Copy link
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 2

    ♻️ Duplicate comments (3)
    frontend/components/layout/AppSidebar.tsx (3)

    34-34: Replace Chinese comments with English for better internationalization.

    This is the same issue flagged in previous reviews. Chinese comments should be replaced with English for better team collaboration.


    59-65: Remove unused navigation data or implement it in the UI.

    The navSecondary data is still defined but unused in the sidebar UI, as flagged in previous reviews. This creates dead code.


    81-81: Replace Chinese comments with English for better internationalization.

    Multiple Chinese comments throughout the component need to be translated to English, as flagged in previous reviews.

    Also applies to: 86-86, 92-92, 111-111, 133-133

    🧹 Nitpick comments (2)
    frontend/components/layout/AppSidebar.tsx (2)

    6-10: Consider consolidating icon libraries for consistency.

    The component imports icons from both lucide-react and @tabler/icons-react. Using a single icon library would improve consistency and reduce bundle size.

    Consider standardizing on one icon library. If you prefer Tabler icons, you could replace the Lucide icons:

    import {
    -  Settings,
      ChevronUp,
    } from "lucide-react";
    -import { IconCirclePlusFilled,IconHome,IconDashboard,IconTags,IconMessageChatbot,IconInnerShadowTop,IconUser } from "@tabler/icons-react";
    +import { 
    +  IconCirclePlusFilled,
    +  IconHome,
    +  IconDashboard,
    +  IconTags,
    +  IconMessageChatbot,
    +  IconInnerShadowTop,
    +  IconUser,
    +  IconSettings,
    +  IconChevronUp
    +} from "@tabler/icons-react";

    147-151: Improve fallback values for user information display.

    The fallback values "User" and "[email protected]" could be more descriptive and less confusing for users.

    Consider more appropriate fallback values:

                        <span className="truncate font-semibold">
    -                      {user?.full_name || "User"}
    +                      {user?.full_name || "Guest User"}
                        </span>
                        <span className="truncate text-xs">
    -                      {user?.email || "[email protected]"}
    +                      {user?.email || "Not signed in"}
                        </span>
    📜 Review details

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

    📥 Commits

    Reviewing files that changed from the base of the PR and between 5867968 and 19f2f98.

    📒 Files selected for processing (3)
    • Makefile (1 hunks)
    • frontend/app/content-library/page.tsx (3 hunks)
    • frontend/components/layout/AppSidebar.tsx (1 hunks)
    ✅ Files skipped from review due to trivial changes (1)
    • Makefile
    🚧 Files skipped from review as they are similar to previous changes (1)
    • frontend/app/content-library/page.tsx
    🧰 Additional context used
    🧬 Code Graph Analysis (1)
    frontend/components/layout/AppSidebar.tsx (3)
    frontend/components/ui/sidebar.tsx (11)
    • Sidebar (702-702)
    • SidebarHeader (709-709)
    • SidebarTrigger (724-724)
    • SidebarContent (703-703)
    • SidebarGroup (705-705)
    • SidebarGroupContent (707-707)
    • SidebarMenu (712-712)
    • SidebarMenuItem (716-716)
    • SidebarMenuButton (715-715)
    • SidebarFooter (704-704)
    • SidebarRail (722-722)
    frontend/jest.setup.ts (1)
    • usePathname (191-193)
    frontend/components/ui/dropdown-menu.tsx (4)
    • DropdownMenu (287-287)
    • DropdownMenuTrigger (289-289)
    • DropdownMenuContent (290-290)
    • DropdownMenuItem (293-293)
    ⏰ Context from checks skipped due to timeout of 90000ms (7)
    • GitHub Check: test-playwright (4, 4)
    • GitHub Check: test-playwright (3, 4)
    • GitHub Check: test-playwright (1, 4)
    • GitHub Check: test-playwright (2, 4)
    • GitHub Check: Complete CI/CD Pipeline
    • GitHub Check: test-backend
    • GitHub Check: test-docker-compose

    Comment on lines +163 to +165
    <DropdownMenuItem onClick={() => logout()}>
    <span>Sign out</span>
    </DropdownMenuItem>
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Add error handling for logout action.

    The logout function is called without error handling, which could lead to silent failures if the logout process encounters issues.

    Add error handling for the logout action:

    -                <DropdownMenuItem onClick={() => logout()}>
    +                <DropdownMenuItem onClick={async () => {
    +                  try {
    +                    await logout();
    +                  } catch (error) {
    +                    console.error('Logout failed:', error);
    +                    // Optionally show user notification
    +                  }
    +                }}>
    📝 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
    <DropdownMenuItem onClick={() => logout()}>
    <span>Sign out</span>
    </DropdownMenuItem>
    <DropdownMenuItem onClick={async () => {
    try {
    await logout();
    } catch (error) {
    console.error('Logout failed:', error);
    // Optionally show user notification
    }
    }}>
    <span>Sign out</span>
    </DropdownMenuItem>
    🤖 Prompt for AI Agents
    In frontend/components/layout/AppSidebar.tsx around lines 163 to 165, the logout
    function is called without any error handling, which may cause silent failures.
    Wrap the logout call in a try-catch block or use a promise catch to handle
    potential errors. In the catch block, log the error or display a user-friendly
    message to ensure any issues during logout are properly handled and visible.
    

    Comment on lines +71 to +73
    export function AppSidebar({ onAddContentClick, ...props }: AppSidebarProps) {
    const pathname = usePathname();
    const { user } = useAuth();
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    🛠️ Refactor suggestion

    Add error handling for authentication context.

    The component assumes useAuth() will always return a valid user object, but should handle cases where authentication might fail or user data is unavailable.

    Consider adding error boundaries or fallback handling:

    export function AppSidebar({ onAddContentClick, ...props }: AppSidebarProps) {
      const pathname = usePathname();
    -  const { user } = useAuth();
    +  const { user, isLoading, error } = useAuth();
    +  
    +  if (error) {
    +    console.error('Authentication error in sidebar:', error);
    +  }

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

    🤖 Prompt for AI Agents
    In frontend/components/layout/AppSidebar.tsx around lines 71 to 73, the code
    assumes useAuth() always returns a valid user object, which may not be true if
    authentication fails or user data is missing. Add error handling to check if the
    user object exists before using it. Implement fallback UI or logic to handle
    cases when user is undefined or null, ensuring the component does not break and
    provides a graceful fallback or error message.
    

    @kubbot kubbot closed this Jun 2, 2025
    @github-project-automation github-project-automation bot moved this from Backlog to Done in nexus Jun 2, 2025
    @kubbot kubbot deleted the feature/ui branch June 2, 2025 01:28
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    Status: Done
    Development

    Successfully merging this pull request may close these issues.

    2 participants