Skip to content

[RIPES-4] Fixed UI of admin dashboard#108

Open
Fahleen1 wants to merge 45 commits intomainfrom
RIPES-4
Open

[RIPES-4] Fixed UI of admin dashboard#108
Fahleen1 wants to merge 45 commits intomainfrom
RIPES-4

Conversation

@Fahleen1
Copy link
Copy Markdown
Collaborator

@Fahleen1 Fahleen1 commented Feb 13, 2025

Description

[Provide a more detailed explanation of the changes and the reason for them]

Related Issue

[Link to the related issue or ticket, if applicable]

Type of Change

  • Bug fix
  • New feature
  • Enhancement
  • Breaking change
  • Documentation update

How Has This Been Tested?

[Describe the steps you perform to verify your changes. Provide instructions so we can reproduce. Preferablly a LOOM would be helpful]

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Screenshots (if appropriate):

[Add screenshots here]

Additional Notes:

[Any additional information that might be helpful for reviewers]

Summary by CodeRabbit

  • New Features
    • Launched enhanced admin authentication including login, registration, and secure credentials input.
    • Introduced an interactive brand settings dashboard with live previews and intuitive controls.
    • Rolled out a refined chat experience featuring modern message layouts, responsive sidebars, and real-time notifications.
    • Added a dynamic dashboard summary with interactive charts, data displays, and streamlined document management.
  • UI Improvements
    • Updated visual styling and theme configurations for a cohesive, modern user interface.

@rs-coolify
Copy link
Copy Markdown

rs-coolify Bot commented Feb 13, 2025

The preview deployment is in progress. 🟡

Open Build Logs

Last updated at: 2025-02-13 12:19:32 CET

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 13, 2025

Walkthrough

This pull request implements a comprehensive update across the project. New IDE and project configurations are introduced, and dependency as well as package management settings are revised. Several new API endpoints and middleware functions handle brand settings, files, prompts, questions, bot credentials, and authentication. Moreover, a wide array of React components for admin interfaces, dashboards, chat UIs, and knowledge bases are added along with a full suite of new UI components. New Zustand stores and custom hooks provide state management, while numerous Mongoose schemas and models support data persistence. Import paths have been reorganized to reflect the new directory structure.

Changes

Files Change Summary
.idea/…, .vscode/settings.json, package.json Added new IDE code style schemes, Prettier automation, version control settings, and updated dependencies/package manager.
src/app/api/(admin)/…, middleware.ts New API routes for bot credentials, brand settings (POST/GET), file uploads/deletion, prompts, questions, authentication endpoints, and middleware for route redirection.
src/app/(admin)/… (auth, dashboard, knowledgebase) Introduced numerous new React components for login, registration, layouts, sidebars, carousels, previews, and chat sections for admin and dashboard interfaces.
src/app/(chat)/… Updated and added chat-related components and layouts; reorganized import paths to a dedicated (chat) directory with updated styling.
src/components/ui/… Added a full suite of new UI elements such as Accordion, Card, Carousel, Chart, Checkbox, Form, Tabs, Toast, Table, Slider, and Sidebar components.
src/app/(chat)/_utils/store/…, src/hooks/… Added new Zustand stores and custom hooks (e.g., useIsMobile, useToast) for managing theme, brand, knowledge, and toast state.
src/models/… Added new Mongoose schemas/models for Bot, BrandSettings, File, Prompt, AskAnything, AskMainefest, and User, plus exported the DB connection function.
src/utils/axios.ts, tailwind.config.ts Introduced an Axios instance with a base URL and restructured Tailwind CSS theme with expanded color and styling definitions.
src/components/… (Sidebar, Header, ChatButtonsHeader, etc.) Updated import paths to reflect reorganized directories; minor styling adjustments applied.

Sequence Diagram(s)

sequenceDiagram
  participant C as Client
  participant API as BrandSettings API
  participant FS as File System
  participant DB as Database
  C->>API: POST /brandsettings (formData with logo and settings)
  API->>FS: Validate and save logo file
  API->>DB: Check for existing brand settings
  alt Exists
      DB-->>API: Existing settings found
      API->>DB: Update settings with new data
  else Not Exists
      API->>DB: Create new brand settings entry
  end
  API-->>C: Return success response
Loading
sequenceDiagram
  participant C as Client
  participant API as Registration API
  participant DB as Database
  participant JWT as JWT Service
  C->>API: POST /auth/register (user details)
  API->>DB: Query user by email
  alt User exists
      DB-->>API: User found
      API-->>C: Return error (user exists)
  else New user
      API->>DB: Hash password & create user record
      DB-->>API: New user data
      API->>JWT: Generate JWT token with user ID
      JWT-->>API: Return token
      API-->>C: Return user data (without password) and token
  end
Loading

Poem

Oh, hopping through the code I roam,
New components make our project home.
API routes, models, and UI so bright,
Import paths streamlined in the night.
I nibble on bugs and debug with glee,
A rabbit’s code dance, wild and free!
🐰💻 Hop to it, the updates are key!

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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. (Beta)
  • @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.

@Fahleen1 Fahleen1 changed the title Ripes 4 [RIPES-4] Fixed UI of admin dashboard Feb 13, 2025
Copy link
Copy Markdown

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (81)
src/app/(chat)/layout.tsx (1)

21-26: ⚠️ Potential issue

Consider accessibility implications of fixed viewport scale.

Setting maximumScale: 1 prevents users from zooming the page, which can create accessibility issues for users with visual impairments.

Apply this diff to improve accessibility:

 export const viewport: Viewport = {
   themeColor: 'black',
   initialScale: 1,
-  maximumScale: 1,
+  maximumScale: 5,
   width: 'device-width',
 }
📝 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.

export const viewport: Viewport = {
  themeColor: 'black',
  initialScale: 1,
  maximumScale: 5,
  width: 'device-width',
}
src/app/(chat)/_components/GeneralSidebar.tsx (1)

79-79: ⚠️ Potential issue

Fix incomplete class name.

The class name -300 appears to be incomplete or incorrect. This could be a Tailwind class that was partially deleted (e.g., bg-gray-300).

Please verify and fix the class name. If it's meant to be a background color class, you might want to apply this diff:

-    <div className='-300 h-screen bg-[#EBEBEB] text-white'>
+    <div className='h-screen bg-[#EBEBEB] text-white'>
📝 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.

    <div className='h-screen bg-[#EBEBEB] text-white'>
src/lib/auth.ts (1)

1-3: 💡 Verification agent

🧩 Analysis chain

Verify the use of bcryptjs and NextAuth versions.
Make sure the pinned versions are secure and stable, as outdated credentials or hashing libraries can introduce vulnerabilities.


🏁 Script executed:

#!/bin/bash
# Checking installed versions of bcryptjs and next-auth
grep '"bcryptjs":' package.json
grep '"next-auth":' package.json

Length of output: 128


Action Required: Revisit NextAuth Beta Usage

After verifying the package versions, we have:

  • bcryptjs: "^2.4.3" – This appears to be current.
  • next-auth: "5.0.0-beta.25" – This beta release may not offer the same stability and security guarantees as a stable release.

Please confirm that using a beta version of NextAuth is intentional. If production security and stability are priorities, consider switching to a stable version.

src/app/api/(admin)/knowledgebase/file/route.ts (1)

115-127: 🛠️ Refactor suggestion

Implement pagination for large knowledge base retrievals.
If there are numerous uploaded files, returning all documents at once could degrade performance. Consider a paginated response.

src/components/ui/chart.tsx (1)

85-86: ⚠️ Potential issue

Avoid using dangerouslySetInnerHTML without sanitizing user-controlled data.
If config can include untrusted input, it might introduce an XSS risk. Consider generating CSS strings via a safer method or ensure config is always controlled and sanitized.

-<style
-  dangerouslySetInnerHTML={{ __html: Object.entries(THEMES)...
-}}
+/*******************************
+ * Potential safer approach
+ *******************************/
+{Object.entries(THEMES).map(([theme, prefix]) => (
+  <style key={theme} data-theme={theme}>
+    { /* Generate required rules here in a safe manner */ }
+  </style>
+))}
📝 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.

