Skip to content

Conversation

@cyri113
Copy link
Contributor

@cyri113 cyri113 commented Apr 24, 2025

Summary by CodeRabbit

  • New Features

    • Introduced new dashboard layout, navigation, and authentication context for improved user experience.
    • Added modules and platforms marketplace with interactive activation, upvoting, and management controls.
    • Implemented sidebar with nested navigation and responsive design.
    • Added loading screens and enhanced visual layouts with logos and modern styling.
  • Bug Fixes

    • Improved handling of search parameters and loading states to prevent runtime errors.
  • Refactor

    • Streamlined layout components and centralized context/configuration for modules and platforms.
    • Simplified and modernized sidebar logic and structure.
  • Style

    • Enhanced UI with new theme, backgrounds, rounded corners, and consistent spacing.
  • Chores

    • Updated dependencies, added DaisyUI integration, and improved TypeScript configuration.
  • Documentation

    • Added and updated type definitions and interfaces for better maintainability.
  • Revert

    • Removed the legacy "Welcome" page in favor of the new dashboard experience.

@coderabbitai
Copy link

coderabbitai bot commented Apr 24, 2025

Walkthrough

This update introduces a comprehensive refactor and expansion of a Next.js-based community management platform. Major changes include the addition of new root and dashboard layouts, modularization of platform and module contexts, and the implementation of state management using Jotai atoms. Several new hooks are introduced for authentication, module, and platform management, and the sidebar/navigation logic is refactored for dynamic, role-based rendering. Multiple new components are added for platform and module listings, upvoting, and loading indicators. Styling is enhanced with DaisyUI and Tailwind, and type safety is improved through new TypeScript interfaces and type definitions. Several pages are visually and structurally updated, and obsolete or redundant code is removed.

Changes

File(s) Change Summary
package.json, tailwind.config.js, tsconfig.json, src/styles/globals.css Updated dependencies, added DaisyUI, improved Tailwind config, and added tooltip styling. Reformatted TypeScript config and included new plugin and paths.
src/atoms/authState.atom.ts, src/atoms/ui.atom.ts Introduced Jotai atoms for authentication and UI state, enabling persistent, reactive state management.
src/components/LoadingScreen.tsx Added a new loading screen component with centered logo and spinner.
src/components/auth/ProtectedRoute.tsx Added a protected route component to enforce authentication and redirect unauthenticated users.
src/components/layouts/DashboardLayout.tsx, src/components/layouts/Navbar.tsx, src/components/layouts/Sidebar.tsx Introduced and refactored dashboard layout, navbar, and sidebar components for dynamic, role-based navigation and improved UI state handling.
src/components/layouts/xs/SidebarXs.tsx Updated sidebar navigation path for Home to /dashboard.
src/components/home/modules/ModuleItem.tsx, src/components/home/modules/ModuleList.tsx, src/components/home/platforms/PlatformItem.tsx, src/components/home/platforms/PlatformList.tsx, src/components/home/platforms/UpvoteButton.tsx Added new components for listing modules and platforms, including upvote functionality and admin controls.
src/constants/ModuleContext.ts, src/constants/PlatformContext.ts, src/utils/interfaces.ts, src/utils/JwtPayloadType.ts Added new context constants and TypeScript interfaces/types for modules, platforms, and JWT payloads.
src/context/AuthProvider.tsx Introduced a new authentication provider using Jotai and JWT, with auto-refresh and context API.
src/hooks/modules/useModuleActions.ts, src/hooks/modules/useModules.ts, src/hooks/platforms/usePlatforms.ts, src/hooks/sidebar/useSidebar.ts, src/hooks/useAdmin.ts, src/hooks/useDatasources.ts, src/hooks/useApi.ts Added new hooks for modules, platforms, sidebar, admin status, datasources, and API fetching, with improved type safety and error handling.
src/app/layout.tsx, src/app/dashboard/layout.tsx, src/app/dashboard/page.tsx, src/app/dashboard/agent/page.tsx, src/app/dashboard/community-guardian/page.tsx Introduced new root and dashboard layouts, refactored pages to use new layouts, and added new community guardian page.
src/components/centric/selectCommunity/TcSelectCommunity.tsx, src/pages/centric/select-community.tsx Enhanced community selection with loading state management and improved navigation.
src/pages/centric/create-new-community.tsx, src/pages/centric/index.tsx, src/pages/centric/tac.tsx Updated centric pages to include logo, improved layout, and replaced loading indicators.
src/pages/centric/welcome.tsx Removed the old welcome page and its complex logic in favor of new modular components.
src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx, src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx, src/components/communitySettings/communityPlatforms/TcDiscourse.tsx, src/components/communitySettings/communityPlatforms/TcGithubIntegration.tsx, src/components/communitySettings/communityPlatforms/TcMediaWiki.tsx, src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx, src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx, src/components/communitySettings/communityPlatforms/TcWebsite.tsx Refactored handling of search params in effects for safety and consistency; mostly internal changes.
src/components/chat/Chat.tsx, src/components/chat/ChatForm.tsx Updated chat components' styling for improved layout and background colors.
src/layouts/defaultLayout.tsx, src/layouts/centricLayout.tsx Refactored layouts to use new dashboard layout and simplified centric layout.
src/pages/_app.tsx, src/pages/index.tsx Minor formatting changes (added blank lines).
src/pages/announcements/index.tsx, src/pages/community-settings/ai-assistant/index.tsx, src/pages/community-settings/index.tsx, src/pages/community-settings/violation-detection/index.tsx, src/pages/statistics.tsx Added or updated background color and rounded corners for containers; minor styling improvements.
src/pages/callback.tsx Swapped loading component, added logging for certain status codes.
src/axiosInstance.ts Refined 401 error handling, improved local storage cleanup and redirect logic.
src/components/centric/selectCommunity/TcCommunityItem.tsx, src/components/centric/selectCommunity/TcCommunityListItems.tsx Reordered import statements for clarity; no functional changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant AuthProvider
    participant ProtectedRoute
    participant DashboardLayout
    participant Sidebar
    participant Navbar

    User->>App: Accesses dashboard page
    App->>AuthProvider: Provides authentication context
    App->>ProtectedRoute: Wraps dashboard content
    ProtectedRoute->>AuthProvider: Checks authentication
    alt Not authenticated
        ProtectedRoute->>User: Redirects to /centric
        ProtectedRoute->>LoadingScreen: Shows loading
    else Authenticated
        ProtectedRoute->>DashboardLayout: Renders layout
        DashboardLayout->>Sidebar: Renders sidebar (role-based)
        DashboardLayout->>Navbar: Renders navbar
        DashboardLayout->>User: Renders dashboard content
    end
Loading

Poem

In the warren of code, new tunnels appear,
With sidebars and modules, the dashboard is clear!
A bunny hops through layouts, both root and nested,
Jotai keeps state where the carrots are bested.
Platforms and modules, all tidy and neat,
With upvotes and icons, the UI’s a treat!
🥕 Hooray for the changes—now hop in and play,
For this dashboard’s for bunnies, by bunnies, today!

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

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

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings 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.

@cloudflare-workers-and-pages
Copy link

Deploying frontend with  Cloudflare Pages  Cloudflare Pages

Latest commit: bfcd885
Status: ✅  Deploy successful!
Preview URL: https://29a30f39.frontend-28o.pages.dev
Branch Preview URL: https://development.frontend-28o.pages.dev

View logs

Copy link

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

🔭 Outside diff range comments (1)
src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1)

50-58: ⚠️ Potential issue

Add missing dependencies to the second useEffect's dependency array.

The second useEffect calls getUser and accesses userProfile but doesn't list them in the dependency array.

  useEffect(() => {
    const fetchUser = async () => {
      await getUser();
      const { id } = userProfile;
      console.log("userProfile", userProfile);
      setUserId(id);
    };
    fetchUser();
-  }, []);
+  }, [getUser, userProfile]);

Additionally, you should remove the console.log statement for production code.

🧹 Nitpick comments (53)
src/pages/index.tsx (1)

20-20: Styling nit: extra blank line.

A blank line was inserted immediately after the Index function signature. Please confirm this aligns with the project's formatting conventions (e.g., Prettier/ESLint). If it’s unintended, consider removing it to keep the code style consistent.

src/components/communitySettings/communityPlatforms/TcWebsite.tsx (1)

