Skip to content

SCRUM-238-QA 반영#38

Merged
gs0428 merged 14 commits into
devfrom
SCRUM-238
Jul 14, 2025
Merged

SCRUM-238-QA 반영#38
gs0428 merged 14 commits into
devfrom
SCRUM-238

Conversation

@gs0428

@gs0428 gs0428 commented Jul 14, 2025

Copy link
Copy Markdown
Member

🛠️ 구현한 부분

🖼️ 실행 화면(선택)

🔥 어려웠던 부분(선택)

🔍 참고(선택)

Summary by CodeRabbit

  • New Features

    • Added toast notifications for success, info, and error messages throughout the app.
    • Introduced dynamic filtering for keyword suggestions in input fields.
    • Enabled interactive, resizable chat UI with improved session management and loading states.
    • Added support for category creation directly from the bookmarks sidebar.
    • Added a new plus icon and enhanced dropdown menus for navigation and bookmark themes.
  • Improvements

    • Simplified bookmark visualization by removing advanced filter, color, and theme controls.
    • Enhanced modal and spinner components for better usability and visual feedback.
    • Updated bookmark creation and editing flows with improved navigation and UI feedback.
    • Streamlined chat session handling and removed unnecessary session creation steps.
    • Improved accessibility and visual feedback for buttons and loading states.
  • Bug Fixes

    • Fixed potential issues with undefined values in bookmark detail views.
    • Improved validation and user feedback for category addition.
  • Refactor

    • Migrated several client components to server components for better performance.
    • Consolidated and simplified state management by removing unnecessary stores and enums.
  • Chores

    • Updated dependencies and added new libraries for theming and toast notifications.
    • Added utility functions for URL parameter handling and search filtering.

@gs0428 gs0428 self-assigned this Jul 14, 2025
@gs0428 gs0428 added ✨ feat 기능 구현을 진행합니다. 🚨 fix 버그를 수정합니다. labels Jul 14, 2025
@coderabbitai

coderabbitai Bot commented Jul 14, 2025

Copy link
Copy Markdown

Walkthrough

This update refactors and streamlines the bookmark and chat features across both the extension and web app. It removes redundant state management, simplifies navigation and UI flows, introduces toast notifications, and enhances chat and bookmark visualizations with improved control and flexibility. Several utility functions and components are added, while unused models, mutations, and constants are removed.

Changes

File(s) / Area Change Summary
apps/extension/src/components/loading/index.tsx Added optional description prop to Loading component; updated rendering logic.
apps/extension/src/hooks/use-detect-path.ts Integrated user login state into path detection and navigation logic.
apps/extension/src/index.css Added button cursor styles for interactive and disabled states.
apps/extension/src/pages/bookmark.tsx Removed star graph, refactored logout to modal in menu, updated loading usage.
apps/extension/src/pages/create-bookmark.tsx Switched to new navigation hook, simplified save logic/UI, improved AI summary controls.
apps/extension/src/state/mutation/star.ts Updated loading state access, changed navigation after mutations, improved query invalidation.
apps/www/package.json Added next-themes and sonner dependencies.
apps/www/src/app/api/chat/route.ts Avoids sending undefined session_id in downstream chat API requests.
apps/www/src/app/bookmarks/page.tsx Replaced client component with async server component; delegates logic to new BookmarksPage.
apps/www/src/app/page/bookmarks/index.tsx New BookmarksPage client component: manages detail modal, deletion, and visualization theme.
apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx Added isNewChat prop, removed session mutation, unified chat input logic, improved streaming.
apps/www/src/components/bookmarks/graph/chat-bot/index.tsx Made chat UI resizable, improved session management, added loading states.
apps/www/src/components/bookmarks/graph/graph-detail.tsx Uses props for star data, adds delete callback, improves node fallback and toast usage.
apps/www/src/components/bookmarks/graph/index.tsx Removed dynamic node styling/state, simplified node rendering and click handling.
apps/www/src/components/bookmarks/graph/planet.tsx Switched to category-based grouping, removed dynamic color/type, simplified keyword logic.
apps/www/src/components/bookmarks/sidebar/dropdown.tsx Supports "Category"/"Keyword" types, adds category creation modal, uses toasts for feedback.
apps/www/src/components/bookmarks/sidebar/index.tsx Removed all theme/filter controls, simplified to categories, keywords, and profile/logout.
apps/www/src/components/bookmarks/tree/index.tsx Removed onUpdate logging from tree component.
apps/www/src/components/common/icon.tsx Added new plus icon to icon set.
apps/www/src/components/common/nav-dropdown.tsx Added bookmark theme submenu, removed "Introduce", improved dropdown state management.
apps/www/src/components/layout/root-provider.tsx Added Toaster for toast notifications at root level.
apps/www/src/components/ui/sonner.tsx New Toaster component wrapping sonner with theme support.
apps/www/src/constants/bookmark.ts Removed LINK_TYPE and GRAPH_TYPE enums.
apps/www/src/lib/tanstack/mutation/chat.ts Deleted: Removed useCreateChatSession mutation hook.
apps/www/src/lib/tanstack/mutation/star.ts Replaced alert with toast for delete success notification.
apps/www/src/lib/tanstack/query/chat.ts Refactored useGetChatMessages to accept object with isNewChat flag.
apps/www/src/lib/zustand/bookmark.ts Deleted: Removed Zustand store for bookmark UI state.
apps/www/src/models/chat.ts Removed ChatSessionDTO interface.
apps/www/src/service/chat.ts Removed createChatSession, updated query param logic for session list.
apps/www/src/utils/params.ts New: Added getParams and calculateNextPageParam utility functions.
apps/www/src/utils/toast.ts New: Added successToast, infoToast, errorToast utilities using sonner.
packages/ui/src/graph-2d/index.tsx Changed default height from 300 to 150.
packages/ui/src/index.ts Exported new searchFilter utility.
packages/ui/src/keyword/index.tsx Added dynamic keyword filtering using searchFilter.
packages/ui/src/modal/index.tsx Modal now uses React portal for rendering.
packages/ui/src/spinner/index.tsx Added optional small prop for spinner sizing.
packages/ui/src/textarea/index.tsx Added rightElement prop, made textarea resizable.
packages/ui/utils/search.ts New: Added searchFilter function for multi-word matching.