/*******************************
 * Potential safer approach
 *******************************/
{Object.entries(THEMES).map(([theme, prefix]) => (
  <style key={theme} data-theme={theme}>
    { /* Generate required rules here in a safe manner */ }
  </style>
))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 86-86: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

src/app/(admin)/_components/AuthSession.tsx (1)

12-20: 🛠️ Refactor suggestion

⚠️ Potential issue

Consider security implications and add cleanup handling.

  1. Storing sensitive data like user ID in localStorage poses security risks. Consider using more secure alternatives like HTTP-only cookies.
  2. Add cleanup logic to remove stored data when the component unmounts.
 export const AuthSession = ({ session }: { session: TSession }) => {
   useEffect(() => {
     if (session?.user) {
-      localStorage.setItem('user', JSON.stringify(session.user.id))
+      // TODO: Use a more secure storage mechanism
+      // For now, at least add cleanup on unmount
     }
+    return () => {
+      localStorage.removeItem('user')
+    }
   }, [session])

   return 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.

export const AuthSession = ({ session }: { session: TSession }) => {
  useEffect(() => {
    if (session?.user) {
      // TODO: Use a more secure storage mechanism
      // For now, at least add cleanup on unmount
    }
    return () => {
      localStorage.removeItem('user')
    }
  }, [session])

  return null
}
src/models/botCredentials/Bot.model.ts (1)

3-18: ⚠️ Potential issue

Consider encrypting sensitive data.

The schema stores the OpenAI API key as plain text. Consider encrypting sensitive credentials before storing them in the database.

Here's a recommended approach:

  1. Add encryption/decryption middleware to the schema
  2. Use environment variables for the encryption key
  3. Encrypt the API key before saving and decrypt when retrieving

Would you like me to provide an example implementation of the encryption middleware?

src/models/knowledgeBase/File.model.ts (1)

5-8: ⚠️ Potential issue

Fix typo in the required field.

There's a typo in the required field which will prevent proper validation.

    fileName: {
      type: String,
-      reqired: true,
+      required: true,
    },
📝 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.

    fileName: {
      type: String,
      required: true,
    },
src/models/user/user.model.ts (2)

17-20: ⚠️ Potential issue

Add password hashing middleware for security.

The password field should be hashed before storage to ensure security.

Add this pre-save middleware to hash the password:

import bcrypt from 'bcrypt';

UserSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  
  try {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
    next();
  } catch (error) {
    next(error as Error);
  }
});

3-23: 🛠️ Refactor suggestion

Add email validation and uniqueness constraint.

The schema structure looks good, but the email field should be unique and validated to ensure data integrity.

 email: {
   type: String,
   required: true,
+  unique: true,
+  validate: {
+    validator: function(v: string) {
+      return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
+    },
+    message: (props: { value: string }) => `${props.value} is not a valid email!`
+  }
 },
📝 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.

const UserSchema = new mongoose.Schema(
  {
    firstName: {
      type: String,
      required: true,
    },
    lastName: {
      type: String,
      required: true,
    },
    email: {
      type: String,
      required: true,
      unique: true,
      validate: {
        validator: function(v: string) {
          return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
        },
        message: (props: { value: string }) => `${props.value} is not a valid email!`
      }
    },
    password: {
      type: String,
      required: true,
    },
  },
  { timestamps: true },
)
src/app/api/(admin)/knowledgebase/file/[id]/route.ts (1)

4-23: 🛠️ Refactor suggestion

Enhance error handling and response data.

The route needs better error handling and more informative responses.

 export const DELETE = async (
   request: NextRequest,
   { params }: { params: { id: string } }
 ) => {
   try {
     const { id } = params;
     
-    const file = await FileModel.findByIdAndDelete(id)
+    const file = await FileModel.findById(id);
+    
+    if (!file) {
+      return NextResponse.json(
+        { error: "File not found" },
+        { status: 404 }
+      );
+    }
+    
+    await file.deleteOne();
 
     return NextResponse.json(
-      { message: "File Deleted" },
+      { 
+        message: "File deleted successfully",
+        deletedFile: {
+          id: file._id,
+          name: file.name
+        }
+      },
       { status: 200 }
     );
   } catch (error) {
+    console.error('Error deleting file:', error);
     return NextResponse.json(
-      { error: "Internal Server Error" },
+      { 
+        error: "Internal Server Error",
+        message: error instanceof Error ? error.message : "Unknown error occurred"
+      },
       { status: 500 }
     );
   }
 };
📝 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.

export const DELETE = async (
  request: NextRequest,
  { params }: { params: { id: string } }
) => {
  try {
    const { id } = params;
    
    const file = await FileModel.findById(id);
    
    if (!file) {
      return NextResponse.json(
        { error: "File not found" },
        { status: 404 }
      );
    }
    
    await file.deleteOne();

    return NextResponse.json(
      { 
        message: "File deleted successfully",
        deletedFile: {
          id: file._id,
          name: file.name
        }
      },
      { status: 200 }
    );
  } catch (error) {
    console.error('Error deleting file:', error);
    return NextResponse.json(
      { 
        error: "Internal Server Error",
        message: error instanceof Error ? error.message : "Unknown error occurred"
      },
      { status: 500 }
    );
  }
};
src/hooks/use-mobile.tsx (1)

8-16: 🛠️ Refactor suggestion

Handle server-side rendering.

The hook uses browser-only APIs (window.matchMedia and window.innerWidth) which are not available during server-side rendering. This could cause hydration errors.

Apply this diff to handle server-side rendering:

 export function useIsMobile() {
   const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
 
   React.useEffect(() => {
+    if (typeof window === 'undefined') return
+
     const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
     const onChange = () => {
       setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
     }
     mql.addEventListener("change", onChange)
     setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
     return () => mql.removeEventListener("change", onChange)
   }, [])
 
   return !!isMobile
 }
📝 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.

export function useIsMobile() {
  const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)

  React.useEffect(() => {
    if (typeof window === 'undefined') return

    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
    const onChange = () => {
      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    }
    mql.addEventListener("change", onChange)
    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    return () => mql.removeEventListener("change", onChange)
  }, [])

  return !!isMobile
}
src/components/ui/toaster.tsx (1)

3-3: 🛠️ Refactor suggestion

Fix import path and improve props spreading.

  1. The import path for useToast is incorrect (should be @/hooks/use-toast).
  2. Spreading unknown props directly to the DOM could lead to security issues.

Apply these diffs:

-import { useToast } from "@/components/hooks/use-toast"
+import { useToast } from "@/hooks/use-toast"
-          <Toast key={id} {...props}>
+          <Toast key={id} {...(props as React.ComponentProps<typeof Toast>)}>

Also applies to: 20-20

src/app/api/(admin)/bot/route.ts (2)

8-9: ⚠️ Potential issue

Add input validation for required fields.

The request body is parsed without validating the required fields. This could lead to runtime errors if any of the fields are missing.

Add validation before destructuring:

    const reqBody = await request.json()
+   if (!reqBody.user || !reqBody.botName || !reqBody.openAIKey) {
+     return NextResponse.json(
+       { error: 'Missing required fields' },
+       { status: 400 }
+     )
+   }
    const { user, botName, openAIKey } = reqBody
📝 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.

    const reqBody = await request.json()
    if (!reqBody.user || !reqBody.botName || !reqBody.openAIKey) {
      return NextResponse.json(
        { error: 'Missing required fields' },
        { status: 400 }
      )
    }
    const { user, botName, openAIKey } = reqBody

36-39: 🛠️ Refactor suggestion

Improve error handling with specific error messages.

The current error handling returns a generic "Internal Server Error" message, which makes debugging difficult.

Add specific error handling:

  } catch (error) {
+   console.error('Bot credentials operation failed:', error)
    return NextResponse.json(
-     { error: 'Internal Server Error' },
+     { error: error instanceof Error ? error.message : 'Internal Server Error' },
      { status: 500 },
    )
📝 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.

} catch (error) {
  console.error('Bot credentials operation failed:', error)
  return NextResponse.json(
    { error: error instanceof Error ? error.message : 'Internal Server Error' },
    { status: 500 },
  )
}
src/apis/admin/brandSettings.ts (1)

51-51: ⚠️ Potential issue

Fix incorrect error message.

The error message mentions "Error in adding the Prompt" but this function handles brand settings.

-   throw new Error('Error in adding the Prompt')
+   throw new Error('Failed to add brand settings')
📝 Committable suggestion

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

    throw new Error('Failed to add brand settings')
src/app/(admin)/layout.tsx (1)

20-31: ⚠️ Potential issue

Add missing dependency to useEffect.

The setUser function is used within useEffect but not included in the dependency array.

-  }, [])
+  }, [setUser])
📝 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.

  useEffect(() => {
    const storedUser = localStorage.getItem('user')

    if (storedUser) {
      try {
        const parsedUser = JSON.parse(storedUser)
        setUser(parsedUser)
      } catch (error) {
        console.error('Failed to parse user data from localStorage', error)
      }
    }
  }, [setUser])
src/app/(chat)/_utils/store/knowledge-store.ts (2)

33-37: ⚠️ Potential issue

Fix type mismatch in initial state.

The questions array is included in the initial state but not defined in the State interface.

interface State {
  prompt: string
  preset: number
  modelConfiguration: {
    temperature: number
    topP: number
    frequency: number
    pressure: number
  }
+ questions: singleQuestion[]
  setPrompt: (newPrompt: string) => void
  setPreset: (newPreset: number) => void
  setModelConfiguration: (newModel: Partial<State['modelConfiguration']>) => void
}
📝 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.