49-53: Handle URL SearchParams Reactively
Moving searchParams.get("addPlatform") into the effect and depending on the searchParams object fixes stale-value bugs. For completeness, consider adding handleOpenDialog to the dependency array or wrapping it in useCallback to satisfy exhaustive-deps lint rules.

src/components/LoadingScreen.tsx (1)

5-14: Good loading screen implementation with improvement opportunities

This reusable loading screen component correctly implements a centered, full-screen loading state using the application logo and DaisyUI's infinity loading animation.

Consider these enhancements for better flexibility and accessibility:

  1. Add props to customize the component (size variants, optional text, etc.)
  2. Add ARIA attributes for better accessibility
-export default function LoadingScreen() {
+export default function LoadingScreen({ 
+  logoSize = 100,
+  text = ''
+}: {
+  logoSize?: number,
+  text?: string
+}) {
   return (
-    <div className="flex flex-col gap-4 h-screen w-screen items-center justify-center">
-      <Image src={tcLogo} alt="Logo" width={100} height={100} />
+    <div className="flex flex-col gap-4 h-screen w-screen items-center justify-center" role="status" aria-live="polite">
+      <Image src={tcLogo} alt="Loading logo" width={logoSize} height={logoSize} />
       <div>
         <span className="loading loading-infinity loading-lg"></span>
       </div>
+      {text && <p className="text-center">{text}</p>}
     </div>
   )
 }
src/atoms/ui.atom.ts (1)

3-4: Consider removing unnecessary empty lines.

These consecutive empty lines could be removed for cleaner code.

src/atoms/authState.atom.ts (2)

13-14: Remove redundant TODO comment

The TODO comment on line 13 suggests renaming to authState, but the variable on line 14 is already named authState. This comment appears to be outdated and can be safely removed.

-// TODO: rename to authState
 export const authState = atomWithStorage<AuthStateType>("TC_user", defaultValue);

3-11: Consider adding token expiration handling

The authentication state manages tokens but doesn't track their expiration time. Consider enhancing the AuthStateType to include an expiration timestamp for proper token lifecycle management.

 type AuthStateType = {
   accessToken: string | null;
   refreshToken: string | null;
+  expiresAt?: number | null;
 }

 const defaultValue: AuthStateType = {
   accessToken: null,
   refreshToken: null,
+  expiresAt: null,
 }
src/pages/centric/tac.tsx (1)

52-52: Add descriptive alt text for better accessibility

The Image component has an empty alt attribute. For accessibility compliance, provide a descriptive alt text.

-      <Image src={tcLogo} alt='' className='mx-auto' />
+      <Image src={tcLogo} alt='TogetherCrew Logo' className='mx-auto' />
src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx (1)

118-134: Improve error handling in fetchPlatformsByType

While the function handles errors by setting platforms to an empty array, consider providing more specific error feedback to users rather than just logging to console.

Consider implementing a toast notification system or error state display:

 try {
   const { results } = await retrievePlatforms({
     name: platformName,
     community: communityId,
   });
   setPlatforms(results || []);
 } catch (error) {
   console.error("Error fetching platforms:", error);
   setPlatforms([]);
+  // Display user-friendly error message
+  // e.g., showToast(`Unable to fetch ${platformName} platforms. Please try again.`);
 } finally {
   setIsLoading(false);
 }
src/hooks/modules/useModuleActions.ts (2)

7-12: Add error handling to mutations

The mutations lack error handling. Add onError callbacks to handle failures gracefully, such as showing error notifications.

 const updateModule = useMutation({
   mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(`/modules/${moduleId}`, update),
   onSuccess: () => {
     queryClient.invalidateQueries({ queryKey: ["modules"] });
   },
+  onError: (error) => {
+    console.error("Failed to update module:", error);
+    // Consider adding a notification system
+    // e.g., showToast("Failed to update module. Please try again.");
+  },
 })

 const createModule = useMutation({
   mutationFn: ({ module }: { module: any }) => axiosInstance.post(`/modules`, module),
   onSuccess: () => {
     queryClient.invalidateQueries({ queryKey: ["modules"] });
   },
+  onError: (error) => {
+    console.error("Failed to create module:", error);
+    // Consider adding a notification system
+    // e.g., showToast("Failed to create module. Please try again.");
+  },
 })

Also applies to: 14-19


1-22: Extract API endpoints as constants

The API endpoints are hardcoded in the mutation functions. Consider extracting them as constants for better maintainability.

 import { useMutation, useQueryClient } from "@tanstack/react-query";

 import { axiosInstance } from "@/axiosInstance";

+const API_ENDPOINTS = {
+  MODULES: "/modules",
+  MODULE_BY_ID: (id: string) => `/modules/${id}`,
+};
+
 export const useModuleActions = () => {
   const queryClient = useQueryClient();
   const updateModule = useMutation({
-    mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(`/modules/${moduleId}`, update),
+    mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(API_ENDPOINTS.MODULE_BY_ID(moduleId), update),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: ["modules"] });
     },
   })

   const createModule = useMutation({
-    mutationFn: ({ module }: { module: any }) => axiosInstance.post(`/modules`, module),
+    mutationFn: ({ module }: { module: any }) => axiosInstance.post(API_ENDPOINTS.MODULES, module),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: ["modules"] });
     },
   })

   return { updateModule, createModule };
 }
src/pages/callback.tsx (2)

163-163: Remove debug logging statements.

Console logs appear to be added for debugging purposes but should be removed from production code. This log statement doesn't provide actionable information and only clutters the console.

-console.log('Settings user to local storage - 1');

173-173: Remove debug logging statements.

Similar to the previous instance, this console log should be removed from production code.

-console.log('Settings user to local storage - 2');
src/hooks/useDatasources.ts (1)

31-34: Memoize the datasources array to prevent unnecessary re-renders.

The current implementation creates a new array on every render, which could cause unnecessary re-renders in components that use this hook.

+import { useMemo } from 'react';
 import { useToken } from "@/context/TokenContext";

 // ... rest of the code ...

 export const useDatasources = () => {
 
   const { community } = useToken();
 
   const platformNames =
     community?.platforms?.map((platform: any) => platform.name) || [];
 
-  const datasources = DATA_SOURCES.map((datasource) => ({
-    ...datasource,
-    activated: platformNames.includes(datasource.name),
-  }));
+  const datasources = useMemo(() => {
+    return DATA_SOURCES.map((datasource) => ({
+      ...datasource,
+      activated: platformNames.includes(datasource.name),
+    }));
+  }, [platformNames]);
 
   return datasources;
src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1)

54-54: Remove debug console.log statement.

Remove console.log statements from production code.

      await getUser();
      const { id } = userProfile;
-      console.log("userProfile", userProfile);
      setUserId(id);
src/hooks/platforms/usePlatforms.ts (1)

4-14: Clean and well-implemented React Query hook

This custom hook is well-structured and follows React Query best practices. The conditional fetching based on communityId presence is handled appropriately.

Consider adding TypeScript typing for the return data to improve type safety:

-export const usePlatforms = (communityId: string | undefined) => {
+interface Platform {
+  // Define platform properties based on your API response
+  id: string;
+  name: string;
+  // other properties...
+}
+
+interface PlatformsResponse {
+  results: Platform[];
+  // other pagination/metadata fields if any
+}
+
+export const usePlatforms = (communityId: string | undefined) => {
src/constants/PlatformContext.ts (1)

3-48: Well-organized platform definitions

The platform context array is well-structured and follows a consistent pattern for all platforms. This provides a centralized definition of supported platforms that can be easily referenced throughout the application.

Consider organizing platforms by availability status or alphabetically to improve readability:

export const PLATFORM_CONTEXT: IPlatformContext[] = [
+  // Available platforms
   {
     name: "discord", title: "Discord", available: true,
     configPath: "/community-settings?managePlatform=discord"
   },
   // ... other available platforms
+  
+  // Unavailable platforms
   {
     name: "x", title: "X (Twitter)", available: false,
     configPath: "/community-settings?managePlatform=x"
   },
   // ... other unavailable platforms
];
src/components/home/modules/ModuleList.tsx (3)

14-16: Enhance type safety and error handling in getModule function

The getModule function could be improved with explicit type safety and a default return mechanism when the module isn't found.

-  const getModule = (name: string) => {
-    return data?.results?.find((module: IModuleProps) => module.name === name);
-  }
+  const getModule = (name: string): IModuleProps | undefined => {
+    return data?.results?.find((module: IModuleProps) => module.name === name);
+  }

28-28: Avoid using array index as React key

Using array index as a key can lead to rendering issues if the module order changes. If context has a unique identifier, consider using that instead.

-        {MODULE_CONTEXT.map((context: IModuleContext, index: number) => <ModuleItem key={index} context={context} module={getModule(context.name)} />)}
+        {MODULE_CONTEXT.map((context: IModuleContext) => <ModuleItem key={context.name} context={context} module={getModule(context.name)} />)}

12-12: Add error handling for data fetching

The component doesn't handle errors that might occur during data fetching. Consider destructuring and using the error property from useModules.

-  const { data, isLoading } = useModules(community?.id);
+  const { data, isLoading, error } = useModules(community?.id);
+
+  if (error) {
+    return <div className="alert alert-error">Failed to load modules. Please try again later.</div>;
+  }
src/components/home/platforms/PlatformList.tsx (4)

14-14: Simplify redundant fallback to undefined

The expression community?.id || undefined is redundant since the optional chaining operator (?.) already returns undefined if community is null or undefined.

-  const { data, isLoading } = usePlatforms(community?.id || undefined);
+  const { data, isLoading } = usePlatforms(community?.id);

16-18: Consider adding type safety to the platformExists function

Adding an explicit return type to the function would improve type safety and make the code more maintainable.

-  const platformExists = (name: string) => {
+  const platformExists = (name: string): boolean => {
     return data?.results?.some((platform: IPlatformProps) => platform.name === name);
   }

30-30: Avoid using array index as React key

Using array index as a key can lead to rendering issues if the platform order changes. Since each platform context has a unique name property, use that as the key instead.

-        {PLATFORM_CONTEXT.map((context, index) => <PlatformItem key={index} context={context} exists={platformExists(context.name)} />)}
+        {PLATFORM_CONTEXT.map((context) => <PlatformItem key={context.name} context={context} exists={platformExists(context.name)} />)}

20-22: Consider adding error handling for data fetching

The component doesn't handle errors that might occur during data fetching. Consider destructuring and using the error property from usePlatforms.

-  const { data, isLoading } = usePlatforms(community?.id);
+  const { data, isLoading, error } = usePlatforms(community?.id);
+
+  if (error) {
+    return <div className="alert alert-error">Failed to load platforms. Please try again later.</div>;
+  }
src/components/auth/ProtectedRoute.tsx (2)

18-20: Enhance authentication state handling

The component doesn't clearly distinguish between "loading authentication status" and "definitely not authenticated". This could lead to showing the loading screen unnecessarily for users who are definitely not logged in.

-  if (!isAuthenticated) {
+  const { isLoading } = useAuth();
+  if (isLoading) {
     return <LoadingScreen />;
   }
+
+  if (!isAuthenticated) {
+    // No need to render anything here as the useEffect will handle the redirect
+    return null;
+  }

12-16: Consider preventing flash of protected content

If isAuthenticated changes after initial render (e.g., token expires), users might briefly see protected content before being redirected.

Add dependency tracking to the authentication state, and consider using a loading state while checking:

+  const { isAuthenticated, isLoading } = useAuth();
-  const { isAuthenticated } = useAuth();
   const router = useRouter();

   useEffect(() => {
-    if (!isAuthenticated) {
+    if (!isLoading && !isAuthenticated) {
       router.push('/centric'); // TODO: change to /login
     }
-  }, [isAuthenticated, router]);
+  }, [isAuthenticated, isLoading, router]);
src/components/centric/selectCommunity/TcSelectCommunity.tsx (1)

25-25: Consider making the prop optional with a default value.

The handleCommunityLoading prop is required, which could break the component if used without providing this callback. Consider making it optional with a default no-op function.

-function TcSelectCommunity({ handleCommunityLoading }: { handleCommunityLoading: (loading: boolean) => void }) {
+function TcSelectCommunity({ handleCommunityLoading = () => {} }: { handleCommunityLoading?: (loading: boolean) => void }) {
src/utils/JwtPayloadType.ts (2)

1-5: Add documentation for JwtIdentityType properties.

This type is well-structured but lacks documentation explaining the purpose of each field. Consider adding JSDoc comments for better code maintainability.

+/**
+ * Represents a user identity within a JWT
+ */
 export type JwtIdentityType = {
+  /** MongoDB ObjectId of the identity */
   _id: string;
+  /** The authentication provider (e.g., 'discord', 'github') */
   provider: string;
+  /** The user ID from the provider */
   id: string;
 }

7-19: Improve documentation for JwtPayloadType.

The JWT payload type lacks documentation for its properties, especially non-standard fields like tcaAt. Adding comments would help developers understand the payload structure.

+/**
+ * Represents the complete JWT payload structure
+ */
 export type JwtPayloadType = {
   sub: {
     communities: string[];
     createdAt: string;
     updatedAt: string;
+    /** Timestamp when Terms and Conditions were accepted */
     tcaAt: string;
     identities: JwtIdentityType[];
     id: string;
   },
+  /** Issued At timestamp */
   iat: number;
+  /** Expiration timestamp */
   exp: number;
+  /** Token type (e.g., 'access', 'refresh') */
   type: string;
 }
src/axiosInstance.ts (2)

131-143: Improve path checking and remove console.log.

The code now checks if the user is already on the login page before showing the expired token message, which prevents redundant notifications. However, there's an inconsistency in path checking and unnecessary console logging.

-          if (window.location.pathname !== '/centric/') {
-            console.log(window.location.pathname);
+          if (window.location.pathname !== '/centric') {
             toast.error('Token expired...', {
               position: 'bottom-left',
               autoClose: 5000,
               hideProgressBar: false,
               closeOnClick: true,
               pauseOnHover: true,
               draggable: true,
               progress: 0,
             });
             window.location.href = '/centric';
           }

127-130: Consider refactoring repeated localStorage removal operations.

There's repetition in localStorage removal operations across different branches of the error handling logic. Consider extracting this into a helper function.

+const clearAuthData = () => {
+  StorageService.removeLocalStorage('community');
+  StorageService.removeLocalStorage('TC_SELECTED_PLATFORM');
+  StorageService.removeLocalStorage('analysis_state');
+  StorageService.removeLocalStorage('user');
+};

// Then replace the repetitive code with:
// clearAuthData();
src/app/layout.tsx (1)

20-32: Reconsider overflow-y-hidden and add metadata.

The root layout is well-structured with the AuthProvider wrapper, but has two potential issues:

  1. The overflow-y-hidden class might prevent scrolling on pages that need it
  2. There's no metadata configuration (title, description)
 export default function RootLayout({ children }: { children: React.ReactNode }) {
   return (
-    <html lang="en" data-theme="light">
+    <html lang="en" data-theme="light">
+      <head>
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <title>Community Management Platform</title>
+        <meta name="description" content="A community management platform" />
+      </head>
       <body className={`${inter.variable} ${roboto_mono.variable} antialiased`}>
         <AuthProvider>
-          <div className="flex min-h-screen bg-gray-100 overflow-y-hidden">
+          <div className="flex min-h-screen bg-gray-100">
             {children}
           </div>
         </AuthProvider>
       </body>
     </html>
   )
 }
src/components/layouts/DashboardLayout.tsx (2)

10-15: Consider renaming the toggle function for clarity

The function name setIsSidebarOpen suggests it's a direct setter, but it actually toggles the state. A more descriptive name like toggleSidebar would better reflect its behavior.

-  const setIsSidebarOpen = () => {
+  const toggleSidebar = () => {
     setUi({ ...ui, isSidebarOpen: !ui.isSidebarOpen });
   }

Then update the prop references in lines 19 and 21.


20-22: Ensure content overflow handling is consistent

Line 20 includes overflow-y-hidden on the parent container while line 22 sets overflow-y-auto on the child div. This approach works but could be simplified. Consider handling overflow only at the child level for better control.

src/hooks/sidebar/useSidebar.ts (2)

27-55: Add TypeScript return type annotation to the hook

The hook lacks explicit return type annotation. Adding it would improve type safety and make the interface clearer for other developers.

-export const useSidebar = () => {
+export const useSidebar = (): { sidebarItems: ISidebarItem[] } => {

30-49: Improve code structure for better readability

The logic for generating sidebar items could be structured more cleanly to avoid the conditional branches. Consider extracting common logic to improve readability.

  const sidebarItems = useMemo(() => {
-
-    if (!isAdmin) {
-      const items = MODULE_CONTEXT.filter(module => !module.adminOnly).map(module => ({
-        label: module.title,
-        icon: module.icon,
-        href: module.modulePath,
-      }))
-
-      return [...defaultItems, ...items]
-    }
-
-    const items: ISidebarItem[] = MODULE_CONTEXT.map(module => ({
+    // Filter modules based on admin status
+    const filteredModules = isAdmin 
+      ? MODULE_CONTEXT 
+      : MODULE_CONTEXT.filter(module => !module.adminOnly);
+    
+    // Map modules to sidebar items
+    const moduleItems: ISidebarItem[] = filteredModules.map(module => ({
       label: module.title,
       icon: module.icon,
       href: module.modulePath,
     }))
-
-    return [...defaultItems, ...items, ...adminItems];
+    
+    // Include admin items only for admins
+    return [...defaultItems, ...moduleItems, ...(isAdmin ? adminItems : [])];
   }, [isAdmin]);
src/components/home/platforms/UpvoteButton.tsx (1)

11-35: Implement debounce for the click handler

The click handler doesn't have any debounce mechanism, which could result in duplicate submissions if clicked rapidly, even with the disabled state.

Consider using a debounce utility (like lodash's debounce) to prevent rapid successive clicks:

+import { debounce } from 'lodash';

 export function UpvoteButton({ community, name }: { community: any, name: string }) {
   const [loading, setLoading] = useState(false);
   const { showMessage } = useSnackbar();

-  const handleClick = () => {
+  const handleClick = debounce(() => {
     setLoading(true);
     try {
       setAmplitudeUserIdFromToken();

       trackAmplitudeEvent({
         eventType: "Upvote Data Source",
         eventProperties: {
           communityId: community?.id,
           communityName: community?.name,
           upvote: name,
         },
         callback: () => {
           showMessage(
             'Thank you for voting!',
             'success',
           );
           setLoading(false);
         }
       });
     } catch (e) {
       console.error(e);
       setLoading(false);
     }
-  };
+  }, 300);

Don't forget to add the lodash dependency if not already installed.

src/context/AuthProvider.tsx (4)

31-33: Effect cleanup is missing loading reset

When the component unmounts, the loading state isn't reset, which could cause issues if the component remounts.

useEffect(() => {
  setLoading(false)
+ return () => {
+   setLoading(true)
+ }
}, [auth])

37-46: Add error handling for token expiration

The jwt decoding logic properly handles invalid tokens, but doesn't specifically check for expired tokens.

const decodedJwt: JwtPayloadType | null =
  useMemo(() => {
    if (!accessToken) return null;
    try {
      const decoded = jwtDecode<JwtPayloadType>(accessToken);
+     if (decoded.exp * 1000 < Date.now()) {
+       console.warn("Token expired");
+       return null;
+     }
      return decoded;
    } catch (error) {
      console.error("Invalid JWT:", error);
      return null;
    }
  }, [accessToken])

68-70: Remove console.log statement

Debug console.log statement should be removed before production deployment.

const refreshAccessToken = async () => {
-  console.log("refreshAccessToken")
  if (!auth.refreshToken) {
    logout();
    return;
  }

89-89: Consider adding configurable refresh buffer time

The 60000ms (1 minute) buffer before token expiry is hardcoded. Consider making this configurable or at least defined as a constant.

+ const TOKEN_REFRESH_BUFFER_MS = 60000; // 1 minute
// ...
- const timeoutId = setTimeout(refreshAccessToken, expiresInMs - 60000); // Refresh 1 min before expiry
+ const timeoutId = setTimeout(refreshAccessToken, expiresInMs - TOKEN_REFRESH_BUFFER_MS);
src/app/dashboard/layout.tsx (2)

10-10: Consider configuring QueryClient with options

The QueryClient is created without any configuration options, which might not be optimal for your application needs.

-const queryClient = new QueryClient();
+const queryClient = new QueryClient({
+  defaultOptions: {
+    queries: {
+      refetchOnWindowFocus: false,
+      retry: 1,
+      staleTime: 5 * 60 * 1000, // 5 minutes
+    },
+  },
+});

12-14: Remove unnecessary empty lines

There are extra empty lines between the function declaration and the return statement.

export default function RootLayout({ children }: { children: React.ReactNode }) {
-

-
  return (
src/components/home/platforms/PlatformItem.tsx (3)

12-26: Remove commented code

The file contains commented-out code for ConnectButton and ManageButton components that should be removed if they're no longer needed.

-// function ConnectButton({ context }: { context: IPlatformContext }) {
-//   return (
-//     <a href={`/community-settings?addPlatform=${context.title.toLocaleLowerCase()}`} className="btn btn-sm btn-square">
-//       <FaCog />
-//     </a>
-//   )
-// }
-
-// function ManageButton({ context }: { context: IPlatformContext }) {
-//   return (
-//     <a href={`/community-settings?managePlatform=${context.title.toLocaleLowerCase()}`} className="btn btn-sm btn-square">
-//       <FaCog />
-//     </a>
-//   )
-// }

39-39: Use consistent case handling

Using toLocaleLowerCase() directly might lead to inconsistencies. Consider creating a utility function for consistent case handling.

-<TcCommunityPlatformIcon platform={context.name.toLocaleLowerCase()} size={20} />
+<TcCommunityPlatformIcon platform={context.name.toLowerCase()} size={20} />

45-60: Simplify nested JSX structure

The nested structure with empty fragments (<>...</>) is unnecessary and can be simplified.

) : (
-  <>
-    <div className="flex items-center gap-4">
-      {exists ? (
-        <div className="w-2 h-2 bg-success rounded-full"></div>
-      ) : (
-        <div className="w-2 h-2 bg-base-300 rounded-full"></div>
-      )}
-      {isAdmin && (
-        <a href={context.configPath} className="btn btn-sm btn-square">
-          <FaCog />
-        </a>
-      )}
-
-    </div>
-  </>
+  <div className="flex items-center gap-4">
+    <div className={`w-2 h-2 rounded-full ${exists ? 'bg-success' : 'bg-base-300'}`}></div>
+    {isAdmin && (
+      <a href={context.configPath} className="btn btn-sm btn-square">
+        <FaCog />
+      </a>
+    )}
+  </div>
)}
src/utils/interfaces.ts (4)

241-241: Add JSDoc comments for the activated property

The newly added activated property lacks documentation explaining its purpose and usage.

  options: {
    platforms: IPlatformModuleProps[];
  };
+  /** Indicates if the module is currently activated for the community */
  activated: boolean;

244-253: Add JSDoc comments for the IModuleContext interface

This new interface lacks documentation for its properties, making it harder for other developers to understand.

+/**
+ * Context information for a community management module
+ */
export interface IModuleContext {
+  /** Icon component to represent the module */
  icon: React.ElementType;
+  /** Unique identifier for the module */
  name: string;
+  /** Display title for the module */
  title: string;
+  /** Description explaining the module's purpose */
  description: string;
+  /** Whether the module is available for use */
  available: boolean;
+  /** Path to the module configuration page */
  configPath: string;
+  /** Path to the module main page */
  modulePath: string;
+  /** If true, only administrators can see and access this module */
  adminOnly?: boolean;
}

255-260: Add JSDoc comments for the IPlatformContext interface

This interface also lacks documentation for its properties.

+/**
+ * Context information for a community platform
+ */
export interface IPlatformContext {
+  /** Unique identifier for the platform */
  name: string;
+  /** Display title for the platform */
  title: string;
+  /** Whether the platform is available for use */
  available: boolean;
+  /** Path to the platform configuration page */
  configPath: string;
}

262-267: Consider adding a key or id field to ISidebarItem

For optimal rendering performance with React's list rendering, a unique identifier might be useful.

export interface ISidebarItem {
+  /** Unique identifier for the sidebar item */
+  id?: string;
  label: string;
  icon: React.ElementType;
  href: string;
  children?: ISidebarItem[];
}
src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (1)

138-145: Provide a clipboard fallback for non-secure contexts / older browsers

navigator.clipboard is only available on HTTPS origins and in some browsers it still requires user gesture permissions. If it fails, users get no feedback.

-    navigator.clipboard.writeText(`/verify ${telegram.value}`);
-    showMessage("Token copied to clipboard!", "success");
+    try {
+      await navigator.clipboard.writeText(`/verify ${telegram.value}`);
+      showMessage("Token copied to clipboard!", "success");
+    } catch {
+      // fallback: select & copy via execCommand
+      const tmp = document.createElement("textarea");
+      tmp.value = `/verify ${telegram.value}`;
+      document.body.appendChild(tmp);
+      tmp.select();
+      document.execCommand("copy");
+      document.body.removeChild(tmp);
+      showMessage("Token copied to clipboard!", "success");
+    }
src/components/home/modules/ModuleItem.tsx (1)

40-50: Avoid double–evaluation & ternary nesting in toast message

The nested ternary is hard to scan and will return an empty string if, in some edge case, both flags flip true in the same tick.

-  useEffect(() => {
-    if (updateModule.isSuccess || createModule.isSuccess) {
-      toast.success(`${updateModule.isSuccess ? "Module updated" : createModule.isSuccess ? "Module created" : ""}`, {
+  useEffect(() => {
+    const message = updateModule.isSuccess
+      ? "Module updated"
+      : createModule.isSuccess
+      ? "Module created"
+      : undefined;
+
+    if (message) {
+      toast.success(message, {
         position: 'bottom-left',
         autoClose: 5000,
         hideProgressBar: false,
         closeOnClick: true,
         pauseOnHover: true,
       });
     }
   }, [updateModule.isSuccess, createModule.isSuccess]);
src/components/layouts/Sidebar.tsx (2)

48-51: Strip debug logging from production build

The sidebar effect logs the entire sidebarItems array on every change. This should be removed or guarded by an env flag.

-	useEffect(() => {
-		console.log(sidebarItems)
-	}, [sidebarItems]);
+	// useEffect(() => {
+	//   if (process.env.NODE_ENV !== 'production') console.log(sidebarItems);
+	// }, [sidebarItems]);

64-65: translate-x-full should respect LTR / RTL direction

If the app ever needs RTL support, hard-coding translate-x may slide the sidebar in the wrong direction. Consider using logical properties or conditionally applying -translate-x-full / translate-x-full based on direction.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ea91472 and bfcd885.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (63)
  • package.json (5 hunks)
  • src/app/dashboard/agent/page.tsx (2 hunks)
  • src/app/dashboard/community-guardian/page.tsx (1 hunks)
  • src/app/dashboard/layout.tsx (1 hunks)
  • src/app/dashboard/page.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/atoms/authState.atom.ts (1 hunks)
  • src/atoms/ui.atom.ts (1 hunks)
  • src/axiosInstance.ts (3 hunks)
  • src/components/LoadingScreen.tsx (1 hunks)
  • src/components/auth/ProtectedRoute.tsx (1 hunks)
  • src/components/centric/selectCommunity/TcCommunityItem.tsx (1 hunks)
  • src/components/centric/selectCommunity/TcCommunityListItems.tsx (1 hunks)
  • src/components/centric/selectCommunity/TcSelectCommunity.tsx (3 hunks)
  • src/components/chat/Chat.tsx (1 hunks)
  • src/components/chat/ChatForm.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcDiscourse.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcGithubIntegration.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcMediaWiki.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcWebsite.tsx (1 hunks)
  • src/components/home/modules/ModuleItem.tsx (1 hunks)
  • src/components/home/modules/ModuleList.tsx (1 hunks)
  • src/components/home/platforms/PlatformItem.tsx (1 hunks)
  • src/components/home/platforms/PlatformList.tsx (1 hunks)
  • src/components/home/platforms/UpvoteButton.tsx (1 hunks)
  • src/components/layouts/DashboardLayout.tsx (1 hunks)
  • src/components/layouts/Navbar.tsx (1 hunks)
  • src/components/layouts/Sidebar.tsx (1 hunks)
  • src/components/layouts/xs/SidebarXs.tsx (1 hunks)
  • src/constants/ModuleContext.ts (1 hunks)
  • src/constants/PlatformContext.ts (1 hunks)
  • src/context/AuthProvider.tsx (1 hunks)
  • src/hooks/modules/useModuleActions.ts (1 hunks)
  • src/hooks/modules/useModules.ts (1 hunks)
  • src/hooks/platforms/usePlatforms.ts (1 hunks)
  • src/hooks/sidebar/useSidebar.ts (1 hunks)
  • src/hooks/useAdmin.ts (1 hunks)
  • src/hooks/useApi.ts (1 hunks)
  • src/hooks/useDatasources.ts (1 hunks)
  • src/layouts/centricLayout.tsx (1 hunks)
  • src/layouts/defaultLayout.tsx (1 hunks)
  • src/pages/_app.tsx (1 hunks)
  • src/pages/announcements/index.tsx (3 hunks)
  • src/pages/callback.tsx (4 hunks)
  • src/pages/centric/create-new-community.tsx (2 hunks)
  • src/pages/centric/index.tsx (2 hunks)
  • src/pages/centric/select-community.tsx (1 hunks)
  • src/pages/centric/tac.tsx (2 hunks)
  • src/pages/centric/welcome.tsx (0 hunks)
  • src/pages/community-settings/ai-assistant/index.tsx (1 hunks)
  • src/pages/community-settings/index.tsx (1 hunks)
  • src/pages/community-settings/violation-detection/index.tsx (1 hunks)
  • src/pages/index.tsx (1 hunks)
  • src/pages/statistics.tsx (6 hunks)
  • src/styles/globals.css (1 hunks)
  • src/utils/JwtPayloadType.ts (1 hunks)
  • src/utils/interfaces.ts (1 hunks)
  • tailwind.config.js (1 hunks)
  • tsconfig.json (2 hunks)
💤 Files with no reviewable changes (1)
  • src/pages/centric/welcome.tsx
🧰 Additional context used
🧬 Code Graph Analysis (24)
src/hooks/modules/useModuleActions.ts (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/components/layouts/DashboardLayout.tsx (2)
src/atoms/ui.atom.ts (1)
  • uiAtom (5-8)
src/components/layouts/Navbar.tsx (1)
  • Navbar (16-51)
src/pages/centric/tac.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/constants/PlatformContext.ts (1)
src/utils/interfaces.ts (1)
  • IPlatformContext (255-260)
src/layouts/defaultLayout.tsx (1)
src/components/layouts/DashboardLayout.tsx (1)
  • DashboardLayout (10-28)
src/hooks/useDatasources.ts (1)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/components/auth/ProtectedRoute.tsx (2)
src/context/AuthProvider.tsx (1)
  • useAuth (103-109)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/axiosInstance.ts (1)
src/services/StorageService.ts (1)
  • StorageService (4-61)
src/constants/ModuleContext.ts (1)
src/utils/interfaces.ts (1)
  • IModuleContext (244-253)
src/hooks/modules/useModules.ts (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/app/dashboard/page.tsx (2)
src/components/home/platforms/PlatformList.tsx (1)
  • PlatformList (10-34)
src/components/home/modules/ModuleList.tsx (1)
  • ModuleList (9-32)
src/hooks/sidebar/useSidebar.ts (3)
src/utils/interfaces.ts (1)
  • ISidebarItem (262-267)
src/hooks/useAdmin.ts (1)
  • useAdmin (5-13)
src/constants/ModuleContext.ts (1)
  • MODULE_CONTEXT (7-69)
src/components/home/platforms/UpvoteButton.tsx (2)
src/context/SnackbarContext.tsx (1)
  • useSnackbar (59-65)
src/helpers/amplitudeHelper.tsx (2)
  • setAmplitudeUserIdFromToken (13-24)
  • trackAmplitudeEvent (26-49)
src/components/home/platforms/PlatformList.tsx (5)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/hooks/platforms/usePlatforms.ts (1)
  • usePlatforms (4-14)
src/utils/interfaces.ts (1)
  • IPlatformProps (142-152)
src/constants/PlatformContext.ts (1)
  • PLATFORM_CONTEXT (3-48)
src/components/home/platforms/PlatformItem.tsx (1)
  • PlatformItem (29-64)
src/pages/callback.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/context/AuthProvider.tsx (4)
src/utils/JwtPayloadType.ts (1)
  • JwtPayloadType (7-19)
src/atoms/authState.atom.ts (1)
  • authState (14-14)
src/configs/index.ts (1)
  • conf (1-17)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/components/home/modules/ModuleItem.tsx (6)
src/utils/interfaces.ts (2)
  • IModuleContext (244-253)
  • IModuleProps (234-242)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/hooks/useAdmin.ts (1)
  • useAdmin (5-13)
src/hooks/modules/useModuleActions.ts (1)
  • useModuleActions (5-22)
src/hooks/modules/useModules.ts (1)
  • useModules (4-14)
src/components/home/platforms/UpvoteButton.tsx (1)
  • UpvoteButton (7-44)
src/components/home/platforms/PlatformItem.tsx (4)
src/utils/interfaces.ts (1)
  • IPlatformContext (255-260)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/hooks/useAdmin.ts (1)
  • useAdmin (5-13)
src/components/home/platforms/UpvoteButton.tsx (1)
  • UpvoteButton (7-44)
src/pages/centric/create-new-community.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/pages/centric/select-community.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/components/layouts/Sidebar.tsx (2)
src/utils/interfaces.ts (1)
  • ISidebarItem (262-267)
src/hooks/sidebar/useSidebar.ts (1)
  • useSidebar (27-55)
src/hooks/platforms/usePlatforms.ts (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (3)
src/context/SnackbarContext.tsx (1)
  • useSnackbar (59-65)
src/services/StorageService.ts (1)
  • StorageService (4-61)
src/rainbowKitConfig.ts (1)
  • isProduction (7-7)
src/app/dashboard/community-guardian/page.tsx (1)
src/constants/ModuleContext.ts (1)
  • MODULE_CONTEXT (7-69)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (56)
src/pages/_app.tsx (1)

42-42: No-op formatting change
Only a blank line was added after the App function declaration; there’s no functional impact.

src/pages/statistics.tsx (2)

310-310: Removed trailing whitespace in scrollToHash
This is a whitespace-only cleanup, with no change to logic or behavior.


383-384: Uniform background styling
Added the bg-base-100 class to all Box containers for consistent background color across the statistics sections. Aligns with the updated design system without altering functionality.

Also applies to: 398-399, 413-414, 429-430, 444-445

src/components/centric/selectCommunity/TcCommunityListItems.tsx (1)

2-4: Non-functional import formatting change
Imports have been reordered and separated by blank lines for clarity; there’s no logic change.

src/components/layouts/xs/SidebarXs.tsx (1)

54-61: Updated home route to /dashboard
The "Home" menu item now points to the new dashboard path, reflecting the removal of /centric/welcome and the introduction of the dashboard home page.

src/pages/community-settings/ai-assistant/index.tsx (1)

31-31: Added bg-base-100 rounded-lg for container styling
This brings the AI assistant settings panel in line with other community settings pages by applying a consistent background and rounded corners.

src/styles/globals.css (1)

5-8: Consistent Tooltip Font Styling
The new .tooltip::before rule sets the font size to 0.75rem, matching the Tailwind text-xs scale and ensuring tooltip content is appropriately sized across the app.

src/pages/community-settings/violation-detection/index.tsx (1)

165-165: Apply Unified Container Styling
Adding bg-base-100 rounded-lg to the TcBoxContainer ensures this settings panel matches the background and corner radius conventions used in other dashboard and settings pages.

src/pages/community-settings/index.tsx (1)

68-68: Unify Community Settings Container Styles
The bg-base-100 rounded-lg classes bring the main container in line with the rest of the community settings UI, improving visual consistency.

src/components/chat/ChatForm.tsx (1)

16-16: Enhance Chat Form Styling for Consistency
Replacing the old border with rounded-lg, mb-4, bg-base-100, w-full, and max-w-3xl aligns the chat form with the application’s card-style containers and enforces responsive width limits.

src/pages/announcements/index.tsx (2)

195-195: Improved UI consistency with background styling.

Adding the bg-base-100 class to the main container aligns this page with the global styling pattern used across other pages in the application.


243-243: Fixed indentation for better code readability.

The conditional rendering and pagination calculation now have proper indentation, which improves code readability and maintainability.

Also applies to: 279-279

src/layouts/centricLayout.tsx (1)

12-17: Simplified layout structure by commenting out Container.

The Container component and its wrapping of children have been commented out, which simplifies the layout structure. This aligns with the broader layout restructuring in the application where specialized components like DashboardLayout now handle specific layout responsibilities.
[suggest_verification]
Please verify that this change doesn't negatively impact pages that still use the centricLayout component, as the children are now rendered directly in the Box component without additional styling.

#!/bin/bash
# Find files that import or use centricLayout to verify impact
rg "from ['|\"].*layouts/centricLayout" --type=ts --type=tsx
rg "centricLayout" --type=ts --type=tsx
src/components/communitySettings/communityPlatforms/TcMediaWiki.tsx (1)

48-53: Improved search parameters handling.

Moving the addPlatform declaration inside the useEffect hook and updating the dependency array from [addPlatform] to [searchParams] ensures the component correctly reacts to URL parameter changes. This is more reactive and aligns with React's best practices.

src/components/communitySettings/communityPlatforms/TcGithubIntegration.tsx (1)

37-42: Improved search parameters handling.

Moving the addPlatform declaration inside the useEffect hook and updating the dependency array from [addPlatform] to [searchParams] ensures the component correctly reacts to URL parameter changes. This change is consistent with similar updates across other platform integration components.

tailwind.config.js (1)

144-147: Great addition of DaisyUI to the project!

Adding DaisyUI as a plugin will provide a set of pre-built components and utilities that work well with Tailwind CSS. Limiting the theme to just "light" helps maintain consistency across the application.

src/components/communitySettings/communityPlatforms/TcDiscourse.tsx (1)

57-62: Good refactoring to prevent stale closure issues.

Moving the addPlatform extraction inside the useEffect and changing the dependency array from [addPlatform] to [searchParams] is a good practice. This ensures the effect runs whenever search parameters change, preventing potential stale closure issues where the component would use outdated query parameter values.

tsconfig.json (1)

4-8: Improved TypeScript configuration with better readability and Next.js support.

The changes to this configuration file are well-structured and add important Next.js TypeScript support:

  1. Expanded arrays for better readability.
  2. Added the Next.js plugin for proper TypeScript support of Next.js features.
  3. Included .next/types/**/*.ts for type generation compatibility.

These changes will improve the developer experience and TypeScript support for Next.js-specific features like app router and client/server components.

Also applies to: 23-31, 38-43

src/pages/centric/index.tsx (2)

3-7: Enhanced landing page with logo and improved layout.

Adding the TogetherCrew logo and improving the layout with flexbox provides a more polished and professional appearance to the login page. This change aligns with design improvements across the application.

Also applies to: 18-19


24-24: Improved content layout with flexbox.

Converting the content container to use flex layout with proper spacing and alignment creates a more visually balanced interface with consistent spacing between elements.

package.json (4)

19-19: Appropriate dependency classification

Moving "3d-force-graph-vr" from devDependencies to dependencies correctly reflects its usage at runtime rather than just during development.


51-51: Good addition of state management library

Adding Jotai aligns with the PR objectives of implementing atom-based state management. This lightweight state management library will help with the refactoring of the platform and module contexts.


90-90: Good UI enhancement with DaisyUI

Adding DaisyUI as a dev dependency is appropriate for enhancing Tailwind styling. This aligns with the UI improvements mentioned in the PR objectives.


73-73:

Details

✅ Verification successful

Verify TypeScript compatibility

The TypeScript version has been slightly downgraded to "^5.6.0". Ensure this version is compatible with all other dependencies and doesn't introduce type-checking regressions.


🏁 Script executed:

#!/bin/bash
# Check for potential TypeScript compatibility issues
npm info typescript@^5.6.0 peerDependencies
npm info typescript@^5.6.0 engines

# Search for TypeScript version constraints in other dependencies
grep -r '"typescript"' node_modules/*/package.json | grep "peerDependencies\|engines"

Length of output: 1075


TypeScript 5.6.0 Compatibility Confirmed

No other dependencies declare a TypeScript peerDependency or tighter engine requirement, and the TypeScript 5.x line all require only Node >=14.17.0. Upgrading/downgrading to "^5.6.0" therefore poses no compatibility risk with existing packages.

– No peerDependencies on "typescript" found in installed packages
– Engines requirement remains node >=14.17.0 (same as before)

src/components/centric/selectCommunity/TcCommunityItem.tsx (1)

1-10: Improved import organization

The reorganization of imports follows a more logical structure, grouping related imports together and adding proper spacing. This improves code readability and aligns with common import ordering conventions.

src/hooks/useAdmin.ts (1)

1-13: Well-structured admin permission hook

This hook follows React best practices by having a single responsibility, handling potential undefined values, and encapsulating the admin check logic. The 'use client' directive ensures it works correctly in Next.js client components.

src/atoms/ui.atom.ts (1)

1-8: LGTM! Good implementation of persistent UI state management.

Using atomWithStorage is an excellent choice for persisting UI preferences across sessions. This atom will effectively manage both the sidebar state and theme preferences.

src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx (1)

41-46: Good improvement to useEffect dependency management.

Moving the addPlatform extraction inside the useEffect hook and updating the dependency array to depend on searchParams ensures the effect always uses the latest query parameters and correctly reacts to URL changes.

src/layouts/defaultLayout.tsx (2)

3-4: Good addition of DashboardLayout import.

This import enables the layout refactoring that follows.


13-18: Excellent refactoring to improve component composition.

The changes improve the architecture by:

  1. Adding proper container styling with flex layout and minimum height
  2. Delegating sidebar and layout management to the dedicated DashboardLayout component
  3. Simplifying the defaultLayout component's responsibilities

This separation of concerns makes the code more maintainable and aligns with the centralized UI state management approach using the uiAtom.

src/hooks/useApi.ts (2)

5-5: Good type enhancement to support optional URLs.

Updating the hook to accept string | null makes the API more flexible and aligns with common patterns where URL parameters might not be immediately available.


13-13: Excellent guard clause to prevent unnecessary API calls.

Adding this early return when the URL is falsy prevents unnecessary network requests and potential errors when no valid URL is provided. This makes the hook more robust for conditional fetching scenarios.

src/pages/centric/tac.tsx (2)

47-47: LGTM - Loading UI enhancement

Good improvement replacing the previous loading indicator with the standardized LoadingScreen component.


51-52: UI improvement with Tailwind and logo

Nice enhancement using Tailwind CSS for consistent styling and adding the logo at the top of the page. Matches the styling pattern used in other pages.

src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx (1)

111-113: Defensive coding with optional chaining - good practice

Good defensive programming practice using optional chaining to prevent potential runtime errors when accessing search parameters. This ensures the code won't crash if searchParams is null or undefined.

src/pages/callback.tsx (1)

275-275: LGTM: Successfully replaced SimpleBackdrop with LoadingScreen.

The component swap looks good and aligns with the broader effort to standardize loading UI across the application.

src/components/chat/Chat.tsx (1)

131-131: Darker background for user messages improves readability

Changing the user message background from bg-gray-100 to bg-gray-200 provides better contrast and visibility.

src/components/home/modules/ModuleList.tsx (1)

18-20: The loading state visualization looks good

The skeleton loader provides a good user experience while waiting for module data to load.

src/app/dashboard/agent/page.tsx (4)

1-1: Good use of 'use client' directive

Correctly marking this as a client component for Next.js App Router.


3-3: Updated icon import to newer version

Updating from react-icons/fa to react-icons/fa6 is a good practice to use the latest available icons.


8-8: Improved function naming

Renaming from Index to AgentPage improves semantic clarity and code readability.


12-12: Review scrolling behavior

Adding overflow-y-auto without a defined height constraint might not work as expected for scrolling. Consider setting a max-height or ensure there's a parent container with a defined height.

Could you verify that the scrolling behavior works as expected in this container? You might need to add a height constraint like max-h-screen or ensure the parent container defines a height.

src/components/auth/ProtectedRoute.tsx (2)

14-14: Address TODO comment before production

The TODO comment about changing the redirect path to /login should be addressed before merging to production, or tracked in a ticket.

Is there a ticket tracking this TODO item? If not, please create one to ensure this gets addressed in a future update.


8-23: Good implementation of route protection

Overall, this is a solid implementation of route protection that correctly guards routes based on authentication status and provides a loading indicator while checking auth state.

src/components/centric/selectCommunity/TcSelectCommunity.tsx (3)

42-44: Good implementation of the state lifting pattern.

This useEffect properly propagates the loading state to the parent component, which aligns with React's "lifting state up" pattern.


82-82: Navigation route updated to dashboard.

The navigation target has been changed from the welcome page to the dashboard, which aligns with the broader architectural changes in the application.


86-88: Loading state is now managed externally.

The component no longer renders its own loading indicator, returning null instead. This is consistent with the parent component now handling the loading UI.

src/axiosInstance.ts (2)

61-61: Reordering of localStorage removals.

The order of localStorage item removal has been adjusted, moving 'user' removal before potential redirects. This is a good change that ensures authentication state is properly cleared.


79-80: Proper destructuring of refreshToken.

Direct destructuring of the refreshToken from the user object improves code readability.

src/app/layout.tsx (2)

1-18: Well-structured font configuration using Next.js best practices.

The Google fonts configuration follows Next.js best practices for performance, using proper subsets and CSS variables.


5-5: Good implementation of centralized authentication.

The AuthProvider wrapper implements centralized authentication state management, making auth context available throughout the application.

src/components/layouts/DashboardLayout.tsx (1)

1-28: Well-structured dashboard layout with clean state management

The layout component is well-organized and implements a clean pattern for managing sidebar state using Jotai. The transition effects on sidebar toggle provide a smooth user experience.

src/app/dashboard/community-guardian/page.tsx (1)

22-23: 🛠️ Refactor suggestion

Add fallback for missing module data

Line 22 directly accesses data.icon without checking if data exists first, but there's a condition that redirects if data is missing. This could cause errors during the brief moment before redirect happens.

-        {data && <data.icon size={24} className="text-secondary" />}
-        <h1 className="text-2xl font-semibold">{data?.title}</h1>
+        {data ? (
+          <>
+            <data.icon size={24} className="text-secondary" />
+            <h1 className="text-2xl font-semibold">{data.title}</h1>
+          </>
+        ) : (
+          <h1 className="text-2xl font-semibold">Loading...</h1>
+        )}

Likely an incorrect or invalid review comment.

src/context/AuthProvider.tsx (1)

103-109: Good error handling in useAuth hook

The error message is clear and specific about how to resolve the issue.

src/app/dashboard/layout.tsx (1)

15-25: Well-structured component composition

The layout properly composes multiple context providers and wraps the children with appropriate layout components.

src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (1)

57-63: Effect dependency update looks correct

Moving the addPlatform extraction inside the effect and switching the dependency from [addPlatform] to [searchParams] prevents stale-closure issues and matches other integration components.
No further action required.

})

const createModule = useMutation({
mutationFn: ({ module }: { module: any }) => axiosInstance.post(`/modules`, module),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace any type with specific interface for type safety

Using any for the module parameter reduces type safety. Define a specific interface for module creation.

-  mutationFn: ({ module }: { module: any }) => axiosInstance.post(`/modules`, module),
+  mutationFn: ({ module }: { module: ModuleCreateDto }) => axiosInstance.post(`/modules`, module),

You'll need to define the ModuleCreateDto interface at the top of the file:

interface ModuleCreateDto {
  name: string;
  community: string;
  active?: boolean;
  settings?: Record<string, unknown>;
  // Add other required fields
}

export const useModuleActions = () => {
const queryClient = useQueryClient();
const updateModule = useMutation({
mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(`/modules/${moduleId}`, update),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace any type with specific interface for type safety

Using any for the update parameter reduces type safety and can lead to errors. Define a specific interface for module updates.

-  mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(`/modules/${moduleId}`, update),
+  mutationFn: ({ moduleId, update }: { moduleId: string, update: ModuleUpdateDto }) => axiosInstance.patch(`/modules/${moduleId}`, update),

You'll need to define the ModuleUpdateDto interface at the top of the file:

interface ModuleUpdateDto {
  name?: string;
  active?: boolean;
  settings?: Record<string, unknown>;
  // Add other updatable fields
}

Comment on lines +6 to +8
return useQuery({
queryKey: ["modules"],
enabled: !!communityId,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Include communityId in the query key for proper cache management.

The current implementation uses a static query key that doesn't include the communityId. This can lead to cache issues where data for one community might be served for another community.

  return useQuery({
-    queryKey: ["modules"],
+    queryKey: ["modules", communityId],
    enabled: !!communityId,
    queryFn: async () => {

Comment on lines +1 to +14
import { useQuery } from "@tanstack/react-query";

import { axiosInstance } from "@/axiosInstance";
export const useModules = (communityId: string | undefined) => {

return useQuery({
queryKey: ["modules"],
enabled: !!communityId,
queryFn: async () => {
const res = await axiosInstance.get(`/modules?community=${communityId}`);
return res.data;
},
});
}; No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add proper TypeScript typing for the return value and response data.

While the hook works correctly, it lacks type definitions for the module data structure and return type, which could lead to type errors when consuming this hook.

import { useQuery } from "@tanstack/react-query";

import { axiosInstance } from "@/axiosInstance";
+
+interface Module {
+  id: string;
+  name: string;
+  // Add other module properties based on your API response
+}
+
+interface ModulesResponse {
+  results: Module[];
+  // Add other response properties like pagination if applicable
+}

-export const useModules = (communityId: string | undefined) => {
+export const useModules = (communityId: string | undefined) => {

  return useQuery({
    queryKey: ["modules"],
    enabled: !!communityId,
    queryFn: async () => {
      const res = await axiosInstance.get(`/modules?community=${communityId}`);
-      return res.data;
+      return res.data as ModulesResponse;
    },
  });
};
📝 Committable suggestion

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

Suggested change
import { useQuery } from "@tanstack/react-query";
import { axiosInstance } from "@/axiosInstance";
export const useModules = (communityId: string | undefined) => {
return useQuery({
queryKey: ["modules"],
enabled: !!communityId,
queryFn: async () => {
const res = await axiosInstance.get(`/modules?community=${communityId}`);
return res.data;
},
});
};
import { useQuery } from "@tanstack/react-query";
import { axiosInstance } from "@/axiosInstance";
interface Module {
id: string;
name: string;
// Add other module properties based on your API response
}
interface ModulesResponse {
results: Module[];
// Add other response properties like pagination if applicable
}
export const useModules = (communityId: string | undefined) => {
return useQuery({
queryKey: ["modules"],
enabled: !!communityId,
queryFn: async () => {
const res = await axiosInstance.get(`/modules?community=${communityId}`);
return res.data as ModulesResponse;
},
});
};

Comment on lines +28 to +30
const platformNames =
community?.platforms?.map((platform: any) => platform.name) || [];

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace any type with a proper interface for platform objects.

Using any type reduces type safety. Create a proper interface for platform objects to ensure type checking and code completion.

+interface Platform {
+  name: string;
+  // Add other platform properties as needed
+}

export const useDatasources = () => {

  const { community } = useToken();

  const platformNames =
-    community?.platforms?.map((platform: any) => platform.name) || [];
+    community?.platforms?.map((platform: Platform) => platform.name) || [];
📝 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 platformNames =
community?.platforms?.map((platform: any) => platform.name) || [];
// Define a proper interface for platforms
interface Platform {
name: string;
// Add other platform properties as needed
}
export const useDatasources = () => {
const { community } = useToken();
const platformNames =
community?.platforms?.map((platform: Platform) => platform.name) || [];
// ...rest of your hook logic
};

Comment on lines +53 to +55
<a href={context.configPath} className="btn btn-sm btn-square">
<FaCog />
</a>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use Next.js Link component instead of anchor tag

For client-side navigation, use Next.js Link component instead of the HTML <a> tag.

+import Link from 'next/link';

// ...

-<a href={context.configPath} className="btn btn-sm btn-square">
-  <FaCog />
-</a>
+<Link href={context.configPath} className="btn btn-sm btn-square">
+  <FaCog />
+</Link>
📝 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
<a href={context.configPath} className="btn btn-sm btn-square">
<FaCog />
</a>
// At the top of src/components/home/platforms/PlatformItem.tsx
import Link from 'next/link';
import { FaCog } from 'react-icons/fa';
// …other imports
// …inside your component’s JSX, replace:
- <a href={context.configPath} className="btn btn-sm btn-square">
- <FaCog />
- </a>
// with:
+ <Link href={context.configPath} className="btn btn-sm btn-square">
+ <FaCog />
+ </Link>


export interface ISidebarItem {
label: string;
icon: React.ElementType;
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider narrowing the icon type for better type safety

Using React.ElementType is very generic. If you're using a specific icon library, consider narrowing the type.

- icon: React.ElementType;
+ import { IconType } from 'react-icons';
+ icon: IconType;

🌐 Web query:

What's the TypeScript type for react-icons components?

💡 Result:

TypeScript Type for React-Icons Components

Recommended Type: IconType

The React Icons library provides a built-in TypeScript type called IconType. This type represents any of the icon components exported by the react-icons package:

import { IconType } from "react-icons";

type Props = {
  icon: IconType
};

You can use this when passing an icon component (not an element instance) as a prop, enabling you to render it like this:

const IconComponent: React.FC<{ icon: IconType }> = ({ icon: Icon }) => {
  return <Icon />;
};

Example usage:

import { FaBeer } from "react-icons/fa";

<IconComponent icon={FaBeer} />

This approach is clean and ensures strong type safety when dealing with icon components from react-icons[1][2].

Alternative: React.ReactNode

If you want to allow passing any rendered icon element, or need broader flexibility (such as inlining icons as JSX), you can type your prop as React.ReactNode:

type Props = {
  icon: React.ReactNode
};

This covers scenarios where the icon prop is an actual element (e.g., <FaBeer size={20} />) rather than the component itself. However, using IconType is preferred when you want to accept the component and handle props within your reusable Icon renderer[1].

Summary Table

Scenario Recommended Type Example Usage
Accepting icon component (to render within) IconType <IconComponent icon={FaBeer} />
Accepting ready-to-render JSX React.ReactNode <IconComponent icon={<FaBeer />} />

Conclusion

  • Use IconType from react-icons when the prop expects an icon component to be rendered internally.
  • Use React.ReactNode if the prop expects a rendered icon instance or needs to support any JSX[1][2].

Citations:


Narrow the icon prop to IconType for stronger type safety

Using React.ElementType is overly permissive when you know you’re only passing icons from react-icons. Switch to the library’s built-in IconType:

• File: src/utils/interfaces.ts
• Line: 264

-import React from 'react';
+import React from 'react';
+import { IconType } from 'react-icons';

-export interface MyComponentProps {
-  // …
-  icon: React.ElementType;
-}
+export interface MyComponentProps {
+  // …
+  icon: IconType;
+}

If you ever need to accept a fully rendered icon (JSX) instead of the component itself, consider React.ReactNode—but for passing icon components, IconType is the right choice.

Comment on lines +20 to +38
const handleToggle = async (checked: boolean) => {

if (!module?.id) {
await createModule.mutateAsync({
module: {
name: context.name,
activated: checked
}
})
} else {
await updateModule.mutateAsync({
moduleId: module.id,
update: {
activated: checked
}
})
}

}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add optimistic-UI disable & error handling around mutations

While the toggle is disabled during network calls, failures currently leave the UI desynced (the switch stays in the new position although the request may have failed) and provide no feedback.

   const handleToggle = async (checked: boolean) => {
-    if (!module?.id) {
-      await createModule.mutateAsync({ module: { name: context.name, activated: checked } })
-    } else {
-      await updateModule.mutateAsync({ moduleId: module.id, update: { activated: checked } })
-    }
+    try {
+      if (!module?.id) {
+        await createModule.mutateAsync({
+          module: {
+            name: context.name,
+            community: community?.id, // backend expects community id
+            activated: checked,
+          },
+        });
+      } else {
+        await updateModule.mutateAsync({
+          moduleId: module.id,
+          update: { activated: checked },
+        });
+      }
+    } catch (e) {
+      toast.error("Unable to update module. Please try again.");
+    }
   }

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

Comment on lines +34 to +35
console.log(item.href, window.location.pathname)
return (
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove console.log from render path

console.log inside render will fire on every re-render and pollute the console.

-	console.log(item.href, window.location.pathname)
📝 Committable suggestion

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

Suggested change
console.log(item.href, window.location.pathname)
return (
return (

Comment on lines +37 to +39
<Link href={item.href || ''} className={`hidden lg:flex tooltip tooltip-right btn btn-square btn-ghost ${item.href === window.location.pathname ? 'text-secondary bg-base-200' : ''}`} data-tip={item.label}><SidebarLabel item={item} /></Link>
</li>
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use usePathname() instead of window.location.pathname for route matching

Directly accessing window ties the component to the browser environment and can lead to hydration mismatches. Next.js provides usePathname which is reactive and SSR-safe for client components.

-import Link from "next/link";
+import Link from "next/link";
+import { usePathname } from "next/navigation";
...
-function SidebarItem({ item }: { item: ISidebarItem }) {
+function SidebarItem({ item }: { item: ISidebarItem }) {
+  const pathname = usePathname();
...
-  <Link ... className={`py-3 lg:hidden ${item.href === window.location.pathname ? 'text-secondary' : ''}`}>…
+  <Link ... className={`py-3 lg:hidden ${item.href === pathname ? 'text-secondary' : ''}`}>…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants