diff --git a/client/src/components/common/BaseDropdown.tsx b/client/src/components/common/BaseDropdown.tsx index e361010..da390c8 100644 --- a/client/src/components/common/BaseDropdown.tsx +++ b/client/src/components/common/BaseDropdown.tsx @@ -16,6 +16,7 @@ export interface BaseDropdownProps { className?: string; disabled?: boolean; maxLength?: number; + showChevron?: boolean; } const BaseDropdown: React.FC = ({ @@ -27,7 +28,8 @@ const BaseDropdown: React.FC = ({ placeholder = "Select or type a value", className = "", disabled = false, - maxLength + maxLength, + showChevron = true, }) => { const [isOpen, setIsOpen] = useState(false); const [highlightedIndex, setHighlightedIndex] = useState(-1); @@ -138,7 +140,7 @@ const BaseDropdown: React.FC = ({ setIsOpen(true)} @@ -147,10 +149,13 @@ const BaseDropdown: React.FC = ({ disabled={disabled} maxLength={maxLength} /> - + {showChevron && ( + + ) + } {isOpen && sections.length > 0 && (
    = ({ id="title" value={title} onChange={(e) => setTitle(e.target.value.slice(0, 100))} - className="mt-1 block w-full rounded-md bg-gray-700 border border-gray-600 text-white p-2 text-sm" + className="mt-1 block w-full rounded-md bg-gray-700 text-white p-2 text-sm" required placeholder="Enter the title of the snippet (max 100 characters)" maxLength={100} @@ -223,7 +223,7 @@ const EditSnippetModal: React.FC = ({ id="description" value={description} onChange={(e) => setDescription(e.target.value)} - className="mt-1 block w-full rounded-md bg-gray-700 border border-gray-600 text-white p-2 text-sm" + className="mt-1 block w-full rounded-md bg-gray-700 text-white p-2 text-sm" rows={3} placeholder="Write a short description of the snippet" /> @@ -258,7 +258,7 @@ const EditSnippetModal: React.FC = ({
    -
    +
    = ({ } }, [searchTerm]); - const handleInputChange = (value: string) => { - setInputValue(value); - onSearchChange(value); + const getSections = (searchTerm: string) => { + if (!searchTerm.includes('#')) return []; + + const term = searchTerm.slice(searchTerm.lastIndexOf('#') + 1).trim().toLowerCase(); + const sections = []; + + const availableCategories = existingCategories.filter( + cat => !selectedCategories.includes(cat.toLowerCase()) + ); + + const filtered = term + ? availableCategories.filter(cat => cat.toLowerCase().includes(term)) + : availableCategories; + + if (filtered.length > 0) { + sections.push({ + title: 'Categories', + items: filtered + }); + } + + if (term && !existingCategories.some(cat => cat.toLowerCase() === term)) { + sections.push({ + title: 'Add New', + items: [`Add new: ${term}`] + }); + } + + return sections; + }; + + const handleSelect = (option: string) => { + const newCategory = option.startsWith('Add new:') + ? option.slice(9).trim() + : option; + + const hashtagIndex = inputValue.lastIndexOf('#'); + if (hashtagIndex !== -1) { + const newValue = inputValue.substring(0, hashtagIndex).trim(); + setInputValue(newValue); + onSearchChange(newValue); + } + + onCategorySelect(newCategory.toLowerCase()); }; return (
    - { + setInputValue(value); + onSearchChange(value); + }} + onSelect={handleSelect} + getSections={getSections} placeholder="Search snippets... (Type # to see all available categories)" - className="w-full bg-gray-800 rounded-lg py-2 px-4 pr-10 focus:outline-none" - handleHashtag={true} + className="h-10 mt-0 bg-gray-800" + showChevron={false} + /> + -
    ); }; diff --git a/client/src/components/snippets/categories/CategorySuggestions.tsx b/client/src/components/snippets/categories/CategorySuggestions.tsx index 140639d..6a45364 100644 --- a/client/src/components/snippets/categories/CategorySuggestions.tsx +++ b/client/src/components/snippets/categories/CategorySuggestions.tsx @@ -110,6 +110,7 @@ const CategorySuggestions: React.FC = ({ placeholder={placeholder} className={className} disabled={disabled || (maxCategories !== undefined && selectedCategories.length >= maxCategories)} + showChevron={false} /> ); };