feat: add smart tag auto-suggestions for notes

- Create smartTags utility with keyword extraction algorithm
- Filter out 100+ French stop words for better keyword quality
- Implement category-based tag suggestions (travail, dev, design, etc.)
- Suggest tags from similar notes based on content similarity
- Display smart suggestions with one-click add in note editor
- Show sparkle icon to indicate AI-assisted suggestions
- Combine multiple suggestion strategies for best results
- Limit to top 8 most relevant suggestions per note
This commit is contained in:
Claude committed 2025-11-27 14:03:41 +00:00
1 parent 712d3fd21a
commit e48bc1eaf1
2 files changed
+209 -1

No files matched your search

+30 -1
View File
@@ -15,7 +15,7 @@ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, Command
import { RichTextEditor } from "@/components/RichTextEditor";
import {
PlusCircle, Search, User, LogOut, Settings, ChevronDown, Plus, Archive, Trash2,
Image as ImageIcon, CheckSquare, FileText, Rss, ExternalLink, RefreshCw, Key, Zap, Paperclip, X, Edit, Calendar as CalendarIcon, Tag as TagIcon, MessageSquare, Send, Check, ChevronsUpDown, Star, Activity, FileDown, LayoutGrid, List
Image as ImageIcon, CheckSquare, FileText, Rss, ExternalLink, RefreshCw, Key, Zap, Paperclip, X, Edit, Calendar as CalendarIcon, Tag as TagIcon, MessageSquare, Send, Check, ChevronsUpDown, Star, Activity, FileDown, LayoutGrid, List, Sparkles
} from "lucide-react";
import AuthService from "@/services/AuthService";
import AdminService from "@/services/AdminService";
@@ -39,6 +39,7 @@ import type { NoteTemplate } from "@/utils/noteTemplates";
import { AdvancedSearch, type SearchFilters, type TagOption } from "@/components/AdvancedSearch";
import { PomodoroTimer } from "@/components/PomodoroTimer";
import { KanbanBoard } from "@/components/KanbanBoard";
import { getSmartTagSuggestions } from "@/utils/smartTags";
// ===== FONCTIONS UTILITAIRES TIMEZONE EUROPE/PARIS =====
@@ -1603,6 +1604,34 @@ const Index = () => {
</div>
)}
{/* Smart Tag Suggestions */}
{openNote && (() => {
const existingTags = noteTags.map(t => t.tag);
const suggestions = getSmartTagSuggestions(openNote, notes, existingTags);
return suggestions.length > 0 && (
<div className="space-y-2">
<p className="text-xs text-muted-foreground flex items-center gap-1">
<Sparkles className="h-3 w-3" />
Suggestions de tags
</p>
<div className="flex gap-2 flex-wrap">
{suggestions.map((suggestion) => (
<Badge
key={suggestion}
variant="outline"
className="text-xs px-2 py-1 gap-1 cursor-pointer hover:bg-primary hover:text-primary-foreground transition-colors"
onClick={() => confirmAddTag(suggestion)}
>
<Plus className="h-3 w-3" />
{suggestion}
</Badge>
))}
</div>
</div>
);
})()}
{/* Todos */}
{openNote.todos && openNote.todos.length > 0 && (
<>