"use client" import { useState } from "react" import { dmSans125ClassName, dmSansClassName } from "@/lib/fonts" import { Dialog, DialogContent, DialogTitle } from "@repo/ui/components/dialog" import { cn } from "@lib/utils" import * as DialogPrimitive from "@radix-ui/react-dialog" import { XIcon, Loader2 } from "lucide-react" import { Button } from "@ui/components/button" import { useProjectMutations } from "@/hooks/use-project-mutations" import { Popover, PopoverContent, PopoverTrigger } from "@ui/components/popover" import { analytics } from "@/lib/analytics" import { $fetch } from "@lib/api" const EMOJI_LIST = [ "πŸ“", "πŸ“‚", "πŸ—‚οΈ", "πŸ“š", "πŸ“–", "πŸ“", "✏️", "πŸ“Œ", "🎯", "πŸš€", "πŸ’‘", "⭐", "πŸ”₯", "πŸ’Ž", "🎨", "🎡", "🏠", "πŸ’Ό", "πŸ› οΈ", "βš™οΈ", "πŸ”§", "πŸ“Š", "πŸ“ˆ", "πŸ’°", "🌟", "✨", "🌈", "🌸", "🌺", "πŸ€", "🌿", "🌴", "🐢", "🐱", "🦊", "🦁", "🐼", "🐨", "πŸ¦„", "🐝", "❀️", "πŸ’œ", "πŸ’™", "πŸ’š", "πŸ’›", "🧑", "πŸ–€", "🀍", ] export const CONTEXT_PRESETS: { label: string; text: string }[] = [ { label: "Work project", text: "Tracks a work project β€” decisions, owners, deadlines, and current status.", }, { label: "Client", text: "About a client β€” meetings, requirements, and account context.", }, { label: "Research", text: "Research notes β€” sources, key findings, and open questions.", }, { label: "Personal", text: "My personal space β€” notes, ideas, and things to remember.", }, ] export function AddSpaceModal({ isOpen, onClose, onCreated, }: { isOpen: boolean onClose: () => void onCreated?: (containerTag: string) => void }) { const [spaceName, setSpaceName] = useState("") const [spaceContext, setSpaceContext] = useState("") const [showContext, setShowContext] = useState(false) const [emoji, setEmoji] = useState("πŸ“") const [isEmojiOpen, setIsEmojiOpen] = useState(false) const { createProjectMutation } = useProjectMutations() const handleClose = () => { onClose() setSpaceName("") setSpaceContext("") setShowContext(false) setEmoji("πŸ“") } const handleCreate = () => { const trimmedName = spaceName.trim() if (!trimmedName) return createProjectMutation.mutate( { name: trimmedName, emoji: emoji || undefined }, { onSuccess: async (data) => { analytics.spaceCreated() const tag = data?.containerTag const context = showContext ? spaceContext.trim() : "" if (tag && context) { try { await $fetch(`@patch/container-tags/${tag}`, { body: { entityContext: context }, }) } catch {} } if (tag) onCreated?.(tag) handleClose() }, }, ) } const handleKeyDown = (e: React.KeyboardEvent) => { if ( e.key === "Enter" && spaceName.trim() && !createProjectMutation.isPending ) { e.preventDefault() handleCreate() } } const handleEmojiSelect = (selectedEmoji: string) => { setEmoji(selectedEmoji) setIsEmojiOpen(false) } return ( !open && handleClose()}>
New space

Group related memories and give Nova context for this space.

Close
{EMOJI_LIST.map((e) => ( ))}
setSpaceName(e.target.value)} onKeyDown={handleKeyDown} placeholder="Space name" className={cn( "flex-1 bg-[#14161A] border border-[rgba(82,89,102,0.2)] px-4 py-3 rounded-[12px] text-[#fafafa] text-[14px] placeholder:text-[#737373] focus:outline-none focus:ring-1 focus:ring-[rgba(115,115,115,0.3)]", dmSansClassName(), )} style={{ boxShadow: "0px 1px 2px 0px rgba(0,43,87,0.1), inset 0px 0px 0px 1px rgba(43,49,67,0.08), inset 0px 1px 1px 0px rgba(0,0,0,0.08), inset 0px 2px 4px 0px rgba(0,0,0,0.02)", }} autoFocus />
{!showContext ? ( ) : (
What to remember Optional