Sequence Diagram(s)

Chat Session Creation and Messaging (New Flow)

sequenceDiagram
    participant User
    participant ChatBot (UI)
    participant Chat (UI)
    participant API /chat/route.ts
    participant Downstream /chat/stream

    User->>ChatBot: Click "New Chat"
    ChatBot->>Chat: Render with isNewChat=true
    User->>Chat: Submit question (no sessionId)
    Chat->>API /chat/route.ts: POST { userId, message }
    API /chat/route.ts->>Downstream /chat/stream: POST { userId, message }
    Downstream /chat/stream-->>API /chat/route.ts: Streamed response (with session_id)
    API /chat/route.ts-->>Chat: Streamed response (with session_id)
    Chat->>ChatBot: onSessionCreated(session_id)
    ChatBot->>Chat: Set sessionId, isNewChat=false
    User->>Chat: Continue chatting (sessionId present)
Loading

Bookmark Visualization: Theme Selection and Deletion

sequenceDiagram
    participant User
    participant BookmarksPage
    participant Sidebar
    participant Graph/Tree/Planet
    participant GraphDetail

    User->>Sidebar: Select Bookmark View Theme
    Sidebar->>BookmarksPage: Pass selected theme
    BookmarksPage->>Graph/Tree/Planet: Render with filtered data
    User->>Graph/Tree/Planet: Click node
    Graph/Tree/Planet->>BookmarksPage: Open detail modal
    BookmarksPage->>GraphDetail: Show details
    User->>GraphDetail: Click delete
    GraphDetail->>BookmarksPage: onDelete(id)
    BookmarksPage->>Graph/Tree/Planet: Remove node, update view
Loading

Poem

🐇✨
A toast now pops, not an alert’s old ring,
Bookmarks and chatbots, with portals, take wing.
Categories bloom, plus icons appear,
Spinners shrink down, and themes become clear.
Filtering is sharper, the UI more bright—
Hopping through features, everything feels light!
—Your code rabbit, with a twitch of delight.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 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 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 for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@gs0428 gs0428 merged commit 2bf15c6 into dev Jul 14, 2025
2 of 3 checks passed

@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: 7

🔭 Outside diff range comments (2)
apps/www/src/components/bookmarks/graph/index.tsx (1)

90-97: Fix event listener cleanup to prevent memory leak.

The removeEventListener is using a different function reference, so the original handler won't be removed.

+const handleResize = () => {
+  graph.width(graphRef.current?.clientWidth || 0);
+  graph.height(graphRef.current?.clientHeight || 0);
+};

-window.addEventListener("resize", function handleResize() {
-  graph.width(graphRef.current?.clientWidth || 0);
-  graph.height(graphRef.current?.clientHeight || 0);
-});
+window.addEventListener("resize", handleResize);

 return () => {
-  window.removeEventListener("resize", function handleRemoveResize() {});
+  window.removeEventListener("resize", handleResize);
 };
apps/www/src/components/bookmarks/graph/graph-detail.tsx (1)

300-312: Node sizing is fixed at a constant value and ignores computed views
Graph2D uses a custom nodeCanvasObject with a hard-coded radius (nodeSize = 5), and you’re also mapping every node’s val to 1. As a result, even if you pass a view-based value, it won’t affect node size.

• File: apps/www/src/components/bookmarks/graph/graph-detail.tsx
Lines 300–312 — change

<Graph2D
  graphData={{
    nodes: graphData.nodes.map((star) => ({
-     id: star.id,
-     name: star.name,
-     val: 1,
+     id: star.id,
+     name: star.name,
+     val: star.viewCount,    // preserve the computed view-based value
    })),
    links: graphData.links.map((link) => ({
      source: link.source,
      target: link.target,
    })),
  }}
/>

• File: packages/ui/src/graph-2d/index.tsx — inside nodeCanvasObject, replace the fixed size:

// before
const nodeSize = 5;
// after
const nodeSize = (node.val ?? 1) * 2; // scale factor as needed

This ensures your computed val flows through into the canvas drawing and node sizes reflect view counts.

🧹 Nitpick comments (6)
apps/www/src/components/ui/sonner.tsx (1)

7-24: LGTM! Well-implemented theme-aware toast wrapper with minor type safety consideration.

The component correctly integrates with next-themes and forwards props appropriately. The inline CSS custom properties provide good theme integration.

Consider adding validation for the theme casting to ensure type safety:

 const Toaster = ({ ...props }: ToasterProps) => {
   const { theme = "system" } = useTheme();
+  
+  // Validate theme value before casting
+  const validTheme = ["light", "dark", "system"].includes(theme) ? theme : "system";

   return (
     <Sonner
-      theme={theme as ToasterProps["theme"]}
+      theme={validTheme as ToasterProps["theme"]}
       className="toaster group"
apps/www/src/components/common/nav-dropdown.tsx (1)

76-95: Consider showing bookmark themes only on bookmark pages.

The "Bookmark View" dropdown appears on all pages when the nav is open. Consider showing it only when on bookmark-related routes for better UX.

 )}
+{pathname.includes('/bookmarks') && (
   <div className="relative">
     <button
       className="flex items-center gap-2"
       onClick={() => setIsBookmarkThemeOpen(!isBookmarkThemeOpen)}
     >
       <p>Bookmark View</p>
       <div className={cn("transition-transform", isBookmarkThemeOpen && "rotate-180")}>
         <Icon.arrowDown fill="#fff" size={16} />
       </div>
     </button>
     {isBookmarkThemeOpen && (
       <div className="absolute left-1/2 top-full mt-2 flex -translate-x-1/2 flex-col gap-2">
         {BOOKMARK_THEMES.map((theme) => (
           <button key={theme.label} onClick={() => onClickNav(theme.href)}>
             {theme.label}
           </button>
         ))}
       </div>
     )}
   </div>
+)}
apps/www/src/components/bookmarks/graph/graph-detail.tsx (3)

335-372: Good defensive programming for UI fields.

The fallback values prevent undefined errors when star data fields are missing. Consider extracting common patterns for cleaner code.

You could simplify the repeated patterns by extracting a helper function:

const getFieldValue = (fieldName: keyof typeof starData.result) => {
  return edit.activated ? edit[fieldName] || "" : starData?.result?.[fieldName] || "";
};

Then use it as:

-value={edit.activated ? edit.summaryAI : starData?.result?.summaryAI || ""}
+value={getFieldValue("summaryAI")}

58-80: Consider consistent node value calculation for visual uniformity.

The graph node value calculation is inconsistent:

  • Related nodes use Math.min(star.views, 10) (line 67)
  • Standalone current star gets hardcoded val: 10 (line 75)

This could cause the current bookmark to appear larger than it should when it has fewer views.

Apply consistent value calculation:

             : currentStar
               ? [
                   {
                     id: currentStar.starId,
                     name: currentStar.title,
-                    val: 10,
+                    val: Math.min(currentStar.views || 0, 10),
                     url: currentStar.siteUrl,
                   },
                 ]
               : [];

219-227: Optimize event listener management with proper dependencies.

The useEffect hook managing mouse event listeners lacks a dependency array, causing listeners to be added/removed on every render.

Add proper dependencies to the useEffect:

   useEffect(() => {
+    if (holdX < 0) return;
+    
     window.addEventListener("mousemove", onMouseMove);
     window.addEventListener("mouseup", onMouseUp);
 
     return () => {
       window.removeEventListener("mousemove", onMouseMove);
       window.removeEventListener("mouseup", onMouseUp);
     };
-  });
+  }, [holdX, saveWidth]);
apps/www/src/components/bookmarks/graph/chat-bot/index.tsx (1)

103-129: Proper event listener management with cleanup.

The implementation correctly manages event listeners and cleans them up. Consider splitting into separate effects for better readability.

Consider splitting into three separate useEffect hooks for clearer separation of concerns:

useEffect(() => {
  if (!isDragging) return;
  // isDragging logic
}, [isDragging, onMouseMove, onMouseUp]);

useEffect(() => {
  if (!isResizingWidth) return;
  // isResizingWidth logic
}, [isResizingWidth, onResizeWidthMouseMove, onResizeWidthMouseUp]);

useEffect(() => {
  if (!isResizingHeight) return;
  // isResizingHeight logic
}, [isResizingHeight, onResizeHeightMouseMove, onResizeHeightMouseUp]);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0944b01 and fac1c7c.