interface State {
  prompt: string
  preset: number
  modelConfiguration: {
    temperature: number
    topP: number
    frequency: number
    pressure: number
  }
  questions: singleQuestion[]
  setPrompt: (newPrompt: string) => void
  setPreset: (newPreset: number) => void
  setModelConfiguration: (newModel: Partial<State['modelConfiguration']>) => void
}

27-32: 💡 Verification agent

🧩 Analysis chain

Review model configuration default values.

The default values for model configuration parameters seem unusually high. Temperature is typically between 0 and 1, and topP is usually between 0 and 1.


🌐 Web query:

What are the typical ranges for temperature and top_p parameters in language models?

💡 Result:

Temperature and Top-P are key parameters for controlling output randomness in language models. Here's a breakdown of their typical ranges:

Temperature

  • Range: Typically spans 0-2 in modern LLMs[4][7][9]
  • Common settings:
    • <1 (e.g., 0-0.5): Produces focused, predictable outputs (ideal for technical tasks)[3][4]
    • 1: Default setting maintaining original probability distribution[4]
    • >1 (up to 2): Increases randomness for creative writing/exploratory tasks[9]
Value Range Use Case Examples
0-0.3 Code generation[3], factual Q&A[2]
0.4-0.7 Balanced chatbot responses[3]
0.8-2 Poetry generation[2], brainstorming[9]

Top-P (Nucleus Sampling)

  • Range: Always 0-1[1][5]
  • Common thresholds:
    • <0.5: Highly deterministic outputs (e.g., medical reports)[2]
    • 0.7-0.9: Balanced creativity/reliability[1][5]
    • 1: Full vocabulary consideration (rarely used)[5]

Practical combinations often pair:

  • Low temp (0.2) + low Top-P (0.1) for code generation[3]
  • High temp (1) + high Top-P (0.9) for creative writing[2]

Most implementations default to Temperature=1 and Top-P=1 when not specified[9], but optimal settings vary significantly by use case—experimentation is recommended[2][3].

Citations:


Action: Adjust Default Values in Model Configuration

  • In src/app/(chat)/_utils/store/knowledge-store.ts (lines 27-32), the current defaults (temperature: 10 and topP: 2) are well outside conventional ranges.
  • Modern language models typically use a temperature within roughly 0–2 (with many defaults around 1) and a topP strictly between 0 and 1.
  • Please review and update these configuration values to ensure stable and expected behavior.
src/app/api/auth/register/route.ts (5)

11-13: ⚠️ Potential issue

Add input validation for user registration data.

The request body is processed without validating the required fields or their formats. This could lead to security vulnerabilities and data integrity issues.

Consider using a validation library like Zod or Joi:

import { z } from 'zod'

const userSchema = z.object({
  firstName: z.string().min(1),
  lastName: z.string().min(1),
  email: z.string().email(),
  password: z.string().min(8)
})

const { firstName, lastName, email, password } = userSchema.parse(reqBody)

17-22: ⚠️ Potential issue

Use appropriate HTTP status code for existing user.

Using 500 (Internal Server Error) for an existing user is incorrect. This should be a 409 (Conflict) status code.

- { status: 500 }
+ { status: 409 }
📝 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.

    if (user) {
      return NextResponse.json(
        { error: 'User with this email already Exists' },
        { status: 409 },
      )
    }

39-40: ⚠️ Potential issue

Improve JWT secret handling.

Using double non-null assertion (!!) is unsafe. The application should fail fast if the JWT secret is not configured.

- let secret: string = process.env.JWT_SEC!!
+ const secret = process.env.JWT_SEC
+ if (!secret) {
+   throw new Error('JWT_SEC environment variable is not configured')
+ }
📝 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.

    const secret = process.env.JWT_SEC
    if (!secret) {
      throw new Error('JWT_SEC environment variable is not configured')
    }
    const token = jwt.sign(data, secret)
🧰 Tools
🪛 Biome (1.9.4)

[error] 39-39: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


44-47: ⚠️ Potential issue

Improve error handling.

Generic error messages can leak internal implementation details. Consider logging the error and returning a user-friendly message.

- return NextResponse.json(
-   { error: 'Internal Server Error' },
-   { status: 500 }
- )
+ console.error('Registration error:', error)
+ return NextResponse.json(
+   { error: 'Failed to create account. Please try again later.' },
+   { status: 500 }
+ )
📝 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.

    console.error('Registration error:', error)
    return NextResponse.json(
      { error: 'Failed to create account. Please try again later.' },
      { status: 500 }
    )

13-13: ⚠️ Potential issue

Remove console.log of sensitive data.

Logging the request body could expose sensitive information like passwords in the logs.

Remove this line or replace it with sanitized logging:

- console.log(reqBody)
+ console.log('Processing registration for:', email)
📝 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.

    console.log('Processing registration for:', email)
src/app/(admin)/dashboard/brandsettings/page.tsx (1)

15-20: ⚠️ Potential issue

Add meaningful alt text for the image.

Empty alt text reduces accessibility. Provide a descriptive alt text for screen readers.

- alt=''
+ alt='Publish changes globally icon'
📝 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.

          <Image
            src={`/assets/brandSettings/global.svg`}
            width={20}
            height={20}
            alt='Publish changes globally icon'
          />
src/app/api/(admin)/knowledgebase/questions/ask-anything/route.ts (4)

20-25: ⚠️ Potential issue

Add file type validation.

The code doesn't validate file types, which could lead to security vulnerabilities.

const allowedTypes = ['image/png', 'image/jpeg', 'image/svg+xml'];
if (!icon || !(icon instanceof File) || !allowedTypes.includes(icon.type)) {
  return NextResponse.json(
    { error: 'Invalid file type. Only PNG, JPEG, and SVG files are allowed.' },
    { status: 400 }
  );
}

36-38: ⚠️ Potential issue

Sanitize file paths and use safe file names.

Using raw file names without sanitization could lead to path traversal attacks.

import { sanitizeFileName } from '@/utils/security'

const safeName = sanitizeFileName(icon.name)
const filePath = path.join(uploadDir, safeName)

11-15: ⚠️ Potential issue

Add file size limits.

Missing file size limits could lead to denial of service attacks.

const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
if (icon.size > MAX_FILE_SIZE) {
  return NextResponse.json(
    { error: 'File size exceeds limit of 5MB' },
    { status: 400 }
  );
}

38-38: ⚠️ Potential issue

Fix unsafe buffer type casting.

The current type casting is unsafe and could lead to data corruption.

- await writeFile(filePath, buffer as unknown as string | Uint8Array)
+ await writeFile(filePath, buffer)
📝 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.

      await writeFile(filePath, buffer)
src/app/api/(admin)/knowledgebase/questions/ask-mainefest/route.ts (4)

38-38: ⚠️ Potential issue

Fix Type Casting Issue with Buffer

The current type casting of buffer to string is incorrect and potentially unsafe.

-      await writeFile(filePath, buffer as unknown as string | Uint8Array)
+      await writeFile(filePath, buffer)
📝 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.

      await writeFile(filePath, buffer)

11-14: ⚠️ Potential issue

Add Input Validation for User and Title

The code lacks validation for user and title fields from the form data.

     const form = await request.formData()
     const user = form.get('user')
     const titles = form.getAll('title')
     const icons = form.getAll('icon')
+    
+    if (!user || typeof user !== 'string') {
+      return NextResponse.json(
+        { error: 'Invalid user data' },
+        { status: 400 },
+      )
+    }
+    
+    if (!titles.length || !titles.every(title => typeof title === 'string')) {
+      return NextResponse.json(
+        { error: 'Invalid title data' },
+        { status: 400 },
+      )
+    }
📝 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.

    const form = await request.formData()
    const user = form.get('user')
    const titles = form.getAll('title')
    const icons = form.getAll('icon')
    
    if (!user || typeof user !== 'string') {
      return NextResponse.json(
        { error: 'Invalid user data' },
        { status: 400 },
      )
    }
    
    if (!titles.length || !titles.every(title => typeof title === 'string')) {
      return NextResponse.json(
        { error: 'Invalid title data' },
        { status: 400 },
      )
    }

40-47: ⚠️ Potential issue

Race Condition in Database Operations

Multiple async operations without proper transaction handling could lead to inconsistent state.

