import { fetchContentForSpace, getSpace } from "@/actions/db" import { useMemory } from "@/contexts/MemoryContext" import { StoredContent, StoredSpace } from '@/server/db/schema' import { Edit3, Loader, Plus, Search, Sparkles, StickyNote, Text, Undo2 } from "lucide-react" import { useEffect, useRef, useState } from "react" import { Input, InputWithIcon } from "../ui/input" import { useDebounce } from "@/hooks/useDebounce" import { useAutoAnimate } from "@formkit/auto-animate/react" import { AddMemoryModal, MemoryItem } from "./MemoriesBar" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu" import { DialogTrigger } from "../ui/dialog" export function ExpandedSpace({ spaceId, back }: { spaceId: number, back: () => void; }) { const { updateMemory, updateSpace, search } = useMemory() const [parent, enableAnimations] = useAutoAnimate(); const inputRef = useRef(null); const [contentForSpace, setContentForSpace] = useState([]) const [lastUpdatedTitle, setLastUpdatedTitle] = useState(null); const [title, setTitle] = useState(''); const debouncedTitle = useDebounce(title, 500) const [loading, setLoading] = useState(true) const [saveLoading, setSaveLoading] = useState(false); const [searchQuery, setSearcyQuery] = useState(""); const [searchLoading, setSearchLoading] = useState(false); const query = useDebounce(searchQuery, 500); const [searchResults, setSearchResults] = useState([]); const [addMemoryState, setAddMemoryState] = useState< "page" | "note" | "existing-memory" | "space" | null >(null); const [isDropdownOpen, setIsDropdownOpen] = useState(false); useEffect(() => { (async () => { const title = (await getSpace(spaceId))?.name ?? ""; setTitle(title) setLastUpdatedTitle(title) setContentForSpace((await fetchContentForSpace(spaceId)) ?? []) setLoading(false) })(); }, []) useEffect(() => { if (debouncedTitle.trim().length < 1 || debouncedTitle.trim() === lastUpdatedTitle?.trim()) return (async () => { setSaveLoading(true) await updateSpace(spaceId, debouncedTitle.trim()) setLastUpdatedTitle(debouncedTitle) setSaveLoading(false) })() }, [debouncedTitle]) useEffect(() => { const q = query.trim(); if (q.length < 1) { setSearchResults([]); return; } setSearchLoading(true); (async () => { setSearchResults((await search(q, { filter: { spaces: false }, memoriesRelativeToSpace: { fromSpaces: [spaceId] } })).map(i => i.memory!)); setSearchLoading(false); })(); }, [query]); if (loading) { return (
) } return (
setTitle(e.target.value)} />
) : ( ) } className="bg-rgray-4 mt-2 w-full" value={searchQuery} onChange={(e) => setSearcyQuery(e.target.value)} />
{ if (!data) { setLoading(true); (async () => { const title = (await getSpace(spaceId))?.name ?? ""; setTitle(title) setLastUpdatedTitle(title) setContentForSpace((await fetchContentForSpace(spaceId)) ?? []) setLoading(false) })(); } else if (Object.hasOwn(data, "url")) { const _data = data as StoredContent; setContentForSpace(prev => [...prev, _data]) } }} data={{ space: { title, id: spaceId }, notInSpaces: [spaceId] }} defaultSpaces={[spaceId]} type={addMemoryState}> e.preventDefault()}> { setAddMemoryState("existing-memory"); }} > Existing Memory { setAddMemoryState("page"); }} > Page { setAddMemoryState("note"); }} > Note
{query.trim().length > 0 ? ( <> {searchResults.map((memory, i) => ( { await updateMemory(memory.id, { removedFromSpaces: [spaceId] }) setContentForSpace(prev => prev.filter(s => s.id !== memory.id)) setSearchResults(prev => prev.filter(i => i.id !== memory.id)) }} {...memory!} key={i} onDelete={() => { setContentForSpace(prev => prev.filter(s => s.id !== memory.id)) setSearchResults(prev => prev.filter(i => i.id !== memory.id)) }} /> ))} ) : contentForSpace.map(m => ( setContentForSpace(prev => prev.filter(s => s.id !== m.id))} removeFromSpace={async () => { await updateMemory(m.id, { removedFromSpaces: [spaceId] }) setContentForSpace(prev => prev.filter(s => s.id !== m.id)) }} /> )) }
) }