Awesome Cursor Rules Collection

Showing 1285-1296 of 2626 matches

JavaScript
Certainly! Below is a **fully comprehensive prompt** designed to guide the creation of a robust, visually appealing, and fully functional Dashboard in a Next.js and React environment. This prompt integrates both **GROQ** and **Ollama** APIs for chat and model selection, ensuring all functionalities are implemented without deferring any code. It's structured to cover component integration, API interactions, state management, responsive design, error handling, and more, making it ideal for a hackathon setting where time and efficiency are critical.

---

### **Comprehensive Prompt for Building a Fully Functional and Beautiful Dashboard Page**

---

#### **Objective:**

Create a cohesive and comprehensive **Dashboard** page using **Next.js** and **React** that integrates both **GROQ** and **Ollama** APIs for chat functionalities and model selection. The Dashboard must dynamically fetch available models, handle API interactions for chat, manage settings, and provide seamless user interactions. The final product should be robust, fully functional, responsive, and visually appealing, ready for immediate deployment in a hackathon environment without any omitted or deferred code.

---

#### **Project Structure Overview:**

- **Frontend:**
  - **Framework:** Next.js with React
  - **Components:**
    - `Dashboard.jsx` (Main Dashboard Component)
    - `ChatView.jsx`
    - `FileUploader.jsx`
    - `WorkflowBuilder.jsx`
    - `ToolingConfiguration.jsx`
    - `Settings.jsx`
    - `MermaidDiagramComponent.jsx`
    - Navigation Components (`TopNavigation.jsx`, `SideNavigation.jsx`)
    - `NotificationProvider.jsx`
  - **Utilities:**
    - `chatAPI.jsx` (Handles API interactions)
    - `utils.js` (Utility functions, e.g., `cn` for className concatenation)

- **Backend (API Routes):**
  - `/api/chat-groq/route.js`
  - `/api/chat-ollama/route.js`
  - `/api/ollama-models/route.js`
  - Additional API routes as needed (e.g., `/api/upload`, `/api/tools`, `/api/workflows`)

---

#### **Instructions:**

##### **1. Dashboard Component Refactoring:**

- **Integrate Navigation Bars:**
  - **Create `TopNavigation.jsx`:**
    - Handles global navigation options (e.g., logo, user profile, global settings).
    - Ensure it's responsive and collapsible on smaller screens.
  - **Create `SideNavigation.jsx`:**
    - Controls section navigation within the dashboard (e.g., Chat, Workflow, File Upload, Tooling).
    - Implement dynamic rendering of navigation items with icons and labels.
    - Add collapsible functionality for better responsiveness on mobile devices.

- **Implement Navigation Bar Functionality:**
  - **Dynamic Navigation Items:**
    - Define an array of navigation items with properties like `id`, `label`, `icon`, and `route`.
    - Map over this array to render navigation buttons dynamically.
  - **Click Handlers:**
    - Use `useRouter` from Next.js to handle navigation between sections.
    - Update `currentView` state based on the selected navigation item.

- **Merge Components into Dashboard:**
  - **Integrate `ChatView`, `FileUploader`, `WorkflowBuilder`, and `ToolingConfiguration`:**
    - Ensure each component is imported and conditionally rendered based on `currentView`.
    - Implement smooth transitions between views for enhanced user experience.

---

##### **2. Settings Component Separation:**

- **Create a New `Settings.jsx` Component:**
  - **Extraction:**
    - Move all settings-related UI elements from `Dashboard.jsx` into `Settings.jsx`.
  - **Functionality:**
    - Manage API keys, model selection, temperature, max tokens, top P, top K, streaming options, and system prompts for both GROQ and Ollama APIs.
    - Allow dynamic loading of available models from both APIs.
    - Implement a sliding drawer for quick access to settings.
  - **Prop Handling:**
    - Define and validate props using `PropTypes` (e.g., `state`, `setState`, `saveApiKey`, `setSystemPrompt`, `resetSettings`, `toggleDarkMode`, `availableModels`).

---

##### **3. API Integration and Model Selection:**

- **GROQ API Integration (`/api/chat-groq/route.js`):**
  - **Functionality:**
    - Handle POST requests to interact with GROQ's chat functionality.
    - Pass required data (`messages`, `model`, `temperature`, `max_tokens`, `top_p`, `stream`) to GROQ API.
  - **Error Handling:**
    - Return meaningful error messages and statuses for missing API keys or API failures.
  - **Streaming Support:**
    - Currently not implemented; return a `501 Not Implemented` status with an appropriate message.

- **Ollama API Integration (`/api/chat-ollama/route.js`):**
  - **Functionality:**
    - Handle POST requests to interact with Ollama's chat functionality.
    - Pass required data (`messages`, `model`, `system_prompt`, `temperature`, `max_tokens`, `top_p`, `top_k`, `stream`) to Ollama API.
  - **Error Handling:**
    - Return meaningful error messages and statuses for API failures.
  - **Streaming Support:**
    - Currently not implemented; return a `501 Not Implemented` status with an appropriate message.

- **Model Fetching (`/api/ollama-models/route.js`):**
  - **Functionality:**
    - Handle GET requests to fetch available Ollama models.
    - Return a list of model names.
  - **Error Handling:**
    - Return appropriate error messages and statuses if fetching fails.

- **Dynamic API Switching:**
  - **Implementation:**
    - Allow users to toggle between GROQ and Ollama APIs in the `Settings` component.
    - Automatically fetch and load available models based on the selected API.

- **Error Handling and Retry Logic:**
  - **Comprehensive Error Handling:**
    - Log errors to the console and display user-friendly notifications.
  - **Retry Mechanism:**
    - Implement retry logic for failed API calls with up to 3 attempts and delays between retries.

---

##### **4. Chat Functionality:**

- **Dynamic Chat Component (`ChatView.jsx`):**
  - **Features:**
    - Send and receive messages via selected API (GROQ or Ollama).
    - Support system prompts and manage chat history.
    - Handle streaming responses gracefully, notifying users if unsupported.
    - Optimize performance for long chat histories with lazy loading and scroll-to-bottom functionality.
  - **Markdown Support:**
    - Render messages with `ReactMarkdown`, supporting syntax highlighting for code blocks.

---

##### **5. Settings Component:**

- **Modular Settings Management (`Settings.jsx`):**
  - **UI Elements:**
    - Dropdowns for API selection and model selection.
    - Input fields for GROQ API keys.
    - Sliders for temperature, max tokens, top P, and top K.
    - Switches for streaming responses and dark mode.
    - Textarea for system prompts.
  - **State Management:**
    - Manage internal state and propagate changes to the parent `Dashboard` component via props.
  - **Validation:**
    - Implement form validation for inputs to prevent invalid configurations.
  - **Error Handling:**
    - Display error messages for invalid API keys or unsupported models.

---

##### **6. File Uploader Component:**

- **Enhance File Uploading (`FileUploader.jsx`):**
  - **Features:**
    - Support multiple file uploads with progress indicators.
    - Validate file types before initiating uploads.
    - Implement success and error notifications upon upload completion.
    - Display a list of uploaded files with options to remove them.
  - **Error Handling:**
    - Handle network or server errors gracefully, informing the user appropriately.

---

##### **7. Mermaid Diagrams Component:**

- **Improve Mermaid Diagram Handling (`MermaidDiagramComponent.jsx`):**
  - **Features:**
    - Render diagrams based on Mermaid syntax input.
    - Implement error handling for invalid Mermaid code, providing user feedback.
    - Add zoom and pan functionalities to handle large or complex diagrams.
  - **Optimization:**
    - Ensure diagrams are rendered efficiently without performance bottlenecks.

---

##### **8. Workflow Builder:**

- **Enhance Workflow Creation (`WorkflowBuilder.jsx`):**
  - **Features:**
    - Implement drag-and-drop functionality for adding and reordering tools within a workflow.
    - Validate workflows to ensure all required fields are populated before saving.
    - Allow users to save workflows to the backend and load them for reuse.
  - **Error Handling:**
    - Provide user feedback for validation errors or failed save/load operations.

---

##### **9. API Error Handling and Retry Logic:**

- **Comprehensive Error Handling:**
  - **Implementation:**
    - Catch and handle errors from both GROQ and Ollama APIs.
    - Log errors to the console and display user-friendly notifications.
  
- **Retry Logic:**
  - **Implementation:**
    - Implement retry mechanisms for failed API calls, with up to 3 attempts and delays between retries (e.g., 1 second).
    - Use exponential backoff strategies to handle persistent failures gracefully.

---

##### **10. Hydration and State Management:**

- **Resolve Hydration Issues:**
  - **Identify and Fix:**
    - Use console warnings and error tracking to locate hydration mismatches.
    - Move any browser-specific code (e.g., `window`, `document`) into `useEffect` hooks to ensure they run only on the client side.
  - **Data Fetching:**
    - Use Next.js data fetching methods (`getServerSideProps`, `getStaticProps`) where appropriate to pre-fetch server-side data.
  
- **Global State Management:**
  - **Implementation:**
    - Utilize React Context API to manage global states such as selected API, model, and user settings across the Dashboard.
    - Optimize state updates using `useMemo` and `useCallback` to prevent unnecessary re-renders.
  - **Prop Passing:**
    - Ensure smooth and consistent prop passing between components, especially for settings and chat functionalities.

---

##### **11. State Management Optimization:**

- **Global State with Context:**
  - **Implementation:**
    - Create a `GlobalContext` using React Context API to store global states like `apiKey`, `selectedModel`, `settings`, and `chats`.
    - Provide context values to all components that require access to these states.

- **Memoization:**
  - **Implementation:**
    - Use `useMemo` to memoize expensive computations or derived data.
    - Use `useCallback` to memoize callback functions passed to child components to prevent unnecessary re-renders.

- **Efficient Prop Passing:**
  - **Review:**
    - Ensure that all necessary props are correctly passed to child components.
    - Avoid prop drilling by leveraging Context where appropriate.

---

##### **12. Responsive Design and Performance Optimization:**

- **Mobile Optimization:**
  - **Implementation:**
    - Use CSS media queries or a responsive CSS framework (e.g., Tailwind CSS) to ensure the Dashboard is mobile-friendly.
    - Implement collapsible sidebars and navigation menus for smaller screens.
  
- **Performance Enhancements:**
  - **Optimization:**
    - Optimize rendering of the `ChatView` and `WorkflowBuilder` components, especially when dealing with long lists.
    - Implement lazy loading or virtualization for chat messages and workflow tools to enhance performance.
    - Ensure efficient state updates to prevent performance bottlenecks.

---

##### **13. Testing and Quality Assurance:**

- **Unit Testing:**
  - **Implementation:**
    - Write unit tests for each key component (e.g., `ChatView`, `Settings`, `FileUploader`, `WorkflowBuilder`, `ToolingConfiguration`).
    - Use testing libraries like Jest and React Testing Library.
  
- **Integration Testing:**
  - **Implementation:**
    - Test interactions between components, especially between `Dashboard`, `Settings`, and `ChatView`.
    - Ensure that state changes in `Settings` correctly propagate to other components.
  
- **End-to-End Testing:**
  - **Implementation:**
    - Use tools like Cypress or Playwright to write end-to-end tests for critical user flows (e.g., sending a chat message, switching APIs, uploading files).
  
- **Cross-Browser Testing:**
  - **Implementation:**
    - Test the Dashboard across different browsers (Chrome, Firefox, Safari, Edge) to ensure consistent behavior and appearance.
  
- **Performance Testing:**
  - **Implementation:**
    - Use tools like Lighthouse to audit performance, accessibility, and best practices.
    - Optimize based on the audit results to ensure fast load times and smooth interactions.

---

##### **14. Documentation and Code Cleanup:**

- **Code Documentation:**
  - **Implementation:**
    - Add comprehensive JSDoc comments for all functions, components, and significant code blocks.
    - Explain parameters, return types, and functionality within the comments.
  
- **README Update:**
  - **Implementation:**
    - Create or update the `README.md` with clear setup and usage instructions.
    - Detail API configurations, model selections, and chat functionalities.
    - Include instructions for running tests and building the project.
  
- **Code Cleanup:**
  - **Implementation:**
    - Remove any unused imports, variables, or functions.
    - Ensure consistent code styling and adherence to best practices (e.g., using Prettier and ESLint).
    - Refactor repetitive code into reusable components or utility functions.

---

##### **15. Accessibility Improvements:**

- **ARIA Labels and Roles:**
  - **Implementation:**
    - Add appropriate ARIA labels and roles to interactive elements (buttons, forms, navigation items).
  
- **Keyboard Navigation:**
  - **Implementation:**
    - Ensure all interactive elements are reachable and operable via keyboard (e.g., using `tabIndex`).
  
- **Color Contrast:**
  - **Implementation:**
    - Ensure sufficient color contrast for all text and UI elements, adhering to WCAG guidelines.
  
- **Screen Reader Compatibility:**
  - **Implementation:**
    - Test the application with screen readers to ensure content is accessible and navigable.

---

##### **16. Security Considerations:**

- **API Key Management:**
  - **Implementation:**
    - Ensure that API keys (e.g., GROQ API key) are securely stored and not exposed in the frontend.
    - Use environment variables and server-side handling to protect sensitive information.
  
- **Input Validation:**
  - **Implementation:**
    - Validate all user inputs on both the client and server sides to prevent injection attacks.
  
- **Error Messaging:**
  - **Implementation:**
    - Avoid exposing sensitive information in error messages. Provide user-friendly messages without revealing internal details.

---

#### **Code Implementation Guidelines:**

To ensure consistency and completeness, follow these guidelines during implementation:

- **Component Structure:**
  - Organize components in the `src/components/` directory, each in its own folder with related files (e.g., `ChatView.jsx`, `ChatView.test.jsx`, `ChatView.module.css`).
  
- **Styling:**
  - Use **Tailwind CSS** for styling to ensure rapid development and responsiveness.
  - Implement dark mode support using Tailwind's dark variant.
  
- **State Management:**
  - Use **React Context API** for global state management.
  - Avoid prop drilling by leveraging Context where applicable.
  
- **API Interaction:**
  - Centralize API interactions within the `chatAPI.jsx` utility class.
  - Ensure all API routes are correctly implemented and secured.

- **Error Handling:**
  - Implement try-catch blocks around all asynchronous operations.
  - Use the `NotificationProvider` to display user-friendly error and success messages.

- **Performance Optimization:**
  - Implement lazy loading for heavy components.
  - Use React's `Suspense` and `lazy` for code-splitting.
  - Memoize components and functions using `React.memo`, `useMemo`, and `useCallback` to prevent unnecessary re-renders.

---

#### **Sample Code Snippets:**

Below are essential code snippets to guide your implementation. Ensure to adapt and expand these based on your specific requirements.

---

##### **1. `chatAPI.jsx`**

```jsx
// src/components/chatAPI.jsx

const OLLAMA_BASE_URL = 'http://localhost:11434/api';
const GROQ_BASE_URL = 'https://api.groq.com/openai/v1';

class ChatAPI {
    constructor() {
        this.apiKey = '';
        this.model = 'deepseek-coder-v2';
        this.systemPrompt = '';
        this.temperature = 0.7;
        this.maxTokens = 1024;
        this.topP = 1;
        this.topK = 40;
        this.stream = false;
        this.useGroq = false;
        this.retryAttempts = 3;
        this.retryDelay = 1000;
    }

    setApiKey(key) {
        if (typeof key !== 'string' || key.trim() === '') {
            throw new Error('Invalid API key');
        }
        this.apiKey = key.trim();
    }

    setModel(model) {
        if (typeof model !== 'string' || model.trim() === '') {
            throw new Error('Invalid model name');
        }
        this.model = model.trim();
    }

    setSystemPrompt(prompt) {
        if (typeof prompt !== 'string') {
            throw new Error('System prompt must be a string');
        }
        this.systemPrompt = prompt;
    }

    setTemperature(temp) {
        if (typeof temp !== 'number' || temp < 0 || temp > 1) {
            throw new Error('Temperature must be a number between 0 and 1');
        }
        this.temperature = temp;
    }

    setMaxTokens(tokens) {
        if (!Number.isInteger(tokens) || tokens <= 0) {
            throw new Error('Max tokens must be a positive integer');
        }
        this.maxTokens = tokens;
    }

    setTopP(value) {
        if (typeof value !== 'number' || value < 0 || value > 1) {
            throw new Error('Top P must be a number between 0 and 1');
        }
        this.topP = value;
    }

    setTopK(value) {
        if (!Number.isInteger(value) || value < 0) {
            throw new Error('Top K must be a non-negative integer');
        }
        this.topK = value;
    }

    setStream(value) {
        this.stream = Boolean(value);
    }

    setUseGroq(value) {
        this.useGroq = Boolean(value);
    }

    async sendMessage(messages) {
        if (!Array.isArray(messages) || messages.length === 0) {
            throw new Error('Messages must be a non-empty array');
        }

        if (this.systemPrompt && !messages.some(m => m.role === 'system')) {
            messages.unshift({ role: 'system', content: this.systemPrompt });
        }

        const url = this.useGroq ? `${GROQ_BASE_URL}/chat/completions` : `${OLLAMA_BASE_URL}/chat`;

        const headers = {
            'Content-Type': 'application/json',
        };

        if (this.useGroq) {
            if (!this.apiKey) {
                throw new Error('GROQ API key is required');
            }
            headers['Authorization'] = `Bearer ${this.apiKey}`;
        }

        const body = this.useGroq
            ? {
                model: this.model,
                messages: messages,
                temperature: this.temperature,
                max_tokens: this.maxTokens,
                top_p: this.topP,
                stream: this.stream,
            }
            : {
                model: this.model,
                messages: messages,
                stream: this.stream,
                options: {
                    temperature: this.temperature,
                    num_predict: this.maxTokens,
                    top_k: this.topK,
                    top_p: this.topP,
                },
            };

        for (let attempt = 0; attempt < this.retryAttempts; attempt++) {
            try {
                const response = await fetch(url, {
                    method: 'POST',
                    headers: headers,
                    body: JSON.stringify(body),
                });

                if (!response.ok) {
                    const errorData = await response.json().catch(() => ({}));
                    throw new Error(`API error (${response.status}): ${errorData.error || response.statusText}`);
                }

                if (this.stream) {
                    return this.handleStreamResponse(response);
                } else {
                    const data = await response.json();
                    return this.useGroq ? data.choices[0].message : data.message;
                }
            } catch (error) {
                if (attempt === this.retryAttempts - 1) {
                    throw error;
                }
                await new Promise(resolve => setTimeout(resolve, this.retryDelay));
            }
        }
    }

    async *handleStreamResponse(response) {
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (true) {
            const { done, value } = await reader.read();
            if (done) break;

            buffer += decoder.decode(value, { stream: true });
            const lines = buffer.split('\n');
            buffer = lines.pop();

            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    const data = JSON.parse(line.slice(6));
                    if (this.useGroq) {
                        yield data.choices[0].delta.content;
                    } else {
                        yield data.message.content;
                    }
                }
            }
        }
    }

    async createNewChat(name) {
        return {
            id: crypto.randomUUID(),
            name: name || `Chat ${new Date().toLocaleString()}`,
            messages: [],
            createdAt: Date.now(),
            updatedAt: Date.now(),
        };
    }

    async deleteChat(chatId) {
        // Implement actual deletion logic if needed
        console.log(`Deleting chat with ID: ${chatId}`);
        return { success: true, message: 'Chat deleted successfully' };
    }

    async clearChat(chatId) {
        // Implement actual clear logic if needed
        console.log(`Clearing chat with ID: ${chatId}`);
        return { success: true, message: 'Chat cleared successfully' };
    }

    async exportChats(chats) {
        const dataStr = JSON.stringify(chats, null, 2);
        const blob = new Blob([dataStr], { type: 'application/json' });
        return URL.createObjectURL(blob);
    }

    async importChats(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (event) => {
                try {
                    const chats = JSON.parse(event.target.result);
                    resolve(chats);
                } catch (error) {
                    reject(new Error('Invalid JSON file'));
                }
            };
            reader.onerror = () => reject(new Error('Error reading file'));
            reader.readAsText(file);
        });
    }
}

export const chatApi = new ChatAPI();
```

