From aa9710f60f9902367d11c22e32d99dbb37bfb644 Mon Sep 17 00:00:00 2001 From: Marcus Monterroso Date: Wed, 5 Mar 2025 14:30:00 -0600 Subject: [PATCH 01/11] Basic modal implementation --- .cursorrules | 62 +++++++ SPEC.md | 57 ++++++ components/ChatModal.jsx | 211 ++++++++++++++++++++++ components/ChatSettingsModal.jsx | 116 ++++++++++++ components/Header.jsx | 23 ++- contexts/AppContext.jsx | 10 +- jsconfig.json | 3 +- package-lock.json | 24 +++ package.json | 1 + services/ChatService.js | 202 +++++++++++++++++++++ styles/.ChatModal.module.scss.swp | Bin 0 -> 16384 bytes styles/ChatModal.module.scss | 260 +++++++++++++++++++++++++++ styles/ChatSettingsModal.module.scss | 77 ++++++++ 13 files changed, 1043 insertions(+), 3 deletions(-) create mode 100644 .cursorrules create mode 100644 SPEC.md create mode 100644 components/ChatModal.jsx create mode 100644 components/ChatSettingsModal.jsx create mode 100644 services/ChatService.js create mode 100644 styles/.ChatModal.module.scss.swp create mode 100644 styles/ChatModal.module.scss create mode 100644 styles/ChatSettingsModal.module.scss diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..14717c2 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,62 @@ + +START SPECIFICATION: +# Technical Specification + +## Rules + +## System Overview +The system is a web application designed to manage and manipulate color palettes. It allows users to create, edit, save, load, and share color palettes. The application features a user-friendly interface with drag-and-drop functionality for reordering colors, a color picker for selecting new colors, and various modals for importing, exporting, and saving palettes. The system is built using React for the frontend, with Next.js for server-side rendering and routing. It utilizes a global state management context (`AppContext`) to handle application-wide state. + +### Main Components and Their Roles +- **Frontend Components**: React components such as `App`, `ColorItem`, `ColorPicker`, `Colors`, `Header`, and various modals handle the user interface and interactions. +- **Functions**: Utility functions like `adjustTextColor`, `calculateNewColor`, `generateColorVariables`, and `ntc.name` provide core functionality for color manipulation and naming. +- **Global State**: `AppContext` manages the global state of the application, including color palettes and user actions. +- **Styles**: SCSS modules define the styling for various components and the overall layout. +- **CI/CD**: GitHub Actions workflow (`nextjs.yml`) for building and deploying the application. +- **License**: GNU General Public License Version 3 (GPLv3) governs the usage and distribution of the software. + +## Core Functionality +### Primary Features and Their Implementation +1. **Color Palette Management** + - **`components/App.jsx`**: Initializes the application state and manages the main layout. + - **`components/Colors.jsx`**: Manages the list of colors with drag-and-drop reordering. + - **`components/ColorItem.jsx`**: Renders individual color items with drag-and-drop functionality and color picker display. + - **`functions/calculateNewColor.js`**: Generates a new color based on an array of existing colors and an index. + - **`functions/generateColorVariables.js`**: Generates CSS, SCSS, and JS variables for an array of colors. + +2. **Color Manipulation** + - **`functions/adjustTextColor.js`**: Determines the appropriate text color based on the luminance of a given background color. + - **`functions/ntc.js`**: Matches input colors to predefined color names using RGB and HSL values. + +3. **User Interface and Interactions** + - **`components/Header.jsx`**: Renders the application header with various action buttons. + - **`components/Modal.module.scss`**: Comprehensive styles for modal overlay and content. + - **`components/Formik.jsx`**: Custom Formik components for input and textarea fields with validation styling. + +4. **Export and Import Functionality** + - **`components/ExportModal.jsx`**: Renders a modal for exporting color palettes in different formats. + - **`components/ImportModal.jsx`**: Renders a modal for importing color palettes via a textarea. + +5. **State Management** + - **`contexts/AppContext.jsx`**: Defines the `AppContext` for global state management, including colors, palettes, and other app-wide states. + +### Complex Algorithms and Business Logic +- **Color Matching Algorithm in `ntc.name(color)`**: Calculates the distance between the input color and each color in the `ntc.names` array using both RGB and HSL values to find the closest match. +- **New Color Generation in `calculateNewColor`**: Converts hex colors to RGB, calculates the average color between two given colors, and shifts a color by a random amount within a specified range based on the index. + +## Architecture +### Data Flow Patterns +1. **Initialization**: + - The application initializes by loading cookies and setting the initial colors in `components/App.jsx`. +2. **User Interactions**: + - Users can add new colors using `NewColorButton`, which calls `calculateNewColor` to generate a new color and updates the state. + - Users can reorder colors using drag-and-drop functionality in `components/Colors.jsx`. + - Users can select new colors using the `ColorPicker` component. +3. **State Management**: + - The global state is managed using `AppContext`, which provides access to the application state and state setter across components. +4. **Export and Import**: + - Users can export color palettes using `ExportModal`, which generates variable declarations for CSS, SCSS, and JS. + - Users can import color palettes using `ImportModal`, which parses the input and updates the state. +5. **CI/CD**: + - The GitHub Actions workflow (`nextjs.yml`) builds and deploys the application to GitHub Pages. +END SPECIFICATION \ No newline at end of file diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..d0a1757 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,57 @@ +# Technical Specification + +## System Overview +The system is a web application designed to manage and manipulate color palettes. It allows users to create, edit, save, load, and share color palettes. The application features a user-friendly interface with drag-and-drop functionality for reordering colors, a color picker for selecting new colors, and various modals for importing, exporting, and saving palettes. The system is built using React for the frontend, with Next.js for server-side rendering and routing. It utilizes a global state management context (`AppContext`) to handle application-wide state. + +### Main Components and Their Roles +- **Frontend Components**: React components such as `App`, `ColorItem`, `ColorPicker`, `Colors`, `Header`, and various modals handle the user interface and interactions. +- **Functions**: Utility functions like `adjustTextColor`, `calculateNewColor`, `generateColorVariables`, and `ntc.name` provide core functionality for color manipulation and naming. +- **Global State**: `AppContext` manages the global state of the application, including color palettes and user actions. +- **Styles**: SCSS modules define the styling for various components and the overall layout. +- **CI/CD**: GitHub Actions workflow (`nextjs.yml`) for building and deploying the application. +- **License**: GNU General Public License Version 3 (GPLv3) governs the usage and distribution of the software. + +## Core Functionality +### Primary Features and Their Implementation +1. **Color Palette Management** + - **`components/App.jsx`**: Initializes the application state and manages the main layout. + - **`components/Colors.jsx`**: Manages the list of colors with drag-and-drop reordering. + - **`components/ColorItem.jsx`**: Renders individual color items with drag-and-drop functionality and color picker display. + - **`functions/calculateNewColor.js`**: Generates a new color based on an array of existing colors and an index. + - **`functions/generateColorVariables.js`**: Generates CSS, SCSS, and JS variables for an array of colors. + +2. **Color Manipulation** + - **`functions/adjustTextColor.js`**: Determines the appropriate text color based on the luminance of a given background color. + - **`functions/ntc.js`**: Matches input colors to predefined color names using RGB and HSL values. + +3. **User Interface and Interactions** + - **`components/Header.jsx`**: Renders the application header with various action buttons. + - **`components/Modal.module.scss`**: Comprehensive styles for modal overlay and content. + - **`components/Formik.jsx`**: Custom Formik components for input and textarea fields with validation styling. + +4. **Export and Import Functionality** + - **`components/ExportModal.jsx`**: Renders a modal for exporting color palettes in different formats. + - **`components/ImportModal.jsx`**: Renders a modal for importing color palettes via a textarea. + +5. **State Management** + - **`contexts/AppContext.jsx`**: Defines the `AppContext` for global state management, including colors, palettes, and other app-wide states. + +### Complex Algorithms and Business Logic +- **Color Matching Algorithm in `ntc.name(color)`**: Calculates the distance between the input color and each color in the `ntc.names` array using both RGB and HSL values to find the closest match. +- **New Color Generation in `calculateNewColor`**: Converts hex colors to RGB, calculates the average color between two given colors, and shifts a color by a random amount within a specified range based on the index. + +## Architecture +### Data Flow Patterns +1. **Initialization**: + - The application initializes by loading cookies and setting the initial colors in `components/App.jsx`. +2. **User Interactions**: + - Users can add new colors using `NewColorButton`, which calls `calculateNewColor` to generate a new color and updates the state. + - Users can reorder colors using drag-and-drop functionality in `components/Colors.jsx`. + - Users can select new colors using the `ColorPicker` component. +3. **State Management**: + - The global state is managed using `AppContext`, which provides access to the application state and state setter across components. +4. **Export and Import**: + - Users can export color palettes using `ExportModal`, which generates variable declarations for CSS, SCSS, and JS. + - Users can import color palettes using `ImportModal`, which parses the input and updates the state. +5. **CI/CD**: + - The GitHub Actions workflow (`nextjs.yml`) builds and deploys the application to GitHub Pages. \ No newline at end of file diff --git a/components/ChatModal.jsx b/components/ChatModal.jsx new file mode 100644 index 0000000..7bd54b3 --- /dev/null +++ b/components/ChatModal.jsx @@ -0,0 +1,211 @@ +import { useState, useRef, useEffect } from 'react' +import { MdClose } from 'react-icons/md' +import Draggable from 'react-draggable' +import { PiPaperPlaneTilt, PiGear } from 'react-icons/pi' + +import styles from '@styles/ChatModal.module.scss' +import { useAppContext } from '@contexts/AppContext' +import { createChatService } from '@services/ChatService' +import ChatSettingsModal from './ChatSettingsModal' + +export default ({ modalIsOpen, closeModal }) => { + const { state, setState } = useAppContext() + const { colors, chatHistory = [], useLLM = false, llmConfig = {} } = state + const [message, setMessage] = useState('') + const [isLoading, setIsLoading] = useState(false) + const [settingsModalIsOpen, setSettingsModalIsOpen] = useState(false) + const chatContainerRef = useRef(null) + const nodeRef = useRef(null) // Required by react-draggable in React 18 + const chatService = useRef(createChatService(useLLM, llmConfig)) + + // Update chat service if useLLM or llmConfig changes + useEffect(() => { + chatService.current = createChatService(useLLM, llmConfig) + }, [useLLM, llmConfig]) + + // Scroll to bottom when chat history changes + useEffect(() => { + if (chatContainerRef.current) { + chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight + } + }, [chatHistory]) + + const handleSendMessage = async () => { + if (!message.trim() || isLoading) return + + // Add user message to chat history + const userMessage = { + isUser: true, + message: message.trim(), + timestamp: new Date().toISOString() + } + + setState(prevState => ({ + chatHistory: [...prevState.chatHistory, userMessage] + })) + + // Clear input after sending + setMessage('') + setIsLoading(true) + + try { + // Process message with chat service + const response = await chatService.current.processMessage(userMessage.message, colors) + + // Add assistant response to chat history + const assistantMessage = { + isUser: false, + message: response.message, + suggestedColors: response.suggestedColors, + timestamp: new Date().toISOString() + } + + setState(prevState => ({ + chatHistory: [...prevState.chatHistory, assistantMessage] + })) + } catch (error) { + console.error('Error processing message:', error) + + // Add error message to chat history + const errorMessage = { + isUser: false, + message: 'Sorry, I encountered an error processing your request. Please try again.', + timestamp: new Date().toISOString() + } + + setState(prevState => ({ + chatHistory: [...prevState.chatHistory, errorMessage] + })) + } finally { + setIsLoading(false) + } + } + + const handleKeyDown = (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + handleSendMessage() + } + } + + const handleAddColor = (color) => { + // Add the suggested color to the palette + setState(prevState => ({ + colors: [...prevState.colors, color.hex] + })) + } + + const openSettingsModal = () => setSettingsModalIsOpen(true) + const closeSettingsModal = () => setSettingsModalIsOpen(false) + + if (!modalIsOpen) return null; + + return ( + <> + +
+
+
+
+ Color Assistant +
+
+ + +
+
+ +
+
+ {chatHistory.length === 0 ? ( +
+

Ask me about color suggestions or palette advice!

+
+ ) : ( + chatHistory.map((chat, index) => ( +
+
+ {chat.message} +
+ {!chat.isUser && chat.suggestedColors && chat.suggestedColors.length > 0 && ( +
+ {chat.suggestedColors.map((color, colorIndex) => ( +
+
+ {color.name} + +
+ ))} +
+ )} +
+ )) + )} + {isLoading && ( +
+
+ +
+
+ )} +
+ +
+