-      let newQuestion = await AskMainefest.create({
-        user,
-        title,
-        icon: `public/knowledgebase/questions/ask-mainefest${icon.name}`,
-      })
-      questions.push(newQuestion)
-      await newQuestion.save()
+      const session = await AskMainefest.startSession()
+      try {
+        await session.withTransaction(async () => {
+          const newQuestion = await AskMainefest.create([{
+            user,
+            title,
+            icon: filePath,
+          }], { session })
+          questions.push(newQuestion[0])
+        })
+      } finally {
+        await session.endSession()
+      }
📝 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.

      const session = await AskMainefest.startSession()
      try {
        await session.withTransaction(async () => {
          const newQuestion = await AskMainefest.create([{
            user,
            title,
            icon: filePath,
          }], { session })
          questions.push(newQuestion[0])
        })
      } finally {
        await session.endSession()
      }

30-38: ⚠️ Potential issue

Security Risk: Unsafe File Operations in Public Directory

Writing files directly to the public directory poses several security risks:

  1. Path traversal attacks if filename contains ../
  2. Overwriting existing files
  3. Executing malicious files through public access

Implement these security measures:

  1. Move uploads outside public directory
  2. Validate file types
  3. Sanitize filenames
  4. Add file size limits
-      const uploadDir = path.join(
-        process.cwd(),
-        'public/knowledgebase/questions/ask-mainefest',
-      )
+      const uploadDir = path.join(process.cwd(), 'uploads/questions')
+      const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
+      if (!allowedTypes.includes(icon.type)) {
+        return NextResponse.json(
+          { error: 'Invalid file type' },
+          { status: 400 },
+        )
+      }
+      if (icon.size > 5 * 1024 * 1024) { // 5MB limit
+        return NextResponse.json(
+          { error: 'File too large' },
+          { status: 400 },
+        )
+      }
+      const sanitizedName = icon.name.replace(/[^a-zA-Z0-9.-]/g, '_')
+      const uniqueName = `${Date.now()}-${sanitizedName}`
+      const filePath = path.join(uploadDir, uniqueName)
📝 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.

      const uploadDir = path.join(process.cwd(), 'uploads/questions')
      const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
      if (!allowedTypes.includes(icon.type)) {
        return NextResponse.json(
          { error: 'Invalid file type' },
          { status: 400 },
        )
      }
      if (icon.size > 5 * 1024 * 1024) { // 5MB limit
        return NextResponse.json(
          { error: 'File too large' },
          { status: 400 },
        )
      }
      const sanitizedName = icon.name.replace(/[^a-zA-Z0-9.-]/g, '_')
      const uniqueName = `${Date.now()}-${sanitizedName}`
      const filePath = path.join(uploadDir, uniqueName)
      await mkdir(uploadDir, { recursive: true })
      await writeFile(filePath, buffer as unknown as string | Uint8Array)
src/app/api/(admin)/knowledgebase/prompt/route.ts (3)

55-61: ⚠️ Potential issue

Secure Error Handling

Avoid exposing internal error details in production.