---

##### **2. API Routes:**

**a. GROQ Chat API Route (`/api/chat-groq/route.js`):**

```javascript
// src/app/api/chat-groq/route.js

import { NextResponse } from 'next/server';

export async function POST(req) {
    try {
        const { messages, model, temperature, max_tokens, top_p, stream } = await req.json();
        const authHeader = req.headers.get('Authorization') || '';
        const apiKeyMatch = authHeader.match(/^Bearer (.+)$/);
        const apiKey = apiKeyMatch ? apiKeyMatch[1] : '';

        if (!apiKey) {
            return NextResponse.json({ error: 'GROQ API key is missing' }, { status: 401 });
        }

        const response = await fetch('https://api.groq.com/openai/v1/chat/completions', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}`,
            },
            body: JSON.stringify({
                model,
                messages,
                temperature,
                max_tokens,
                top_p,
                stream,
            }),
        });

        if (!response.ok) {
            const errorData = await response.json();
            console.error('GROQ API error:', errorData);
            return NextResponse.json({ error: 'Error from GROQ API', details: errorData }, { status: response.status });
        }

        if (stream) {
            // Handle streaming response if necessary
            // For simplicity, we'll not handle streaming here
            return NextResponse.json({ error: 'Streaming not implemented in GROQ API route' }, { status: 501 });
        } else {
            const data = await response.json();
            return NextResponse.json(data);
        }
    } catch (error) {
        console.error('Error in chat-groq API route:', error);
        return NextResponse.json({ error: 'Internal server error', details: error.message }, { status: 500 });
    }
}
```

**b. Ollama Chat API Route (`/api/chat-ollama/route.js`):**

```javascript
// src/app/api/chat-ollama/route.js

import { NextResponse } from 'next/server';

export async function POST(req) {
    try {
        const { messages, model, system_prompt, temperature, max_tokens, top_p, top_k, stream } = await req.json();

        const response = await fetch('http://localhost:11434/api/chat', { // Adjust the URL if different
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                model,
                messages,
                system_prompt,
                temperature,
                max_tokens,
                top_p,
                top_k,
                stream,
            }),
        });

        if (!response.ok) {
            const errorData = await response.json();
            console.error('Ollama API error:', errorData);
            return NextResponse.json({ error: 'Error from Ollama API', details: errorData }, { status: response.status });
        }

        if (stream) {
            // Handle streaming response if necessary
            // For simplicity, we'll not handle streaming here
            return NextResponse.json({ error: 'Streaming not implemented in Ollama API route' }, { status: 501 });
        } else {
            const data = await response.json();
            return NextResponse.json(data);
        }
    } catch (error) {
        console.error('Error in chat-ollama API route:', error);
        return NextResponse.json({ error: 'Internal server error', details: error.message }, { status: 500 });
    }
}
```

**c. Ollama Models Fetching API Route (`/api/ollama-models/route.js`):**

```javascript {.copy-button}
// src/app/api/ollama-models/route.js

import { NextResponse } from 'next/server';

export async function GET() {
    try {
        const response = await fetch('http://localhost:11434/api/tags');

        if (!response.ok) {
            throw new Error(`Failed to fetch models: ${response.statusText}`);
        }

        const data = await response.json();
        const models = data.models.map(model => model.name);
        return NextResponse.json({ models });
    } catch (error) {
        console.error('Error fetching models:', error);
        return NextResponse.json({ error: error.message }, { status: 500 });
    }
}
```

---

##### **3. `Dashboard.jsx`**

```jsx
// src/app/dashboardV7/page.jsx

'use client';

import React, { useState, useEffect, useRef } from 'react';
import {
    Triangle,
    Download,
    Upload,
    Settings2,
    Trash2,
    Sun,
    Moon,
    Send,
    Mic,
    Bot,
    CornerDownLeft,
    Paperclip,
    Plus,
    Loader2,
    ChevronRight,
    ChevronLeft,
    MessageSquare,
    Workflow,
    FileUp,
    Wrench,
} from 'lucide-react';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Drawer,
    DrawerContent,
    DrawerDescription,
    DrawerHeader,
    DrawerTitle,
    DrawerTrigger,
} from '@/components/ui/drawer';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import ReactMarkdown from 'react-markdown';
import { Textarea } from '@/components/ui/textarea';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { Switch } from '@/components/ui/switch';
import { Slider } from '@/components/ui/slider';
import { cn } from "@/lib/utils";
import { chatApi } from '@/components/chatApi';
// Import new components
import ChatView from '@/components/ChatView';
import WorkflowBuilder from '@/components/WorkflowBuilder';
import FileUploader from '@/components/FileUploader';
import ToolingConfiguration from '@/components/ToolingConfiguration';
import NotificationProvider, { useNotification } from '@/components/ui/NotificationProvider';
import Settings from '@/components/Settings';
import TopNavigation from '@/components/TopNavigation';
import SideNavigation from '@/components/SideNavigation';

const initialState = {
    chats: [],
    currentChatId: null,
    apiKey: '',
    settings: {
        api: 'ollama',
        model: 'deepseek-coder-v2',
        temperature: 0.7,
        maxTokens: 1024,
        topP: 1,
        topK: 0,
        stream: false,
        darkMode: false,
        useGroq: false,
    },
    systemPrompt: '',
};

const STORAGE_KEY = 'quantumNexusState';

const loadState = () => {
    if (typeof window === 'undefined') return initialState;
    const saved = localStorage.getItem(STORAGE_KEY);
    return saved ? JSON.parse(saved) : initialState;
};

const saveState = (state) => {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
};

