import React, { useState, useEffect, useCallback } from "react"; import { X, Plus, Check, Loader2, ChevronRight, FolderPlus, } from "lucide-react"; import CollectionIcon from "../common/CollectionIcon"; import { ICON_MAP } from "../common/iconMap"; import EmojiPicker, { Theme } from "emoji-picker-react"; import { useStore } from "@nanostores/react"; import { $user } from "../../store/auth"; import { $theme } from "../../store/theme"; import { getCollections, addCollectionItem, createCollection, getCollectionsContaining, type Collection, } from "../../api/client"; interface AddToCollectionModalProps { isOpen: boolean; onClose: () => void; annotationUri: string; } export default function AddToCollectionModal({ isOpen, onClose, annotationUri, }: AddToCollectionModalProps) { const user = useStore($user); const theme = useStore($theme); const [collections, setCollections] = useState([]); const [loading, setLoading] = useState(true); const [addingTo, setAddingTo] = useState(null); const [addedTo, setAddedTo] = useState>(new Set()); const [error, setError] = useState(null); const [showNewForm, setShowNewForm] = useState(false); const [newName, setNewName] = useState(""); const [newDescription, setNewDescription] = useState(""); const [newIcon, setNewIcon] = useState(""); const [activeTab, setActiveTab] = useState<"icon" | "emoji">("icon"); const [creating, setCreating] = useState(false); useEffect(() => { if (isOpen) { document.body.style.overflow = "hidden"; } return () => { document.body.style.overflow = "unset"; }; }, [isOpen]); const loadCollections = useCallback(async () => { if (!user) return; try { setLoading(true); const data = await getCollections(user.did); setCollections(data); } catch (err) { console.error(err); setError("Failed to load collections"); } finally { setLoading(false); } }, [user]); useEffect(() => { if (isOpen && user) { loadCollections(); setError(null); getCollectionsContaining(annotationUri).then((uris) => { setAddedTo(new Set(uris)); }); } }, [isOpen, user, loadCollections, annotationUri]); const handleAdd = async (collectionUri: string) => { if (addedTo.has(collectionUri)) return; try { setAddingTo(collectionUri); await addCollectionItem(collectionUri, annotationUri); setAddedTo((prev) => new Set([...prev, collectionUri])); } catch (err) { console.error(err); setError("Failed to add to collection"); } finally { setAddingTo(null); } }; const handleCreate = async (e: React.FormEvent) => { e.preventDefault(); if (!newName.trim()) return; try { setCreating(true); const iconValue = newIcon ? ICON_MAP[newIcon] ? `icon:${newIcon}` : newIcon : undefined; const newCollection = await createCollection( newName.trim(), newDescription.trim() || undefined, iconValue, ); if (newCollection) { setCollections((prev) => [newCollection, ...prev]); setNewName(""); setNewDescription(""); setNewIcon(""); setShowNewForm(false); } } catch (err) { console.error(err); setError("Failed to create collection"); } finally { setCreating(false); } }; if (!isOpen) return null; return (
e.stopPropagation()} >

Add to Collection

{loading ? (

Loading collections...

) : showNewForm ? (
setNewName(e.target.value)} placeholder="My Collection" autoFocus />