'use client'; import { useState, useMemo } from 'react'; import { Note } from '@/services/notes'; import { Search, Plus, Calendar, Trash2, Tags, List } from 'lucide-react'; import { formatDistanceToNow } from 'date-fns'; import { fr } from 'date-fns/locale'; import { TagDisplay } from '@/components/ui/TagDisplay'; import { Tag } from '@/lib/types'; interface NotesListProps { notes: Note[]; onSelectNote: (note: Note) => void; onCreateNote: () => void; onDeleteNote: (noteId: string) => void; selectedNoteId?: string; isLoading?: boolean; availableTags?: Tag[]; } export function NotesList({ notes, onSelectNote, onCreateNote, onDeleteNote, selectedNoteId, isLoading = false, availableTags = [], }: NotesListProps) { const [searchQuery, setSearchQuery] = useState(''); const [showDeleteConfirm, setShowDeleteConfirm] = useState( null ); const [groupByTags, setGroupByTags] = useState(true); // Filter notes based on search query const filteredNotes = notes.filter( (note) => note.title.toLowerCase().includes(searchQuery.toLowerCase()) || note.content.toLowerCase().includes(searchQuery.toLowerCase()) ); // Group notes by tags const groupedNotes = useMemo(() => { if (!groupByTags) { return { 'Toutes les notes': filteredNotes }; } const groups: { [key: string]: Note[] } = {}; // Notes avec tags filteredNotes.forEach((note) => { if (note.tags && note.tags.length > 0) { note.tags.forEach((tag) => { if (!groups[tag]) { groups[tag] = []; } groups[tag].push(note); }); } else { // Notes sans tags if (!groups['Sans tags']) { groups['Sans tags'] = []; } groups['Sans tags'].push(note); } }); // Trier les groupes par nom de tag const sortedGroups: { [key: string]: Note[] } = {}; Object.keys(groups) .sort() .forEach((key) => { sortedGroups[key] = groups[key]; }); return sortedGroups; }, [filteredNotes, groupByTags]); const handleDeleteClick = (noteId: string, e: React.MouseEvent) => { e.stopPropagation(); setShowDeleteConfirm(noteId); }; const handleDeleteConfirm = (noteId: string) => { onDeleteNote(noteId); setShowDeleteConfirm(null); }; const handleDeleteCancel = () => { setShowDeleteConfirm(null); }; const getNoteTitle = (content: string): string => { // Extract title from first line, removing markdown headers const firstLine = content.split('\n')[0] || ''; return firstLine.replace(/^#+\s*/, '').trim() || 'Sans titre'; }; return (
{/* Header */}
{/* Search */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-[var(--border)]/60 rounded-md bg-[var(--card)]/40 backdrop-blur-sm text-[var(--foreground)] placeholder-[var(--muted-foreground)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)]/50 focus:border-[var(--primary)]/50 focus:bg-[var(--card)]/60 transition-all duration-200" />
{/* Notes List */}
{isLoading ? (
Chargement des notes...
) : filteredNotes.length === 0 ? (
{searchQuery ? 'Aucune note trouvée' : 'Aucune note pour le moment'}
) : (
{Object.entries(groupedNotes).map(([groupName, groupNotes]) => (
{/* Group Header */}

{groupName} ({groupNotes.length})

{/* Group Notes */}
{groupNotes.map((note) => (
onSelectNote(note)} className={`group relative p-3 cursor-pointer transition-all duration-200 backdrop-blur-sm ${ selectedNoteId === note.id ? 'bg-[var(--primary)]/20 border border-[var(--primary)]/30 shadow-lg shadow-[var(--primary)]/10' : 'bg-[var(--card)]/30 hover:bg-[var(--card)]/50 border border-[var(--border)]/40 hover:border-[var(--border)]/60 hover:shadow-md' }`} >

{getNoteTitle(note.content)}

{/* Tags - seulement si pas groupé par tags */} {!groupByTags && note.tags && note.tags.length > 0 && (
)}
{formatDistanceToNow(new Date(note.updatedAt), { addSuffix: true, locale: fr, })}
{/* Delete Confirmation */} {showDeleteConfirm === note.id && (
Supprimer cette note ?
)}
))}
))}
)}
); }