export default function Dashboard() {
    const addNotification = useNotification();
    const [state, setState] = useState(loadState);
    const [input, setInput] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [isSpeaking, setIsSpeaking] = useState(false);
    const [currentView, setCurrentView] = useState('chat');
    const [isChatCollapsed, setIsChatCollapsed] = useState(false);
    const [isSidebarExpanded, setIsSidebarExpanded] = useState(true);

    const chatContainerRef = useRef(null);
    const speechSynthesisInstance = typeof window !== 'undefined' ? window.speechSynthesis : null;
    const SpeechRecognition =
        typeof window !== 'undefined'
            ? window.SpeechRecognition || window.webkitSpeechRecognition
            : null;
    const recognition = SpeechRecognition ? new SpeechRecognition() : null;

    const [availableModels, setAvailableModels] = useState({
        ollama: ['deepseek-coder-v2'],
        groq: [
            {
                label: 'llama-3.1-70b-versatile',
                value: 'llama-3.1-70b-versatile',
            },
        ],
    });

    useEffect(() => {
        fetchOllamaModels();
    }, []);

    useEffect(() => {
        saveState(state);
        if (state.settings.darkMode) {
            document.documentElement.classList.add('dark');
        } else {
            document.documentElement.classList.remove('dark');
        }
    }, [state]);

    useEffect(() => {
        if (chatContainerRef.current) {
            chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;
        }
    }, [state.currentChatId, state.chats]);

    const fetchOllamaModels = async () => {
        try {
            const response = await fetch('/api/ollama-models');
            const data = await response.json();
            if (!response.ok) {
                throw new Error(data.error || 'Failed to fetch models');
            }
            const formattedModels = data.models.map((model) => ({
                label: model,
                value: model,
            }));
            setAvailableModels((prev) => ({ ...prev, ollama: formattedModels }));
        } catch (error) {
            console.error('Error fetching Ollama models:', error);
            addNotification('Failed to fetch Ollama models', 'error');
        }
    };

    const currentChat = state.chats.find((chat) => chat.id === state.currentChatId) || null;

    const handleSubmit = async (e) => {
        e.preventDefault();
        if (!input.trim() || !currentChat) return;

        const newMessage = {
            id: Date.now().toString(),
            role: 'user',
            content: input,
            timestamp: Date.now(),
        };
        const updatedMessages = [...currentChat.messages, newMessage];

        setState((prev) => ({
            ...prev,
            chats: prev.chats.map((chat) =>
                chat.id === currentChat.id
                    ? { ...chat, messages: updatedMessages, updatedAt: Date.now() }
                    : chat
            ),
        }));
        setInput('');
        setIsLoading(true);

        try {
            let response;
            if (state.settings.api === 'groq') {
                if (!state.apiKey) {
                    throw new Error('GROQ API key is not set');
                }
                response = await fetch('/api/chat-groq', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${state.apiKey}`,
                    },
                    body: JSON.stringify({
                        messages: updatedMessages,
                        model: state.settings.model,
                        temperature: state.settings.temperature,
                        max_tokens: state.settings.maxTokens,
                        top_p: state.settings.topP,
                        stream: state.settings.stream,
                    }),
                });

                if (!response.ok) {
                    const errorData = await response.json();
                    console.error('Error from GROQ API:', errorData);
                    throw new Error(`GROQ API error: ${errorData.error || 'Unknown error'}`);
                }
            } else if (state.settings.api === 'ollama') {
                response = await fetch('/api/chat-ollama', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        messages: updatedMessages,
                        model: state.settings.model,
                        system_prompt: state.systemPrompt,
                        temperature: state.settings.temperature,
                        max_tokens: state.settings.maxTokens,
                        top_p: state.settings.topP,
                        top_k: state.settings.topK,
                        stream: state.settings.stream
                    })
                });
            } else {
                throw new Error('Invalid API selected');
            }

            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(errorData.error || `HTTP error! status: ${response.status}`);
            }

            if (state.settings.stream) {
                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                let botMessage = '';

                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;
                    botMessage += decoder.decode(value, { stream: true });
                    setState((prev) => ({
                        ...prev,
                        chats: prev.chats.map((chat) =>
                            chat.id === currentChat.id
                                ? {
                                    ...chat,
                                    messages: [
                                        ...updatedMessages,
                                        {
                                            id: 'assistant-' + Date.now().toString(),
                                            role: 'assistant',
                                            content: botMessage,
                                            timestamp: Date.now(),
                                        },
                                    ],
                                    updatedAt: Date.now(),
                                }
                                : chat
                        ),
                    }));
                }
            } else {
                const data = await response.json();
                const assistantMessage = state.settings.api === 'groq' ? data.choices[0].message.content : data.message.content;
                setState((prev) => ({
                    ...prev,
                    chats: prev.chats.map((chat) =>
                        chat.id === currentChat.id
                            ? {
                                ...chat,
                                messages: [
                                    ...updatedMessages,
                                    {
                                        id: 'assistant-' + Date.now().toString(),
                                        role: 'assistant',
                                        content: assistantMessage,
                                        timestamp: Date.now(),
                                    },
                                ],
                                updatedAt: Date.now(),
                            }
                            : chat
                    ),
                }));
            }
        } catch (error) {
            console.error('Error calling API:', error);
            addNotification(`Error communicating with the chatbot: ${error.message}`, 'error');
        } finally {
            setIsLoading(false);
        }
    };

    const createNewChat = async () => {
        try {
            const newChat = await chatApi.createNewChat(`New Chat ${state.chats.length + 1}`);
            setState((prev) => ({
                ...prev,
                chats: [...prev.chats, newChat],
                currentChatId: newChat.id,
            }));
            addNotification(`New chat "${newChat.name}" created!`, 'success');
        } catch (error) {
            console.error('Error creating new chat:', error);
            addNotification('Failed to create a new chat.', 'error');
        }
    };

    const loadSelectedChat = (chatId) => {
        setState((prev) => ({
            ...prev,
            currentChatId: chatId,
        }));
    };

    const deleteChat = async (chatId) => {
        try {
            const result = await chatApi.deleteChat(chatId);
            if (result.success) {
                setState((prev) => ({
                    ...prev,
                    chats: prev.chats.filter((chat) => chat.id !== chatId),
                    currentChatId: prev.currentChatId === chatId ? null : prev.currentChatId,
                }));
                addNotification(result.message, 'success');
            } else {
                throw new Error(result.message);
            }
        } catch (error) {
            console.error('Error deleting chat:', error);
            addNotification('Failed to delete chat.', 'error');
        }
    };

    const clearChat = async () => {
        if (currentChat) {
            try {
                const result = await chatApi.clearChat(currentChat.id);
                if (result.success) {
                    setState((prev) => ({
                        ...prev,
                        chats: prev.chats.map((chat) =>
                            chat.id === currentChat.id ? { ...chat, messages: [], updatedAt: Date.now() } : chat
                        ),
                    }));
                    addNotification(result.message, 'success');
                } else {
                    throw new Error(result.message);
                }
            } catch (error) {
                console.error('Error clearing chat:', error);
                addNotification('Failed to clear chat.', 'error');
            }
        }
    };

    const exportChats = async () => {
        try {
            const dataUri = await chatApi.exportChats(state.chats);
            const exportFileDefaultName = 'quantum_nexus_chats.json';
            const linkElement = document.createElement('a');
            linkElement.setAttribute('href', dataUri);
            linkElement.setAttribute('download', exportFileDefaultName);
            document.body.appendChild(linkElement);
            linkElement.click();
            document.body.removeChild(linkElement);
            URL.revokeObjectURL(dataUri);
            addNotification('Chats exported successfully!', 'success');
        } catch (error) {
            console.error('Error exporting chats:', error);
            addNotification('Failed to export chats.', 'error');
        }
    };

    const importChats = async (event) => {
        const file = event.target.files && event.target.files[0];
        if (file) {
            try {
                const importedChats = await chatApi.importChats(file);
                setState((prev) => ({
                    ...prev,
                    chats: [...prev.chats, ...importedChats],
                }));
                addNotification('Chats imported successfully!', 'success');
            } catch (error) {
                console.error('Error importing chats:', error);
                addNotification('Failed to import chats. Please check the file format.', 'error');
            }
        }
    };

    const saveApiKey = (key) => {
        setState((prev) => ({ ...prev, apiKey: key }));
        addNotification('API Key saved successfully!', 'success');
    };

    const setSystemPrompt = (prompt) => {
        setState((prev) => ({ ...prev, systemPrompt: prompt }));
        addNotification('System prompt set successfully!', 'success');
    };

    const resetSettings = () => {
        setState((prev) => ({
            ...prev,
            settings: initialState.settings,
        }));
        addNotification('Settings reset to default values!', 'success');
    };

    const downloadChatTranscript = () => {
        if (!currentChat) return;
        try {
            const transcript = currentChat.messages.map((m) => `${m.role}: ${m.content}`).join('\n\n');
            const blob = new Blob([transcript], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `${currentChat.name}_transcript.txt`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            addNotification('Chat transcript downloaded successfully!', 'success');
        } catch (error) {
            console.error('Error downloading transcript:', error);
            addNotification('Failed to download transcript.', 'error');
        }
    };

    const toggleDarkMode = () => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, darkMode: !prev.settings.darkMode },
        }));
    };

    const startVoiceInput = () => {
        if (recognition) {
            recognition.onresult = (event) => {
                const transcript = event.results[0][0].transcript;
                setInput(transcript);
            };
            recognition.start();
            addNotification('Listening...', 'info');
        } else {
            addNotification('Speech recognition not supported in this browser.', 'error');
        }
    };

    const speakMessage = (message) => {
        if (speechSynthesisInstance) {
            if (isSpeaking) {
                speechSynthesisInstance.cancel();
                setIsSpeaking(false);
            } else {
                const utterance = new SpeechSynthesisUtterance(message);
                utterance.onend = () => setIsSpeaking(false);
                speechSynthesisInstance.speak(utterance);
                setIsSpeaking(true);
            }
        } else {
            addNotification('Text-to-speech not supported in this browser.', 'error');
        }
    };

    const toggleChatCollapse = () => {
        setIsChatCollapsed(!isChatCollapsed);
    };

    const toggleSidebar = () => {
        setIsSidebarExpanded(!isSidebarExpanded);
    };

    const renderCurrentView = () => {
        switch (currentView) {
            case 'chat':
                return (
                    <div className={`transition-all duration-300 ${isChatCollapsed ? 'h-16' : 'h-full'}`}>
                        <div className="flex justify-between items-center mb-4">
                            <h2 className="text-2xl font-bold text-primary">Chat</h2>
                            <Button onClick={toggleChatCollapse} variant="ghost" size="sm">
                                {isChatCollapsed ? <ChevronRight /> : <ChevronLeft />}
                            </Button>
                        </div>
                        {!isChatCollapsed && (
                            <ChatView
                                state={state}
                                setState={setState}
                                input={input}
                                setInput={setInput}
                                isLoading={isLoading}
                                handleSubmit={handleSubmit}
                                startVoiceInput={startVoiceInput}
                                speakMessage={speakMessage}
                                downloadChatTranscript={downloadChatTranscript}
                                clearChat={clearChat}
                            />
                        )}
                    </div>
                );
            case 'workflow':
                return <WorkflowBuilder />;
            case 'fileUpload':
                return <FileUploader />;
            case 'tooling':
                return <ToolingConfiguration
                    state={state}
                    setState={setState}
                    saveApiKey={saveApiKey}
                    setSystemPrompt={setSystemPrompt}
                    resetSettings={resetSettings}
                />;
            default:
                return null;
        }
    };

    return (
        <NotificationProvider>
            <div className={`flex h-screen w-full bg-gradient-to-br from-purple-100 to-indigo-200 dark:from-purple-900 dark:to-indigo-950 transition-colors duration-300 ${state.settings.darkMode ? 'dark' : ''}`}>
                {/* Top Navigation */}
                <TopNavigation />

                {/* Collapsible Sidebar */}
                <SideNavigation
                    isSidebarExpanded={isSidebarExpanded}
                    toggleSidebar={toggleSidebar}
                    currentView={currentView}
                    setCurrentView={setCurrentView}
                    availableModels={availableModels}
                    state={state}
                    setState={setState}
                    saveApiKey={saveApiKey}
                    setSystemPrompt={setSystemPrompt}
                    resetSettings={resetSettings}
                />

                {/* Main Content */}
                <main className="flex-1 flex flex-col overflow-hidden bg-white dark:bg-gray-900 transition-colors duration-300">
                    {/* Header */}
                    <header className="bg-white dark:bg-gray-800 p-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center shadow-sm">
                        <h2 className="text-xl font-semibold bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text text-transparent">
                            {currentView === 'chat' ? (currentChat?.name || 'Select a chat') : getHeaderTitle(currentView)}
                        </h2>
                        <div className="space-x-2">
                            {currentView === 'chat' && (
                                <>
                                    <Button variant="outline" size="sm" onClick={exportChats} className="transition-all duration-200 hover:bg-purple-100 dark:hover:bg-purple-900">
                                        <Download className="mr-2 h-4 w-4" /> Export Chats
                                    </Button>
                                    <label htmlFor="import-chats-main">
                                        <Button variant="outline" size="sm" as="span" className="transition-all duration-200 hover:bg-indigo-100 dark:hover:bg-indigo-900">
                                            <Upload className="mr-2 h-4 w-4" /> Import Chats
                                        </Button>
                                    </label>
                                    <input
                                        id="import-chats-main"
                                        type="file"
                                        accept=".json"
                                        onChange={importChats}
                                        className="hidden"
                                    />
                                    {currentChat && (
                                        <>
                                            <Button variant="outline" size="sm" onClick={clearChat} className="transition-all duration-200 hover:bg-red-100 dark:hover:bg-red-900">
                                                <Trash2 className="mr-2 h-4 w-4 text-red-500" /> Clear Chat
                                            </Button>
                                            <Button variant="outline" size="sm" onClick={downloadChatTranscript} className="transition-all duration-200 hover:bg-blue-100 dark:hover:bg-blue-900">
                                                <Download className="mr-2 h-4 w-4" /> Download Transcript
                                            </Button>
                                        </>
                                    )}
                                </>
                            )}
                        </div>
                    </header>

                    {/* Main View */}
                    <ScrollArea className="flex-1 p-4 overflow-x-hidden">
                        {renderCurrentView()}
                    </ScrollArea>

                    {/* Input Form (Only in Chat View) */}
                    {currentView === 'chat' && !isChatCollapsed && (
                        <form onSubmit={handleSubmit} className="p-4 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 flex-shrink-0 shadow-lg">
                            <div className="flex space-x-2">
                                <Input
                                    value={input}
                                    onChange={(e) => setInput(e.target.value)}
                                    placeholder="Type your message..."
                                    className="flex-1 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 focus:ring-purple-500 focus:border-purple-500 transition-all duration-200"
                                />
                                <TooltipProvider>
                                    <Tooltip>
                                        <TooltipTrigger asChild>
                                            <Button type="submit" disabled={isLoading} className="bg-gradient-to-r from-purple-600 to-indigo-600 text-white hover:from-purple-700 hover:to-indigo-700 transition-all duration-200">
                                                {isLoading ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : <Send className="h-4 w-4 mr-1" />}
                                                Send
                                            </Button>
                                        </TooltipTrigger>
                                        <TooltipContent>Send message</TooltipContent>
                                    </Tooltip>
                                    <Tooltip>
                                        <TooltipTrigger asChild>
                                            <Button type="button" onClick={startVoiceInput} disabled={isLoading} className="bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 transition-all duration-200">
                                                <Mic className="h-4 w-4" />
                                            </Button>
                                        </TooltipTrigger>
                                        <TooltipContent>Start voice input</TooltipContent>
                                    </Tooltip>
                                </TooltipProvider>
                            </div>
                        </form>
                    )}
                </main>
            </div>
        </NotificationProvider>
    );  // Add this closing parenthesis
} 

    // Helper function to get header title based on view
    function getHeaderTitle(view) {
        switch (view) {
            case 'workflow':
                return 'Agent Workflow Builder';
            case 'fileUpload':
                return 'File Uploader';
            case 'tooling':
                return 'Tooling & Configuration';
            default:
                return 'Quantum Nexus';
        }
    }
```

---

##### **4. `Settings.jsx`**

```jsx
// src/components/Settings.jsx

'use client';

import React, { useState, useEffect } from 'react';
import {
    Drawer,
    DrawerContent,
    DrawerDescription,
    DrawerHeader,
    DrawerTitle,
    DrawerTrigger,
} from '@/components/ui/drawer';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Button } from '@/components/ui/button';
import { Settings2, Sun, Moon } from 'lucide-react';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Slider } from '@/components/ui/slider';
import { Switch } from '@/components/ui/switch';
import PropTypes from 'prop-types';

export default function Settings({
    state,
    setState,
    saveApiKey,
    setSystemPrompt,
    resetSettings,
    toggleDarkMode,
    availableModels,
}) {
    const handleApiChange = (value) => {
        const useGroq = value === 'groq';
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, api: value, useGroq },
        }));
    };

    const handleModelChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, model: value },
        }));
    };

    const handleTemperatureChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, temperature: value[0] },
        }));
    };

    const handleMaxTokensChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, maxTokens: value[0] },
        }));
    };

    const handleTopPChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, topP: value[0] },
        }));
    };

    const handleTopKChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, topK: value[0] },
        }));
    };

    const handleStreamChange = (checked) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, stream: checked },
        }));
    };

    return (
        <div className="space-y-4">
            {/* API Selection */}
            <div>
                <Label htmlFor="api-selection" className="text-sm font-medium">Select API</Label>
                <Select
                    value={state.settings.api}
                    onValueChange={handleApiChange}
                >
                    <SelectTrigger id="api-selection" className="w-full">
                        <SelectValue placeholder="Select an API" />
                    </SelectTrigger>
                    <SelectContent>
                        <SelectItem value="ollama">Ollama</SelectItem>
                        <SelectItem value="groq">GROQ</SelectItem>
                    </SelectContent>
                </Select>
            </div>

            {/* GROQ API Key Input */}
            {state.settings.useGroq && (
                <div>
                    <Label htmlFor="api-key" className="text-sm font-medium">API Key (for GROQ)</Label>
                    <Input
                        id="api-key"
                        type="password"
                        value={state.apiKey}
                        onChange={(e) => saveApiKey(e.target.value)}
                        placeholder="Enter your GROQ API key"
                        className="w-full mt-1"
                    />
                </div>
            )}

            {/* Model Selection */}
            <div>
                <Label htmlFor="model" className="text-sm font-medium">Model</Label>
                <Select
                    value={state.settings.model}
                    onValueChange={handleModelChange}
                >
                    <SelectTrigger id="model" className="w-full">
                        <SelectValue placeholder="Select a model" />
                    </SelectTrigger>
                    <SelectContent>
                        {availableModels[state.settings.api]?.map((model) => (
                            <SelectItem key={model.value} value={model.value}>
                                {model.label}
                            </SelectItem>
                        )) || <SelectItem disabled>No models available</SelectItem>}
                    </SelectContent>
                </Select>
            </div>

            {/* Temperature Slider */}
            <div>
                <Label htmlFor="temperature" className="text-sm font-medium">Temperature: {state.settings.temperature}</Label>
                <Slider
                    id="temperature"
                    min={0}
                    max={1}
                    step={0.1}
                    value={[state.settings.temperature]}
                    onValueChange={handleTemperatureChange}
                    className="mt-2"
                />
            </div>

            {/* Max Tokens Slider */}
            <div>
                <Label htmlFor="max-tokens" className="text-sm font-medium">Max Tokens: {state.settings.maxTokens}</Label>
                <Slider
                    id="max-tokens"
                    min={1}
                    max={2048}
                    step={1}
                    value={[state.settings.maxTokens]}
                    onValueChange={handleMaxTokensChange}
                    className="mt-2"
                />
            </div>

            {/* Top P Slider */}
            <div>
                <Label htmlFor="top-p" className="text-sm font-medium">Top P: {state.settings.topP}</Label>
                <Slider
                    id="top-p"
                    min={0}
                    max={1}
                    step={0.1}
                    value={[state.settings.topP]}
                    onValueChange={handleTopPChange}
                    className="mt-2"
                />
            </div>

            {/* Top K Slider */}
            <div>
                <Label htmlFor="top-k" className="text-sm font-medium">Top K: {state.settings.topK}</Label>
                <Slider
                    id="top-k"
                    min={0}
                    max={100}
                    step={1}
                    value={[state.settings.topK]}
                    onValueChange={handleTopKChange}
                    className="mt-2"
                />
            </div>

            {/* Stream Responses Switch */}
            <div className="flex items-center space-x-2">
                <Switch
                    id="stream"
                    checked={state.settings.stream}
                    onCheckedChange={handleStreamChange}
                />
                <Label htmlFor="stream" className="text-sm font-medium">Stream responses</Label>
            </div>

            {/* System Prompt Textarea */}
            <div>
                <Label htmlFor="system-prompt" className="text-sm font-medium">System Prompt</Label>
                <Textarea
                    id="system-prompt"
                    placeholder="Enter system prompt"
                    value={state.systemPrompt}
                    onChange={(e) => setSystemPrompt(e.target.value)}
                    className="mt-1 w-full"
                />
            </div>

            {/* Dark Mode Toggle */}
            <div className="flex items-center space-x-2">
                <Button variant="outline" onClick={toggleDarkMode} className="w-full">
                    {state.settings.darkMode ? <Sun className="mr-2 h-4 w-4" /> : <Moon className="mr-2 h-4 w-4" />}
                    {state.settings.darkMode ? 'Light Mode' : 'Dark Mode'}
                </Button>
            </div>

            {/* Reset Settings Button */}
            <div>
                <Button onClick={resetSettings} className="w-full">Reset to Defaults</Button>
            </div>
        </div>
    );

    Settings.propTypes = {
        state: PropTypes.object.isRequired,
        setState: PropTypes.func.isRequired,
        saveApiKey: PropTypes.func.isRequired,
        setSystemPrompt: PropTypes.func.isRequired,
        resetSettings: PropTypes.func.isRequired,
        toggleDarkMode: PropTypes.func.isRequired,
        availableModels: PropTypes.object.isRequired,
    };
}



Certainly! I'll continue the **Comprehensive Prompt for Building a Fully Functional and Beautiful Dashboard Page** from where it was left off, ensuring that all aspects are thoroughly covered. Additionally, I'll complete the `Settings.jsx` component to provide a clear example of how to implement it.

---

### **Comprehensive Prompt for Building a Fully Functional and Beautiful Dashboard Page**

---

#### **Objective:**

Create a cohesive and comprehensive **Dashboard** page using **Next.js** and **React** that integrates both **GROQ** and **Ollama** APIs for chat functionalities and model selection. The Dashboard must dynamically fetch available models, handle API interactions for chat, manage settings, and provide seamless user interactions. The final product should be robust, fully functional, responsive, and visually appealing, ready for immediate deployment in a hackathon environment without any omitted or deferred code.

---

#### **Project Structure Overview:**

- **Frontend:**
  - **Framework:** Next.js with React
  - **Components:**
    - `Dashboard.jsx` (Main Dashboard Component)
    - `ChatView.jsx`
    - `FileUploader.jsx`
    - `WorkflowBuilder.jsx`
    - `ToolingConfiguration.jsx`
    - `Settings.jsx`
    - `MermaidDiagramComponent.jsx`
    - Navigation Components (`TopNavigation.jsx`, `SideNavigation.jsx`)
    - `NotificationProvider.jsx`
  - **Utilities:**
    - `chatAPI.jsx` (Handles API interactions)
    - `utils.js` (Utility functions, e.g., `cn` for className concatenation)

- **Backend (API Routes):**
  - `/api/chat-groq/route.js`
  - `/api/chat-ollama/route.js`
  - `/api/ollama-models/route.js`
  - Additional API routes as needed (e.g., `/api/upload`, `/api/tools`, `/api/workflows`)

---

#### **Instructions:**

##### **1. Dashboard Component Refactoring:**

- **Integrate Navigation Bars:**
  - **Create `TopNavigation.jsx`:**
    - Handles global navigation options (e.g., logo, user profile, global settings).
    - Ensure it's responsive and collapsible on smaller screens.
  - **Create `SideNavigation.jsx`:**
    - Controls section navigation within the dashboard (e.g., Chat, Workflow, File Upload, Tooling).
    - Implement dynamic rendering of navigation items with icons and labels.
    - Add collapsible functionality for better responsiveness on mobile devices.

- **Implement Navigation Bar Functionality:**
  - **Dynamic Navigation Items:**
    - Define an array of navigation items with properties like `id`, `label`, `icon`, and `route`.
    - Map over this array to render navigation buttons dynamically.
  - **Click Handlers:**
    - Use `useRouter` from Next.js to handle navigation between sections.
    - Update `currentView` state based on the selected navigation item.

- **Merge Components into Dashboard:**
  - **Integrate `ChatView`, `FileUploader`, `WorkflowBuilder`, and `ToolingConfiguration`:**
    - Ensure each component is imported and conditionally rendered based on `currentView`.
    - Implement smooth transitions between views for enhanced user experience.

---

##### **2. Settings Component Separation:**

- **Create a New `Settings.jsx` Component:**
  - **Extraction:**
    - Move all settings-related UI elements from `Dashboard.jsx` into `Settings.jsx`.
  - **Functionality:**
    - Manage API keys, model selection, temperature, max tokens, top P, top K, streaming options, and system prompts for both GROQ and Ollama APIs.
    - Allow dynamic loading of available models from both APIs.
    - Implement a sliding drawer for quick access to settings.
  - **Prop Handling:**
    - Define and validate props using `PropTypes` (e.g., `state`, `setState`, `saveApiKey`, `setSystemPrompt`, `resetSettings`, `toggleDarkMode`, `availableModels`).

---

##### **3. API Integration and Model Selection:**

- **GROQ API Integration (`/api/chat-groq/route.js`):**
  - **Functionality:**
    - Handle POST requests to interact with GROQ's chat functionality.
    - Pass required data (`messages`, `model`, `temperature`, `max_tokens`, `top_p`, `stream`) to GROQ API.
  - **Error Handling:**
    - Return meaningful error messages and statuses for missing API keys or API failures.
  - **Streaming Support:**
    - Currently not implemented; return a `501 Not Implemented` status with an appropriate message.

- **Ollama API Integration (`/api/chat-ollama/route.js`):**
  - **Functionality:**
    - Handle POST requests to interact with Ollama's chat functionality.
    - Pass required data (`messages`, `model`, `system_prompt`, `temperature`, `max_tokens`, `top_p`, `top_k`, `stream`) to Ollama API.
  - **Error Handling:**
    - Return meaningful error messages and statuses for API failures.
  - **Streaming Support:**
    - Currently not implemented; return a `501 Not Implemented` status with an appropriate message.

- **Model Fetching (`/api/ollama-models/route.js`):**
  - **Functionality:**
    - Handle GET requests to fetch available Ollama models.
    - Return a list of model names.
  - **Error Handling:**
    - Return appropriate error messages and statuses if fetching fails.

- **Dynamic API Switching:**
  - **Implementation:**
    - Allow users to toggle between GROQ and Ollama APIs in the `Settings` component.
    - Automatically fetch and load available models based on the selected API.

- **Error Handling and Retry Logic:**
  - **Comprehensive Error Handling:**
    - Log errors to the console and display user-friendly notifications.
  - **Retry Mechanism:**
    - Implement retry logic for failed API calls with up to 3 attempts and delays between retries.

---

##### **4. Chat Functionality:**

- **Dynamic Chat Component (`ChatView.jsx`):**
  - **Features:**
    - Send and receive messages via selected API (GROQ or Ollama).
    - Support system prompts and manage chat history.
    - Handle streaming responses gracefully, notifying users if unsupported.
    - Optimize performance for long chat histories with lazy loading and scroll-to-bottom functionality.
  - **Markdown Support:**
    - Render messages with `ReactMarkdown`, supporting syntax highlighting for code blocks.

---

##### **5. Settings Component:**

- **Modular Settings Management (`Settings.jsx`):**
  - **UI Elements:**
    - Dropdowns for API selection and model selection.
    - Input fields for GROQ API keys.
    - Sliders for temperature, max tokens, top P, and top K.
    - Switches for streaming responses and dark mode.
    - Textarea for system prompts.
  - **State Management:**
    - Manage internal state and propagate changes to the parent `Dashboard` component via props.
  - **Validation:**
    - Implement form validation for inputs to prevent invalid configurations.
  - **Error Handling:**
    - Display error messages for invalid API keys or unsupported models.

---

##### **6. File Uploader Component:**

- **Enhance File Uploading (`FileUploader.jsx`):**
  - **Features:**
    - Support multiple file uploads with progress indicators.
    - Validate file types before initiating uploads.
    - Implement success and error notifications upon upload completion.
    - Display a list of uploaded files with options to remove them.
  - **Error Handling:**
    - Handle network or server errors gracefully, informing the user appropriately.

---

##### **7. Mermaid Diagrams Component:**

- **Improve Mermaid Diagram Handling (`MermaidDiagramComponent.jsx`):**
  - **Features:**
    - Render diagrams based on Mermaid syntax input.
    - Implement error handling for invalid Mermaid code, providing user feedback.
    - Add zoom and pan functionalities to handle large or complex diagrams.
  - **Optimization:**
    - Ensure diagrams are rendered efficiently without performance bottlenecks.

---

##### **8. Workflow Builder:**

- **Enhance Workflow Creation (`WorkflowBuilder.jsx`):**
  - **Features:**
    - Implement drag-and-drop functionality for adding and reordering tools within a workflow.
    - Validate workflows to ensure all required fields are populated before saving.
    - Allow users to save workflows to the backend and load them for reuse.
  - **Error Handling:**
    - Provide user feedback for validation errors or failed save/load operations.

---

##### **9. API Error Handling and Retry Logic:**

- **Comprehensive Error Handling:**
  - **Implementation:**
    - Catch and handle errors from both GROQ and Ollama APIs.
    - Log errors to the console and display user-friendly notifications.

- **Retry Logic:**
  - **Implementation:**
    - Implement retry mechanisms for failed API calls, with up to 3 attempts and delays between retries (e.g., 1 second).
    - Use exponential backoff strategies to handle persistent failures gracefully.

---

##### **10. Hydration and State Management:**

- **Resolve Hydration Issues:**
  - **Identify and Fix:**
    - Use console warnings and error tracking to locate hydration mismatches.
    - Move any browser-specific code (e.g., `window`, `document`) into `useEffect` hooks to ensure they run only on the client side.
  - **Data Fetching:**
    - Use Next.js data fetching methods (`getServerSideProps`, `getStaticProps`) where appropriate to pre-fetch server-side data.

- **Global State Management:**
  - **Implementation:**
    - Utilize React Context API to manage global states such as selected API, model, and user settings across the Dashboard.
    - Optimize state updates using `useMemo` and `useCallback` to prevent unnecessary re-renders.
  - **Prop Passing:**
    - Ensure smooth and consistent prop passing between components, especially for settings and chat functionalities.

---

##### **11. State Management Optimization:**

- **Global State with Context:**
  - **Implementation:**
    - Create a `GlobalContext` using React Context API to store global states like `apiKey`, `selectedModel`, `settings`, and `chats`.
    - Provide context values to all components that require access to these states.

- **Memoization:**
  - **Implementation:**
    - Use `useMemo` to memoize expensive computations or derived data.
    - Use `useCallback` to memoize callback functions passed to child components to prevent unnecessary re-renders.

- **Efficient Prop Passing:**
  - **Review:**
    - Ensure that all necessary props are correctly passed to child components.
    - Avoid prop drilling by leveraging Context where appropriate.

---

##### **12. Responsive Design and Performance Optimization:**

- **Mobile Optimization:**
  - **Implementation:**
    - Use CSS media queries or a responsive CSS framework (e.g., Tailwind CSS) to ensure the Dashboard is mobile-friendly.
    - Implement collapsible sidebars and navigation menus for smaller screens.

- **Performance Enhancements:**
  - **Optimization:**
    - Optimize rendering of the `ChatView` and `WorkflowBuilder` components, especially when dealing with long lists.
    - Implement lazy loading or virtualization for chat messages and workflow tools to enhance performance.
    - Ensure efficient state updates to prevent performance bottlenecks.

---

##### **13. Testing and Quality Assurance:**

- **Unit Testing:**
  - **Implementation:**
    - Write unit tests for each key component (e.g., `ChatView`, `Settings`, `FileUploader`, `WorkflowBuilder`, `ToolingConfiguration`).
    - Use testing libraries like Jest and React Testing Library.

- **Integration Testing:**
  - **Implementation:**
    - Test interactions between components, especially between `Dashboard`, `Settings`, and `ChatView`.
    - Ensure that state changes in `Settings` correctly propagate to other components.

- **End-to-End Testing:**
  - **Implementation:**
    - Use tools like Cypress or Playwright to write end-to-end tests for critical user flows (e.g., sending a chat message, switching APIs, uploading files).

- **Cross-Browser Testing:**
  - **Implementation:**
    - Test the Dashboard across different browsers (Chrome, Firefox, Safari, Edge) to ensure consistent behavior and appearance.

- **Performance Testing:**
  - **Implementation:**
    - Use tools like Lighthouse to audit performance, accessibility, and best practices.
    - Optimize based on the audit results to ensure fast load times and smooth interactions.

---

##### **14. Documentation and Code Cleanup:**

- **Code Documentation:**
  - **Implementation:**
    - Add comprehensive JSDoc comments for all functions, components, and significant code blocks.
    - Explain parameters, return types, and functionality within the comments.

- **README Update:**
  - **Implementation:**
    - Create or update the `README.md` with clear setup and usage instructions.
    - Detail API configurations, model selections, and chat functionalities.
    - Include instructions for running tests and building the project.

- **Code Cleanup:**
  - **Implementation:**
    - Remove any unused imports, variables, or functions.
    - Ensure consistent code styling and adherence to best practices (e.g., using Prettier and ESLint).
    - Refactor repetitive code into reusable components or utility functions.

---

##### **15. Accessibility Improvements:**

- **ARIA Labels and Roles:**
  - **Implementation:**
    - Add appropriate ARIA labels and roles to interactive elements (buttons, forms, navigation items).

- **Keyboard Navigation:**
  - **Implementation:**
    - Ensure all interactive elements are reachable and operable via keyboard (e.g., using `tabIndex`).

- **Color Contrast:**
  - **Implementation:**
    - Ensure sufficient color contrast for all text and UI elements, adhering to WCAG guidelines.

- **Screen Reader Compatibility:**
  - **Implementation:**
    - Test the application with screen readers to ensure content is accessible and navigable.

---

##### **16. Security Considerations:**

- **API Key Management:**
  - **Implementation:**
    - Ensure that API keys (e.g., GROQ API key) are securely stored and not exposed in the frontend.
    - Use environment variables and server-side handling to protect sensitive information.

- **Input Validation:**
  - **Implementation:**
    - Validate all user inputs on both the client and server sides to prevent injection attacks.

- **Error Messaging:**
  - **Implementation:**
    - Avoid exposing sensitive information in error messages. Provide user-friendly messages without revealing internal details.

---

#### **Code Implementation Guidelines:**

To ensure consistency and completeness, follow these guidelines during implementation:

- **Component Structure:**
  - Organize components in the `src/components/` directory, each in its own folder with related files (e.g., `ChatView.jsx`, `ChatView.test.jsx`, `ChatView.module.css`).

- **Styling:**
  - Use **Tailwind CSS** for styling to ensure rapid development and responsiveness.
  - Implement dark mode support using Tailwind's dark variant.

- **State Management:**
  - Use **React Context API** for global state management.
  - Avoid prop drilling by leveraging Context where applicable.

- **API Interaction:**
  - Centralize API interactions within the `chatAPI.jsx` utility class.
  - Ensure all API routes are correctly implemented and secured.

- **Error Handling:**
  - Implement try-catch blocks around all asynchronous operations.
  - Use the `NotificationProvider` to display user-friendly error and success messages.

- **Performance Optimization:**
  - Implement lazy loading for heavy components.
  - Use React's `Suspense` and `lazy` for code-splitting.
  - Memoize components and functions using `React.memo`, `useMemo`, and `useCallback` to prevent unnecessary re-renders.

---

#### **Sample Code Snippets:**

Below are essential code snippets to guide your implementation. Ensure to adapt and expand these based on your specific requirements.

---

##### **1. `chatAPI.jsx`**

```jsx
// src/components/chatAPI.jsx

const OLLAMA_BASE_URL = 'http://localhost:11434/api';
const GROQ_BASE_URL = 'https://api.groq.com/openai/v1';

class ChatAPI {
    constructor() {
        this.apiKey = '';
        this.model = 'deepseek-coder-v2';
        this.systemPrompt = '';
        this.temperature = 0.7;
        this.maxTokens = 1024;
        this.topP = 1;
        this.topK = 40;
        this.stream = false;
        this.useGroq = false;
        this.retryAttempts = 3;
        this.retryDelay = 1000;
    }

    setApiKey(key) {
        if (typeof key !== 'string' || key.trim() === '') {
            throw new Error('Invalid API key');
        }
        this.apiKey = key.trim();
    }

    setModel(model) {
        if (typeof model !== 'string' || model.trim() === '') {
            throw new Error('Invalid model name');
        }
        this.model = model.trim();
    }

    setSystemPrompt(prompt) {
        if (typeof prompt !== 'string') {
            throw new Error('System prompt must be a string');
        }
        this.systemPrompt = prompt;
    }

    setTemperature(temp) {
        if (typeof temp !== 'number' || temp < 0 || temp > 1) {
            throw new Error('Temperature must be a number between 0 and 1');
        }
        this.temperature = temp;
    }

    setMaxTokens(tokens) {
        if (!Number.isInteger(tokens) || tokens <= 0) {
            throw new Error('Max tokens must be a positive integer');
        }
        this.maxTokens = tokens;
    }

    setTopP(value) {
        if (typeof value !== 'number' || value < 0 || value > 1) {
            throw new Error('Top P must be a number between 0 and 1');
        }
        this.topP = value;
    }

    setTopK(value) {
        if (!Number.isInteger(value) || value < 0) {
            throw new Error('Top K must be a non-negative integer');
        }
        this.topK = value;
    }

    setStream(value) {
        this.stream = Boolean(value);
    }

    setUseGroq(value) {
        this.useGroq = Boolean(value);
    }

    async sendMessage(messages) {
        if (!Array.isArray(messages) || messages.length === 0) {
            throw new Error('Messages must be a non-empty array');
        }

        if (this.systemPrompt && !messages.some(m => m.role === 'system')) {
            messages.unshift({ role: 'system', content: this.systemPrompt });
        }

        const url = this.useGroq ? `${GROQ_BASE_URL}/chat/completions` : `${OLLAMA_BASE_URL}/chat`;

        const headers = {
            'Content-Type': 'application/json',
        };

        if (this.useGroq) {
            if (!this.apiKey) {
                throw new Error('GROQ API key is required');
            }
            headers['Authorization'] = `Bearer ${this.apiKey}`;
        }

        const body = this.useGroq
            ? {
                model: this.model,
                messages: messages,
                temperature: this.temperature,
                max_tokens: this.maxTokens,
                top_p: this.topP,
                stream: this.stream,
            }
            : {
                model: this.model,
                messages: messages,
                stream: this.stream,
                options: {
                    temperature: this.temperature,
                    num_predict: this.maxTokens,
                    top_k: this.topK,
                    top_p: this.topP,
                },
            };

        for (let attempt = 0; attempt < this.retryAttempts; attempt++) {
            try {
                const response = await fetch(url, {
                    method: 'POST',
                    headers: headers,
                    body: JSON.stringify(body),
                });

                if (!response.ok) {
                    const errorData = await response.json().catch(() => ({}));
                    throw new Error(`API error (${response.status}): ${errorData.error || response.statusText}`);
                }

                if (this.stream) {
                    return this.handleStreamResponse(response);
                } else {
                    const data = await response.json();
                    return this.useGroq ? data.choices[0].message : data.message;
                }
            } catch (error) {
                if (attempt === this.retryAttempts - 1) {
                    throw error;
                }
                await new Promise(resolve => setTimeout(resolve, this.retryDelay));
            }
        }
    }

    async *handleStreamResponse(response) {
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (true) {
            const { done, value } = await reader.read();
            if (done) break;

            buffer += decoder.decode(value, { stream: true });
            const lines = buffer.split('\n');
            buffer = lines.pop();

            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    const data = JSON.parse(line.slice(6));
                    if (this.useGroq) {
                        yield data.choices[0].delta.content;
                    } else {
                        yield data.message.content;
                    }
                }
            }
        }
    }

    async createNewChat(name) {
        return {
            id: crypto.randomUUID(),
            name: name || `Chat ${new Date().toLocaleString()}`,
            messages: [],
            createdAt: Date.now(),
            updatedAt: Date.now(),
        };
    }

    async deleteChat(chatId) {
        // Implement actual deletion logic if needed
        console.log(`Deleting chat with ID: ${chatId}`);
        return { success: true, message: 'Chat deleted successfully' };
    }

    async clearChat(chatId) {
        // Implement actual clear logic if needed
        console.log(`Clearing chat with ID: ${chatId}`);
        return { success: true, message: 'Chat cleared successfully' };
    }

    async exportChats(chats) {
        const dataStr = JSON.stringify(chats, null, 2);
        const blob = new Blob([dataStr], { type: 'application/json' });
        return URL.createObjectURL(blob);
    }

    async importChats(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (event) => {
                try {
                    const chats = JSON.parse(event.target.result);
                    resolve(chats);
                } catch (error) {
                    reject(new Error('Invalid JSON file'));
                }
            };
            reader.onerror = () => reject(new Error('Error reading file'));
            reader.readAsText(file);
        });
    }
}

export const chatApi = new ChatAPI();
```

---

##### **2. API Routes:**

**a. GROQ Chat API Route (`/api/chat-groq/route.js`):**

```javascript
// src/app/api/chat-groq/route.js

import { NextResponse } from 'next/server';

export async function POST(req) {
    try {
        const { messages, model, temperature, max_tokens, top_p, stream } = await req.json();
        const authHeader = req.headers.get('Authorization') || '';
        const apiKeyMatch = authHeader.match(/^Bearer (.+)$/);
        const apiKey = apiKeyMatch ? apiKeyMatch[1] : '';

        if (!apiKey) {
            return NextResponse.json({ error: 'GROQ API key is missing' }, { status: 401 });
        }

        const response = await fetch('https://api.groq.com/openai/v1/chat/completions', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}`,
            },
            body: JSON.stringify({
                model,
                messages,
                temperature,
                max_tokens,
                top_p,
                stream,
            }),
        });

        if (!response.ok) {
            const errorData = await response.json();
            console.error('GROQ API error:', errorData);
            return NextResponse.json({ error: 'Error from GROQ API', details: errorData }, { status: response.status });
        }

        if (stream) {
            // Handle streaming response if necessary
            // For simplicity, we'll not handle streaming here
            return NextResponse.json({ error: 'Streaming not implemented in GROQ API route' }, { status: 501 });
        } else {
            const data = await response.json();
            return NextResponse.json(data);
        }
    } catch (error) {
        console.error('Error in chat-groq API route:', error);
        return NextResponse.json({ error: 'Internal server error', details: error.message }, { status: 500 });
    }
}
```

**b. Ollama Chat API Route (`/api/chat-ollama/route.js`):**

```javascript
// src/app/api/chat-ollama/route.js

import { NextResponse } from 'next/server';

export async function POST(req) {
    try {
        const { messages, model, system_prompt, temperature, max_tokens, top_p, top_k, stream } = await req.json();

        const response = await fetch('http://localhost:11434/api/chat', { // Adjust the URL if different
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                model,
                messages,
                system_prompt,
                temperature,
                max_tokens,
                top_p,
                top_k,
                stream,
            }),
        });

        if (!response.ok) {
            const errorData = await response.json();
            console.error('Ollama API error:', errorData);
            return NextResponse.json({ error: 'Error from Ollama API', details: errorData }, { status: response.status });
        }

        if (stream) {
            // Handle streaming response if necessary
            // For simplicity, we'll not handle streaming here
            return NextResponse.json({ error: 'Streaming not implemented in Ollama API route' }, { status: 501 });
        } else {
            const data = await response.json();
            return NextResponse.json(data);
        }
    } catch (error) {
        console.error('Error in chat-ollama API route:', error);
        return NextResponse.json({ error: 'Internal server error', details: error.message }, { status: 500 });
    }
}
```

**c. Ollama Models Fetching API Route (`/api/ollama-models/route.js`):**

```javascript
// src/app/api/ollama-models/route.js

import { NextResponse } from 'next/server';

export async function GET() {
    try {
        const response = await fetch('http://localhost:11434/api/tags');

        if (!response.ok) {
            throw new Error(`Failed to fetch models: ${response.statusText}`);
        }

        const data = await response.json();
        const models = data.models.map(model => model.name);
        return NextResponse.json({ models });
    } catch (error) {
        console.error('Error fetching models:', error);
        return NextResponse.json({ error: error.message }, { status: 500 });
    }
}
```

---

##### **3. `Dashboard.jsx`**

```jsx
// src/app/dashboardV7/page.jsx

'use client';

import React, { useState, useEffect, useRef } from 'react';
import {
    Triangle,
    Download,
    Upload,
    Settings2,
    Trash2,
    Sun,
    Moon,
    Send,
    Mic,
    Bot,
    CornerDownLeft,
    Paperclip,
    Plus,
    Loader2,
    ChevronRight,
    ChevronLeft,
    MessageSquare,
    Workflow,
    FileUp,
    Wrench,
} from 'lucide-react';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Drawer,
    DrawerContent,
    DrawerDescription,
    DrawerHeader,
    DrawerTitle,
    DrawerTrigger,
} from '@/components/ui/drawer';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import ReactMarkdown from 'react-markdown';
import { Textarea } from '@/components/ui/textarea';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { Switch } from '@/components/ui/switch';
import { Slider } from '@/components/ui/slider';
import { cn } from "@/lib/utils";

// Import new components
import ChatView from '@/components/ChatView';
import WorkflowBuilder from '@/components/WorkflowBuilder';
import FileUploader from '@/components/FileUploader';
import ToolingConfiguration from '@/components/ToolingConfiguration';
import NotificationProvider, { useNotification } from '@/components/ui/NotificationProvider';
import Settings from '@/components/Settings';
import TopNavigation from '@/components/TopNavigation';
import SideNavigation from '@/components/SideNavigation';
import { chatApi } from '@/components/chatApi';

const initialState = {
    chats: [],
    currentChatId: null,
    apiKey: '',
    settings: {
        api: 'ollama',
        model: 'deepseek-coder-v2',
        temperature: 0.7,
        maxTokens: 1024,
        topP: 1,
        topK: 0,
        stream: false,
        darkMode: false,
        useGroq: false,
    },
    systemPrompt: '',
};

const STORAGE_KEY = 'quantumNexusState';

const loadState = () => {
    if (typeof window === 'undefined') return initialState;
    const saved = localStorage.getItem(STORAGE_KEY);
    return saved ? JSON.parse(saved) : initialState;
};

const saveState = (state) => {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
};

export default function Dashboard() {
    const addNotification = useNotification();
    const [state, setState] = useState(loadState);
    const [input, setInput] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [isSpeaking, setIsSpeaking] = useState(false);
    const [currentView, setCurrentView] = useState('chat');
    const [isChatCollapsed, setIsChatCollapsed] = useState(false);
    const [isSidebarExpanded, setIsSidebarExpanded] = useState(true);

    const chatContainerRef = useRef(null);
    const speechSynthesisInstance = typeof window !== 'undefined' ? window.speechSynthesis : null;
    const SpeechRecognition =
        typeof window !== 'undefined'
            ? window.SpeechRecognition || window.webkitSpeechRecognition
            : null;
    const recognition = SpeechRecognition ? new SpeechRecognition() : null;

    const [availableModels, setAvailableModels] = useState({
        ollama: ['deepseek-coder-v2'],
        groq: [
            {
                label: 'llama-3.1-70b-versatile',
                value: 'llama-3.1-70b-versatile',
            },
        ],
    });

    useEffect(() => {
        fetchOllamaModels();
    }, []);

    useEffect(() => {
        saveState(state);
        if (state.settings.darkMode) {
            document.documentElement.classList.add('dark');
        } else {
            document.documentElement.classList.remove('dark');
        }
    }, [state]);

    useEffect(() => {
        if (chatContainerRef.current) {
            chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;
        }
    }, [state.currentChatId, state.chats]);

    const fetchOllamaModels = async () => {
        try {
            const response = await fetch('/api/ollama-models');
            const data = await response.json();
            if (!response.ok) {
                throw new Error(data.error || 'Failed to fetch models');
            }
            const formattedModels = data.models.map((model) => ({
                label: model,
                value: model,
            }));
            setAvailableModels((prev) => ({ ...prev, ollama: formattedModels }));
        } catch (error) {
            console.error('Error fetching Ollama models:', error);
            addNotification('Failed to fetch Ollama models', 'error');
        }
    };

    const currentChat = state.chats.find((chat) => chat.id === state.currentChatId) || null;

    const handleSubmit = async (e) => {
        e.preventDefault();
        if (!input.trim() || !currentChat) return;

        const newMessage = {
            id: Date.now().toString(),
            role: 'user',
            content: input,
            timestamp: Date.now(),
        };
        const updatedMessages = [...currentChat.messages, newMessage];

        setState((prev) => ({
            ...prev,
            chats: prev.chats.map((chat) =>
                chat.id === currentChat.id
                    ? { ...chat, messages: updatedMessages, updatedAt: Date.now() }
                    : chat
            ),
        }));
        setInput('');
        setIsLoading(true);

        try {
            let response;
            if (state.settings.api === 'groq') {
                if (!state.apiKey) {
                    throw new Error('GROQ API key is not set');
                }
                response = await fetch('/api/chat-groq', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${state.apiKey}`,
                    },
                    body: JSON.stringify({
                        messages: updatedMessages,
                        model: state.settings.model,
                        temperature: state.settings.temperature,
                        max_tokens: state.settings.maxTokens,
                        top_p: state.settings.topP,
                        stream: state.settings.stream,
                    }),
                });

                if (!response.ok) {
                    const errorData = await response.json();
                    console.error('Error from GROQ API:', errorData);
                    throw new Error(`GROQ API error: ${errorData.error || 'Unknown error'}`);
                }
            } else if (state.settings.api === 'ollama') {
                response = await fetch('/api/chat-ollama', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        messages: updatedMessages,
                        model: state.settings.model,
                        system_prompt: state.systemPrompt,
                        temperature: state.settings.temperature,
                        max_tokens: state.settings.maxTokens,
                        top_p: state.settings.topP,
                        top_k: state.settings.topK,
                        stream: state.settings.stream
                    })
                });
            } else {
                throw new Error('Invalid API selected');
            }

            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(errorData.error || `HTTP error! status: ${response.status}`);
            }

            if (state.settings.stream) {
                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                let botMessage = '';

                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;
                    botMessage += decoder.decode(value, { stream: true });
                    setState((prev) => ({
                        ...prev,
                        chats: prev.chats.map((chat) =>
                            chat.id === currentChat.id
                                ? {
                                    ...chat,
                                    messages: [
                                        ...updatedMessages,
                                        {
                                            id: 'assistant-' + Date.now().toString(),
                                            role: 'assistant',
                                            content: botMessage,
                                            timestamp: Date.now(),
                                        },
                                    ],
                                    updatedAt: Date.now(),
                                }
                                : chat
                        ),
                    }));
                }
            } else {
                const data = await response.json();
                const assistantMessage = state.settings.api === 'groq' ? data.choices[0].message.content : data.message.content;
                setState((prev) => ({
                    ...prev,
                    chats: prev.chats.map((chat) =>
                        chat.id === currentChat.id
                            ? {
                                ...chat,
                                messages: [
                                    ...updatedMessages,
                                    {
                                        id: 'assistant-' + Date.now().toString(),
                                        role: 'assistant',
                                        content: assistantMessage,
                                        timestamp: Date.now(),
                                    },
                                ],
                                updatedAt: Date.now(),
                            }
                            : chat
                    ),
                }));
            }
        } catch (error) {
            console.error('Error calling API:', error);
            addNotification(`Error communicating with the chatbot: ${error.message}`, 'error');
        } finally {
            setIsLoading(false);
        }
    };

    const createNewChat = async () => {
        try {
            const newChat = await chatApi.createNewChat(`New Chat ${state.chats.length + 1}`);
            setState((prev) => ({
                ...prev,
                chats: [...prev.chats, newChat],
                currentChatId: newChat.id,
            }));
            addNotification(`New chat "${newChat.name}" created!`, 'success');
        } catch (error) {
            console.error('Error creating new chat:', error);
            addNotification('Failed to create a new chat.', 'error');
        }
    };

    const loadSelectedChat = (chatId) => {
        setState((prev) => ({
            ...prev,
            currentChatId: chatId,
        }));
    };

    const deleteChat = async (chatId) => {
        try {
            const result = await chatApi.deleteChat(chatId);
            if (result.success) {
                setState((prev) => ({
                    ...prev,
                    chats: prev.chats.filter((chat) => chat.id !== chatId),
                    currentChatId: prev.currentChatId === chatId ? null : prev.currentChatId,
                }));
                addNotification(result.message, 'success');
            } else {
                throw new Error(result.message);
            }
        } catch (error) {
            console.error('Error deleting chat:', error);
            addNotification('Failed to delete chat.', 'error');
        }
    };

    const clearChat = async () => {
        if (currentChat) {
            try {
                const result = await chatApi.clearChat(currentChat.id);
                if (result.success) {
                    setState((prev) => ({
                        ...prev,
                        chats: prev.chats.map((chat) =>
                            chat.id === currentChat.id ? { ...chat, messages: [], updatedAt: Date.now() } : chat
                        ),
                    }));
                    addNotification(result.message, 'success');
                } else {
                    throw new Error(result.message);
                }
            } catch (error) {
                console.error('Error clearing chat:', error);
                addNotification('Failed to clear chat.', 'error');
            }
        }
    };

    const exportChats = async () => {
        try {
            const dataUri = await chatApi.exportChats(state.chats);
            const exportFileDefaultName = 'quantum_nexus_chats.json';
            const linkElement = document.createElement('a');
            linkElement.setAttribute('href', dataUri);
            linkElement.setAttribute('download', exportFileDefaultName);
            document.body.appendChild(linkElement);
            linkElement.click();
            document.body.removeChild(linkElement);
            URL.revokeObjectURL(dataUri);
            addNotification('Chats exported successfully!', 'success');
        } catch (error) {
            console.error('Error exporting chats:', error);
            addNotification('Failed to export chats.', 'error');
        }
    };

    const importChats = async (event) => {
        const file = event.target.files && event.target.files[0];
        if (file) {
            try {
                const importedChats = await chatApi.importChats(file);
                setState((prev) => ({
                    ...prev,
                    chats: [...prev.chats, ...importedChats],
                }));
                addNotification('Chats imported successfully!', 'success');
            } catch (error) {
                console.error('Error importing chats:', error);
                addNotification('Failed to import chats. Please check the file format.', 'error');
            }
        }
    };

    const saveApiKey = (key) => {
        setState((prev) => ({ ...prev, apiKey: key }));
        addNotification('API Key saved successfully!', 'success');
    };

    const setSystemPrompt = (prompt) => {
        setState((prev) => ({ ...prev, systemPrompt: prompt }));
        addNotification('System prompt set successfully!', 'success');
    };

    const resetSettings = () => {
        setState((prev) => ({
            ...prev,
            settings: initialState.settings,
        }));
        addNotification('Settings reset to default values!', 'success');
    };

    const downloadChatTranscript = () => {
        if (!currentChat) return;
        try {
            const transcript = currentChat.messages.map((m) => `${m.role}: ${m.content}`).join('\n\n');
            const blob = new Blob([transcript], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `${currentChat.name}_transcript.txt`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            addNotification('Chat transcript downloaded successfully!', 'success');
        } catch (error) {
            console.error('Error downloading transcript:', error);
            addNotification('Failed to download transcript.', 'error');
        }
    };

    const toggleDarkMode = () => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, darkMode: !prev.settings.darkMode },
        }));
    };

    const startVoiceInput = () => {
        if (recognition) {
            recognition.onresult = (event) => {
                const transcript = event.results[0][0].transcript;
                setInput(transcript);
            };
            recognition.start();
            addNotification('Listening...', 'info');
        } else {
            addNotification('Speech recognition not supported in this browser.', 'error');
        }
    };

    const speakMessage = (message) => {
        if (speechSynthesisInstance) {
            if (isSpeaking) {
                speechSynthesisInstance.cancel();
                setIsSpeaking(false);
            } else {
                const utterance = new SpeechSynthesisUtterance(message);
                utterance.onend = () => setIsSpeaking(false);
                speechSynthesisInstance.speak(utterance);
                setIsSpeaking(true);
            }
        } else {
            addNotification('Text-to-speech not supported in this browser.', 'error');
        }
    };

    const toggleChatCollapse = () => {
        setIsChatCollapsed(!isChatCollapsed);
    };

    const toggleSidebar = () => {
        setIsSidebarExpanded(!isSidebarExpanded);
    };

    const renderCurrentView = () => {
        switch (currentView) {
            case 'chat':
                return (
                    <div className={`transition-all duration-300 ${isChatCollapsed ? 'h-16' : 'h-full'}`}>
                        <div className="flex justify-between items-center mb-4">
                            <h2 className="text-2xl font-bold text-primary">Chat</h2>
                            <Button onClick={toggleChatCollapse} variant="ghost" size="sm">
                                {isChatCollapsed ? <ChevronRight /> : <ChevronLeft />}
                            </Button>
                        </div>
                        {!isChatCollapsed && (
                            <ChatView
                                state={state}
                                setState={setState}
                                input={input}
                                setInput={setInput}
                                isLoading={isLoading}
                                handleSubmit={handleSubmit}
                                startVoiceInput={startVoiceInput}
                                speakMessage={speakMessage}
                                downloadChatTranscript={downloadChatTranscript}
                                clearChat={clearChat}
                            />
                        )}
                    </div>
                );
            case 'workflow':
                return <WorkflowBuilder />;
            case 'fileUpload':
                return <FileUploader />;
            case 'tooling':
                return <ToolingConfiguration
                    state={state}
                    setState={setState}
                    saveApiKey={saveApiKey}
                    setSystemPrompt={setSystemPrompt}
                    resetSettings={resetSettings}
                />;
            default:
                return null;
        }
    };

    return (
        <NotificationProvider>
            <div className={`flex h-screen w-full bg-gradient-to-br from-purple-100 to-indigo-200 dark:from-purple-900 dark:to-indigo-950 transition-colors duration-300 ${state.settings.darkMode ? 'dark' : ''}`}>
                {/* Top Navigation */}
                <TopNavigation />

                {/* Collapsible Sidebar */}
                <SideNavigation
                    isSidebarExpanded={isSidebarExpanded}
                    toggleSidebar={toggleSidebar}
                    currentView={currentView}
                    setCurrentView={setCurrentView}
                    availableModels={availableModels}
                    state={state}
                    setState={setState}
                    saveApiKey={saveApiKey}
                    setSystemPrompt={setSystemPrompt}
                    resetSettings={resetSettings}
                />

                {/* Main Content */}
                <main className="flex-1 flex flex-col overflow-hidden bg-white dark:bg-gray-900 transition-colors duration-300">
                    {/* Header */}
                    <header className="bg-white dark:bg-gray-800 p-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center shadow-sm">
                        <h2 className="text-xl font-semibold bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text text-transparent">
                            {currentView === 'chat' ? (currentChat?.name || 'Select a chat') : getHeaderTitle(currentView)}
                        </h2>
                        <div className="space-x-2">
                            {currentView === 'chat' && (
                                <>
                                    <Button variant="outline" size="sm" onClick={exportChats} className="transition-all duration-200 hover:bg-purple-100 dark:hover:bg-purple-900">
                                        <Download className="mr-2 h-4 w-4" /> Export Chats
                                    </Button>
                                    <label htmlFor="import-chats-main">
                                        <Button variant="outline" size="sm" as="span" className="transition-all duration-200 hover:bg-indigo-100 dark:hover:bg-indigo-900">
                                            <Upload className="mr-2 h-4 w-4" /> Import Chats
                                        </Button>
                                    </label>
                                    <input
                                        id="import-chats-main"
                                        type="file"
                                        accept=".json"
                                        onChange={importChats}
                                        className="hidden"
                                    />
                                    {currentChat && (
                                        <>
                                            <Button variant="outline" size="sm" onClick={clearChat} className="transition-all duration-200 hover:bg-red-100 dark:hover:bg-red-900">
                                                <Trash2 className="mr-2 h-4 w-4 text-red-500" /> Clear Chat
                                            </Button>
                                            <Button variant="outline" size="sm" onClick={downloadChatTranscript} className="transition-all duration-200 hover:bg-blue-100 dark:hover:bg-blue-900">
                                                <Download className="mr-2 h-4 w-4" /> Download Transcript
                                            </Button>
                                        </>
                                    )}
                                </>
                            )}
                        </div>
                    </header>

                    {/* Main View */}
                    <ScrollArea className="flex-1 p-4 overflow-x-hidden">
                        {renderCurrentView()}
                    </ScrollArea>

                    {/* Input Form (Only in Chat View) */}
                    {currentView === 'chat' && !isChatCollapsed && (
                        <form onSubmit={handleSubmit} className="p-4 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 flex-shrink-0 shadow-lg">
                            <div className="flex space-x-2">
                                <Input
                                    value={input}
                                    onChange={(e) => setInput(e.target.value)}
                                    placeholder="Type your message..."
                                    className="flex-1 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 focus:ring-purple-500 focus:border-purple-500 transition-all duration-200"
                                />
                                <TooltipProvider>
                                    <Tooltip>
                                        <TooltipTrigger asChild>
                                            <Button type="submit" disabled={isLoading} className="bg-gradient-to-r from-purple-600 to-indigo-600 text-white hover:from-purple-700 hover:to-indigo-700 transition-all duration-200">
                                                {isLoading ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : <Send className="h-4 w-4 mr-1" />}
                                                Send
                                            </Button>
                                        </TooltipTrigger>
                                        <TooltipContent>Send message</TooltipContent>
                                    </Tooltip>
                                    <Tooltip>
                                        <TooltipTrigger asChild>
                                            <Button type="button" onClick={startVoiceInput} disabled={isLoading} className="bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 transition-all duration-200">
                                                <Mic className="h-4 w-4" />
                                            </Button>
                                        </TooltipTrigger>
                                        <TooltipContent>Start voice input</TooltipContent>
                                    </Tooltip>
                                </TooltipProvider>
                            </div>
                        </form>
                    )}
                </main>
            </div>
        </NotificationProvider>
    );

    // Helper function to get header title based on view
    function getHeaderTitle(view) {
        switch (view) {
            case 'workflow':
                return 'Agent Workflow Builder';
            case 'fileUpload':
                return 'File Uploader';
            case 'tooling':
                return 'Tooling & Configuration';
            default:
                return 'Quantum Nexus';
        }
    }
}
```

---

##### **4. `Settings.jsx`**

```jsx
// src/components/Settings.jsx

'use client';

import React, { useState, useEffect } from 'react';
import {
    Drawer,
    DrawerContent,
    DrawerDescription,
    DrawerHeader,
    DrawerTitle,
    DrawerTrigger,
} from '@/components/ui/drawer';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Button } from '@/components/ui/button';
import { Settings2, Sun, Moon } from 'lucide-react';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Slider } from '@/components/ui/slider';
import { Switch } from '@/components/ui/switch';
import PropTypes from 'prop-types';

export default function Settings({
    state,
    setState,
    saveApiKey,
    setSystemPrompt,
    resetSettings,
    toggleDarkMode,
    availableModels,
}) {
    const handleApiChange = (value) => {
        const useGroq = value === 'groq';
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, api: value, useGroq },
        }));
    };

    const handleModelChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, model: value },
        }));
    };

    const handleTemperatureChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, temperature: value[0] },
        }));
    };

    const handleMaxTokensChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, maxTokens: value[0] },
        }));
    };

    const handleTopPChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, topP: value[0] },
        }));
    };

    const handleTopKChange = (value) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, topK: value[0] },
        }));
    };

    const handleStreamChange = (checked) => {
        setState((prev) => ({
            ...prev,
            settings: { ...prev.settings, stream: checked },
        }));
    };

    return (
        <div className="space-y-4">
            {/* API Selection */}
            <div>
                <Label htmlFor="api-selection" className="text-sm font-medium">Select API</Label>
                <Select
                    value={state.settings.api}
                    onValueChange={handleApiChange}
                >
                    <SelectTrigger id="api-selection" className="w-full">
                        <SelectValue placeholder="Select an API" />
                    </SelectTrigger>
                    <SelectContent>
                        <SelectItem value="ollama">Ollama</SelectItem>
                        <SelectItem value="groq">GROQ</SelectItem>
                    </SelectContent>
                </Select>
            </div>

            {/* GROQ API Key Input */}
            {state.settings.useGroq && (
                <div>
                    <Label htmlFor="api-key" className="text-sm font-medium">API Key (for GROQ)</Label>
                    <Input
                        id="api-key"
                        type="password"
                        value={state.apiKey}
                        onChange={(e) => saveApiKey(e.target.value)}
                        placeholder="Enter your GROQ API key"
                        className="w-full mt-1"
                    />
                </div>
            )}

            {/* Model Selection */}
            <div>
                <Label htmlFor="model" className="text-sm font-medium">Model</Label>
                <Select
                    value={state.settings.model}
                    onValueChange={handleModelChange}
                >
                    <SelectTrigger id="model" className="w-full">
                        <SelectValue placeholder="Select a model" />
                    </SelectTrigger>
                    <SelectContent>
                        {availableModels[state.settings.api]?.map((model) => (
                            <SelectItem key={model.value} value={model.value}>
                                {model.label}
                            </SelectItem>
                        )) || <SelectItem disabled>No models available</SelectItem>}
                    </SelectContent>
                </Select>
            </div>

            {/* Temperature Slider */}
            <div>
                <Label htmlFor="temperature" className="text-sm font-medium">Temperature: {state.settings.temperature}</Label>
                <Slider
                    id="temperature"
                    min={0}
                    max={1}
                    step={0.1}
                    value={[state.settings.temperature]}
                    onValueChange={handleTemperatureChange}
                    className="mt-2"
                />
            </div>

            {/* Max Tokens Slider */}
            <div>
                <Label htmlFor="max-tokens" className="text-sm font-medium">Max Tokens: {state.settings.maxTokens}</Label>
                <Slider
                    id="max-tokens"
                    min={1}
                    max={2048}
                    step={1}
                    value={[state.settings.maxTokens]}
                    onValueChange={handleMaxTokensChange}
                    className="mt-2"
                />
            </div>

            {/* Top P Slider */}
            <div>
                <Label htmlFor="top-p" className="text-sm font-medium">Top P: {state.settings.topP}</Label>
                <Slider
                    id="top-p"
                    min={0}
                    max={1}
                    step={0.1}
                    value={[state.settings.topP]}
                    onValueChange={handleTopPChange}
                    className="mt-2"
                />
            </div>

            {/* Top K Slider */}
            <div>
                <Label htmlFor="top-k" className="text-sm font-medium">Top K: {state.settings.topK}</Label>
                <Slider
                    id="top-k"
                    min={0}
                    max={100}
                    step={1}
                    value={[state.settings.topK]}
                    onValueChange={handleTopKChange}
                    className="mt-2"
                />
            </div>

            {/* Stream Responses Switch */}
            <div className="flex items-center space-x-2">
                <Switch
                    id="stream"
                    checked={state.settings.stream}
                    onCheckedChange={handleStreamChange}
                />
                <Label htmlFor="stream" className="text-sm font-medium">Stream responses</Label>
            </div>

            {/* System Prompt Textarea */}
            <div>
                <Label htmlFor="system-prompt" className="text-sm font-medium">System Prompt</Label>
                <Textarea
                    id="system-prompt"
                    placeholder="Enter system prompt"
                    value={state.systemPrompt}
                    onChange={(e) => setSystemPrompt(e.target.value)}
                    className="mt-1 w-full"
                />
            </div>

            {/* Dark Mode Toggle */}
            <div className="flex items-center space-x-2">
                <Button variant="outline" onClick={toggleDarkMode} className="w-full">
                    {state.settings.darkMode ? <Sun className="mr-2 h-4 w-4" /> : <Moon className="mr-2 h-4 w-4" />}
                    {state.settings.darkMode ? 'Light Mode' : 'Dark Mode'}
                </Button>
            </div>

            {/* Reset Settings Button */}
            <div>
                <Button onClick={resetSettings} className="w-full">Reset to Defaults</Button>
            </div>
        </div>
    );

    Settings.propTypes = {
        state: PropTypes.object.isRequired,
        setState: PropTypes.func.isRequired,
        saveApiKey: PropTypes.func.isRequired,
        setSystemPrompt: PropTypes.func.isRequired,
        resetSettings: PropTypes.func.isRequired,
        toggleDarkMode: PropTypes.func.isRequired,
        availableModels: PropTypes.object.isRequired,
    };
}
```

---

##### **5. `TopNavigation.jsx`**

```jsx
// src/components/TopNavigation.jsx

'use client';

import React from 'react';
import { Sun, Moon, Settings2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import PropTypes from 'prop-types';

export default function TopNavigation({ toggleDarkMode, toggleSettings }) {
    return (
        <div className="w-full bg-white dark:bg-gray-800 p-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center shadow-sm">
            <h1 className="text-2xl font-bold bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text text-transparent">Quantum Nexus</h1>
            <div className="flex space-x-2">
                <TooltipProvider>
                    <Tooltip>
                        <TooltipTrigger asChild>
                            <Button variant="ghost" onClick={toggleDarkMode} aria-label="Toggle Dark Mode">
                                <Sun className="h-5 w-5" />
                            </Button>
                        </TooltipTrigger>
                        <TooltipContent>Toggle Dark Mode</TooltipContent>
                    </Tooltip>
                    <Tooltip>
                        <TooltipTrigger asChild>
                            <Button variant="ghost" onClick={toggleSettings} aria-label="Open Settings">
                                <Settings2 className="h-5 w-5" />
                            </Button>
                        </TooltipTrigger>
                        <TooltipContent>Settings</TooltipContent>
                    </Tooltip>
                </TooltipProvider>
            </div>
        </div>
    );
}

TopNavigation.propTypes = {
    toggleDarkMode: PropTypes.func.isRequired,
    toggleSettings: PropTypes.func.isRequired,
};
```

---

##### **6. `SideNavigation.jsx`**

```jsx
// src/components/SideNavigation.jsx

'use client';

import React from 'react';
import {
    MessageSquare,
    Workflow,
    FileUp,
    Wrench,
    ChevronLeft,
    ChevronRight,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import PropTypes from 'prop-types';

const navigationItems = [
    { id: 'chat', label: 'Chat', icon: <MessageSquare className="h-5 w-5 mr-2" /> },
    { id: 'workflow', label: 'Workflow', icon: <Workflow className="h-5 w-5 mr-2" /> },
    { id: 'fileUpload', label: 'File Upload', icon: <FileUp className="h-5 w-5 mr-2" /> },
    { id: 'tooling', label: 'Tooling', icon: <Wrench className="h-5 w-5 mr-2" /> },
];

export default function SideNavigation({
    isSidebarExpanded,
    toggleSidebar,
    currentView,
    setCurrentView,
    availableModels,
    state,
    setState,
    saveApiKey,
    setSystemPrompt,
    resetSettings,
}) {
    return (
        <aside className={`transition-all duration-300 ease-in-out ${isSidebarExpanded ? 'w-64' : 'w-16'} bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 flex flex-col shadow-lg`}>
            <div className="p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
                {isSidebarExpanded && (
                    <h1 className="text-2xl font-bold bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text text-transparent">Quantum Nexus</h1>
                )}
                <Button variant="ghost" size="sm" onClick={toggleSidebar}>
                    {isSidebarExpanded ? <ChevronLeft /> : <ChevronRight />}
                </Button>
            </div>
            <div className="flex-1 p-4">
                <nav className="space-y-2">
                    <TooltipProvider>
                        {navigationItems.map(item => (
                            <Tooltip key={item.id}>
                                <TooltipTrigger asChild>
                                    <Button
                                        variant="ghost"
                                        size={isSidebarExpanded ? "default" : "icon"}
                                        onClick={() => setCurrentView(item.id)}
                                        className={`w-full justify-start ${currentView === item.id ? 'bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-300' : ''}`}
                                    >
                                        {item.icon}
                                        {isSidebarExpanded && item.label}
                                    </Button>
                                </TooltipTrigger>
                                <TooltipContent side="right">{item.label}</TooltipContent>
                            </Tooltip>
                        ))}
                    </TooltipProvider>
                </nav>
            </div>
            <div className="p-4 border-t border-gray-200 dark:border-gray-700">
                {/* Additional Sidebar Content if needed */}
            </div>
        </aside>
    );
}

SideNavigation.propTypes = {
    isSidebarExpanded: PropTypes.bool.isRequired,
    toggleSidebar: PropTypes.func.isRequired,
    currentView: PropTypes.string.isRequired,
    setCurrentView: PropTypes.func.isRequired,
    availableModels: PropTypes.object.isRequired,
    state: PropTypes.object.isRequired,
    setState: PropTypes.func.isRequired,
    saveApiKey: PropTypes.func.isRequired,
    setSystemPrompt: PropTypes.func.isRequired,
    resetSettings: PropTypes.func.isRequired,
};
```

---

##### **7. `NotificationProvider.jsx`**

```jsx
// src/components/ui/NotificationProvider.jsx

'use client';

import React, { createContext, useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { Toast, ToastContainer, ToastDescription, ToastTitle } from '@/components/ui/toast';
import { X } from 'lucide-react';
import { Button } from '@/components/ui/button';

const NotificationContext = createContext();

export function NotificationProvider({ children }) {
    const [notifications, setNotifications] = useState([]);

    const addNotification = (message, type = 'info') => {
        const id = Date.now();
        setNotifications(prev => [...prev, { id, message, type }]);
    };

    const removeNotification = (id) => {
        setNotifications(prev => prev.filter(notif => notif.id !== id));
    };

    return (
        <NotificationContext.Provider value={addNotification}>
            {children}
            <ToastContainer className="fixed bottom-4 right-4 space-y-2">
                {notifications.map(notif => (
                    <Toast key={notif.id} onOpenChange={() => removeNotification(notif.id)}>
                        <div className="flex flex-col">
                            <ToastTitle>{notif.type.charAt(0).toUpperCase() + notif.type.slice(1)}</ToastTitle>
                            <ToastDescription>{notif.message}</ToastDescription>
                        </div>
                        <Button variant="ghost" size="icon" onClick={() => removeNotification(notif.id)}>
                            <X className="h-4 w-4" />
                        </Button>
                    </Toast>
                ))}
            </ToastContainer>
        </NotificationContext.Provider>
    );
}

NotificationProvider.propTypes = {
    children: PropTypes.node.isRequired,
};

export const useNotification = () => {
    return useContext(NotificationContext);
};
```

---

##### **8. `ChatView.jsx`**

```jsx
// src/components/ChatView.jsx

'use client';

import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import ReactMarkdown from 'react-markdown';
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from '@/components/ui/button';
import { Loader2 } from 'lucide-react';

export default function ChatView({
    state,
    setState,
    input,
    setInput,
    isLoading,
    handleSubmit,
    startVoiceInput,
    speakMessage,
    downloadChatTranscript,
    clearChat,
}) {
    const chatEndRef = useRef(null);

    useEffect(() => {
        if (chatEndRef.current) {
            chatEndRef.current.scrollIntoView({ behavior: 'smooth' });
        }
    }, [state.chats]);

    const currentChat = state.chats.find(chat => chat.id === state.currentChatId);

    return (
        <div className="flex flex-col h-full">
            <div className="flex-1 overflow-y-auto">
                {currentChat?.messages.map(message => (
                    <div key={message.id} className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'} mb-4`}>
                        {message.role === 'assistant' && (
                            <Avatar className="mr-2">
                                <AvatarImage src="/bot-avatar.png" alt="Bot Avatar" />
                                <AvatarFallback>Bot</AvatarFallback>
                            </Avatar>
                        )}
                        <div className={`max-w-md p-2 rounded-lg ${message.role === 'user' ? 'bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-200' : 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-200'}`}>
                            <ReactMarkdown>{message.content}</ReactMarkdown>
                        </div>
                        {message.role === 'user' && (
                            <Avatar className="ml-2">
                                <AvatarImage src="/user-avatar.png" alt="User Avatar" />
                                <AvatarFallback>User</AvatarFallback>
                            </Avatar>
                        )}
                    </div>
                ))}
                <div ref={chatEndRef} />
            </div>
            {isLoading && (
                <div className="flex justify-center p-2">
                    <Loader2 className="h-5 w-5 animate-spin text-purple-500" />
                </div>
            )}
        </div>
    );
}

ChatView.propTypes = {
    state: PropTypes.object.isRequired,
    setState: PropTypes.func.isRequired,
    input: PropTypes.string.isRequired,
    setInput: PropTypes.func.isRequired,
    isLoading: PropTypes.bool.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    startVoiceInput: PropTypes.func.isRequired,
    speakMessage: PropTypes.func.isRequired,
    downloadChatTranscript: PropTypes.func.isRequired,
    clearChat: PropTypes.func.isRequired,
};
```

---

##### **9. `WorkflowBuilder.jsx`**

```jsx
// src/components/WorkflowBuilder.jsx

'use client';

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { Button, Input, Textarea } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { useNotification } from '@/components/ui/NotificationProvider';

export default function WorkflowBuilder() {
    const addNotification = useNotification();
    const [workflow, setWorkflow] = useState([
        { id: '1', name: 'Tool 1', description: 'Description for Tool 1' },
        { id: '2', name: 'Tool 2', description: 'Description for Tool 2' },
    ]);

    const handleDragEnd = (result) => {
        if (!result.destination) return;
        const reordered = Array.from(workflow);
        const [moved] = reordered.splice(result.source.index, 1);
        reordered.splice(result.destination.index, 0, moved);
        setWorkflow(reordered);
    };

    const addTool = () => {
        const newTool = { id: Date.now().toString(), name: `Tool ${workflow.length + 1}`, description: `Description for Tool ${workflow.length + 1}` };
        setWorkflow([...workflow, newTool]);
        addNotification('New tool added to workflow!', 'success');
    };

    const removeTool = (id) => {
        setWorkflow(workflow.filter(tool => tool.id !== id));
        addNotification('Tool removed from workflow.', 'info');
    };

    const saveWorkflow = () => {
        // Implement save logic (e.g., API call)
        addNotification('Workflow saved successfully!', 'success');
    };

    return (
        <div>
            <div className="flex justify-between items-center mb-4">
                <h2 className="text-2xl font-bold text-indigo-600">Workflow Builder</h2>
                <Button onClick={addTool}>Add Tool</Button>
            </div>
            <DragDropContext onDragEnd={handleDragEnd}>
                <Droppable droppableId="workflow">
                    {(provided) => (
                        <div
                            {...provided.droppableProps}
                            ref={provided.innerRef}
                            className="space-y-2"
                        >
                            {workflow.map((tool, index) => (
                                <Draggable key={tool.id} draggableId={tool.id} index={index}>
                                    {(provided) => (
                                        <div
                                            ref={provided.innerRef}
                                            {...provided.draggableProps}
                                            {...provided.dragHandleProps}
                                            className="flex items-center justify-between p-4 bg-gray-100 dark:bg-gray-700 rounded-lg"
                                        >
                                            <div>
                                                <Label className="block text-sm font-medium">Name</Label>
                                                <Input value={tool.name} readOnly className="mt-1" />
                                                <Label className="block text-sm font-medium mt-2">Description</Label>
                                                <Textarea value={tool.description} readOnly className="mt-1" />
                                            </div>
                                            <Button variant="ghost" onClick={() => removeTool(tool.id)}>Remove</Button>
                                        </div>
                                    )}
                                </Draggable>
                            ))}
                            {provided.placeholder}
                        </div>
                    )}
                </Droppable>
            </DragDropContext>
            <Button onClick={saveWorkflow} className="mt-4">Save Workflow</Button>
        </div>
    );
}

WorkflowBuilder.propTypes = {
    // Define prop types if needed
};
```

---

##### **10. `FileUploader.jsx`**

```jsx
// src/components/FileUploader.jsx

'use client';

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { useNotification } from '@/components/ui/NotificationProvider';

export default function FileUploader() {
    const addNotification = useNotification();
    const [files, setFiles] = useState([]);
    const [uploading, setUploading] = useState(false);

    const handleFileChange = (e) => {
        const selectedFiles = Array.from(e.target.files);
        setFiles(selectedFiles);
    };

    const uploadFiles = async () => {
        setUploading(true);
        try {
            // Implement actual upload logic (e.g., API call)
            // For demonstration, we'll simulate upload with a timeout
            await new Promise(resolve => setTimeout(resolve, 2000));
            addNotification('Files uploaded successfully!', 'success');
            setFiles([]);
        } catch (error) {
            console.error('Error uploading files:', error);
            addNotification('Failed to upload files.', 'error');
        } finally {
            setUploading(false);
        }
    };

    const removeFile = (index) => {
        const updatedFiles = [...files];
        updatedFiles.splice(index, 1);
        setFiles(updatedFiles);
    };

    return (
        <div>
            <h2 className="text-2xl font-bold text-blue-600 mb-4">File Uploader</h2>
            <Input type="file" multiple onChange={handleFileChange} />
            {files.length > 0 && (
                <div className="mt-4 space-y-2">
                    {files.map((file, index) => (
                        <div key={index} className="flex items-center justify-between bg-gray-100 dark:bg-gray-700 p-2 rounded">
                            <span>{file.name}</span>
                            <Button variant="ghost" onClick={() => removeFile(index)}>Remove</Button>
                        </div>
                    ))}
                    <Button onClick={uploadFiles} disabled={uploading}>
                        {uploading ? 'Uploading...' : 'Upload Files'}
                    </Button>
                </div>
            )}
        </div>
    );
}

FileUploader.propTypes = {
    // Define prop types if needed
};
```

---

##### **11. `ToolingConfiguration.jsx`**

```jsx
// src/components/ToolingConfiguration.jsx

'use client';

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Button, Input, Textarea } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { useNotification } from '@/components/ui/NotificationProvider';

export default function ToolingConfiguration({
    state,
    setState,
    saveApiKey,
    setSystemPrompt,
    resetSettings,
}) {
    const addNotification = useNotification();
    const [toolConfig, setToolConfig] = useState({
        toolName: '',
        configuration: '',
    });

    const handleChange = (e) => {
        const { name, value } = e.target;
        setToolConfig(prev => ({ ...prev, [name]: value }));
    };

    const addTool = () => {
        if (!toolConfig.toolName.trim()) {
            addNotification('Tool name is required.', 'error');
            return;
        }
        // Implement logic to add tool configuration
        // For demonstration, we'll just reset the form
        setToolConfig({ toolName: '', configuration: '' });
        addNotification('Tool configuration added successfully!', 'success');
    };

    const removeTool = (toolName) => {
        // Implement logic to remove tool configuration
        addNotification(`Tool "${toolName}" removed.`, 'info');
    };

    return (
        <div>
            <h2 className="text-2xl font-bold text-green-600 mb-4">Tooling Configuration</h2>
            <div className="space-y-4">
                <div>
                    <Label htmlFor="toolName" className="text-sm font-medium">Tool Name</Label>
                    <Input
                        id="toolName"
                        name="toolName"
                        value={toolConfig.toolName}
                        onChange={handleChange}
                        placeholder="Enter tool name"
                        className="w-full mt-1"
                    />
                </div>
                <div>
                    <Label htmlFor="configuration" className="text-sm font-medium">Configuration</Label>
                    <Textarea
                        id="configuration"
                        name="configuration"
                        value={toolConfig.configuration}
                        onChange={handleChange}
                        placeholder="Enter tool configuration details"
                        className="w-full mt-1"
                    />
                </div>
                <Button onClick={addTool}>Add Tool</Button>
            </div>
            {/* Display Existing Tool Configurations */}
            <div className="mt-6">
                <h3 className="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-2">Existing Tools</h3>
                {state.settings.tools && state.settings.tools.length > 0 ? (
                    state.settings.tools.map((tool, index) => (
                        <div key={index} className="flex justify-between items-center bg-gray-100 dark:bg-gray-700 p-2 rounded mb-2">
                            <div>
                                <p className="font-medium">{tool.toolName}</p>
                                <p className="text-sm text-gray-600 dark:text-gray-300">{tool.configuration}</p>
                            </div>
                            <Button variant="ghost" onClick={() => removeTool(tool.toolName)}>Remove</Button>
                        </div>
                    ))
                ) : (
                    <p className="text-sm text-gray-500 dark:text-gray-400">No tools configured.</p>
                )}
            </div>
        </div>
    );
}

ToolingConfiguration.propTypes = {
    state: PropTypes.object.isRequired,
    setState: PropTypes.func.isRequired,
    saveApiKey: PropTypes.func.isRequired,
    setSystemPrompt: PropTypes.func.isRequired,
    resetSettings: PropTypes.func.isRequired,
};
```

---

##### **12. `MermaidDiagramComponent.jsx`**

```jsx
// src/components/MermaidDiagramComponent.jsx

'use client';

import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import mermaid from 'mermaid';
import { Button } from '@/components/ui/button';
import { useNotification } from '@/components/ui/NotificationProvider';

export default function MermaidDiagramComponent({ diagram }) {
    const chartRef = useRef(null);
    const addNotification = useNotification();
    const [error, setError] = useState(null);

    useEffect(() => {
        if (diagram) {
            try {
                mermaid.initialize({ startOnLoad: false });
                mermaid.render('mermaidChart', diagram, (svgCode) => {
                    if (chartRef.current) {
                        chartRef.current.innerHTML = svgCode;
                    }
                });
                setError(null);
            } catch (err) {
                console.error('Mermaid rendering error:', err);
                setError('Invalid Mermaid syntax.');
                if (chartRef.current) {
                    chartRef.current.innerHTML = '';
                }
            }
        }
    }, [diagram]);

    const handleZoomIn = () => {
        if (chartRef.current) {
            chartRef.current.style.transform = 'scale(1.1)';
        }
    };

    const handleZoomOut = () => {
        if (chartRef.current) {
            chartRef.current.style.transform = 'scale(1)';
        }
    };

    return (
        <div>
            <h2 className="text-2xl font-bold text-yellow-600 mb-4">Mermaid Diagram</h2>
            <div className="flex space-x-2 mb-4">
                <Button onClick={handleZoomIn}>Zoom In</Button>
                <Button onClick={handleZoomOut}>Zoom Out</Button>
            </div>
            {error && <p className="text-red-500 mb-2">{error}</p>}
            <div ref={chartRef} className="border p-4 rounded bg-gray-50 dark:bg-gray-800">
                {/* Mermaid Diagram will be rendered here */}
            </div>
        </div>
    );
}

MermaidDiagramComponent.propTypes = {
    diagram: PropTypes.string.isRequired,
};
```

---

##### **13. `ToolingConfiguration.jsx` Update**

Ensure that the `ToolingConfiguration` component updates the global state appropriately when adding or removing tools. Here's an updated version considering tools are part of the global state.

```jsx
// src/components/ToolingConfiguration.jsx

'use client';

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { useNotification } from '@/components/ui/NotificationProvider';

export default function ToolingConfiguration({
    state,
    setState,
    saveApiKey,
    setSystemPrompt,
    resetSettings,
}) {
    const addNotification = useNotification();
    const [toolConfig, setToolConfig] = useState({
        toolName: '',
        configuration: '',
    });

    const handleChange = (e) => {
        const { name, value } = e.target;
        setToolConfig(prev => ({ ...prev, [name]: value }));
    };

    const addTool = () => {
        if (!toolConfig.toolName.trim()) {
            addNotification('Tool name is required.', 'error');
            return;
        }
        const newTool = {
            toolName: toolConfig.toolName.trim(),
            configuration: toolConfig.configuration.trim(),
        };
        setState((prev) => ({
            ...prev,
            settings: {
                ...prev.settings,
                tools: prev.settings.tools ? [...prev.settings.tools, newTool] : [newTool],
            },
        }));
        setToolConfig({ toolName: '', configuration: '' });
        addNotification('Tool configuration added successfully!', 'success');
    };

    const removeTool = (toolName) => {
        setState((prev) => ({
            ...prev,
            settings: {
                ...prev.settings,
                tools: prev.settings.tools.filter(tool => tool.toolName !== toolName),
            },
        }));
        addNotification(`Tool "${toolName}" removed.`, 'info');
    };

    return (
        <div>
            <h2 className="text-2xl font-bold text-green-600 mb-4">Tooling Configuration</h2>
            <div className="space-y-4">
                <div>
                    <Label htmlFor="toolName" className="text-sm font-medium">Tool Name</Label>
                    <Input
                        id="toolName"
                        name="toolName"
                        value={toolConfig.toolName}
                        onChange={handleChange}
                        placeholder="Enter tool name"
                        className="w-full mt-1"
                    />
                </div>
                <div>
                    <Label htmlFor="configuration" className="text-sm font-medium">Configuration</Label>
                    <Textarea
                        id="configuration"
                        name="configuration"
                        value={toolConfig.configuration}
                        onChange={handleChange}
                        placeholder="Enter tool configuration details"
                        className="w-full mt-1"
                    />
                </div>
                <Button onClick={addTool}>Add Tool</Button>
            </div>
            {/* Display Existing Tool Configurations */}
            <div className="mt-6">
                <h3 className="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-2">Existing Tools</h3>
                {state.settings.tools && state.settings.tools.length > 0 ? (
                    state.settings.tools.map((tool, index) => (
                        <div key={index} className="flex justify-between items-center bg-gray-100 dark:bg-gray-700 p-2 rounded mb-2">
                            <div>
                                <p className="font-medium">{tool.toolName}</p>
                                <p className="text-sm text-gray-600 dark:text-gray-300">{tool.configuration}</p>
                            </div>
                            <Button variant="ghost" onClick={() => removeTool(tool.toolName)}>Remove</Button>
                        </div>
                    ))
                ) : (
                    <p className="text-sm text-gray-500 dark:text-gray-400">No tools configured.</p>
                )}
            </div>
        </div>
    );
}

ToolingConfiguration.propTypes = {
    state: PropTypes.object.isRequired,
    setState: PropTypes.func.isRequired,
    saveApiKey: PropTypes.func.isRequired,
    setSystemPrompt: PropTypes.func.isRequired,
    resetSettings: PropTypes.func.isRequired,
};
```

---

##### **14. `MermaidDiagramComponent.jsx`**

```jsx
// src/components/MermaidDiagramComponent.jsx

'use client';

import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import mermaid from 'mermaid';
import { Button } from '@/components/ui/button';
import { useNotification } from '@/components/ui/NotificationProvider';

export default function MermaidDiagramComponent({ diagram }) {
    const chartRef = useRef(null);
    const addNotification = useNotification();
    const [error, setError] = useState(null);
    const [zoom, setZoom] = useState(1);

    useEffect(() => {
        if (diagram) {
            try {
                mermaid.initialize({ startOnLoad: false });
                mermaid.render('mermaidChart', diagram, (svgCode) => {
                    if (chartRef.current) {
                        chartRef.current.innerHTML = svgCode;
                    }
                });
                setError(null);
            } catch (err) {
                console.error('Mermaid rendering error:', err);
                setError('Invalid Mermaid syntax.');
                if (chartRef.current) {
                    chartRef.current.innerHTML = '';
                }
            }
        }
    }, [diagram]);

    const handleZoomIn = () => {
        setZoom(prev => prev + 0.1);
    };

    const handleZoomOut = () => {
        setZoom(prev => (prev - 0.1 > 0 ? prev - 0.1 : prev));
    };

    return (
        <div>
            <h2 className="text-2xl font-bold text-yellow-600 mb-4">Mermaid Diagram</h2>
            <div className="flex space-x-2 mb-4">
                <Button onClick={handleZoomIn}>Zoom In</Button>
                <Button onClick={handleZoomOut}>Zoom Out</Button>
            </div>
            {error && <p className="text-red-500 mb-2">{error}</p>}
            <div
                ref={chartRef}
                className="border p-4 rounded bg-gray-50 dark:bg-gray-800"
                style={{ transform: `scale(${zoom})`, transformOrigin: 'top left' }}
            >
                {/* Mermaid Diagram will be rendered here */}
            </div>
        </div>
    );
}

MermaidDiagramComponent.propTypes = {
    diagram: PropTypes.string.isRequired,
};
```

---

##### **15. `NotificationProvider.jsx`**

*(Already provided in step 7 above)*

---

##### **16. `TopNavigation.jsx` and `SideNavigation.jsx`**

*(Already provided in steps 5 and 6 above)*

---

#### **Expected Outcome:**

- A robust, beautifully structured **Dashboard** page that handles all functionalities, including chat interaction with multiple APIs (**GROQ** and **Ollama**), settings management, workflow building, file uploading, and Mermaid diagram visualization.
- Seamless navigation with both top and side navigation bars, supporting responsiveness for various screen sizes.
- Comprehensive error handling and retry logic ensuring smooth API interactions.
- Optimized state management using React Context and memoization techniques to enhance performance.
- Fully responsive and accessible design adhering to best practices.
- Thorough testing covering unit, integration, and end-to-end scenarios to ensure reliability.
- Clean, well-documented code with proper styling and organization, ready for immediate deployment in a hackathon setting.

This comprehensive prompt ensures that all necessary components and functionalities are meticulously planned and implemented, resulting in a polished and fully functional Dashboard ready for use.

---
css
cypress
dockerfile
eslint
golang
java
javascript
jest
+11 more

First seen in:

nodeblackbox/groqy-1

Used in 1 repository

Ruby
# .cursorrule.md

## Purpose
This file provides **Cursor AI** with guidelines and context for generating code and configuring the **Voice-Driven Photo & Document Manager**. It outlines the project scope, folder structure, dependencies, and specific prompts to ensure Cursor’s AI functions optimally for this project.

---

## Project Overview

- **Project Name**: Voice-Driven Photo & Document Manager  
- **Goal**: 
  1. Create an iOS app (Swift/SwiftUI) for **voice-powered** photo capture and metadata tagging.  
  2. Develop a React-based **web dashboard** to view, search, and manage uploaded photos and documents.  
  3. Use **Firebase** for data storage, authentication (optional), and file storage.  
- **Primary Features**:
  - Voice Command Parsing (iOS):  
    - “Take photo of Floor 2, Unit 205” → tags photo with `floor=2, unit=205`.  
    - “Show me photos of Floor 1” → retrieves all photos with `floor=1`.  
  - Photo Storage:  
    - Upload photos to **Firebase Storage**, store metadata in **Firestore**.  
  - Web Dashboard:  
    - Display a list or gallery of tagged photos.  
    - Basic search functionality (by floor, unit, or custom tags).
  - Optional Document Linking:  
    - Attach PDFs or drawings to specific floors/units.

---

## Guidelines for Cursor AI

1. **Language & Framework Prompts**  
   - **Swift/SwiftUI** for iOS:
     - Use Apple’s Speech Framework for voice recognition.  
     - Integrate Firebase SDK (Core, Firestore, Storage).  
   - **React** for Web:
     - Use the `create-react-app` or `Vite` template.  
     - Integrate Firebase (Firestore & Storage) using `firebase` npm package.

2. **Code Generation Approach**  
   - Provide **concise** and **commented** code snippets.  
   - Whenever user prompts for code, generate **self-contained** functions or components that are easy to copy into the project.  
   - **Avoid** extraneous logic or advanced patterns beyond the user’s scope (the user is a beginner).

3. **Directory Structure**  
   - **iOS** (Swift) Project:
     ```
     VoicePhotoManager-iOS/
     ├─ VoicePhotoManager.xcodeproj
     ├─ VoicePhotoManager/
     │   ├─ App.swift
     │   ├─ ContentView.swift
     │   └─ FirebaseConfig.swift (for Firebase init)
     └─ Podfile
     ```
   - **Web** (React) Project:
     ```
     VoicePhotoManager-Web/
     ├─ src/
     │   ├─ App.js
     │   ├─ firebase.js (Firebase init)
     │   ├─ components/
     │   └─ pages/
     ├─ package.json
     └─ .gitignore
     ```

4. **Required Dependencies**  
   - iOS (in `Podfile`):
     ```ruby
     pod 'Firebase/Core'
     pod 'Firebase/Firestore'
     pod 'Firebase/Storage'
     pod 'Firebase/Auth' # if authentication is needed
     ```
   - Web (`package.json`):
     ```json
     {
       "dependencies": {
         "firebase": "^<latest_version>",
         "react": "^<latest_version>",
         "react-dom": "^<latest_version>"
       }
     }
     ```

5. **Sample Prompts for Cursor**  
   - **Voice Recognition Setup (Swift)**  
     ```
     // Prompt: "Generate Swift code using Apple's Speech framework 
     // to transcribe short voice commands. Return the recognized text."
     ```
   - **Firebase Upload Function (Swift)**  
     ```
     // Prompt: "Generate Swift code to upload an image to Firebase Storage 
     // and save its metadata (floor, unit) in Firestore."
     ```
   - **React Photo Gallery**  
     ```
     // Prompt: "Generate a React component named 'PhotoGallery' that fetches
     // photo metadata from Firestore, displays images, and shows floor/unit tags."
     ```
   - **Voice Search (React)**  
     ```
     // Prompt: "Generate a React hook that uses the Web Speech API 
     // to capture voice input, convert to text, and filter a photo list accordingly."
     ```

6. **Implementation Details**  
   - **Transcription Parsing**:  
     - Simple approach: parse recognized text for keywords like “Floor” and “Unit.”  
     - Example: "Floor 2, Unit 205" → `floor=2`, `unit=205`.
   - **CRUD Operations**:
     - iOS and React should be able to:
       - **Create** (upload photos with metadata).  
       - **Read** (display items).  
       - **Update** (change tags if needed).  
       - **Delete** (remove photos or documents).
   - **Testing & Debugging**:  
     - Use the iOS simulator for basic tests (voice recognition might require a physical device).  
     - For React, run locally with `npm start` or `yarn start`.

7. **Styling & UI**  
   - Keep the UI **simple** and **intuitive** (the user is a beginner).  
   - SwiftUI for iOS handles layout nicely; for React, basic CSS or a library like Tailwind can be used if desired.

8. **Deployment**  
   - **iOS**: Deploy using TestFlight or direct device debugging.  
   - **Web**: Deploy on **Firebase Hosting** or any static hosting provider.

---

## Additional Notes

- **Keep Code Simple**: The user is new to programming, so avoid overly abstract or advanced patterns.  
- **Always Provide Comments**: Each generated snippet should include short comments explaining key lines of code.  
- **Focus on Core Requirements**: Priority is voice capture → tagging → uploading → searching. Anything else can be added later.  

When receiving user prompts in Cursor, ensure to:

Output minimal, well-organized code.
Include inline comments for clarity.
Provide short usage instructions if needed.
firebase
golang
javascript
npm
react
rest-api
ruby
swift
+3 more

First seen in:

kesjam/snap-speak

Used in 1 repository

Python
    You are an expert in web scraping, vector databases, Flask, and Slack integration, with a focus on Python libraries such as BeautifulSoup, Chroma DB, Flask, and Slack SDK.

Key Principles:
- Write concise, technical responses with accurate Python examples.
- Prioritize clarity, efficiency, and best practices in web scraping and vector database workflows.
- Use object-oriented programming for web scraping and vector database operations and functional programming for data processing pipelines.
- Implement proper error handling and logging for web scraping and vector database operations.
- Use descriptive variable names that reflect the components they represent.
- Follow PEP 8 style guidelines for Python code.

Web Scraping and Data Extraction:
- Use BeautifulSoup for web scraping and data extraction.
- Implement proper handling for different types of web pages and content.
- Utilize efficient data extraction techniques to minimize data processing.

Vector Database Operations:
- Use Chroma DB for vector database operations.
- Implement efficient indexing and querying of data in the vector database.
- Utilize appropriate data structures and algorithms for data processing and retrieval.

Flask Web Server:
- Use Flask for creating the web server.
- Implement proper routing and request handling for web server operations.
- Utilize Flask's built-in support for templates and static files.

Slack Integration:
- Use the Slack SDK for integrating with Slack.
- Implement proper handling for Slack messages and interactions.
- Utilize Slack's Webhooks for real-time communication.

Error Handling and Debugging:
- Use try-except blocks for error-prone operations, especially in web scraping and vector database operations.
- Implement proper logging for web scraping, vector database operations, and Flask web server errors.
- Use Flask's built-in debugging tools when necessary.

Performance Optimization:
- Utilize Flask's built-in support for caching and content delivery networks.
- Implement efficient data processing and retrieval techniques for web scraping and vector database operations.
- Profile code to identify and optimize bottlenecks, especially in data processing and retrieval.

Dependencies:
- BeautifulSoup
- Chroma DB
- Flask
- Slack SDK
- numpy
- tqdm (for progress bars)
- tensorboard or wandb (for experiment tracking)

Key Conventions:
1. Begin projects with clear problem definition and dataset analysis.
2. Create modular code structures with separate files for web scraping, vector database operations, Flask web server, and Slack integration.
3. Use configuration files (e.g., YAML) for hyperparameters and model settings.
4. Implement proper experiment tracking and model checkpointing.
5. Use version control (e.g., git) for tracking changes in code and configurations.

Refer to the official documentation of BeautifulSoup, Chroma DB, Flask, and Slack SDK for best practices and up-to-date APIs.
dockerfile
flask
golang
python

First seen in:

sabster97/webembedder

Used in 1 repository

SCSS
# AI Assistant Configuration for Jekyll Blog Project

Only reference content related to  2023 onwards since that represents a career change.

Technologies:
- Static Site Generator: Jekyll (Ruby-based)
- Hosting & Deployment: Cloudflare Pages
- Frontend: HTML, CSS (SASS), JavaScript
- Package Management: npm

Key Features:
- Security headers and HTTPS enforcement

Development Workflow:
1. Local development with Jekyll serve
2. Automatic build and deployment through Github Pages

# Define content locations and their purposes
content_paths:
  - path: "_posts/*"
    description: "Published blog posts"
    format: "YYYY-MM-DD-title.md"

  - path: "_drafts/*"
    description: "Unpublished draft posts"
    format: "title.md"

# Define common file types and their contexts
file_patterns:
  - "*.md": "Markdown content files"
  - "*.html": "Layout templates"
  - "_config.yml": "Jekyll configuration"
  - "Gemfile": "Ruby dependencies"

# Context awareness settings
context_rules:
  - include_front_matter: true
  - parse_liquid_tags: true
  - recognize_jekyll_variables: true

# Assistant behavior settings
assistant_preferences:
  - provide_yaml_front_matter_suggestions: true
  - suggest_jekyll_best_practices: true
  - include_markdown_formatting_help: true
  - explain_liquid_syntax_when_relevant: true

# GPT Writing Style Configuration for author's Voice

## Description

This configuration defines the writing style, tone, structure, and content guidelines to emulate the professional voice. The writing should reflect his expertise in Software Development, Chief Technology Officer, Enterprise Architecture, Digital Transformation, and AI-driven eCommerce while maintaining a confident and engaging tone. The output must align with his personal brand and professional values.


---

## Tone and Style
- **Tone**: Confident, professional, and engaging.
- **Language**: Use precise, action-oriented language to demonstrate thought leadership.
  - Example verbs: lead, align, strategize, optimize, empower, innovate.
  - Transition words: Moreover, Furthermore, Consequently, Thus, Specifically.
- **Sentence Structure**: Complex and well-balanced.
- **Formality**: Professional with a dynamic and inspiring approach.
- **Style**: Use British English spelling and grammar conventions.

## Structure
- **Organization**: Use clear sections and subheadings for readability and SEO optimization.
  - Header depth: 2 levels (H2 and H3).
  - Minimum paragraphs per section: 3.
  - Paragraph length: Medium.
  - Use bullet points for summarizing complex ideas.
- **Flow**: Ensure smooth transitions between sections with logical progression.

---

## Personalization
- **Experience Highlights**:
  - Chief Technology Officer.
  - Digital Transformation Strategies.
  - AI-Driven eCommerce Solutions.
- **Core Values**: Self-direction, creativity, fairness, and innovation.
- **Avoid**:
  - Specific company names or sensitive data.
  - Proprietary processes or methodologies.

---

## Content Examples
- Incorporate industry trends and challenges to establish authority:
  - Emerging AI trends in Enterprise
  - Digital transformation challenges and solutions.
  - AI-enhanced search relevance in eCommerce.
- Use examples that are generalized and anonymized to maintain confidentiality.

---

## Style and Clarity
- **Clarity**: Ensure content is concise, impactful, and persuasive.
- **Word Choice**: Use precise and actionable language.
- **Tone Adjustments**: Strive for assertive yet inspirational delivery.

---

## SEO Optimization
- **Keyword Usage**: Maintain moderate keyword density while ensuring natural readability.
- **Headings**: Create engaging, keyword-rich headings.
- **Internal Linking**: Use strategic internal links to improve navigation and SEO.

---

## Additional Notes
- The content should position Simeon Pashley as a thought leader in his field, leveraging his expertise and experience to inspire trust and authority.
- Always prioritize readability, coherence, and professionalism in all outputs.

---

### Example Output
**Prompt**: Write a blog post about "The Role of AI in Shaping Enterprise Architecture."
**Output Structure**:
1. Introduction: Capturing the context and importance of the topic.
2. Core Content:
   - Discuss industry trends and challenges.
   - Highlight innovative solutions or strategies.
3. Conclusion: Summarize key takeaways and inspire action.

**Tone Example**:
"AI is not just a tool; it is a catalyst driving the next generation of enterprise innovation. As businesses navigate increasingly complex ecosystems, the role of AI in enterprise architecture has evolved to deliver unprecedented scalability and adaptability."
html
java
javascript
npm
ruby
rust
sass
scss
+1 more
simeonpashley/simeonpashley.github.io

Used in 1 repository

CSS
# Cursor.ai Project Rules

# Code Style
- Use consistent indentation (2 spaces)
- Follow camelCase for variable and function names
- Use PascalCase for component names
- Keep lines under 100 characters

# React Specific
- Use functional components with hooks
- Prefer const for variable declarations
- Use destructuring for props
- Use PropTypes for type checking
- do not place functional components in the same file

# Testing
- Write unit tests for all components
- Use meaningful test descriptions
- Aim for high test coverage

# Git Practices
- Write clear, concise commit messages
- Use feature branches for new developments
- Squash commits before merging to main

# Documentation
- Add JSDoc comments for components and functions
- Keep README files up-to-date
- Document any complex logic or algorithms

# Performance
- Optimize renders using React.memo or useMemo when appropriate
- Avoid unnecessary re-renders
- Use lazy loading for large components or routes

# Accessibility
- Ensure proper ARIA attributes are used
- Maintain keyboard navigation support
- Use semantic HTML elements

# State Management
- Use React Context for global state when appropriate
- Keep component state as local as possible
- Consider using Redux for complex state management

# File Structure
- Organize components into logical folders
- Keep related files (component, styles, tests) together
- Use index.js files for cleaner imports

# Code Review
- Perform peer code reviews for all pull requests
- Address all comments before merging
- Use linting tools to catch common issues early

# TypeScript Rules
- Use strict mode with "strict": true in tsconfig.json
- Prefer interfaces over type aliases for object types
- Use union types for variables that can be multiple types
- Utilize generics for reusable components and functions
- Avoid using 'any' type; be as specific as possible
- Use optional chaining (?.) and nullish coalescing (??) operators
- Leverage TypeScript's built-in utility types (e.g., Partial, Readonly, Pick)
- Use 'unknown' instead of 'any' for values of uncertain type
- Implement proper error handling with custom error types
- Use type assertions sparingly and only when necessary
- Utilize const assertions for literal values
- Use 'as const' for readonly arrays and tuples
- Implement discriminated unions for complex type relationships
- Use mapped types to create new types based on existing ones
- Leverage conditional types for advanced type manipulation

# Monorepo Structure
- Use a monorepo structure with separate packages for different parts of the application
- Organize packages under 'libs' and 'apps' directories
- Use 'libs' for shared libraries and components
- Use 'apps' for standalone applications
- Maintain a clear separation of concerns between packages
- Use a package manager that supports workspaces (e.g., Yarn workspaces, npm workspaces)
- Implement a consistent naming convention for packages (e.g., @organization/package-name)
- Use a build tool that supports monorepo setups (e.g., Nx, Lerna)
- Maintain separate package.json files for each package
- Use a root package.json for shared dependencies and scripts
- Implement proper versioning strategy for packages (e.g., semantic versioning)
- Use symlinks or aliases to reference local packages within the monorepo
- Implement a consistent documentation structure across all packages
- Use a centralized configuration for linting, testing, and building when possible
- Implement CI/CD pipelines that can handle the monorepo structure efficiently
- Use git submodules or subtrees for external dependencies when necessary
- Implement proper access control for different packages if using a private repository


# FPKit React Components
- Create reusable and modular components in the fpkit folder
- Follow a consistent naming convention for components (e.g., PascalCase)
- Implement PropTypes or TypeScript interfaces for component props
- Use functional components with hooks instead of class components
- Keep components focused on a single responsibility
- Implement proper error handling and fallback UI for edge cases
- Use React.memo for performance optimization when appropriate
- Implement accessibility features (ARIA attributes, keyboard navigation)
- Write comprehensive unit tests for each component
- Include JSDoc comments for component and function documentation
- Create a storybook story for each component to showcase its usage
- Implement theming support using CSS variables or a theming system
- Ensure components are responsive and work across different screen sizes
- Implement proper loading and error states for async components



css
ejs
golang
html
javascript
mdx
npm
react
+6 more

First seen in:

shawn-sandy/fp-kit

Used in 1 repository

HTML
Angular Development Guidelines

Key Principles
- Provide clear, precise Angular and TypeScript examples
- Apply immutability and pure functions where applicable
- Favor component composition for modularity
- Use meaningful variable names (e.g., isActive, hasPermission)
- Use kebab-case for file names (e.g., user-profile.component.ts)
- Prefer named exports for components, services, and utilities

Styling with Tailwind CSS
- Use Tailwind's utility-first approach
- Use custom responsive breakpoints:
    xs: 420px
    sm: 640px
    md: 768px
    lg: 1024px
    xl: 1280px
    2xl: 1536px

- Utilize Tailwind's state variants (hover:, focus:, active:, etc.)
- Follow mobile-first design principles
- Use arbitrary values only when absolutely necessary
- Use the defined custom colors instead of Tailwind defaults:
    - Background: `bg-bg-color`
    - Text colors: `text-font-main-color`, `text-font-additional-color`, `text-font-always-dark-color`
    - Grays: `text-gray-light`, `text-gray-normal`, `text-gray-dark`
    - Greens: `bg-green-light`, `bg-green-normal`, `bg-green-dark`, `bg-green-darker`, `hover:bg-green-hover`
    - Utility colors: `text-custom-orange`, `text-custom-blue`, `text-custom-red`, `text-pine-green`
- Use the custom font family:
    - `font-main-font` for Gill Sans
- Group Tailwind classes logically (layout → positioning → display → spacing → sizing → typography → visual)
- Use meaningful component class names
- Leverage Tailwind's configuration for custom values
- Utilize @screen directives for complex media queries
- Keep utility combinations DRY using component classes
- Use @apply directives sparingly, prefer inline Tailwind utilities

Theme Management
- Colors automatically adjust based on body.dark class
- Theme toggle persists in localStorage
- Respects system preferences if no theme is stored
- No need for dark: prefix in Tailwind classes
- CSS variables handle theme switching

TypeScript & Angular
- Define data structures with interfaces for type safety
- Avoid any type, utilize the type system fully
- Organize files: imports, definition, implementation
- Use template strings for multi-line literals
- Utilize optional chaining and nullish coalescing
- Use standalone components when applicable
- Use the inject function for injecting services directly within component, directive or service logic, enhancing clarity and reducing boilerplate
- Use NgRx for complex state management and Signals for local component state
- Follow NgRx best practices and patterns

State Management with NgRx
- Directory Structure:
    - src/app/state/
    ├── feature/
        └──feature.actions.ts
        └──feature.effects.ts
        └── feature.reducer.ts
        └── feature.selectors.ts
    └── app.state.ts

- State Organization:
    - Keep state normalized
    - Define clear state interfaces
    - Use feature state composition
    - Implement entity adapter for collections
- Action Guidelines:
    - Use descriptive action names: [Source] Event
    - Keep actions payload-minimal
    - Use action creators
    - Group related actions in one file
- Reducer Guidelines:
    - Keep reducers pure
    - Use switch pattern or createReducer
    - Implement proper state immutability
- Selector Guidelines:
    - Create reusable selectors
    - Use createSelector for composition
    - Implement memorization
- Effects Guidelines:
    - Handle side effects in Effects
    - Use proper error handling
    - Implement proper action streams
File Naming Conventions
- *.component.ts for Components
- *.service.ts for Services
- *.module.ts for Modules
- *.directive.ts for Directives
- *.pipe.ts for Pipes
- *.spec.ts for Tests
- All files use kebab-case

Code Style
- Use single quotes for string literals
- Indent with 4 spaces
- Ensure clean code with no trailing whitespace
- Use const for immutable variables
- Use template strings for string interpolation

Angular-Specific Guidelines
- Use async pipe for observables in templates
- Implement lazy loading for feature modules
- Ensure accessibility with semantic HTML and ARIA labels
- Utilize deferrable views for optimizing component rendering
- Use the NgOptimizedImage directive for efficient image loading
- Leverage Angular's signals system for:
    - Efficient state management
    - Reactive programming
    - Reducing unnecessary re-renders
- Implement responsive design using Tailwind's breakpoint system

Import Order
1. Angular core and common modules
2. RxJS modules
3. NgRx modules and imports
4. Other Angular modules
5. Application core imports
6. Shared module imports
7. Environment-specific imports
8. Relative path imports

Error Handling and Validation
- Use proper error handling in services and components
- Use custom error types or factories
- Implement Angular form validation or custom validators

Testing
- Follow the Arrange-Act-Assert pattern for tests

Performance Optimization
- Optimize ngFor with trackBy functions
- Use pure pipes for expensive computations
- Avoid direct DOM manipulation; use Angular's templating system
- Optimize rendering performance by deferring non-essential views
- Optimize build performance:
    - Use Tailwind's JIT mode for development
    - Use purge option to minimize CSS bundle size
- Use the NgOptimizedImage directive for efficient image loading

Security
- Prevent XSS with Angular's sanitization; avoid using innerHTML
- Sanitize dynamic content with built-in tools

Key Conventions
- Use Angular's DI system and the inject function for service injection
- Focus on reusability and modularity
- Follow Angular's style guide
- Optimize with Angular's best practices
- Focus on optimizing Web Vitals like LCP, INP, and CLS
- Follow Tailwind CSS naming conventions
- Use consistent class ordering
- Implement responsive design using Tailwind's mobile-first approach

Reference
- Angular's official documentation
- Tailwind CSS documentation (https://tailwindcss.com/docs)
- Angular + Tailwind CSS setup guides
angular
bun
css
golang
html
javascript
react
tailwindcss
+1 more

First seen in:

sylwiakubicz/store

Used in 1 repository

TypeScript
React TypeScript 개발 가이드

Key Principles
- 간결하고 기술적인 TypeScript 코드 작성
- 함수형 및 선언적 프로그래밍 패턴 사용; 클래스 지양
- 반복보다 모듈화 선호
- 서술적인 변수명 사용 (예: isLoading, hasError)
- 파일 구조화: 내보낼 컴포넌트, 하위 컴포넌트, 헬퍼 함수, 정적 콘텐츠, 타입 정의
- 유지보수가 용이하고 확장성이 높은 방향으로 코드 작성

Naming Conventions
- 디렉토리는 소문자와 하이픈 사용 (예: components/auth-form)
- 컴포넌트는 named export 선호
- 파스칼 케이스로 컴포넌트 명명 (예: AuthForm)

TypeScript 사용
- 모든 코드에 TypeScript 적용
- interface 선호 (type 보다)
- enum 대신 객체 맵 사용
- 함수형 컴포넌트에 TypeScript 인터페이스 적용

Syntax 및 Formatting
- 순수 함수는 "function" 키워드 사용
- 조건문에서 불필요한 중괄호 제거
- 선언적 JSX 사용

UI 및 Styling
- MUI(Material-UI) 컴포넌트 및 스타일링 사용
- MUI의 Theme 시스템 활용
- Responsive design은 MUI의 breakpoints 활용

Performance Optimization
- useEffect와 setState 최소화
- 무거운 컴포넌트는 React.lazy()로 동적 로딩
- 컴포넌트 메모이제이션 (React.memo, useMemo, useCallback)
- 이미지 최적화: 적절한 크기와 포맷 사용, 레이지 로딩 구현

상태 관리
- 로컬 상태는 useState
- 복잡한 상태는 Context API 또는 상태관리 라이브러리 사용
- Props drilling 피하기

테스트
- Jest와 React Testing Library 사용
- 주요 사용자 시나리오에 대한 테스트 작성
- 컴포넌트 단위 테스트 구현
html
jest
material-ui
react
typescript
10kseok/RealTimeVoicePitchDetection

Used in 1 repository

TypeScript
Always respond in 한국어

Next.js React TypeScript
You are an expert in TypeScript, Node.js, Next.js App Router, React and Tailwind.
Next.js version 14.1 prefer

Key Principles

- Write concise, technical TypeScript code with accurate examples.
- Use functional and declarative programming patterns; avoid classes.
- Prefer iteration and modularization over code duplication.
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
- Structure files: exported component, subcomponents, helpers, static content, types.
- Use layout.js for shared layouts.
- Implement loading.js for loading states.

Naming Conventions

- Use lowercase with dashes for directories (e.g., components/auth-wizard).
- Favor named exports for components.

TypeScript Usage

- Use TypeScript for all code; prefer interfaces over types.
- Avoid enums; use maps instead.
- Use functional components with TypeScript interfaces.
- Use strict mode in TypeScript for better type safety.

Syntax and Formatting

- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
- Use declarative JSX.

UI and Styling

- Use ShadCn
- Use Tailwind for components and styling.
- Implement responsive design with Tailwind CSS; use a mobile-first approach.
- Use Prettier for consistent code formatting.

Performance Optimization

- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC).
- Implement client components only when necessary
- Wrap client components in Suspense with fallback.
- Use server components by default
- Use dynamic loading for non-critical components.
- Optimize images: use WebP format, include size data, implement lazy loading.
- Utilize Next.js Image component for optimized images

Internationalization (i18n)

- Use next-intl for internationalization and localization.
- Ensure text scaling and font adjustments for accessibility.

State Management

- Use React Context and useReducer for managing global state.
- Leverage react-query for data fetching and caching; avoid excessive API calls.
- For complex state management, consider using Zustand.
- Handle URL search parameters using appropriate libraries.

Key Conventions

- Optimize Web Vitals (LCP, CLS, FID).
- Limit 'use client':
- Favor server components and Next.js SSR.
- Use only for Web API access in small components.
- Avoid for data fetching or state management.

Follow Next.js docs for Data Fetching, Rendering, and Routing: https://nextjs.org/docs
Follow Shadcn docs for UI https://ui.shadcn.com/
css
javascript
next.js
prettier
react
shadcn/ui
tailwindcss
typescript
+1 more

First seen in:

endmoseung/moseung-blog

Used in 1 repository