"use client"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { FileText, Loader2, MoreHorizontal, Plus, Search, Trash2, X } from "lucide-react"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { useCallback, useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { useDebouncedValue } from "@/hooks/use-debounced-value"; import { documentsApiService } from "@/lib/apis/documents-api.service"; import { notesApiService } from "@/lib/apis/notes-api.service"; import { cn } from "@/lib/utils"; interface AllNotesSidebarProps { open: boolean; onOpenChange: (open: boolean) => void; searchSpaceId: string; onAddNote?: () => void; } export function AllNotesSidebar({ open, onOpenChange, searchSpaceId, onAddNote, }: AllNotesSidebarProps) { const t = useTranslations("sidebar"); const router = useRouter(); const queryClient = useQueryClient(); const [deletingNoteId, setDeletingNoteId] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const debouncedSearchQuery = useDebouncedValue(searchQuery, 300); // Fetch all notes (when no search query) const { data: notesData, error: notesError, isLoading: isLoadingNotes, } = useQuery({ queryKey: ["all-notes", searchSpaceId], queryFn: () => notesApiService.getNotes({ search_space_id: Number(searchSpaceId), page_size: 1000, }), enabled: !!searchSpaceId && open && !debouncedSearchQuery, }); // Search notes (when there's a search query) const { data: searchData, error: searchError, isLoading: isSearching, } = useQuery({ queryKey: ["search-notes", searchSpaceId, debouncedSearchQuery], queryFn: () => documentsApiService.searchDocuments({ queryParams: { search_space_id: Number(searchSpaceId), document_types: ["NOTE"], title: debouncedSearchQuery, page_size: 100, }, }), enabled: !!searchSpaceId && open && !!debouncedSearchQuery, }); // Handle note navigation const handleNoteClick = useCallback( (noteId: number, noteSearchSpaceId: number) => { router.push(`/dashboard/${noteSearchSpaceId}/editor/${noteId}`); onOpenChange(false); }, [router, onOpenChange] ); // Handle note deletion const handleDeleteNote = useCallback( async (noteId: number, noteSearchSpaceId: number) => { setDeletingNoteId(noteId); try { await notesApiService.deleteNote({ search_space_id: noteSearchSpaceId, note_id: noteId, }); // Invalidate queries to refresh the list queryClient.invalidateQueries({ queryKey: ["all-notes", searchSpaceId] }); queryClient.invalidateQueries({ queryKey: ["notes", searchSpaceId] }); queryClient.invalidateQueries({ queryKey: ["search-notes", searchSpaceId] }); } catch (error) { console.error("Error deleting note:", error); } finally { setDeletingNoteId(null); } }, [queryClient, searchSpaceId] ); // Clear search const handleClearSearch = useCallback(() => { setSearchQuery(""); }, []); // Determine which data to show const isSearchMode = !!debouncedSearchQuery; const isLoading = isSearchMode ? isSearching : isLoadingNotes; const error = isSearchMode ? searchError : notesError; // Transform notes data - handle both regular notes and search results const notes = useMemo(() => { if (isSearchMode && searchData?.items) { return searchData.items.map((doc) => ({ id: doc.id, title: doc.title, search_space_id: doc.search_space_id, })); } return notesData?.items ?? []; }, [isSearchMode, searchData, notesData]); return ( {t("all_notes") || "All Notes"} {t("all_notes_description") || "Browse and manage all your notes"} {/* Search Input */}
setSearchQuery(e.target.value)} className="pl-9 pr-8 h-9" /> {searchQuery && ( )}
{isLoading ? (
) : error ? (
{t("error_loading_notes") || "Error loading notes"}
) : notes.length > 0 ? (
{notes.map((note) => { const isDeleting = deletingNoteId === note.id; return (
{/* Main clickable area for navigation */} {/* Actions dropdown - separate from main click area */} handleDeleteNote(note.id, note.search_space_id)} className="text-destructive focus:text-destructive" > Delete
); })}
) : isSearchMode ? (

{t("no_results_found") || "No notes found"}

{t("try_different_search") || "Try a different search term"}

) : (

{t("no_notes") || "No notes yet"}

{onAddNote && ( )}
)}
{/* Footer with Add Note button */} {onAddNote && notes.length > 0 && (
)}
); }