⛔ Files ignored due to path filters (3)
  • apps/extension/public/icon128.png is excluded by !**/*.png
  • apps/extension/src/assets/menu.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (38)
  • apps/extension/src/components/loading/index.tsx (1 hunks)
  • apps/extension/src/hooks/use-detect-path.ts (5 hunks)
  • apps/extension/src/index.css (1 hunks)
  • apps/extension/src/pages/bookmark.tsx (3 hunks)
  • apps/extension/src/pages/create-bookmark.tsx (8 hunks)
  • apps/extension/src/state/mutation/star.ts (3 hunks)
  • apps/www/package.json (1 hunks)
  • apps/www/src/app/api/chat/route.ts (1 hunks)
  • apps/www/src/app/bookmarks/page.tsx (1 hunks)
  • apps/www/src/app/page/bookmarks/index.tsx (1 hunks)
  • apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (8 hunks)
  • apps/www/src/components/bookmarks/graph/chat-bot/index.tsx (1 hunks)
  • apps/www/src/components/bookmarks/graph/graph-detail.tsx (6 hunks)
  • apps/www/src/components/bookmarks/graph/index.tsx (3 hunks)
  • apps/www/src/components/bookmarks/graph/planet.tsx (4 hunks)
  • apps/www/src/components/bookmarks/sidebar/dropdown.tsx (1 hunks)
  • apps/www/src/components/bookmarks/sidebar/index.tsx (2 hunks)
  • apps/www/src/components/bookmarks/tree/index.tsx (0 hunks)
  • apps/www/src/components/common/icon.tsx (1 hunks)
  • apps/www/src/components/common/nav-dropdown.tsx (3 hunks)
  • apps/www/src/components/layout/root-provider.tsx (2 hunks)
  • apps/www/src/components/ui/sonner.tsx (1 hunks)
  • apps/www/src/constants/bookmark.ts (0 hunks)
  • apps/www/src/lib/tanstack/mutation/chat.ts (0 hunks)
  • apps/www/src/lib/tanstack/mutation/star.ts (2 hunks)
  • apps/www/src/lib/tanstack/query/chat.ts (1 hunks)
  • apps/www/src/lib/zustand/bookmark.ts (0 hunks)
  • apps/www/src/models/chat.ts (0 hunks)
  • apps/www/src/service/chat.ts (1 hunks)
  • apps/www/src/utils/params.ts (1 hunks)
  • apps/www/src/utils/toast.ts (1 hunks)
  • packages/ui/src/graph-2d/index.tsx (2 hunks)
  • packages/ui/src/index.ts (1 hunks)
  • packages/ui/src/keyword/index.tsx (3 hunks)
  • packages/ui/src/modal/index.tsx (3 hunks)
  • packages/ui/src/spinner/index.tsx (2 hunks)
  • packages/ui/src/textarea/index.tsx (1 hunks)
  • packages/ui/utils/search.ts (1 hunks)
💤 Files with no reviewable changes (5)
  • apps/www/src/components/bookmarks/tree/index.tsx
  • apps/www/src/models/chat.ts
  • apps/www/src/lib/tanstack/mutation/chat.ts
  • apps/www/src/constants/bookmark.ts
  • apps/www/src/lib/zustand/bookmark.ts
🧰 Additional context used
🧬 Code Graph Analysis (18)
apps/www/src/lib/tanstack/mutation/star.ts (1)
apps/www/src/utils/toast.ts (1)
  • successToast (3-5)
apps/www/src/lib/tanstack/query/chat.ts (1)
apps/www/src/service/chat.ts (1)
  • getChatMessages (7-11)
packages/ui/src/spinner/index.tsx (1)
packages/ui/utils/cn.ts (1)
  • cn (4-6)
packages/ui/utils/search.ts (1)
packages/ui/src/index.ts (1)
  • searchFilter (11-11)
apps/www/src/components/layout/root-provider.tsx (2)
apps/www/src/lib/tanstack/index.ts (1)
  • queryClient (3-10)
apps/www/src/components/ui/sonner.tsx (1)
  • Toaster (26-26)
apps/extension/src/state/mutation/star.ts (3)
apps/extension/src/state/zustand/loading.ts (1)
  • useLoadingStore (8-11)
apps/extension/src/services/star.ts (1)
  • completeCreateStar (17-21)
apps/extension/src/components/layout/index.tsx (1)
  • queryClient (8-8)
apps/extension/src/hooks/use-detect-path.ts (1)
apps/extension/src/state/zustand/user.ts (1)
  • useUserStore (8-11)
apps/extension/src/components/loading/index.tsx (1)
apps/extension/src/state/zustand/loading.ts (1)
  • useLoadingStore (8-11)
packages/ui/src/textarea/index.tsx (1)
packages/ui/utils/cn.ts (1)
  • cn (4-6)
apps/extension/src/pages/bookmark.tsx (3)
apps/extension/src/state/zustand/tab.ts (1)
  • useTabStore (13-21)
packages/ui/src/index.ts (1)
  • useOutsideClick (13-13)
packages/ui/hooks/use-outside-click.ts (1)
  • useOutsideClick (3-26)
apps/www/src/components/bookmarks/graph/index.tsx (1)
apps/www/src/types/graph.ts (1)
  • NodeObject (17-31)
packages/ui/src/keyword/index.tsx (1)
packages/ui/utils/search.ts (1)
  • searchFilter (1-7)
apps/www/src/components/bookmarks/sidebar/index.tsx (1)
apps/www/src/utils/toast.ts (1)
  • successToast (3-5)
apps/www/src/app/api/chat/route.ts (1)
apps/extension/service-worker.js (1)
  • baseUrl (2-2)
apps/www/src/service/chat.ts (2)
apps/www/src/models/chat.ts (2)
  • ChatMessageDTO (10-23)
  • ChatSessionListDTO (1-8)
apps/www/src/utils/params.ts (1)
  • getParams (1-18)
apps/www/src/components/bookmarks/sidebar/dropdown.tsx (4)
apps/www/src/types/category.ts (1)
  • CategoryProps (1-5)
apps/www/src/lib/tanstack/mutation/category.ts (1)
  • useCreateCategory (7-17)
apps/www/src/utils/toast.ts (1)
  • infoToast (7-9)
packages/ui/src/index.ts (1)
  • cn (10-10)
apps/www/src/components/bookmarks/graph/graph-detail.tsx (2)
packages/types/src/star.ts (1)
  • AllStarDTO (3-9)
apps/www/src/utils/toast.ts (1)
  • infoToast (7-9)
apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (2)
apps/www/src/hooks/use-user-info.ts (1)
  • useUserInfo (6-20)
apps/www/src/lib/tanstack/query/chat.ts (1)
  • useGetChatMessages (5-17)
🔇 Additional comments (81)
apps/extension/src/index.css (1)

56-62: LGTM! Good UX improvement for button interactions.

The button cursor styles enhance user experience by providing clear visual feedback for clickable and disabled states. This follows standard UX patterns and improves accessibility.

apps/www/package.json (1)

23-23: sonner dependency is current and secure

  • File: apps/www/package.json (line 23)
  • Specified version ^2.0.6 is the latest release (published 2 days ago)
  • No known security vulnerabilities reported

No changes required.

packages/ui/src/index.ts (1)

11-11: searchFilter export implementation verified

The searchFilter function is defined and exported correctly:

  • packages/ui/utils/search.ts:
    export const searchFilter = (search: string, target: string) => { … }
  • packages/ui/src/index.ts:
    export { searchFilter } from "../utils/search";
  • packages/ui/src/keyword/index.tsx imports and uses it without errors.

No further changes needed.

apps/www/src/lib/tanstack/mutation/star.ts (2)

4-4: LGTM! Good migration to centralized toast utilities.

The import of successToast from the toast utility module supports the consistent toast notification pattern across the application.


27-27: Excellent UX improvement by replacing native alert with toast.

The migration from alert() to successToast() provides a much better user experience with less intrusive notifications. The Korean message is appropriate for the application's localization.

packages/ui/src/graph-2d/index.tsx (2)

29-29: LGTM! Consistent height reduction for more compact UI.

The default height reduction from 300 to 150 pixels creates a more compact component. Ensure this change doesn't negatively impact graph readability or existing layouts that depend on the previous height.


46-46: Consistent CSS class update to match the new height.

The CSS class change from h-[300px] to h-[9.375rem] (150px) properly aligns with the updated default height prop.

apps/www/src/components/common/icon.tsx (1)

132-145: LGTM! Clean addition of plus icon.

The plus icon implementation follows the established pattern and is consistent with other icons in the object. The SVG path correctly renders a plus sign, and the component properly handles the standard IconProps.

apps/www/src/lib/tanstack/query/chat.ts (2)

5-11: Good refactoring to support new chat session logic.

The updated signature clearly separates the sessionId from the isNewChat flag, making the hook's purpose more explicit and improving code readability.


15-15: Excellent optimization with the enabled condition.

The enabled: !!sessionId && !isNewChat condition prevents unnecessary API calls for new chat sessions, which is both performant and logical. This aligns well with the broader chat session management refactor.

packages/ui/src/modal/index.tsx (2)

1-1: Good addition of createPortal import.

This import is necessary for the portal implementation and follows React best practices.


15-29: Excellent use of createPortal for modal rendering.

Rendering the modal into document.body via a portal is a best practice that prevents z-index conflicts and ensures consistent overlay behavior. The implementation is clean and maintains all existing modal functionality.

apps/www/src/components/layout/root-provider.tsx (2)

3-3: Good addition of Toaster import.

The Toaster component import enables global toast notifications throughout the application.


12-24: Excellent integration of global toast notifications.

The Toaster configuration is well-thought-out with appropriate settings:

  • Top-center position for good visibility
  • 3000ms duration for optimal user experience
  • Close button for user control
  • High z-index (99999) to ensure toast visibility above other UI elements

The integration at the root level ensures consistent toast notifications across the entire application.

apps/www/src/app/api/chat/route.ts (2)

10-11: Excellent conditional request body construction.

This clean approach prevents sending undefined session_id values in the JSON payload, which is more robust and follows good API practices. The conditional logic is clear and handles both new and existing chat sessions appropriately.


17-17: Good use of the conditional requestBody.

Using the conditionally constructed requestBody ensures the API receives only the necessary fields, preventing potential issues with undefined values in the JSON payload.

packages/ui/src/keyword/index.tsx (3)

1-4: LGTM: Clean import organization

The imports are well-organized with the new searchFilter utility properly imported.


25-28: Excellent use of useMemo for performance optimization

The filtered keyword list is properly memoized with appropriate dependencies (keywordList and restProps.value). This prevents unnecessary re-computations when other props change.


58-60: Consistent usage of filtered list in rendering

The UI correctly uses filteredKeywordList for both the visibility condition and the actual rendering, ensuring consistent behavior.

packages/ui/utils/search.ts (1)

1-7: Well-implemented search utility with proper edge case handling

The function correctly handles:

  • Empty/falsy search strings (returns true)
  • Case-insensitive matching
  • Multi-word search with whitespace splitting
  • Efficient word matching using every()

The logic is sound and performance is appropriate for typical keyword filtering use cases.

packages/ui/src/spinner/index.tsx (2)

5-8: Good API design with optional sizing prop

The small prop is well-designed with a sensible default value (false), maintaining backward compatibility while enabling size flexibility.


22-28: Clean conditional sizing implementation

The conditional sizing logic is clear and maintainable, using the cn utility appropriately for class name merging. The size values (28/24 for small, 56/52 for default) maintain good proportions.

apps/www/src/utils/toast.ts (1)

1-13: Excellent abstraction for toast notifications

The utility functions provide a clean, consistent API for toast notifications:

  • Clear naming convention (successToast, infoToast, errorToast)
  • Simple wrapper pattern enables easy future enhancements
  • Centralizes toast functionality for maintainability

This abstraction will make it easy to modify toast behavior globally if needed.

apps/extension/src/state/mutation/star.ts (4)

12-12: Improved Zustand selector usage

Using the selector function (state) => state.setIsLoading is more efficient than destructuring, as it only re-renders when the specific property changes.


33-33: Consistent selector pattern

Good consistency in applying the selector pattern across all mutation hooks.


40-42: Proper cache invalidation and navigation

The implementation correctly:

  • Invalidates the query cache for all stars to ensure fresh data
  • Navigates with the star ID as a query parameter for proper state management

This follows good practices for cache management and URL structure.


54-54: Consistent selector pattern maintained

The selector function usage is consistent across all mutation hooks, improving performance and maintainability.

packages/ui/src/textarea/index.tsx (3)

5-5: Good addition of optional rightElement prop.

The interface extension is clean and maintains backward compatibility.


8-14: Well-implemented flexible layout for label and right element.

The flex container provides clean alignment and spacing between the label and optional right element. The conditional rendering handles the optional prop correctly.


18-18: Good removal of resize-none class.

Removing the resize-none class allows users to resize the textarea, improving usability. This change aligns with the enhanced flexibility provided by the rightElement prop.

apps/extension/src/components/loading/index.tsx (2)

6-6: Good addition of optional description prop.

The interface extension maintains backward compatibility while adding useful functionality.


10-18: Well-implemented description rendering with proper styling.

The component correctly handles the optional description prop and provides appropriate text styling. The centered text container maintains visual consistency.

apps/extension/src/hooks/use-detect-path.ts (4)

28-28: Good integration of authentication state.

The import and usage of isLoggedIn from the user store is appropriate for controlling navigation flow.


57-59: Proper authentication guard implementation.

The early return for non-logged-in users prevents unnecessary navigation logic execution and ensures proper access control.


69-69: Correct dependency array update.

Including isLoggedIn in the dependency array ensures the effect runs when authentication state changes.


41-44: Verify tab status change in use-detect-path.ts

No other occurrences of changeInfo.status checks were found in the repository—this hook is the sole place where we switch from "complete" to "loading". Because "loading" fires earlier in the tab lifecycle, please confirm:

  • File: apps/extension/src/hooks/use-detect-path.ts
    Lines: 41–44
  1. That setIsFindingExistPath(true) and updateCurrentTab still run with a valid URL (i.e. the path you’re detecting is available at "loading").
  2. There are no race conditions if the final URL or other tab properties settle later.
  3. Consider whether you need a fallback on "complete" to catch any edge cases where "loading" may fire without a final URL set.
apps/www/src/service/chat.ts (3)

3-3: Good adoption of getParams utility.

The import of the getParams utility promotes code reuse and consistency across the application.


13-19: Clean refactoring with improved parameter handling.

The function signature change from params to props provides better naming consistency. The use of getParams utility simplifies query string construction and promotes maintainability.


2-2: Import cleanup: ChatSessionDTO safely removed

No occurrences of ChatSessionDTO were found in the codebase, so removing it from the import is safe.

apps/extension/src/pages/bookmark.tsx (6)

1-1: LGTM: Clean import additions for new functionality

The imports are well-organized and include the necessary dependencies for the new menu dropdown and modal functionality. The SVG imports using the ?react syntax are appropriate for the build system.

Also applies to: 3-4, 9-9


17-20: LGTM: Appropriate state management for UI controls

The state management is well-structured with clear naming conventions. The separation of menu and modal state allows for independent control of these UI elements.


54-63: LGTM: Proper event handling with good UX practices

The event handlers are well-implemented with:

  • stopPropagation() preventing unintended event bubbling
  • Proper state management for UX flow (close menu when opening modal)
  • Clear function naming and single responsibility

66-84: LGTM: Well-structured header with accessibility considerations

The header implementation is clean with:

  • Good semantic HTML structure
  • Proper button elements for interactive controls
  • Conditional rendering of the dropdown menu
  • Correct use of the useOutsideClick hook with proper ref assignment

96-98: LGTM: Simplified button logic with clear user feedback

The button implementation properly handles the disabled state with clear messaging to users about when bookmarks cannot be added.


100-113: LGTM: Well-implemented modal with proper UX flow

The modal implementation follows good practices:

  • Conditional rendering based on state
  • Proper modal structure with title and subtitle
  • Action buttons with clear labels and appropriate styling
  • Callback handling for modal dismissal
apps/www/src/components/bookmarks/sidebar/index.tsx (3)

14-14: LGTM: Good import addition for improved user feedback

The import of successToast aligns with the toast notification system being implemented across the application for better user experience.


74-74: LGTM: Improved user feedback with toast notifications

Replacing alert-based notifications with toast notifications provides a better user experience with non-blocking feedback. The message is clear and appropriate for the logout action.


80-136: LGTM: Clean and well-structured sidebar implementation

The sidebar implementation is well-organized with:

  • Proper state management for various dropdown states
  • Good responsive design with dynamic width
  • Clear semantic structure with appropriate accessibility considerations
  • Proper event handling for user interactions
apps/extension/src/pages/create-bookmark.tsx (8)

7-7: LGTM: Good navigation hook adoption

The replacement of previous navigation logic with useReplaceNavigate hook suggests a move toward more consistent navigation patterns across the application.

Also applies to: 56-56


45-45: LGTM: Proper state management for AI summary feature

The addition of isAISummaryPending state prepares the component for future AI summary functionality with appropriate loading state management.


83-104: LGTM: Improved graph data computation with better fallback handling

The updated logic properly handles cases where no related nodes exist by including the current bookmark node. This prevents empty graph scenarios and provides a better user experience.


172-174: LGTM: Simplified mutation calls

The removal of success callbacks from mutation calls suggests a move toward cleaner separation of concerns and potentially centralized state management.


178-180: LGTM: Simple and clear cancel handler

The cancel button implementation is straightforward and provides expected navigation behavior.


194-196: LGTM: Simplified header implementation

The header is clean and focused, removing potentially unnecessary elements while maintaining clear branding.


220-230: LGTM: Well-implemented AI summary button with good UX

The right element button implementation includes:

  • Proper loading state with pulse animation
  • Dynamic label based on pending state
  • Clean styling with conditional classes
  • Appropriate event handling

250-254: LGTM: Proper button layout with cancel option

The button section provides clear actions with appropriate styling variations (outline for cancel, solid for primary action).

apps/www/src/utils/params.ts (2)

1-18: LGTM: Well-implemented URL parameter utility

The getParams function is well-structured with:

  • Proper use of URLSearchParams for URL-safe encoding
  • Truthy value checking to avoid empty parameters
  • Clear separation between conditional and default parameters
  • Appropriate type annotations

20-31: LGTM: Correct pagination logic implementation

The calculateNextPageParam function properly handles:

  • Edge case when totalPages is 0
  • Zero-based page indexing (comparing page === totalPages - 1)
  • Returning undefined when no next page exists (standard pattern for pagination libraries)
  • Clear type annotations and parameter destructuring
apps/www/src/components/bookmarks/graph/planet.tsx (5)

5-5: LGTM: Simplified imports align with refactoring

The import changes reflect the removal of complex state management dependencies, focusing on the core data types needed for the component.


83-94: LGTM: Simplified and more maintainable grouping logic

The new grouping approach using categoryName is:

  • More straightforward and easier to understand
  • Provides a clear fallback ("Uncategorized") for missing categories
  • Eliminates complex union-find logic that may have been over-engineered
  • More predictable in behavior

97-102: LGTM: Cleaner keyword extraction with sensible limits

The keyword extraction logic is improved with:

  • Direct category-based filtering instead of complex shared logic
  • Proper deduplication using Set
  • Sensible limit of 3 keywords for display purposes
  • Clear and readable implementation

169-171: LGTM: Focused label display

The simplified label approach showing only the category name is cleaner and more focused, removing potential visual clutter while maintaining essential information.


179-179: LGTM: Consistent visual design with fixed color

Using a fixed color (#2E40A9) simplifies the component and ensures visual consistency across the application. This removes the complexity of dynamic color selection while maintaining a professional appearance.

apps/www/src/app/bookmarks/page.tsx (1)

1-14: Well-structured server component implementation!

The transformation from client to server component is clean and follows Next.js 13+ patterns correctly. Good use of async/await for handling searchParams.

apps/www/src/components/common/nav-dropdown.tsx (1)

25-38: Good structure for bookmark theme navigation!

The BOOKMARK_THEMES constant follows the same pattern as NAVS and properly uses query parameters for theme selection.

apps/www/src/components/bookmarks/sidebar/dropdown.tsx (1)

27-44: Well-implemented form validation and mutation handling!

Good validation checks for empty and duplicate category names, proper async handling, and appropriate use of the pending state to prevent multiple submissions.

apps/www/src/app/page/bookmarks/index.tsx (2)

45-54: Efficient data filtering implementation!

Good use of useMemo to optimize filtering performance and proper handling of both stars and their associated links.


64-73: Confirm Tree’s data requirements and eliminate non-null assertions.

  • I verified that TreeProps (apps/www/src/components/bookmarks/tree/index.tsx) only defines:
    interface TreeProps {
      onOpen: (id: string) => void;
    }
    – it doesn’t accept a data prop like Graph and Planet.
  • If Tree should render with filteredData passed from the parent, extend its props:
    interface TreeProps {
      onOpen: (id: string) => void;
      data: Bookmark[]; // or the appropriate type
    }
    and update the component to use data.
  • Otherwise, this is an intentional API difference and you can leave the switch case as-is.
  • To remove the non-null assertions on filteredData, add an early guard in renderTheme, for example:
    const renderTheme = () => {
      if (!filteredData) return null;
      switch (theme) {
        case GRAPH_THEME.GRAPH:
          return <Graph onOpen={onOpen} data={filteredData} />;
        case GRAPH_THEME.TREE:
          return <Tree onOpen={onOpen} />;
        default:
          return <Planet onOpen={onOpen} data={filteredData} />;
      }
    };
    This ensures you don’t need to use filteredData!.

Let me know if Tree should consume the same data or if its current standalone behavior is by design.

apps/www/src/components/bookmarks/graph/index.tsx (1)

57-84: Excellent defensive programming in node click handler!

The validation checks ensure all required properties exist before proceeding, preventing potential runtime errors. The type assertion is safe given the thorough validation.

apps/www/src/components/bookmarks/graph/graph-detail.tsx (6)

113-113: Good UX improvement with toast notifications.

Replacing native alerts with toast notifications provides a better user experience.


165-169: Proper deletion flow with parent notification.

The implementation correctly deletes the bookmark first and then notifies the parent component to update its state.


58-79: Graph display fallback and error handling

The graphData fallback in apps/www/src/components/bookmarks/graph/graph-detail.tsx (lines 58–79) correctly shows the current node when there are no related nodes. However, there are two edge cases to verify:

  • If stars.starListDto doesn’t include the current id, currentStar will be undefined → nodes becomes [], and the graph will render empty.
  • If useGetGraphDetail(id) errors (starData.isError), the component falls through without rendering any feedback to the user.

Please confirm that:

  • The parent always supplies a stars prop containing the current id, or add a guard to handle currentStar === undefined.
  • An error state is handled (e.g. display an error message) when starData.isError is true.

113-113: Good use of toast notifications!

Replacing native alerts with toast notifications improves user experience.


165-169: Well-implemented deletion callback pattern.

The addition of the onDelete callback properly notifies the parent component about deletions, enabling centralized state management.


335-372: Good defensive programming with fallback values.

The consistent use of fallback empty strings and arrays prevents undefined values from causing UI issues.

apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (4)

39-42: Efficient query management for chat history.

The implementation correctly prevents unnecessary API calls for new chat sessions by passing the isNewChat flag.


96-98: Proper session ID extraction from stream response.

The implementation safely extracts and propagates the session ID from the streamed response.


112-163: Well-structured form submission handlers.

The separation of concerns between existing and new chat sessions is properly implemented with appropriate error handling.


181-188: Modern form submission pattern with proper validation.

Using requestSubmit() ensures form validation runs before submission, and the keyboard shortcuts enhance UX.

Also applies to: 267-269

apps/www/src/components/bookmarks/graph/chat-bot/index.tsx (2)

158-169: Well-implemented resize handles with proper UX.

The resize handles are correctly positioned with appropriate cursor feedback and z-index layering.


174-177: Good loading state feedback for chat sessions.

The loading spinner provides clear feedback while sessions are being fetched.

Comment thread apps/www/package.json
"dompurify": "^3.2.6",
"marked": "^15.0.12",
"next": "15.0.3",
"next-themes": "^0.4.6",

Copy link
Copy Markdown

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 the latest version and security status of next-themes.

Ensure that the specified version is current and secure.


🌐 Web query:

What is the latest version of next-themes npm package and are there any known security vulnerabilities?

💡 Result:

The latest version of the next-themes npm package is 0.4.6, published approximately four months ago. (npmjs.com) According to Snyk, there are no direct vulnerabilities associated with this version. (security.snyk.io)

However, it's important to note that the next-themes package has been succeeded by nextjs-themes, which offers enhanced features and improved performance. The latest version of nextjs-themes is 4.0.6, released four months ago. (npmjs.com) Snyk reports no direct vulnerabilities for this package either. (socket.dev)

Given that next-themes is no longer actively maintained, transitioning to nextjs-themes is recommended for better support and security.

Citations:


Consider migrating from next-themes to nextjs-themes for long-term support

  • apps/www/package.json currently pins "next-themes": "^0.4.6", which is indeed the latest version and has no known vulnerabilities per Snyk.
  • However, next-themes is no longer actively maintained. Its successor, nextjs-themes (latest 4.0.6), offers improved performance and features with ongoing support.

Please update your dependency accordingly:

- "next-themes": "^0.4.6",
+ "nextjs-themes": "^4.0.6",
📝 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
"next-themes": "^0.4.6",
"nextjs-themes": "^4.0.6",
🤖 Prompt for AI Agents
In apps/www/package.json at line 19, replace the dependency "next-themes":
"^0.4.6" with "nextjs-themes": "^4.0.6" to migrate to the actively maintained
successor package. Update any related import statements and usage in the
codebase to reflect the new package name and API if necessary.

Comment on lines 53 to 56
const onClickNav = (href: string) => {
router.push(href);
setIsOpen(false);
setIsNavOpen(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.

🛠️ Refactor suggestion

Consider closing both dropdowns on navigation.

When a user selects a bookmark theme, only the main navigation closes but the bookmark theme dropdown remains open. This could be confusing.

 const onClickNav = (href: string) => {
   router.push(href);
   setIsNavOpen(false);
+  setIsBookmarkThemeOpen(false);
 };
📝 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
const onClickNav = (href: string) => {
router.push(href);
setIsOpen(false);
setIsNavOpen(false);
};
const onClickNav = (href: string) => {
router.push(href);
setIsNavOpen(false);
setIsBookmarkThemeOpen(false);
};
🤖 Prompt for AI Agents
In apps/www/src/components/common/nav-dropdown.tsx around lines 53 to 56, the
onClickNav function closes only the main navigation dropdown but does not close
the bookmark theme dropdown. Update the function to also set the state
controlling the bookmark theme dropdown to false, ensuring both dropdowns close
when a navigation item is selected.

Comment on lines +73 to +75
<li key={typeof item === "string" ? item : item.id}>
<button
onClick={() => onClickItem(typeof item === "string" ? item : item.categoryId)}

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

Fix property name inconsistency.

The code uses item.categoryId but the CategoryProps interface only has an id field.

-onClick={() => onClickItem(typeof item === "string" ? item : item.categoryId)}
+onClick={() => onClickItem(typeof item === "string" ? item : item.id)}
📝 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
<li key={typeof item === "string" ? item : item.id}>
<button
onClick={() => onClickItem(typeof item === "string" ? item : item.categoryId)}
<li key={typeof item === "string" ? item : item.id}>
<button
onClick={() => onClickItem(typeof item === "string" ? item : item.id)}
🤖 Prompt for AI Agents
In apps/www/src/components/bookmarks/sidebar/dropdown.tsx around lines 73 to 75,
the code incorrectly uses the property name `categoryId` on `item`, but the
CategoryProps interface defines only `id`. Replace `item.categoryId` with
`item.id` to match the interface and fix the property name inconsistency.

Comment on lines +32 to +37
if (!categoryName) {
return infoToast("카테고리 이름을 입력해주세요.");
}
if (items.some((item) => item.name === categoryName)) {
return infoToast("이미 존재하는 카테고리입니다.");
}

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

Fix type safety issue in duplicate check.

The validation incorrectly assumes all items have a name property, but items can be string[] when type is "Keyword".

-if (items.some((item) => item.name === categoryName)) {
+if (isCategory && items.some((item) => (item as CategoryProps).name === categoryName)) {
   return infoToast("이미 존재하는 카테고리입니다.");
 }
📝 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
if (!categoryName) {
return infoToast("카테고리 이름을 입력해주세요.");
}
if (items.some((item) => item.name === categoryName)) {
return infoToast("이미 존재하는 카테고리입니다.");
}
if (!categoryName) {
return infoToast("카테고리 이름을 입력해주세요.");
}
- if (items.some((item) => item.name === categoryName)) {
+ if (isCategory && items.some((item) => (item as CategoryProps).name === categoryName)) {
return infoToast("이미 존재하는 카테고리입니다.");
}
🤖 Prompt for AI Agents
In apps/www/src/components/bookmarks/sidebar/dropdown.tsx around lines 32 to 37,
the duplicate category name check assumes all items have a 'name' property, but
items can be string arrays when the type is "Keyword". To fix this, add a type
check to ensure items are objects with a 'name' property before accessing it, or
adjust the logic to handle string items appropriately when type is "Keyword".

Comment on lines +75 to +86
return (
<>
{renderTheme()}
<GraphDetail
open={detail.open}
id={detail.id}
onClose={onClose}
stars={filteredData!}
onDelete={onDelete}
/>
</>
);

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

Avoid non-null assertion in component rendering.

The non-null assertion on filteredData could cause runtime errors if data becomes undefined.

 return (
   <>
     {renderTheme()}
-    <GraphDetail
-      open={detail.open}
-      id={detail.id}
-      onClose={onClose}
-      stars={filteredData!}
-      onDelete={onDelete}
-    />
+    {filteredData && (
+      <GraphDetail
+        open={detail.open}
+        id={detail.id}
+        onClose={onClose}
+        stars={filteredData}
+        onDelete={onDelete}
+      />
+    )}
   </>
 );
📝 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
return (
<>
{renderTheme()}
<GraphDetail
open={detail.open}
id={detail.id}
onClose={onClose}
stars={filteredData!}
onDelete={onDelete}
/>
</>
);
return (
<>
{renderTheme()}
{filteredData && (
<GraphDetail
open={detail.open}
id={detail.id}
onClose={onClose}
stars={filteredData}
onDelete={onDelete}
/>
)}
</>
);
🤖 Prompt for AI Agents
In apps/www/src/app/page/bookmarks/index.tsx between lines 75 and 86, avoid
using the non-null assertion operator on filteredData when passing it as the
stars prop to GraphDetail. Instead, add a conditional check to ensure
filteredData is defined before rendering GraphDetail or provide a safe default
value to prevent potential runtime errors if filteredData is undefined.

Comment on lines +53 to +57
if (!isNewChat) {
setMessages([]);
setStreamingContent(null);
}
}, [sessionId, isNewChat]);

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

Logic appears inverted for resetting chat state.

The condition should reset messages when starting a new chat, not when continuing an existing chat.

Apply this fix:

-if (!isNewChat) {
+if (isNewChat) {
   setMessages([]);
   setStreamingContent(null);
 }
📝 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
if (!isNewChat) {
setMessages([]);
setStreamingContent(null);
}
}, [sessionId, isNewChat]);
if (isNewChat) {
setMessages([]);
setStreamingContent(null);
}
}, [sessionId, isNewChat]);
🤖 Prompt for AI Agents
In apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx around lines 53 to
57, the condition to reset messages and streaming content is inverted; it
currently resets when continuing an existing chat instead of when starting a new
chat. Change the condition to check if isNewChat is true, so that
setMessages([]) and setStreamingContent(null) are called only when starting a
new chat.

Comment on lines +20 to +21
const [chatBoxWidth, setChatBoxWidth] = useState(() => Math.max(window.innerWidth * 0.5, 480));
const [chatBoxHeight, setChatBoxHeight] = useState(384);

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

Potential SSR issue with window access during initialization.

Accessing window.innerWidth during state initialization can cause hydration mismatches in Next.js.

Use a safer initialization pattern:

-const [chatBoxWidth, setChatBoxWidth] = useState(() => Math.max(window.innerWidth * 0.5, 480));
+const [chatBoxWidth, setChatBoxWidth] = useState(480);
+
+useEffect(() => {
+  setChatBoxWidth(Math.max(window.innerWidth * 0.5, 480));
+}, []);
📝 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
const [chatBoxWidth, setChatBoxWidth] = useState(() => Math.max(window.innerWidth * 0.5, 480));
const [chatBoxHeight, setChatBoxHeight] = useState(384);
const [chatBoxWidth, setChatBoxWidth] = useState(480);
const [chatBoxHeight, setChatBoxHeight] = useState(384);
useEffect(() => {
setChatBoxWidth(Math.max(window.innerWidth * 0.5, 480));
}, []);
🤖 Prompt for AI Agents
In apps/www/src/components/bookmarks/graph/chat-bot/index.tsx around lines 20 to
21, accessing window.innerWidth directly during state initialization can cause
server-side rendering issues and hydration mismatches in Next.js. To fix this,
initialize chatBoxWidth with a safe default value that does not rely on window,
such as a fixed number, and then update it inside a useEffect hook that runs
only on the client side to set the actual width based on window.innerWidth.

@gs0428 gs0428 deleted the SCRUM-238 branch July 14, 2025 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 기능 구현을 진행합니다. 🚨 fix 버그를 수정합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant