"use client" import { useState, useEffect, useCallback } from "react" import { Dialog, DialogContent, DialogTitle } from "@repo/ui/components/dialog" import { cn } from "@lib/utils" import { dmSansClassName } from "@/lib/fonts" import { FileTextIcon, GlobeIcon, ZapIcon, Loader2 } from "lucide-react" import { Button } from "@ui/components/button" import { ConnectContent } from "./connections" import { NoteContent } from "./note" import { LinkContent, type LinkData } from "./link" import { FileContent, type FileData } from "./file" import { useProject } from "@/stores" import { toast } from "sonner" import { useDocumentMutations } from "../../../hooks/use-document-mutations" import { useCustomer } from "autumn-js/react" import { useMemoriesUsage } from "@/hooks/use-memories-usage" import { SpaceSelector } from "../space-selector" import { useIsMobile } from "@hooks/use-mobile" type TabType = "note" | "link" | "file" | "connect" interface AddDocumentModalProps { isOpen: boolean onClose: () => void defaultTab?: TabType } export function AddDocumentModal({ isOpen, onClose, defaultTab, }: AddDocumentModalProps) { const isMobile = useIsMobile() return ( !open && onClose()}> Add Document
) } const tabs = [ { id: "note" as const, icon: FileTextIcon, title: "Write a note", description: "Save your thoughts, notes and summaries, as memories", }, { id: "link" as const, icon: GlobeIcon, title: "Save a link", description: "Add any webpage into your searchable knowledge base", }, { id: "file" as const, icon: FileTextIcon, title: "Upload a file", description: "Turn any image, PDF or document into contextual memories", }, { id: "connect" as const, icon: ZapIcon, title: "Connect knowledge bases", description: "Sync with Google Drive, Notion and OneDrive and import data", isPro: true, }, ] export function AddDocument({ defaultTab, onClose, isOpen, }: { defaultTab?: TabType onClose: () => void isOpen?: boolean }) { const isMobile = useIsMobile() const [activeTab, setActiveTab] = useState(defaultTab ?? "note") const { selectedProject: globalSelectedProject } = useProject() const [localSelectedProject, setLocalSelectedProject] = useState( globalSelectedProject, ) // Form data state for button click handling const [noteContent, setNoteContent] = useState("") const [linkData, setLinkData] = useState({ url: "", title: "", description: "", }) const [fileData, setFileData] = useState({ file: null, title: "", description: "", }) const { noteMutation, linkMutation, fileMutation } = useDocumentMutations({ onClose, }) const autumn = useCustomer() const { memoriesUsed, memoriesLimit, hasProProduct, isLoading: isLoadingMemories, usagePercent, } = useMemoriesUsage(autumn) useEffect(() => { setLocalSelectedProject(globalSelectedProject) }, [globalSelectedProject]) useEffect(() => { if (defaultTab) { setActiveTab(defaultTab) } }, [defaultTab]) // Submit handlers const handleNoteSubmit = useCallback( (content: string) => { if (!content.trim()) { toast.error("Please enter some content") return } noteMutation.mutate({ content, project: localSelectedProject }) }, [noteMutation, localSelectedProject], ) const handleLinkSubmit = useCallback( (data: LinkData) => { if (!data.url.trim()) { toast.error("Please enter a URL") return } linkMutation.mutate({ url: data.url, project: localSelectedProject }) }, [linkMutation, localSelectedProject], ) const handleFileSubmit = useCallback( (data: { file: File; title: string; description: string }) => { if (!data.file) { toast.error("Please select a file") return } fileMutation.mutate({ file: data.file, title: data.title || undefined, description: data.description || undefined, project: localSelectedProject, }) }, [fileMutation, localSelectedProject], ) // Data change handlers const handleNoteContentChange = useCallback((content: string) => { setNoteContent(content) }, []) const handleLinkDataChange = useCallback((data: LinkData) => { setLinkData(data) }, []) const handleFileDataChange = useCallback((data: FileData) => { setFileData(data) }, []) // Button click handler const handleButtonClick = () => { if (activeTab === "note") { handleNoteSubmit(noteContent) } else if (activeTab === "link") { handleLinkSubmit(linkData) } else if (activeTab === "file") { if (fileData.file) { handleFileSubmit( fileData as { file: File; title: string; description: string }, ) } else { toast.error("Please select a file") } } } const isSubmitting = noteMutation.isPending || linkMutation.isPending || fileMutation.isPending return (
{tabs.map((tab) => ( setActiveTab(tab.id)} icon={tab.icon} title={tab.title} description={tab.description} isPro={tab.isPro} compact={isMobile} /> ))}
{!isMobile && (
Memories {isLoadingMemories ? "…" : hasProProduct ? "Unlimited" : `${memoriesUsed}/${memoriesLimit}`}
{!hasProProduct && (
)}
)}
{activeTab === "note" && ( )} {activeTab === "link" && ( )} {activeTab === "file" && ( )} {activeTab === "connect" && ( )}
{!isMobile && ( )}
{activeTab !== "connect" && ( )}
) } function TabButton({ active, onClick, icon: Icon, title, description, isPro, compact, }: { active: boolean onClick: () => void icon: React.ComponentType<{ className?: string }> title: string description: string isPro?: boolean compact?: boolean }) { if (compact) { return ( ) } return ( ) }