import React, { useState, useRef, useEffect } from 'react'; import { DragDropContext, Droppable, Draggable, DropResult } from '@hello-pangea/dnd'; import { getWebsiteIcon } from './utils/iconService'; import { Category, Website } from '../types'; import IconPicker from './IconPicker'; import { icons } from 'lucide-react'; interface EditModalProps { categories: Category[]; onClose: () => void; onSave: (categories: Category[]) => void; } const EditModal: React.FC = ({ categories, onClose, onSave }) => { const [localCategories, setLocalCategories] = useState(categories); const [selectedCategoryId, setSelectedCategoryId] = useState(categories[0]?.id || null); const [newCategoryName, setNewCategoryName] = useState(''); const [newWebsite, setNewWebsite] = useState({ name: '', url: '', icon: '' }); const [showIconPicker, setShowIconPicker] = useState(false); const modalRef = useRef(null); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (modalRef.current && !modalRef.current.contains(event.target as Node)) { onClose(); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [onClose]); const handleOnDragEnd = (result: DropResult) => { if (!result.destination) return; const { source, destination } = result; if (source.droppableId === destination.droppableId) { const category = localCategories.find(cat => cat.id === source.droppableId); if (category) { const items = Array.from(category.websites); const [reorderedItem] = items.splice(source.index, 1); items.splice(destination.index, 0, reorderedItem); const updatedCategories = localCategories.map(cat => cat.id === category.id ? { ...cat, websites: items } : cat ); setLocalCategories(updatedCategories); } } else { const sourceCategory = localCategories.find(cat => cat.id === source.droppableId); const destCategory = localCategories.find(cat => cat.id === destination.droppableId); if (sourceCategory && destCategory) { const sourceItems = Array.from(sourceCategory.websites); const [movedItem] = sourceItems.splice(source.index, 1); const destItems = Array.from(destCategory.websites); destItems.splice(destination.index, 0, { ...movedItem, categoryId: destCategory.id }); const updatedCategories = localCategories.map(cat => { if (cat.id === sourceCategory.id) return { ...cat, websites: sourceItems }; if (cat.id === destCategory.id) return { ...cat, websites: destItems }; return cat; }); setLocalCategories(updatedCategories); } } }; const handleAddCategory = () => { if (newCategoryName.trim() === '') return; const newCategory: Category = { id: Date.now().toString(), name: newCategoryName, websites: [], }; setLocalCategories([...localCategories, newCategory]); setNewCategoryName(''); }; const handleRemoveCategory = (id: string) => { const updatedCategories = localCategories.filter(cat => cat.id !== id); setLocalCategories(updatedCategories); if (selectedCategoryId === id) { setSelectedCategoryId(updatedCategories[0]?.id || null); } }; const handleAddWebsite = async () => { if (!selectedCategoryId || !newWebsite.name || !newWebsite.url) return; let icon = newWebsite.icon; if (!icon || !Object.keys(icons).includes(icon)) { icon = await getWebsiteIcon(newWebsite.url); } const newWebsiteData: Website = { id: Date.now().toString(), name: newWebsite.name, url: newWebsite.url, icon, categoryId: selectedCategoryId, }; const updatedCategories = localCategories.map(cat => { if (cat.id === selectedCategoryId) { return { ...cat, websites: [...cat.websites, newWebsiteData] }; } return cat; }); setLocalCategories(updatedCategories); setNewWebsite({ name: '', url: '', icon: '' }); }; const handleRemoveWebsite = (categoryId: string, websiteId: string) => { const updatedCategories = localCategories.map(cat => { if (cat.id === categoryId) { return { ...cat, websites: cat.websites.filter(web => web.id !== websiteId) }; } return cat; }); setLocalCategories(updatedCategories); }; const selectedCategory = localCategories.find(cat => cat.id === selectedCategoryId); return (

Edit Bookmarks

Categories

{localCategories.map(category => (
setSelectedCategoryId(category.id)} > {category.name}
))}
setNewCategoryName(e.target.value)} className="bg-white/10 p-2 rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-cyan-400" />

Websites

{selectedCategory && ( {(provided) => (
    {selectedCategory.websites.map((website, index) => ( {(provided) => (
  • {Object.keys(icons).includes(website.icon) ? ( React.createElement(icons[website.icon as keyof typeof icons], { className: "h-8 w-8 mr-4" }) ) : ( {website.name} )} {website.name}
  • )}
    ))} {provided.placeholder}
)}
)}

Add New Bookmark

setNewWebsite({ ...newWebsite, name: e.target.value })} className="bg-white/10 p-3 rounded-lg focus:outline-none focus:ring-2 focus:ring-cyan-400" /> setNewWebsite({ ...newWebsite, url: e.target.value })} className="bg-white/10 p-3 rounded-lg focus:outline-none focus:ring-2 focus:ring-cyan-400" />
setNewWebsite({ ...newWebsite, icon: e.target.value })} className="bg-white/10 p-3 rounded-lg focus:outline-none focus:ring-2 focus:ring-cyan-400 w-full" />
{showIconPicker && ( { setNewWebsite({ ...newWebsite, icon: iconName }); setShowIconPicker(false); }} /> )}
); }; export default EditModal;