-    console.error('Error in Prompt creation/update:', error.message)
-
-    return NextResponse.json(
-      { error: 'Internal Server Error', details: error.message },
-      { status: 500 },
-    )
+    console.error('Error in Prompt creation/update:', error)
+
+    return NextResponse.json(
+      { error: 'Internal Server Error' },
+      { status: 500 },
+    )
📝 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.

  } catch (error: any) {
-    console.error('Error in Prompt creation/update:', error.message)
-
-    return NextResponse.json(
-      { error: 'Internal Server Error', details: error.message },
-      { status: 500 },
-    )
+    console.error('Error in Prompt creation/update:', error)
+
+    return NextResponse.json(
+      { error: 'Internal Server Error' },
+      { status: 500 },
+    )

8-11: ⚠️ Potential issue

Add Request Body Validation

The code lacks validation for the request body structure and types.

+    const validateModelConfig = (config: any) => {
+      return typeof config === 'object' &&
+        typeof config.temperature === 'number' &&
+        typeof config.topP === 'number' &&
+        typeof config.frequency === 'number' &&
+        typeof config.pressure === 'number'
+    }
+
     const reqBody = await request.json()
+    const { prompt, preset, modelConfiguration, user } = reqBody
+    
+    if (!prompt || typeof prompt !== 'string' ||
+        !preset || typeof preset !== 'string' ||
+        !user || typeof user !== 'string' ||
+        !validateModelConfig(modelConfiguration)) {
+      return NextResponse.json(
+        { error: 'Invalid request body' },
+        { status: 400 },
+      )
+    }
+
     await connectDB()
-    const { prompt, preset, modelConfiguration, user } = reqBody
📝 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.

    const validateModelConfig = (config: any) => {
      return typeof config === 'object' &&
        typeof config.temperature === 'number' &&
        typeof config.topP === 'number' &&
        typeof config.frequency === 'number' &&
        typeof config.pressure === 'number'
    }
    
    const reqBody = await request.json()
    const { prompt, preset, modelConfiguration, user } = reqBody
    
    if (!prompt || typeof prompt !== 'string' ||
        !preset || typeof preset !== 'string' ||
        !user || typeof user !== 'string' ||
        !validateModelConfig(modelConfiguration)) {
      return NextResponse.json(
        { error: 'Invalid request body' },
        { status: 400 },
      )
    }
    
    await connectDB()

13-37: 🛠️ Refactor suggestion

Optimize Database Operations

The current implementation performs an unnecessary find operation before update.

-    const existingPrompt = await Prompt.findOne({ user })
-
-    if (existingPrompt) {
-      const updatedPrompt = await Prompt.findOneAndUpdate(
-        { user },
-        {
-          $set: {
-            prompt,
-            preset,
-            modelConfiguration: {
-              temperature: modelConfiguration.temperature,
-              topP: modelConfiguration.topP,
-              frequency: modelConfiguration.frequency,
-              pressure: modelConfiguration.pressure,
-            },
-          },
-        },
-        { new: true },
-      )
+    const updatedPrompt = await Prompt.findOneAndUpdate(
+      { user },
+      {
+        $set: {
+          prompt,
+          preset,
+          modelConfiguration: {
+            temperature: modelConfiguration.temperature,
+            topP: modelConfiguration.topP,
+            frequency: modelConfiguration.frequency,
+            pressure: modelConfiguration.pressure,
+          },
+        },
+      },
+      { new: true, upsert: true },
+    )

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

src/app/(admin)/dashboard/brandsettings/_components/MainPreview/_components/SideBar.tsx (1)

11-11: 🛠️ Refactor suggestion

Improve Image Handling and Accessibility

  1. Image paths are hardcoded
  2. Alt text is empty
  3. Small image dimensions might affect quality
+const IMAGES = {
+  logo: { src: '/logo/logo.svg', alt: 'Company Logo' },
+  chat: { src: '/assets/preview/Chat Add.svg', alt: 'New Chat Icon' },
+  work: { src: '/assets/preview/Our Work.svg', alt: 'Our Work Icon' },
+  team: { src: '/assets/preview/Our Team.svg', alt: 'Our Team Icon' },
+  contact: { src: '/assets/preview/Contact.svg', alt: 'Contact Icon' },
+}

-        <Image src={`/logo/logo.svg`} alt='' width={100} height={100} />
+        <Image {...IMAGES.logo} width={100} height={100} />

-          <Image
-            src={`/assets/preview/Chat Add.svg`}
-            alt=''
-            width={15}
-            height={15}
-          />
+          <Image {...IMAGES.chat} width={20} height={20} />

Also applies to: 18-22, 30-35, 40-45, 49-54

src/app/(chat)/_utils/store/brand-store.ts (1)

42-79: 🛠️ Refactor suggestion

Add persistence for brand settings.

The store should persist settings to prevent loss on page refresh.

Use Zustand's persist middleware:

+import { persist } from 'zustand/middleware'
 
-export const useBrandStore = create<State>((set) => ({
+export const useBrandStore = create(
+  persist<State>(
+    (set) => ({
       // ... existing store code
-    }))
+    }),
+    {
+      name: 'brand-settings',
+      partialize: (state) => ({
+        theme: state.theme,
+        fontSetting: state.fontSetting,
+        externalLinks: state.externalLinks,
+      }),
+    }
+  )
+)
📝 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.

import { persist } from 'zustand/middleware'
import create from 'zustand'

export const useBrandStore = create(
  persist<State>(
    (set) => ({
      logoFile: null,
      theme: {
        description: 'AI Chat Assistance',
        colorAdjustments: {
          historyPannelBackground: '#171717',
          chatBackground: '#303030',
          chatUserBubble: '#212121',
          chatBotBubble: '#303030',
        },
      },
      fontSetting: {
        primaryFont: {
          fontSize: 14,
          fontFamily: 'system-ui',
          fontWeight: 400,
        },
        secondaryFont: {
          fontSize: 12,
          fontFamily: 'system-ui',
          fontWeight: 400,
        },
        chatFont: {
          fontSize: 16,
          fontFamily: 'system-ui',
          fontWeight: 400,
        },
      },
      externalLinks: [],

      setTheme: (newTheme) =>
        set((state) => ({ theme: { ...state.theme, ...newTheme } })),

      setFontSetting: (newFont) =>
        set((state) => ({ fontSetting: { ...state.fontSetting, ...newFont } })),
      setExternalLinks: (newLinks) => set(() => ({ externalLinks: newLinks })),
      setLogoFile: (newFile) => set(() => ({ logoFile: newFile })),
    }),
    {
      name: 'brand-settings',
      partialize: (state) => ({
        theme: state.theme,
        fontSetting: state.fontSetting,
        externalLinks: state.externalLinks,
      }),
    }
  )
)
src/app/(admin)/dashboard/knowledgebase/_components/KnowledegeBaseTabs/_components/KnowledegBaseQuestions.tsx (3)

14-14: ⚠️ Potential issue

Fix typo in component name.

The component name has a typo: "Knowledeg" should be "Knowledge".

-export default function KnowledegBaseQuestions() {
+export default function KnowledgeBaseQuestions() {
📝 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.

export default function KnowledgeBaseQuestions() {

49-54: 🛠️ Refactor suggestion

Remove duplicate QuestionAccordion components.

Both TabsContent sections render the same component with the same prop.

-<TabsContent value='askmainefest'>
-  <QuestionAccordion askAnything={askAnything} />
-</TabsContent>
-<TabsContent value='askanything'>
-  <QuestionAccordion askAnything={askAnything} />
-</TabsContent>
+<TabsContent value='askmainefest'>
+  <QuestionAccordion mode='mainefest' />
+</TabsContent>
+<TabsContent value='askanything'>
+  <QuestionAccordion mode='anything' />
+</TabsContent>
📝 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.

          <TabsContent value='askmainefest'>
            <QuestionAccordion mode='mainefest' />
          </TabsContent>
          <TabsContent value='askanything'>
            <QuestionAccordion mode='anything' />
          </TabsContent>

15-45: 🛠️ Refactor suggestion

Improve state management and button accessibility.

The current implementation has redundant state management and accessibility issues.

  1. Use the value prop from Tabs instead of a separate state:
-const [askAnything, setAskAnything] = useState<boolean>(true)
+const [activeTab, setActiveTab] = useState<'askmainefest' | 'askanything'>('askanything')

 return (
   <div className='h-full w-full px-5'>
-    <Tabs defaultValue='askanything' className='h-full w-full px-3'>
+    <Tabs
+      value={activeTab}
+      onValueChange={setActiveTab}
+      className='h-full w-full px-3'
+    >
  1. Remove redundant buttons and improve accessibility:
-<Button
-  onClick={() => {
-    setAskAnything(!askAnything)
-  }}
-  className='w-full rounded-lg border-none bg-transparent px-0 text-black shadow-none'
->
-  <TabsTrigger value='askmainefest'>Ask Mainefest AI</TabsTrigger>
-</Button>
+<TabsTrigger
+  value='askmainefest'
+  aria-label='Switch to Ask Mainefest AI tab'
+>
+  Ask Mainefest AI
+</TabsTrigger>

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

src/models/brandSettings/BrandSettings.model.ts (3)

47-50: 🛠️ Refactor suggestion

Add validation for font weights.

Font weights should be validated to ensure they are standard values (100, 200, ..., 900).

         fontWeight: {
           type: Number,
           required: true,
+          enum: [100, 200, 300, 400, 500, 600, 700, 800, 900],
+          default: 400
         },

Also applies to: 61-64, 75-78


19-22: 🛠️ Refactor suggestion

Fix typo in "historyPannelBackground".

The field name contains a typo: "Pannel" should be "Panel".

-        historyPannelBackground: {
+        historyPanelBackground: {
           type: String,
           required: true,
         },
📝 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.

        historyPanelBackground: {
          type: String,
          required: true,
        },

19-34: 🛠️ Refactor suggestion

Add validation for color values.

The color fields should validate that the values are valid CSS color strings (hex, rgb, rgba, hsl, etc.).

         historyPanelBackground: {
           type: String,
           required: true,
+          validate: {
+            validator: function(v) {
+              return /^(#[0-9A-Fa-f]{6}|rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)|rgba\(\d{1,3},\s*\d{1,3},\s*\d{1,3},\s*[0-1](\.\d+)?\))$/.test(v);
+            },
+            message: props => `${props.value} is not a valid color value!`
+          }
         },

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

src/app/(admin)/dashboard/knowledgebase/_components/KnowledegeBaseTabs/KnowledegeBaseTabs.tsx (2)

16-22: 🛠️ Refactor suggestion

Improve image accessibility and maintainability.

The images lack meaningful alt text and use hardcoded paths.

+const ICON_PATHS = {
+  documents: '/assets/knowledgebase/document-text.svg',
+  prompts: '/assets/knowledgebase/message-programming.svg',
+  questions: '/assets/knowledgebase/message-question.svg',
+} as const;

 <Image
-  src={`/assets/knowledgebase/document-text.svg`}
-  alt=''
+  src={ICON_PATHS.documents}
+  alt='Documents icon'
   width={20}
   height={20}
 />

Also applies to: 25-31, 34-40


6-8: 🛠️ Refactor suggestion

Fix inconsistent spelling of "Knowledge".

The component and import names have inconsistent spelling of "Knowledge" ("Knowledege" vs "Knowledge").

-import KnowledegBasePrompts from './_components/KnowledegBasePrompts'
-import KnowledegBaseQuestions from './_components/KnowledegBaseQuestions'
-import KnowledegeBaseDocuments from './_components/KnowledegeBaseDocuments'
+import KnowledgeBasePrompts from './_components/KnowledgeBasePrompts'
+import KnowledgeBaseQuestions from './_components/KnowledgeBaseQuestions'
+import KnowledgeBaseDocuments from './_components/KnowledgeBaseDocuments'
📝 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.

import KnowledgeBasePrompts from './_components/KnowledgeBasePrompts'
import KnowledgeBaseQuestions from './_components/KnowledgeBaseQuestions'
import KnowledgeBaseDocuments from './_components/KnowledgeBaseDocuments'
src/app/(admin)/dashboard/summary/_components/Chart.tsx (1)

29-78: 🛠️ Refactor suggestion

Add type safety and improve accessibility.

The component lacks TypeScript types and accessibility features.

-const Chart = () => {
+interface DataPoint {
+  month: string;
+  '2021': number;
+  '2020': number;
+  '2019': number;
+}

+const Chart: React.FC = () => {
   return (
     <ResponsiveContainer width='100%' height={300}>
-      <AreaChart
+      <AreaChart
+        aria-label="Monthly data comparison for years 2019-2021"
         data={data}
         margin={{ top: 20, right: 30, left: 0, bottom: 0 }}
       >
📝 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.

interface DataPoint {
  month: string;
  '2021': number;
  '2020': number;
  '2019': number;
}

const Chart: React.FC = () => {
  return (
    <ResponsiveContainer width='100%' height={300}>
      <AreaChart
        aria-label="Monthly data comparison for years 2019-2021"
        data={data}
        margin={{ top: 20, right: 30, left: 0, bottom: 0 }}
      >
        <defs>
          <linearGradient id='color2021' x1='0' y1='0' x2='0' y2='1'>
            <stop offset='5%' stopColor='#FBCD8E' stopOpacity={0.8} />
            <stop offset='95%' stopColor='#F9F1E6' stopOpacity={0} />
          </linearGradient>
          <linearGradient id='color2020' x1='0' y1='0' x2='0' y2='1'>
            <stop offset='5%' stopColor='#F9F4EC' stopOpacity={0.8} />
            <stop offset='95%' stopColor='#F9F5EF' stopOpacity={0} />
          </linearGradient>
          <linearGradient id='color2019' x1='0' y1='0' x2='0' y2='1'>
            <stop offset='5%' stopColor='#F9F5EF' stopOpacity={0.8} />
            <stop offset='95%' stopColor='#F9F7F4' stopOpacity={0} />
          </linearGradient>
        </defs>

        <XAxis dataKey='month' />
        <YAxis />
        <Tooltip />
        <Area
          type='monotone'
          dataKey='2021'
          stroke='#FF7F00'
          fillOpacity={1}
          fill='url(#color2021)'
        />
        <Area
          type='monotone'
          dataKey='2020'
          stroke='#FFA500'
          fillOpacity={1}
          fill='url(#color2020)'
        />
        <Area
          type='monotone'
          dataKey='2019'
          stroke='#FFB347'
          fillOpacity={1}
          fill='url(#color2019)'
        />
      </AreaChart>
    </ResponsiveContainer>
  )
}
src/apis/admin/knowledgeBase.ts (1)

74-91: ⚠️ Potential issue

Inconsistent error handling pattern.

The AddQuestions function returns a NextResponse while other functions throw errors. This inconsistency could lead to confusion.

 export const AddQuestions = async (askAnything: boolean, data: Data) => {
   try {
     const response = await axiosInstance.post(
       `/api/knowledgebase/questions/${askAnything ? 'ask-anything' : 'ask-mainefest'}`,
       data,
       {
         headers: {
           'Content-Type': 'multipart/form-data',
         },
       },
     )
     return response.data
   } catch (error) {
-    return NextResponse.json(
-      { error: 'Internal Server Error' },
-      { status: 500 },
-    )
+    throw new Error('Error adding questions')
   }
 }
📝 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.

export const AddQuestions = async (askAnything: boolean, data: Data) => {
  try {
    const response = await axiosInstance.post(
      `/api/knowledgebase/questions/${askAnything ? 'ask-anything' : 'ask-mainefest'}`,
      data,
      {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      },
    )
    return response.data
  } catch (error) {
    throw new Error('Error adding questions')
  }
}
src/app/(admin)/(auth)/login/page.tsx (2)

31-43: ⚠️ Potential issue

Improve type safety and error handling in form submission.

The form submission uses any type and could benefit from better error handling.

+type FormData = z.infer<typeof formSchema>

-const onSubmit = async (data: any) => {
+const onSubmit = async (data: FormData) => {
   try {
     await signIn('credentials', {
       email: data.email,
       password: data.password,
       redirectTo: '/dashboard/summary',
     })

     form.reset()
   } catch (error) {
-    throw new Error('Error in The Login')
+    throw new Error(error instanceof Error ? error.message : 'Login failed')
   }
 }
📝 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.

+type FormData = z.infer<typeof formSchema>

  const onSubmit = async (data: FormData) => {
    try {
      await signIn('credentials', {
        email: data.email,
        password: data.password,
        redirectTo: '/dashboard/summary',
      })

      form.reset()
    } catch (error) {
      throw new Error(error instanceof Error ? error.message : 'Login failed')
    }
  }

85-90: 🛠️ Refactor suggestion

Add loading state to prevent multiple form submissions.

The submit button should be disabled during form submission to prevent duplicate requests.

+const [isSubmitting, setIsSubmitting] = useState(false)

 const onSubmit = async (data: FormData) => {
+  setIsSubmitting(true)
   try {
     // ... existing code
+  } finally {
+    setIsSubmitting(false)
   }
 }

 <button
   type='submit'
+  disabled={isSubmitting}
-  className='rounded bg-black px-4 py-2 text-white'
+  className='rounded bg-black px-4 py-2 text-white disabled:opacity-50'
 >
-  Submit
+  {isSubmitting ? 'Submitting...' : 'Submit'}
 </button>
📝 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.

import React, { useState } from 'react';

export default function LoginPage() {
  const [isSubmitting, setIsSubmitting] = useState(false);

  const onSubmit = async (data: FormData) => {
    setIsSubmitting(true);
    try {
      // ... existing code to handle form submission
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <form onSubmit={onSubmit}>
      {/* Other form elements */}
      <button
        type='submit'
        disabled={isSubmitting}
        className='rounded bg-black px-4 py-2 text-white disabled:opacity-50'
      >
        {isSubmitting ? 'Submitting...' : 'Submit'}
      </button>
    </form>
  );
}
src/app/(admin)/dashboard/_components/DashboardSideBar/DashboardSideBar.tsx (2)

35-39: 🛠️ Refactor suggestion

Add error handling for signOut operation.

The logout operation should handle potential errors gracefully.

 const handleClick = async () => {
+  try {
     await signOut()
     localStorage.removeItem('user')
     setUser('')
+  } catch (error) {
+    console.error('Logout failed:', error)
+    // Optionally show a user-friendly error message
+  }
 }
📝 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.

  const handleClick = async () => {
    try {
      await signOut()
      localStorage.removeItem('user')
      setUser('')
    } catch (error) {
      console.error('Logout failed:', error)
      // Optionally show a user-friendly error message
    }
  }

58-59: 🛠️ Refactor suggestion

Replace img tag with Next.js Image component for better performance.

Using the HTML img tag instead of Next.js Image component for static assets.

-                  <img src={item.icon} alt='' />
+                  <Image
+                    src={item.icon}
+                    width={24}
+                    height={24}
+                    alt={`${item.title} icon`}
+                  />
📝 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.

                  <Image
                    src={item.icon}
                    width={24}
                    height={24}
                    alt={`${item.title} icon`}
                  />
                  <span>{item.title}</span>
src/app/(admin)/dashboard/brandsettings/_components/MainPreview/_components/ChatSection.tsx (3)

65-67: 🛠️ Refactor suggestion

Use item.id instead of array index as key.

Using array indices as keys can lead to performance issues and bugs with React's reconciliation process when items are reordered or deleted.

-          <SingleMessage key={i} text={item} />
+          <SingleMessage key={item.id} text={item} />
📝 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.

        {messages.map((item, i) => (
          <SingleMessage key={item.id} text={item} />
        ))}

72-78: 🛠️ Refactor suggestion

Add proper type for input element.

The input element is missing proper type definitions and aria-label for accessibility.

           <input
             placeholder='Ask anything...'
             type='text'
-            name=''
-            id=''
+            name='chatInput'
+            id='chatInput'
+            aria-label='Chat message input'
             className='w-[90%] rounded-2xl bg-gray-100 p-1 text-xs outline-none'
           />
📝 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.

          <input
            placeholder='Ask anything...'
            type='text'
            name='chatInput'
            id='chatInput'
            aria-label='Chat message input'
            className='w-[90%] rounded-2xl bg-gray-100 p-1 text-xs outline-none'
          />

55-60: 🛠️ Refactor suggestion

Add alt text for better accessibility.

The Image component is missing meaningful alt text, which is important for screen readers and accessibility.

-          alt=''
+          alt='Settings icon'
📝 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.

        <Image
          src={`/assets/preview/Settings.svg`}
          alt='Settings icon'
          width={15}
          height={15}
        />{' '}
src/app/(admin)/dashboard/knowledgebase/_components/KnowledegeBaseTabs/_components/KnowledegeBaseDocuments.tsx (3)

59-63: ⚠️ Potential issue

Add file size and type validation.

The file selection lacks proper validation for file size and type, which could lead to failed uploads or security issues.

           onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
             if (e.target.files?.[0]) {
+              const file = e.target.files[0];
+              const maxSize = 10 * 1024 * 1024; // 10MB
+              if (file.size > maxSize) {
+                alert('File size must be less than 10MB');
+                return;
+              }
+              if (!file.type.includes('pdf')) {
+                alert('Only PDF files are allowed');
+                return;
+              }
               setFile(e.target.files[0])
             }
           }}
📝 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.

          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            if (e.target.files?.[0]) {
              const file = e.target.files[0];
              const maxSize = 10 * 1024 * 1024; // 10MB
              if (file.size > maxSize) {
                alert('File size must be less than 10MB');
                return;
              }
              if (!file.type.includes('pdf')) {
                alert('Only PDF files are allowed');
                return;
              }
              setFile(e.target.files[0])
            }
          }}

34-43: ⚠️ Potential issue

Add error handling for file upload mutation.

The mutation lacks error handling, which could lead to silent failures. Consider adding error handling and user feedback.

 const { mutate, isPending, data } = useMutation({
   mutationFn: async (form: FormData) => {
     return await fileUpload(form)
   },
+  onError: (error) => {
+    console.error('Upload failed:', error);
+    // Add user notification here
+  },
   onSuccess: (data) => {
     setFile(null)
-    console.log('isPending', isPending)
-    console.log('Success', data)
+    // Add success notification here
   },
 })
📝 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.

  const { mutate, isPending, data } = useMutation({
    mutationFn: async (form: FormData) => {
      return await fileUpload(form)
    },
    onError: (error) => {
      console.error('Upload failed:', error);
      // Add user notification here
    },
    onSuccess: (data) => {
      setFile(null)
      // Add success notification here
    },
  })

29-32: 🛠️ Refactor suggestion

Add error handling for file data query.

The query lacks error handling and loading state management for the file data fetch.

-  const { data: FileData, isLoading: FileLoading } = useQuery({
+  const { data: FileData, isLoading: FileLoading, error } = useQuery({
     queryKey: ['getAllFile'],
     queryFn: GetKnowledegeBaseFiles,
+    onError: (error) => {
+      console.error('Failed to fetch files:', error);
+      // Add user notification here
+    }
   })
📝 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.

  const { data: FileData, isLoading: FileLoading, error } = useQuery({
    queryKey: ['getAllFile'],
    queryFn: GetKnowledegeBaseFiles,
    onError: (error) => {
      console.error('Failed to fetch files:', error);
      // Add user notification here
    }
  })
src/app/(admin)/(auth)/token/page.tsx (3)

21-25: ⚠️ Potential issue

Update schema to validate OpenAI API key format.

The current schema validates username instead of an API key. Update it to match OpenAI API key format.

 const formSchema = z.object({
-  username: z.string().min(2, {
-    message: 'Username must be at least 2 characters.',
+  apiKey: z.string().regex(/^sk-[A-Za-z0-9]{48}$/, {
+    message: 'Invalid OpenAI API key format. It should start with "sk-" followed by 48 characters.',
   }),
 })
📝 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.

const formSchema = z.object({
  apiKey: z.string().regex(/^sk-[A-Za-z0-9]{48}$/, {
    message: 'Invalid OpenAI API key format. It should start with "sk-" followed by 48 characters.',
  }),
})

28-29: ⚠️ Potential issue

Implement the onSubmit handler and add proper type safety.

The onSubmit handler is empty and the form initialization lacks proper type safety.

-  const form = useForm()
-  function onSubmit(values: z.infer<typeof formSchema>) {}
+  const form = useForm<z.infer<typeof formSchema>>({
+    resolver: zodResolver(formSchema),
+    defaultValues: {
+      apiKey: '',
+    },
+  })
+
+  async function onSubmit(values: z.infer<typeof formSchema>) {
+    try {
+      // Add API call to save the key
+      // Add success notification
+      // Redirect to dashboard
+    } catch (error) {
+      // Add error handling
+    }
+  }
📝 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.

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      apiKey: '',
    },
  })

  async function onSubmit(values: z.infer<typeof formSchema>) {
    try {
      // Add API call to save the key
      // Add success notification
      // Redirect to dashboard
    } catch (error) {
      // Add error handling
    }
  }

72-77: ⚠️ Potential issue

Move Skip link outside the submit button.

The Skip link is incorrectly placed inside a submit button, which can lead to unexpected form submissions.

-              <Button
-                type='submit'
-                className='border-1 w-1/2 border-solid border-black bg-transparent text-black'
-              >
-                <Link href={`/dashboard/summary`}>Skip</Link>
-              </Button>
+              <Link href={`/dashboard/summary`} className='w-1/2'>
+                <Button
+                  type='button'
+                  className='w-full border-1 border-solid border-black bg-transparent text-black'
+                >
+                  Skip
+                </Button>
+              </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.

              <Link href={`/dashboard/summary`} className='w-1/2'>
                <Button
                  type='button'
                  className='w-full border-1 border-solid border-black bg-transparent text-black'
                >
                  Skip
                </Button>
              </Link>
src/app/(admin)/dashboard/brandsettings/_components/Preview.tsx (2)

36-43: ⚠️ Potential issue

Add error handling to the mutation.

The mutation lacks error handling which could lead to silent failures. Consider adding an onError callback to handle and display errors to users.

 const { mutate, isPending, isSuccess } = useMutation({
   mutationFn: async (data: FormData) => {
     await AddBrandSettings(data)
   },
   onSuccess(data, variables, context) {
     console.log(data)
   },
+  onError(error) {
+    console.error('Failed to save brand settings:', error)
+    // Add toast notification or error state handling
+  },
 })
📝 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.

  const { mutate, isPending, isSuccess } = useMutation({
    mutationFn: async (data: FormData) => {
      await AddBrandSettings(data)
    },
    onSuccess(data, variables, context) {
      console.log(data)
    },
    onError(error) {
      console.error('Failed to save brand settings:', error)
      // Add toast notification or error state handling
    },
  })

74-82: 🛠️ Refactor suggestion

Improve accessibility of the Undo action button.

The image lacks meaningful alt text and the button's purpose isn't clear to screen readers.

 <Button className='flex cursor-pointer items-center justify-center space-x-2 rounded-lg border-[2px] border-solid border-dashboardBorder bg-transparent text-dashboardSecondaryText shadow-none'>
   <Image
     src={`/assets/brandSettings/refresh.svg`}
-    alt=''
+    alt='Undo icon'
     width={20}
     height={20}
   />
-  <span>Undo action</span>
+  <span aria-label="Undo previous changes">Undo action</span>
 </Button>
📝 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.

        <Button className='flex cursor-pointer items-center justify-center space-x-2 rounded-lg border-[2px] border-solid border-dashboardBorder bg-transparent text-dashboardSecondaryText shadow-none'>
          <Image
            src={`/assets/brandSettings/refresh.svg`}
            alt='Undo icon'
            width={20}
            height={20}
          />
          <span aria-label="Undo previous changes">Undo action</span>
        </Button>
src/app/api/(admin)/brandsettings/route.ts (3)

95-106: 🛠️ Refactor suggestion

Add pagination to GET endpoint.

The GET endpoint fetches all brand settings without pagination, which could cause performance issues with large datasets.

-export const GET = async () => {
+export const GET = async (request: NextRequest) => {
   try {
-    const themeCredentials = await BrandSetting.find()
+    const url = new URL(request.url)
+    const page = parseInt(url.searchParams.get('page') || '1')
+    const limit = parseInt(url.searchParams.get('limit') || '10')
+    
+    const skip = (page - 1) * limit
+    const total = await BrandSetting.countDocuments()
+    const themeCredentials = await BrandSetting.find()
+      .skip(skip)
+      .limit(limit)
+      .lean()

-    return NextResponse.json({ themeCredentials }, { status: 200 })
+    return NextResponse.json({
+      themeCredentials,
+      pagination: {
+        total,
+        page,
+        pages: Math.ceil(total / limit)
+      }
+    }, { status: 200 })
   } catch (error) {
     return NextResponse.json(
       { error: 'Internal Server Error' },
📝 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.

export const GET = async (request: NextRequest) => {
  try {
    const url = new URL(request.url)
    const page = parseInt(url.searchParams.get('page') || '1')
    const limit = parseInt(url.searchParams.get('limit') || '10')
    
    const skip = (page - 1) * limit
    const total = await BrandSetting.countDocuments()
    const themeCredentials = await BrandSetting.find()
      .skip(skip)
      .limit(limit)
      .lean()

    return NextResponse.json({
      themeCredentials,
      pagination: {
        total,
        page,
        pages: Math.ceil(total / limit)
      }
    }, { status: 200 })
  } catch (error) {
    return NextResponse.json(
      { error: 'Internal Server Error' },
      { status: 500 },
    )
  }
}

26-33: ⚠️ Potential issue

Validate file path to prevent directory traversal.

The file path construction needs validation to prevent potential directory traversal attacks.

+import { basename } from 'path'
+
+const sanitizeFileName = (fileName: string) => {
+  return basename(fileName).replace(/[^a-zA-Z0-9.-]/g, '_')
+}

 const uploadDir = path.join(process.cwd(), 'public/brandSettings/logo')
 await mkdir(uploadDir, { recursive: true })

-const uniqueFileName = `${Date.now()}-${logo.name}`
+const uniqueFileName = `${Date.now()}-${sanitizeFileName(logo.name)}`
 const filePath = path.join(uploadDir, uniqueFileName)
📝 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.

import { basename } from 'path'

const sanitizeFileName = (fileName: string) => {
  return basename(fileName).replace(/[^a-zA-Z0-9.-]/g, '_')
}

const uploadDir = path.join(process.cwd(), 'public/brandSettings/logo')
await mkdir(uploadDir, { recursive: true })

const uniqueFileName = `${Date.now()}-${sanitizeFileName(logo.name)}`
const filePath = path.join(uploadDir, uniqueFileName)
const logoUrl = `public/brandSettings/logo/${uniqueFileName}`

await writeFile(filePath, buffer as unknown as string | Uint8Array)

12-14: ⚠️ Potential issue

Add file size and type validation.

The logo file upload lacks size and type validation, which could lead to security issues.

+const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
+const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/png', 'image/gif'];

 const form = await request.formData()
 const logo = form.get('logo')
 const data = JSON.parse(form.get('data') as string)

+if (logo instanceof File) {
+  if (logo.size > MAX_FILE_SIZE) {
+    return NextResponse.json(
+      { error: 'File size exceeds 5MB limit.' },
+      { status: 400 }
+    )
+  }
+  if (!ALLOWED_FILE_TYPES.includes(logo.type)) {
+    return NextResponse.json(
+      { error: 'Invalid file type. Only JPEG, PNG, and GIF are allowed.' },
+      { status: 400 }
+    )
+  }
+}
📝 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.

    const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
    const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/png', 'image/gif'];

    const form = await request.formData()
    const logo = form.get('logo')
    const data = JSON.parse(form.get('data') as string)

    if (logo instanceof File) {
      if (logo.size > MAX_FILE_SIZE) {
        return NextResponse.json(
          { error: 'File size exceeds 5MB limit.' },
          { status: 400 }
        )
      }
      if (!ALLOWED_FILE_TYPES.includes(logo.type)) {
        return NextResponse.json(
          { error: 'Invalid file type. Only JPEG, PNG, and GIF are allowed.' },
          { status: 400 }
        )
      }
    }
src/app/(admin)/dashboard/summary/_components/CircleChart.tsx (1)

80-108: 🛠️ Refactor suggestion

Add aria-label to chart for better accessibility.

The chart's label content should include ARIA attributes for screen readers.

 <Label
   content={({ viewBox }) => {
     if (viewBox && 'cx' in viewBox && 'cy' in viewBox) {
       return (
         <text
           x={viewBox.cx}
           y={viewBox.cy}
           textAnchor='middle'
           dominantBaseline='middle'
+          role="img"
+          aria-label={`Total visitors: ${totalVisitors.toLocaleString()}`}
         >
📝 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.

              <Label
                content={({ viewBox }) => {
                  if (viewBox && 'cx' in viewBox && 'cy' in viewBox) {
                    return (
                      <text
                        x={viewBox.cx}
                        y={viewBox.cy}
                        textAnchor='middle'
                        dominantBaseline='middle'
                        role="img"
                        aria-label={`Total visitors: ${totalVisitors.toLocaleString()}`}
                      >
                        <tspan
                          x={viewBox.cx}
                          y={viewBox.cy}
                          className='fill-foreground text-3xl font-bold'
                        >
                          {totalVisitors.toLocaleString()}
                        </tspan>
                        <tspan
                          x={viewBox.cx}
                          y={(viewBox.cy || 0) + 24}
                          className='fill-muted-foreground'
                        >
                          Visitors
                        </tspan>
                      </text>
                    )
                  }
                }}
              />
src/app/(admin)/dashboard/knowledgebase/page.tsx (3)

71-78: ⚠️ Potential issue

Enhance security for OpenAI key input.

The OpenAI key input should be treated as a password field and masked for security.

 <input
   {...register('openAIKey')}
-  type='text'
+  type='password'
+  autoComplete='off'
   className='h-9 rounded-lg border-2 border-solid border-dashboardBorder p-1 text-sm outline-none'
-  placeholder='Paste link here...'
+  placeholder='Enter your OpenAI API key'
 />
📝 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.

              <Label>OpenAI token</Label>
              <input
                {...register('openAIKey')}
                type='password'
                autoComplete='off'
                className='h-9 rounded-lg border-2 border-solid border-dashboardBorder p-1 text-sm outline-none'
                placeholder='Enter your OpenAI API key'
              />
              {errors.openAIKey && <>{errors.openAIKey.message}</>}

48-48: 🛠️ Refactor suggestion

Remove console.log statement.

Remove debugging console.log statement before deploying to production.

-console.log(data)
📝 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.



26-30: ⚠️ Potential issue

Add error handling to the mutation.

The mutation lacks error handling which could lead to silent failures.

 const { mutate } = useMutation({
   mutationFn: async (data: { user: string | null } & TUpdateSchema) => {
     await AddOpenAIKey(data)
   },
+  onError: (error) => {
+    console.error('Failed to update OpenAI key:', error)
+    // Add toast notification or error state handling
+  }
 })
📝 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.

  const { mutate } = useMutation({
    mutationFn: async (data: { user: string | null } & TUpdateSchema) => {
      await AddOpenAIKey(data)
    },
    onError: (error) => {
      console.error('Failed to update OpenAI key:', error)
      // Add toast notification or error state handling
    }
  })
src/app/(admin)/dashboard/knowledgebase/_components/KnowledegeBaseTabs/_components/DocuementDataTable.tsx (1)

56-58: ⚠️ Potential issue

Enhance delete operation with error handling and user confirmation.

The delete operation should:

  1. Show a confirmation dialog
  2. Handle errors gracefully
  3. Show loading state during deletion
  4. Update the UI optimistically
-  const handleDelete=async(id:string)=>{
-    await DeleteFile(id)    
-  }
+  const handleDelete = async (id: string) => {
+    if (!window.confirm('Are you sure you want to delete this file?')) {
+      return
+    }
+    try {
+      setTableData(prev => prev.filter(file => file._id !== id))
+      await DeleteFile(id)
+    } catch (error) {
+      setTableData(prev => [...prev])
+      toast({
+        variant: "destructive",
+        title: "Error",
+        description: "Failed to delete file. Please try again."
+      })
+    }
+  }
📝 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.

  const handleDelete = async (id: string) => {
    if (!window.confirm('Are you sure you want to delete this file?')) {
      return
    }
    try {
      setTableData(prev => prev.filter(file => file._id !== id))
      await DeleteFile(id)
    } catch (error) {
      setTableData(prev => [...prev])
      toast({
        variant: "destructive",
        title: "Error",
        description: "Failed to delete file. Please try again."
      })
    }
  }
src/hooks/use-toast.ts (3)

134-141: 🛠️ Refactor suggestion

Consider using React's state management instead of global variables.

Managing state outside of React can lead to issues with React's reconciliation process and make the code harder to test.

Consider using React Context or a state management library like Zustand instead.


93-117: 🛠️ Refactor suggestion

Move side effects out of reducer.

The reducer contains side effects (addToRemoveQueue). Reducers should be pure functions.

Consider handling the timeout in an effect or in the action creator.


11-12: 🛠️ Refactor suggestion

Adjust TOAST_REMOVE_DELAY to a more reasonable value.

The current delay of 1000000ms (16.6 minutes) seems excessive for a toast notification.

-const TOAST_REMOVE_DELAY = 1000000
+const TOAST_REMOVE_DELAY = 5000  // 5 seconds is more typical for toasts
📝 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.

const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 5000  // 5 seconds is more typical for toasts
src/app/(admin)/dashboard/summary/page.tsx (3)

31-35: ⚠️ Potential issue

Add meaningful alt text for images.

The alt attribute is empty for all images. Add descriptive alt text to improve accessibility.

Apply this diff to add meaningful alt text:

-  alt=''
+  alt='Total Users Icon'

Also applies to: 55-59, 79-83, 216-220, 228-232


42-42: 🛠️ Refactor suggestion

Extract hardcoded values into constants or fetch from API.

The value "193.8K" is hardcoded and repeated multiple times. Consider extracting this into a constant or fetching from an API.

Create a constants file or integrate with an API to manage these values:

// constants.ts
export const DASHBOARD_STATS = {
  totalUsers: '193.8K',
  // ... other stats
}

Also applies to: 66-66, 90-90, 117-117, 131-131, 145-145


26-99: 🛠️ Refactor suggestion

Reduce code duplication by creating reusable components.

The card structures and device usage sections are repeated with similar layouts. Extract these into reusable components.

Create separate components for cards and device usage:

interface StatCardProps {
  icon: string;
  label: string;
  value: string;
  trend: {
    value: string;
    type: 'positive' | 'neutral';
  };
}

function StatCard({ icon, label, value, trend }: StatCardProps) {
  return (
    <div className='flex w-1/3 flex-col space-y-8 rounded-lg bg-white p-3'>
      <div>
        <Image
          src={`/assets/summary/${icon}`}
          alt={`${label} Icon`}
          width={40}
          height={40}
        />
      </div>
      {/* ... rest of the card structure */}
    </div>
  );
}

Also applies to: 111-153

src/app/(admin)/dashboard/brandsettings/_components/BrandAccordion.tsx (3)

35-37: ⚠️ Potential issue

Remove debug console.log statements.

Remove console.log statements before pushing to production.

Apply this diff to remove the debug statements:

-  console.log(theme)
-  console.log(fontSetting)
-  console.log(externalLinks)
-  console.log(logoFile)

Also applies to: 82-82


166-166: ⚠️ Potential issue

Replace 'any' type with proper event types.

The event handlers are using the 'any' type. Use proper TypeScript event types instead.

Apply this diff to fix the type safety issue:

-  onChange={(e: any) => {
+  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {

Also applies to: 189-189, 236-236


275-301: 🛠️ Refactor suggestion

Extract repeated font family options into a constant.

The font family options are duplicated across three select elements. Extract them into a constant to reduce duplication and improve maintainability.

Create a constant for font options:

const FONT_FAMILIES = [
  'Poppins',
  'Arial',
  'Verdana',
  // ... other fonts
] as const;

// Then in the component:
{FONT_FAMILIES.map(font => (
  <option key={font} value={font}>{font}</option>
))}

Also applies to: 383-409, 490-516

src/app/globals.css (1)

31-31: ⚠️ Potential issue

Remove duplicate CSS custom property.

The --dashboard-buttons-bg property is declared twice with different values (#eaeaea and #222222). The second declaration will override the first.

  --dashboard-buttons-bg: #eaeaea;
  --dashboard-preview-bg: #eaeaea;
  --dashboard-preview-text: #637085;
  --dashboard-gray-text: #555555;
  --dashboard-carousel-bg: #f7f4ee;
- --dashboard-buttons-bg: #222222;

Also applies to: 36-36

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