import React from 'react'; import { Plus, Search, Share2, Pin, ChevronRight, ArrowLeft, MoreVertical, Sparkles, Tag as TagIcon, X, BookOpen, Edit3, Eye, Trash2 } from 'lucide-react'; import { motion, AnimatePresence } from 'motion/react'; import { Note, Carnet, Tag } from '../types'; import { SlashMenu } from './SlashMenu'; interface NotebooksViewProps { activeNoteId: string | null; activeCarnet: Carnet | undefined; filteredNotes: Note[]; activeNote: Note | undefined; setActiveNoteId: (id: string | null) => void; togglePin: (id: string) => void; setShowNewNoteModal: (show: boolean) => void; isAISidebarOpen: boolean; setIsAISidebarOpen: (open: boolean) => void; selectedTagIds: string[]; setSelectedTagIds: (ids: string[]) => void; allNotes: Note[]; activeCarnetId: string; setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void; onDeleteNote: (id: string) => void; } export const NotebooksView: React.FC = ({ activeNoteId, activeCarnet, filteredNotes, activeNote, setActiveNoteId, togglePin, setShowNewNoteModal, isAISidebarOpen, setIsAISidebarOpen, selectedTagIds, setSelectedTagIds, allNotes, activeCarnetId, setShowNewCarnetModal, onDeleteNote }) => { const [isTagsExpanded, setIsTagsExpanded] = React.useState(false); const [tagSearchQuery, setTagSearchQuery] = React.useState(''); const [isEditing, setIsEditing] = React.useState(false); const [slashMenu, setSlashMenu] = React.useState<{ isOpen: boolean; top: number; left: number } | null>(null); const handleEditorKeyDown = (e: React.KeyboardEvent) => { if (e.key === '/') { const selection = window.getSelection(); if (selection && selection.rangeCount > 0) { const range = selection.getRangeAt(0); const rect = range.getBoundingClientRect(); setSlashMenu({ isOpen: true, top: rect.bottom + window.scrollY, left: rect.left + window.scrollX }); } } }; const insertCommand = (type: string) => { console.log(`Command selected: ${type}`); setSlashMenu(null); }; const availableTags = React.useMemo(() => { const carnetNotes = allNotes.filter(n => n.carnetId === activeCarnetId); const tagsMap = new Map(); carnetNotes.forEach(note => { note.tags?.forEach(tag => { tagsMap.set(tag.id, tag); }); }); return Array.from(tagsMap.values()).sort((a, b) => { // AI tags first, then alphabetical if (a.type === 'ai' && b.type !== 'ai') return -1; if (a.type !== 'ai' && b.type === 'ai') return 1; return a.label.localeCompare(b.label); }); }, [allNotes, activeCarnetId]); const visibleTags = React.useMemo(() => { let filtered = availableTags; if (tagSearchQuery) { filtered = availableTags.filter(t => t.label.toLowerCase().includes(tagSearchQuery.toLowerCase()) ); } else if (!isTagsExpanded) { filtered = availableTags.slice(0, 10); // Ensure selected tags are always visible even if not in the first 10 selectedTagIds.forEach(id => { if (!filtered.find(t => t.id === id)) { const tag = availableTags.find(t => t.id === id); if (tag) filtered.push(tag); } }); } return filtered; }, [availableTags, isTagsExpanded, tagSearchQuery, selectedTagIds]); const toggleTag = (tagId: string) => { if (selectedTagIds.includes(tagId)) { setSelectedTagIds(selectedTagIds.filter(id => id !== tagId)); } else { setSelectedTagIds([...selectedTagIds, tagId]); } }; if (!activeNoteId) { return (

{activeCarnet?.name} — {filteredNotes[0]?.date || 'Oct 26'}

Filter by Tags {selectedTagIds.length > 0 && ( {selectedTagIds.length} active )}
{availableTags.length > 10 && (
setTagSearchQuery(e.target.value)} />
)}
{visibleTags.map(tag => { const isActive = selectedTagIds.includes(tag.id); return ( toggleTag(tag.id)} className={`px-3 py-1.5 rounded-full text-[10px] font-bold uppercase tracking-wider transition-all border flex items-center gap-2 ${isActive ? 'bg-ink text-paper border-ink shadow-lg shadow-ink/10' : 'bg-white/40 border-border text-concrete hover:border-concrete/40 hover:bg-white/60'}`} > {tag.type === 'ai' && ( )} {tag.label} {isActive && } ); })} {availableTags.length > 10 && !tagSearchQuery && ( )} {selectedTagIds.length > 0 && ( )}
{filteredNotes.map((note, index) => ( setActiveNoteId(note.id)} >

{note.isPinned && } {note.title}

{note.title}
{note.tags?.map(tag => (
{tag.type === 'ai' && } {tag.label}
))}

{note.content}

Read more
))} {filteredNotes.length === 0 && (

This notebook is waiting for its first vision.

)}

© 2024 Architectural Grid. All rights reserved.

); } return (
{slashMenu?.isOpen && ( insertCommand(type)} onClose={() => setSlashMenu(null)} /> )}
{activeCarnet?.name} {activeNote?.date}
{isEditing ? ( ) : (

{activeNote?.title}

)}
{activeNote?.tags?.map(tag => (
{tag.type === 'ai' && } {tag.label} {tag.type === 'ai' && (
)}
))}
{activeNote?.title}
{isEditing ? (