feat: Complete internationalization and code cleanup
## Translation Files - Add 11 new language files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl) - Add 100+ missing translation keys across all 15 languages - New sections: notebook, pagination, ai.batchOrganization, ai.autoLabels - Update nav section with workspace, quickAccess, myLibrary keys ## Component Updates - Update 15+ components to use translation keys instead of hardcoded text - Components: notebook dialogs, sidebar, header, note-input, ghost-tags, etc. - Replace 80+ hardcoded English/French strings with t() calls - Ensure consistent UI across all supported languages ## Code Quality - Remove 77+ console.log statements from codebase - Clean up API routes, components, hooks, and services - Keep only essential error handling (no debugging logs) ## UI/UX Improvements - Update Keep logo to yellow post-it style (from-yellow-400 to-amber-500) - Change selection colors to #FEF3C6 (notebooks) and #EFB162 (nav items) - Make "+" button permanently visible in notebooks section - Fix grammar and syntax errors in multiple components ## Bug Fixes - Fix JSON syntax errors in it.json, nl.json, pl.json, zh.json - Fix syntax errors in notebook-suggestion-toast.tsx - Fix syntax errors in use-auto-tagging.ts - Fix syntax errors in paragraph-refactor.service.ts - Fix duplicate "fusion" section in nl.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Ou une version plus courte si vous préférez : feat(i18n): Add 15 languages, remove logs, update UI components - Create 11 new translation files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl) - Add 100+ translation keys: notebook, pagination, AI features - Update 15+ components to use translations (80+ strings) - Remove 77+ console.log statements from codebase - Fix JSON syntax errors in 4 translation files - Fix component syntax errors (toast, hooks, services) - Update logo to yellow post-it style - Change selection colors (#FEF3C6, #EFB162) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,990 @@
|
||||
# Product Requirements Document (PRD)
|
||||
## Notebooks & Labels Contextuels avec IA
|
||||
|
||||
**Project:** Keep (Memento Phase 1 MVP AI)
|
||||
**Date:** 2026-01-11
|
||||
**Author:** Sally (UX Designer) + Ramez (Product Owner)
|
||||
**Status:** Draft - Ready for Architecture
|
||||
**Priority:** High - Core Feature Reorganization
|
||||
|
||||
---
|
||||
|
||||
## 📋 Executive Summary
|
||||
|
||||
### Vision
|
||||
Transformer l'organisation de Keep d'un système de tags plat en une structure de **Notebooks avec Labels Contextuels**, où chaque notebook a sa propre taxonomie de labels, permettant une organisation plus naturelle et contextuelle.
|
||||
|
||||
### Objectifs Principaux
|
||||
1. ✅ Introduire les **Notebooks** comme organisation principale
|
||||
2. ✅ Rendre les **Labels contextuels** à chaque notebook
|
||||
3. ✅ Créer une **Inbox** ("Notes générales") pour les notes non organisées
|
||||
4. ✅ Intégrer l'**IA** intelligemment dans cette nouvelle structure
|
||||
5. ✅ Permettre une **migration douce** depuis le système actuel
|
||||
|
||||
---
|
||||
|
||||
## 🎯 User Stories
|
||||
|
||||
### Primary Users
|
||||
- **Ramez (Power User):** Utilise Keep quotidiennement pour organiser voyage, travail, vie perso
|
||||
- **Professionnel:** Gère des projets avec des contextes différents
|
||||
- **Voyageur:** Organise ses préparatifs de voyage avec des notes spécifiques
|
||||
|
||||
### User Journey Exemple
|
||||
|
||||
#### Scénario 1: Création de note dans Notebook
|
||||
```
|
||||
1. Ramez ouvre Keep, navigue vers Notebook "Voyage"
|
||||
2. Il voit les labels contextuels: #hôtels, #vols, #restos
|
||||
3. Il clique "Nouvelle note"
|
||||
4. La note est automatiquement assignée au Notebook "Voyage"
|
||||
5. Il peut tagger avec #hôtels (disponible car dans le bon contexte)
|
||||
```
|
||||
|
||||
#### Scénario 2: Note rapide dans Inbox
|
||||
```
|
||||
1. Ramez a une idée rapide, ouvre Keep (page d'accueil)
|
||||
2. Il tape son idée et sauve
|
||||
3. La note va dans "Notes générales" (Inbox)
|
||||
4. Plus tard, il la déplace vers "Notebook Perso"
|
||||
5. Les labels de "Perso" deviennent disponibles
|
||||
```
|
||||
|
||||
#### Scénario 3: Organisation IA-assistée
|
||||
```
|
||||
1. Ramez a 15 notes dans "Notes générales"
|
||||
2. Il clique "Organiser avec l'IA"
|
||||
3. L'IA analyse les notes et propose:
|
||||
- "3 notes pour Notebook Voyage"
|
||||
- "5 notes pour Notebook Travail"
|
||||
- "7 notes pour Notebook Perso"
|
||||
4. Ramez valide les suggestions
|
||||
5. Les notes sont déplacées automatiquement
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Structure de l'Organisation
|
||||
|
||||
### Hiérarchie
|
||||
|
||||
```
|
||||
KEEP
|
||||
├─ 📥 Notes générales (Inbox)
|
||||
│ └─ Notes sans notebook assigné
|
||||
│ └─ PAS de labels (zone temporaire)
|
||||
│
|
||||
├─ 📚 Notebooks (ordonnés manuellement)
|
||||
│ ├─ ✈️ Voyage
|
||||
│ │ ├─ Labels: #hôtels, #vols, #restos, #à_visiter
|
||||
│ │ └─ Notes assignées à "Voyage"
|
||||
│ │
|
||||
│ ├─ 💼 Travail
|
||||
│ │ ├─ Labels: #réunions, #projets, #urgent, #à_faire
|
||||
│ │ └─ Notes assignées à "Travail"
|
||||
│ │
|
||||
│ └─ 📖 Perso
|
||||
│ ├─ Labels: #idées, #rêves, #objectifs, #réflexions
|
||||
│ └─ Notes assignées à "Perso"
|
||||
│
|
||||
└─ [+] Nouveau Notebook
|
||||
```
|
||||
|
||||
### Règles Métier
|
||||
|
||||
#### R1: Appartenance des Notes
|
||||
- **Une note appartient à UN seul notebook** (ou aucune)
|
||||
- Les notes dans "Notes générales" n'appartiennent à aucun notebook
|
||||
- Une note ne peut être dans plusieurs notebooks simultanément
|
||||
|
||||
#### R2: Labels Contextuels
|
||||
- Chaque notebook a ses propres labels (100% isolés)
|
||||
- Les labels sont créés/supprimés au niveau notebook
|
||||
- Les notes dans "Notes générales" n'ont pas accès aux labels
|
||||
|
||||
#### R3: Ordre des Notebooks
|
||||
- Les notebooks sont ordonnés manuellement (drag & drop)
|
||||
- L'ordre est personnalisé par utilisateur
|
||||
- Drag & drop dans la sidebar pour réorganiser
|
||||
|
||||
#### R4: Vue "Notes générales"
|
||||
- Affiche SEULEMENT les notes sans notebook
|
||||
- PAS de vue "Toutes les notes" (tous notebooks confondus)
|
||||
- C'est une zone temporaire d'organisation
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UX/UI Specifications
|
||||
|
||||
### 1. Navigation - Sidebar
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ KEEP LOGO │
|
||||
├─────────────────────────────────────┤
|
||||
│ 🔍 Search │
|
||||
├─────────────────────────────────────┤
|
||||
│ 📚 NOTEBOOKS │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ 📥 Notes générales (12) │ │ ← Compteur de notes
|
||||
│ │ │ │
|
||||
│ │ ✈️ Voyage (8) │ │ ← Notebook actif = highlight
|
||||
│ │ ┌─ 🏷️ Labels contextuels │ │
|
||||
│ │ │ • #hôtels (3) │ │ ← Labels seulement si actif
|
||||
│ │ │ • #vols (2) │ │
|
||||
│ │ │ • #restos (3) │ │
|
||||
│ │ │ [+ Nouveau label] │ │
|
||||
│ │ └─────────────────────────────┘ │
|
||||
│ │ │ │
|
||||
│ │ 💼 Travail (15) │ │ ← Handles pour drag & drop
|
||||
│ │ ║ ║ │ │
|
||||
│ │ 📖 Perso (23) │ │
|
||||
│ │ ║ ║ │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
│ │
|
||||
│ [+ Nouveau Notebook] │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Comportements:**
|
||||
- **Click sur notebook** → Navigue vers ce notebook
|
||||
- **Drag & drop des notebooks** → Réorganise l'ordre
|
||||
- **Hover sur notebook** → Affiche les labels contextuels
|
||||
- **[+ Nouveau label]** → Crée un label dans ce notebook
|
||||
- **Compteurs** → Montre le nombre de notes
|
||||
|
||||
### 2. Création de Note
|
||||
|
||||
#### Cas A: Depuis un Notebook
|
||||
```
|
||||
User dans "Voyage" → [Nouvelle note]
|
||||
├─ Note créée avec notebookId = "voyage"
|
||||
├─ Peut utiliser les labels de "Voyage"
|
||||
└─ UI: Badge "Voyage" visible sur la note
|
||||
```
|
||||
|
||||
#### Cas B: Depuis Notes Générales
|
||||
```
|
||||
User sur page d'accueil → [Nouvelle note]
|
||||
├─ Note créée avec notebookId = null
|
||||
├─ PAS de labels disponibles
|
||||
└─ UI: Badge "À trier" visible
|
||||
```
|
||||
|
||||
#### Cas C: Création dans un autre notebook
|
||||
```
|
||||
User dans "Voyage", veut créer pour "Travail"
|
||||
├─ DOIT naviguer vers "Travail" d'abord
|
||||
├─ OU utilise le raccourci clavier (ex: Ctrl+N → chooser)
|
||||
└─ PAS de modal à chaque création
|
||||
```
|
||||
|
||||
### 3. Déplacement de Notes (Option C: A + B)
|
||||
|
||||
#### Méthode A: Drag & Drop
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 📝 Note à déplacer │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Grip handle │ Note content... │ │ ← Drag depuis ici
|
||||
│ └───────────────────────────────┘ │
|
||||
│ ↓ │
|
||||
│ Drop vers sidebar → │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ ✈️ Voyage [Drop zone] │ │
|
||||
│ │ 💼 Travail [Drop zone] │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Méthode B: Menu Contextuel
|
||||
```
|
||||
Sur une note → Click droit → Menu:
|
||||
├─ 📋 Copier
|
||||
├─ ✏️ Modifier
|
||||
├─ 📚 Déplacer vers...
|
||||
│ ├─ 📥 Notes générales
|
||||
│ ├─ ✈️ Voyage
|
||||
│ ├─ 💼 Travail
|
||||
│ └─ 📖 Perso
|
||||
├─ 🏷️ Ajouter un label
|
||||
├─ 📌 Épingler
|
||||
└─ 🗑️ Supprimer
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
- ✅ Drag & drop vers notebook dans sidebar
|
||||
- ✅ Menu contextuel "Déplacer vers..."
|
||||
- ✅ Les deux méthodes disponibles
|
||||
|
||||
### 4. Labels Contextuels
|
||||
|
||||
#### Création de Label
|
||||
```
|
||||
Dans Notebook "Voyage":
|
||||
┌─────────────────────────────────────┐
|
||||
│ 🏷️ Labels │
|
||||
│ • #hôtels • #vols • #restos │
|
||||
│ [+ Nouveau label] │ ← Click
|
||||
├─────────────────────────────────────┤
|
||||
│ Modal: │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Nom du label: │ │
|
||||
│ │ [___________] │ │
|
||||
│ │ │ │
|
||||
│ │ Couleur: ○ 🟡 ○ 🔴 ○ 🔵 │ │
|
||||
│ │ │ │
|
||||
│ │ [Annuler] [Créer] │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Assignation de Label à Note
|
||||
```
|
||||
Note dans "Voyage" → Click "Ajouter label"
|
||||
├─ Seuls les labels de "Voyage" sont proposés
|
||||
├─ Dropdown avec checkboxes
|
||||
└─ Multi-label possible sur une note
|
||||
|
||||
Exemple:
|
||||
📝 Note: "Hôtel Tokyo Shibuya"
|
||||
├─ Notebook: ✈️ Voyage
|
||||
└─ Labels: #hôtels, #réservations
|
||||
```
|
||||
|
||||
#### Suppression de Label
|
||||
```
|
||||
Options:
|
||||
├─ Supprimer le label (du notebook)
|
||||
│ └─ Warning: "Ce label sera retiré de X notes. Continuer?"
|
||||
└─ Retirer des notes seulement
|
||||
└─ Label existe toujours, mais plus utilisé
|
||||
```
|
||||
|
||||
### 5. Gestion des Notebooks
|
||||
|
||||
#### Création de Notebook
|
||||
```
|
||||
Click [+ Nouveau Notebook]
|
||||
├─ Modal de création
|
||||
│ ├─ Nom: "Voyage"
|
||||
│ ├─ Icône: [Sélecteur d'emoji]
|
||||
│ ├─ Couleur: [Sélecteur de couleur]
|
||||
│ └─ [Créer]
|
||||
└─ Notebook créé à la fin de la liste
|
||||
```
|
||||
|
||||
#### Édition de Notebook
|
||||
```
|
||||
Click droit sur notebook → Menu:
|
||||
├─ ✏️ Modifier
|
||||
│ └─ Modal: Nom, Icône, Couleur
|
||||
├─ 📊 Statistiques
|
||||
│ ├─ Nombre de notes
|
||||
│ ├─ Labels utilisés
|
||||
│ └─ Dernière mise à jour
|
||||
├─ 🗑️ Supprimer
|
||||
│ └─ Warning: "Les notes seront déplacées vers Notes générales"
|
||||
└─ ❌ Fermer
|
||||
```
|
||||
|
||||
#### Réorganisation (Drag & Drop)
|
||||
```
|
||||
✈️ Voyage ║ ║ ← Drag handle
|
||||
💼 Travail ║ ║
|
||||
📖 Perso ║ ║
|
||||
|
||||
Drag "Travail" vers le haut → Réordonne
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Intégration IA
|
||||
|
||||
C'est la partie CRUCIALE qui rend cette feature vraiment puissante.
|
||||
|
||||
### IA1: Suggestion Automatique de Notebook
|
||||
|
||||
#### Scénario
|
||||
```
|
||||
User crée une note dans "Notes générales":
|
||||
"Rendez-vous dermatologue mardi 15h à Paris"
|
||||
|
||||
IA analyse et suggère:
|
||||
┌─────────────────────────────────────┐
|
||||
│ 💡 Suggestion IA │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Cette note semble appartenir │ │
|
||||
│ │ au notebook "Perso". │ │
|
||||
│ │ │ │
|
||||
│ │ [Ignorer] [Déplacer vers Perso]│ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Prompt IA:**
|
||||
```
|
||||
"Analyse cette note et suggère le notebook le plus approprié:
|
||||
Note: {content}
|
||||
Notebooks disponibles: {notebook_names_with_labels}
|
||||
|
||||
Réponds avec:
|
||||
- notebook_suggéré: string
|
||||
- confiance: 0-1
|
||||
- raisonnement: string"
|
||||
```
|
||||
|
||||
**Déclencheurs:**
|
||||
- Note créée dans "Notes générales"
|
||||
- Note modifiée significativement
|
||||
- 5+ secondes après la fin de frappe (pas en temps réel)
|
||||
|
||||
### IA2: Suggestion de Labels Contextuels
|
||||
|
||||
#### Scénario
|
||||
```
|
||||
Note dans Notebook "Voyage":
|
||||
"Hotel Shibuya Excel - 150€/nuit - Booking confirmé"
|
||||
|
||||
IA suggère:
|
||||
┌─────────────────────────────────────┐
|
||||
│ 💡 Suggestions de labels │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ ✅ #hôtels (confiance: 95%) │ │ ← Click pour assigner
|
||||
│ │ ✅ #réservations (80%) │ │
|
||||
│ │ ✅ #tokyo (70%) │ │
|
||||
│ │ │ │
|
||||
│ │ [Tout sélectionner] [Ignorer] │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Prompt IA:**
|
||||
```
|
||||
"Analyse cette note et suggère les labels appropriés:
|
||||
Note: {content}
|
||||
Notebook actuel: {notebook_name}
|
||||
Labels disponibles dans ce notebook: {available_labels}
|
||||
|
||||
Réponds avec un tableau de:
|
||||
- label: string (doit être dans {available_labels})
|
||||
- confiance: 0-1
|
||||
- raisonnement: string"
|
||||
```
|
||||
|
||||
**Comportement:**
|
||||
- ✅ Maximum 3 suggestions
|
||||
- ✅ Seulement si confiance > 60%
|
||||
- ✅ Labels cliquables pour assignation en 1 clic
|
||||
- ✅ Ne pas déranger si l'utilisateur tape activement
|
||||
|
||||
### IA3: Organisation Intelligente (Batch Processing)
|
||||
|
||||
#### Scénario
|
||||
```
|
||||
User a 20 notes dans "Notes générales"
|
||||
|
||||
Click "Organiser avec l'IA"
|
||||
├─ IA analyse toutes les notes
|
||||
├- Groupe par thématique
|
||||
└─ Présente un plan d'organisation:
|
||||
|
||||
┌─────────────────────────────────────┐
|
||||
│ 📋 Plan d'organisation IA │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Notebook: Voyage (5 notes) │ │
|
||||
│ │ • Hotel Tokyo... │ │
|
||||
│ │ • Vols JAL... │ │
|
||||
│ │ • Restaurant Shibuya... │ │
|
||||
│ │ [Tout sélectionner] │ │
|
||||
│ │ │ │
|
||||
│ │ Notebook: Travail (8 notes) │ │
|
||||
│ │ • Réunion lundi... │ │
|
||||
│ │ • Projet Alpha... │ │
|
||||
│ │ ... │ │
|
||||
│ │ │ │
|
||||
│ │ Notebook: Perso (7 notes) │ │
|
||||
│ │ • Idées livre... │ │
|
||||
│ │ ... │ │
|
||||
│ │ │ │
|
||||
│ │ [Annuler] [Appliquer tout] │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Prompt IA:**
|
||||
```
|
||||
"Analyse ces {count} notes et propose une organisation:
|
||||
{notes_with_content}
|
||||
|
||||
Notebooks disponibles: {notebooks}
|
||||
|
||||
Pour chaque notebook, indique:
|
||||
- notebook_cible: string
|
||||
- notes: [{note_id, note_title, confidence, raison}]
|
||||
|
||||
Retourne un plan d'organisation optimisé."
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
- ✅ User peut désélectionner des notes
|
||||
- ✅ User peut ajuster les destinations
|
||||
- ✅ Confirmation avant application
|
||||
- ✅ Undo possible (Ctrl+Z)
|
||||
|
||||
### IA4: Création Automatique de Labels
|
||||
|
||||
#### Scénario
|
||||
```
|
||||
Notebook "Voyage" devient peuplé de notes sur le Japon
|
||||
|
||||
IA détecte:
|
||||
- 10+ notes mentionnant "Tokyo"
|
||||
- 8+ notes mentionnant "Kyoto"
|
||||
- 5+ notes mentionnant "Osaka"
|
||||
|
||||
IA suggère:
|
||||
┌─────────────────────────────────────┐
|
||||
│ 💡 Suggestions de nouveaux labels │ │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ J'ai détecté des thèmes récurrents│
|
||||
│ │ dans vos notes. Créer des labels?│
|
||||
│ │ │ │
|
||||
│ │ ✅ #tokyo (10 notes) │ │
|
||||
│ │ ✅ #kyoto (8 notes) │ │
|
||||
│ │ ✅ #osaka (5 notes) │ │
|
||||
│ │ │ │
|
||||
│ │ [Annuler] [Créer et assigner] │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Déclencheur:**
|
||||
- Notebook atteint 15+ notes
|
||||
- IA détecte 3+ mots-clés récurrents (5+ fois chacun)
|
||||
- Ne propose PAS si les labels existent déjà
|
||||
|
||||
### IA5: Recherche Sémantique par Notebook
|
||||
|
||||
#### Scénario
|
||||
```
|
||||
User dans Notebook "Voyage" tape:
|
||||
"endroit pour dormir pas cher"
|
||||
|
||||
IA comprend le contexte "Voyage" et cherche:
|
||||
├─ Semantic search DANS ce notebook seulement
|
||||
├- Priorise les labels #hôtels, #auberges
|
||||
└- Résultats plus pertinents car contextuels
|
||||
|
||||
Résultats:
|
||||
┌─────────────────────────────────────┐
|
||||
│ 🔍 Résultats dans "Voyage" │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ 📝 Capsule Hotel Shinjuku │ │
|
||||
│ │ #hôtels #tokyo │ │
|
||||
│ │ "Hotel capsule 30€/nuit..." │ │
|
||||
│ │ Correspondance: 87% │ │
|
||||
│ │ │ │
|
||||
│ │ 📝 Airbnb Asakusa │ │
|
||||
│ │ #hôtels #tokyo │ │
|
||||
│ │ "Appartement 45€/nuit..." │ │
|
||||
│ │ Correspondance: 82% │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Avantage:**
|
||||
- ✅ Recherche contextuelle au notebook
|
||||
- ✅ Résultats plus pertinents
|
||||
- ✅ Comprend le jargon spécifique (ex: "vol" dans Voyage vs Travail)
|
||||
|
||||
### IA6: Synthèse par Notebook
|
||||
|
||||
#### Scénario
|
||||
```
|
||||
User clique "Résumer ce notebook" dans "Voyage"
|
||||
|
||||
IA génère:
|
||||
┌─────────────────────────────────────┐
|
||||
│ 📊 Synthèse du Notebook Voyage │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ 🌍 Destinations │ │
|
||||
│ │ • Japon (Tokyo, Kyoto) │ │
|
||||
│ │ • France (Paris) │ │
|
||||
│ │ │ │
|
||||
│ │ 📅 Dates │ │
|
||||
│ │ • 15-25 Mars 2024 │ │
|
||||
│ │ │ │
|
||||
│ │ 🏨 Réservations │ │
|
||||
│ │ • 3 hôtels réservés │ │
|
||||
│ │ • 2 vols confirmés │ │
|
||||
│ │ • 5 restaurants identifiés │ │
|
||||
│ │ │ │
|
||||
│ │ 💰 Budget estimé: 3500€ │ │
|
||||
│ │ │ │
|
||||
│ │ ⚠️ Actions requises │ │
|
||||
│ │ • Réserver visa japonais │ │
|
||||
│ │ • Confirmer assurance voyage │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Prompt IA:**
|
||||
```
|
||||
"Génère une synthèse structurée de ce notebook:
|
||||
{notes_with_labels}
|
||||
|
||||
Inclus:
|
||||
- Destinations/Thèmes principaux
|
||||
- Dates importantes
|
||||
- Éléments réservés vs planifiés
|
||||
- Actions requises
|
||||
- Statistiques (nombre de notes, labels utilisés)
|
||||
|
||||
Format: Markdown structuré avec emojis."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Structure de Données (Database Schema)
|
||||
|
||||
### Prisma Schema - Nouveaux Modèles
|
||||
|
||||
```prisma
|
||||
// Modèle Notebook
|
||||
model Notebook {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
icon String? // Emoji: "✈️", "💼", "📖"
|
||||
color String? // Hex color: "#FF6B6B"
|
||||
order Int // Ordre manuel dans la sidebar
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
notes Note[]
|
||||
labels Label[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([userId, order])
|
||||
}
|
||||
|
||||
// Modèle Label MODIFIÉ - Ajout notebookId
|
||||
model Label {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
color String? // Couleur du label
|
||||
notebookId String // NOUVEAU: Label appartient à un notebook
|
||||
notebook Notebook @relation(fields: [notebookId], references: [id], onDelete: Cascade)
|
||||
notes Note[] // Relation many-to-many via NoteLabel
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([notebookId, name]) // Un label est unique dans un notebook
|
||||
@@index([notebookId])
|
||||
}
|
||||
|
||||
// Modèle Note MODIFIÉ - Ajout notebookId (optionnel)
|
||||
model Note {
|
||||
id String @id @default(cuid())
|
||||
title String?
|
||||
content String
|
||||
// ... autres champs existants ...
|
||||
|
||||
notebookId String? // NOUVEAU: Optionnel - null = dans "Notes générales"
|
||||
notebook Notebook? @relation(fields: [notebookId], references: [id], onDelete: SetNull)
|
||||
|
||||
// Garantir qu'une note est dans UN SEUL notebook
|
||||
@@index([userId, notebookId])
|
||||
}
|
||||
|
||||
// Table de jonction Note-Label (existante mais gardée)
|
||||
model NoteLabel {
|
||||
noteId String
|
||||
labelId String
|
||||
note Note @relation(fields: [noteId], references: [id], onDelete: Cascade)
|
||||
label Label @relation(fields: [labelId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([noteId, labelId])
|
||||
@@index([noteId])
|
||||
@@index([labelId])
|
||||
}
|
||||
```
|
||||
|
||||
### Clés de la Structure
|
||||
|
||||
**Règles d'intégrité:**
|
||||
1. ✅ `Note.notebookId` est **optionnel** (null = Notes générales)
|
||||
2. ✅ `Label.notebookId` est **obligatoire** (labels TOUJOURS contextuels)
|
||||
3. ✅ `@@unique([notebookId, name])` = Unicité des labels DANS un notebook
|
||||
4. ✅ `onDelete: SetNull` sur Note→Notebook = Si notebook supprimé, notes → Notes générales
|
||||
|
||||
### Migration Schema
|
||||
|
||||
```sql
|
||||
-- Étape 1: Ajouter les nouveaux modèles
|
||||
CREATE TABLE "Notebook" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"icon" TEXT,
|
||||
"color" TEXT,
|
||||
"order" INTEGER NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Étape 2: Ajouter notebookId aux Notes (optionnel)
|
||||
ALTER TABLE "Note" ADD COLUMN "notebookId" TEXT;
|
||||
ALTER TABLE "Note" ADD FOREIGN KEY ("notebookId") REFERENCES "Notebook"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- Étape 3: Ajouter notebookId aux Labels (obligatoire)
|
||||
ALTER TABLE "Label" ADD COLUMN "notebookId" TEXT NOT NULL DEFAULT 'TEMP_MIGRATION';
|
||||
ALTER TABLE "Label" ADD FOREIGN KEY ("notebookId") REFERENCES "Notebook"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- Étape 4: Créer notebook par défaut pour la migration
|
||||
INSERT INTO "Notebook" (id, name, icon, color, "order", "userId")
|
||||
VALUES (
|
||||
'migration_default',
|
||||
'Labels existants',
|
||||
'📦',
|
||||
'#9CA3AF',
|
||||
999,
|
||||
{user_id}
|
||||
);
|
||||
|
||||
-- Étape 5: Assigner tous les labels existants à ce notebook
|
||||
UPDATE "Label" SET "notebookId" = 'migration_default' WHERE "notebookId" = 'TEMP_MIGRATION';
|
||||
|
||||
-- Étape 6: Laisser toutes les notes SANS notebook (Notes générales)
|
||||
-- Rien à faire - notebookId est déjà NULL par défaut
|
||||
|
||||
-- Étape 7: Créer index pour performance
|
||||
CREATE INDEX "Note_userId_notebookId_idx" ON "Note"("userId", "notebookId");
|
||||
CREATE UNIQUE INDEX "Label_notebookId_name_key" ON "Label"("notebookId", "name");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Migration des Données Existantes
|
||||
|
||||
### Stratégie de Migration
|
||||
|
||||
#### Phase 1: Pré-migration (Backend)
|
||||
|
||||
```typescript
|
||||
// app/actions/migration/prepare-notebooks.ts
|
||||
'use server'
|
||||
|
||||
export async function prepareNotebookMigration() {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) throw new Error('Unauthorized')
|
||||
|
||||
// 1. Créer notebook "Import" pour les labels existants
|
||||
const importNotebook = await prisma.notebook.create({
|
||||
data: {
|
||||
name: 'Labels existants',
|
||||
icon: '📦',
|
||||
color: '#9CA3AF',
|
||||
order: 999,
|
||||
userId: session.user.id
|
||||
}
|
||||
})
|
||||
|
||||
// 2. Assigner TOUS les labels existants à ce notebook
|
||||
await prisma.label.updateMany({
|
||||
where: { userId: session.user.id },
|
||||
data: { notebookId: importNotebook.id }
|
||||
})
|
||||
|
||||
// 3. Laisser les notes SANS notebook (Notes générales)
|
||||
// Rien à faire - notebookId est NULL par défaut
|
||||
|
||||
return { success: true, importNotebookId: importNotebook.id }
|
||||
}
|
||||
```
|
||||
|
||||
#### Phase 2: Migration Interactive (User Journey)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 🎉 Bienvenue dans les Notebooks ! │
|
||||
│ │
|
||||
│ Nous avons organisé vos étiquettes existantes dans │
|
||||
│ le notebook "Labels existants" pour ne rien perdre. │
|
||||
│ │
|
||||
│ 📊 État actuel: │
|
||||
│ • 15 notes sans notebook (à organiser) │
|
||||
│ • 1 notebook "Labels existants" │
|
||||
│ • 12 étiquettes préservées │
|
||||
│ │
|
||||
│ Que voulez-vous faire ? │
|
||||
│ │
|
||||
│ [1] Laisser l'IA organiser mes notes │
|
||||
│ [2] Explorer et créer mes propres notebooks │
|
||||
│ [3] Tout déplacer vers "Notes générales" │
|
||||
│ │
|
||||
│ [Plus tard] Je déciderai plus tard │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Phase 3: Organisation IA (Option 1)
|
||||
|
||||
Si user choisit "Laisser l'IA organiser":
|
||||
|
||||
```typescript
|
||||
// app/actions/migration/ai-organize.ts
|
||||
'use server'
|
||||
|
||||
export async function organizeWithAI() {
|
||||
const session = await auth()
|
||||
const notesWithoutNotebook = await prisma.note.findMany({
|
||||
where: {
|
||||
userId: session.user.id,
|
||||
notebookId: null
|
||||
}
|
||||
})
|
||||
|
||||
// IA analyse et propose des notebooks
|
||||
const suggestions = await aiService.suggestNotebooks(notesWithoutNotebook)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
suggestions: [
|
||||
{
|
||||
notebookName: 'Voyage',
|
||||
icon: '✈️',
|
||||
color: '#3B82F6',
|
||||
notes: [/* notes suggérées */],
|
||||
confidence: 0.89
|
||||
},
|
||||
{
|
||||
notebookName: 'Travail',
|
||||
icon: '💼',
|
||||
color: '#10B981',
|
||||
notes: [/* notes suggérées */],
|
||||
confidence: 0.92
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Phase 4: Validation User
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 📋 Plan d'organisation proposé par l'IA │
|
||||
│ │
|
||||
│ ✈️ Voyage (5 notes) - Confiance: 89% │
|
||||
│ ☑ Hotel Tokyo Shibuya │
|
||||
│ ☑ Vols JAL Tokyo-Paris │
|
||||
│ ☑ Restaurant Shibuya │
|
||||
│ ☑ Visa japonais │
|
||||
│ ☑ Itinéraire Kyoto │
|
||||
│ │
|
||||
│ 💼 Travail (8 notes) - Confiance: 92% │
|
||||
│ ☑ Réunion lundi │
|
||||
│ ☑ Projet Alpha │
|
||||
│ ☑ ... │
|
||||
│ │
|
||||
│ 📖 Perso (2 notes) - Confiance: 76% │
|
||||
│ ☑ Idées livre │
|
||||
│ ☑ Objectifs 2024 │
|
||||
│ │
|
||||
│ [Désélectionner] [Annuler] [Appliquer] │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Success Metrics
|
||||
|
||||
### KPIs à Mesurer
|
||||
|
||||
**Adoption:**
|
||||
- % d'utilisateurs créant au moins 1 notebook dans les 30 jours
|
||||
- Nombre moyen de notebooks par utilisateur actif
|
||||
- % de notes organisées (avec notebook) vs notes générales
|
||||
|
||||
**Engagement:**
|
||||
- Temps passé par notebook (ex: Voyage plus actif avant un voyage)
|
||||
- Fréquence d'utilisation des labels contextuels
|
||||
- Taux d'utilisation des suggestions IA
|
||||
|
||||
**Satisfaction:**
|
||||
- NPS (Net Promoter Score) sur la feature notebooks
|
||||
- % d'utilisateurs gardant le système par défaut (Import) vs créant les leurs
|
||||
- Taux d'abandon lors de la migration
|
||||
|
||||
**Performance IA:**
|
||||
- Taux d'acceptation des suggestions IA (notebook)
|
||||
- Taux d'acceptation des suggestions IA (labels)
|
||||
- Précision des suggestions (feedback utilisateur)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Implementation Phases
|
||||
|
||||
### Phase 1: MVP (Weeks 1-3)
|
||||
**Objectif:** Structure de base sans IA
|
||||
|
||||
- ✅ Database schema (Notebook, Label modifié, Note modifié)
|
||||
- ✅ API endpoints (CRUD notebooks)
|
||||
- ✅ UI: Sidebar avec notebooks
|
||||
- ✅ UI: Création/édition de notebooks
|
||||
- ✅ UI: Assignation de notebook aux notes
|
||||
- ✅ UI: Labels contextuels (affichage)
|
||||
- ✅ UI: Drag & drop des notebooks
|
||||
- ✅ Migration: Notebook "Import" par défaut
|
||||
- ❌ PAS d'IA encore
|
||||
|
||||
### Phase 2: IA Features (Weeks 4-5)
|
||||
**Objectif:** IA pour organisation intelligente
|
||||
|
||||
- ✅ IA1: Suggestion automatique de notebook
|
||||
- ✅ IA2: Suggestion de labels contextuels
|
||||
- ✅ IA3: Organisation batch (Notes générales → Notebooks)
|
||||
- ✅ UI: Modals de suggestions IA
|
||||
- ✅ Feedback loop (accepter/rejeter suggestions)
|
||||
|
||||
### Phase 3: Advanced IA (Weeks 6-7)
|
||||
**Objectif:** Features IA avancées
|
||||
|
||||
- ✅ IA4: Création automatique de labels
|
||||
- ✅ IA5: Recherche sémantique contextuelle
|
||||
- ✅ IA6: Synthèse par notebook
|
||||
- ✅ Analytics: Dashboard d'utilisation des notebooks
|
||||
|
||||
### Phase 4: Polish & Testing (Week 8)
|
||||
**Objectif:** Finalisation et tests
|
||||
|
||||
- ✅ Playwright E2E tests
|
||||
- ✅ Performance optimization
|
||||
- ✅ Accessibility audit
|
||||
- ✅ Beta testing avec users
|
||||
- ✅ Documentation
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Risques & Mitigations
|
||||
|
||||
### Risque 1: Résistance au changement
|
||||
**Description:** Users habitués aux tags globaux pourraient rejeter les notebooks
|
||||
|
||||
**Mitigation:**
|
||||
- Phase de migration douce (optionnel)
|
||||
- Mode hybride temporaire (garder vue tags pendant transition)
|
||||
- Tutoriels interactifs
|
||||
- Onboarding progressif
|
||||
|
||||
### Risque 2: Performance IA
|
||||
**Description:** Suggestions IA pourraient être lentes ou inexactes
|
||||
|
||||
**Mitigation:**
|
||||
- Cache des suggestions (24h)
|
||||
- Seuils de confiance minimums (>60%)
|
||||
- Feedback loop pour améliorer le modèle
|
||||
- Fallback rapide si IA timeout
|
||||
|
||||
### Risque 3: Migration des données
|
||||
**Description:** Perte de données ou organisation pendant la migration
|
||||
|
||||
**Mitigation:**
|
||||
- Backup automatique avant migration
|
||||
- Migration par défaut (notebook "Import")
|
||||
- Possibilité de revenir en arrière (rollback)
|
||||
- Tests exhaustifs de migration
|
||||
|
||||
### Risque 4: Complexité UX
|
||||
**Description:** Trop de clics pour organiser les notes
|
||||
|
||||
**Mitigation:**
|
||||
- Drag & drop intuitif
|
||||
- Raccourcis clavier
|
||||
- IA pour automatiser l'organisation
|
||||
- Mesures d'usabilité (clics, temps)
|
||||
|
||||
### Risque 5: Labels contextuels = perte de flexibilité
|
||||
**Description:** Users ne peuvent plus utiliser un label global (#urgent partout)
|
||||
|
||||
**Mitigation:**
|
||||
- Éduquer: "Urgent" peut être recréé dans chaque notebook
|
||||
- IA suggère de recréer les labels importants
|
||||
- Option: Labels "favoris" synchronisés (feature future)
|
||||
|
||||
---
|
||||
|
||||
## 📚 Glossaire
|
||||
|
||||
- **Notebook:** Collection de notes sur un thème (ex: Voyage, Travail)
|
||||
- **Labels Contextuels:** Tags spécifiques à un notebook (ex: #hôtels dans Voyage)
|
||||
- **Inbox / Notes générales:** Zone temporaire pour les notes non organisées
|
||||
- **IA:** Intelligence Artificielle (OpenAI ou Ollama)
|
||||
- **Suggestion IA:** Proposition automatique basée sur l'analyse du contenu
|
||||
- **Drag & Drop:** Action de glisser-déposer pour déplacer des éléments
|
||||
- **Migration:** Transition du système de tags vers les notebooks
|
||||
- **Notebook par défaut:** Notebook créé automatiquement pour préserver les tags existants
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes pour l'Architecture Team
|
||||
|
||||
### Points Critiques à Implémenter
|
||||
|
||||
1. **Database:**
|
||||
- `Note.notebookId` est OPTIONNEL (null = Notes générales)
|
||||
- `Label.notebookId` est OBLIGATOIRE
|
||||
- Contrainte d'unicité: `@@unique([notebookId, name])`
|
||||
|
||||
2. **API:**
|
||||
- Nouveau endpoint: `/api/notebooks` (CRUD complet)
|
||||
- Endpoint modifié: `/api/labels` (filtre par notebook)
|
||||
- Endpoint modifié: `/api/notes` (filtre par notebook)
|
||||
|
||||
3. **UI Components:**
|
||||
- `SidebarNotebooks`: Liste des notebooks avec drag & drop
|
||||
- `NotebookSelector`: Dropdown pour choisir le notebook
|
||||
- `ContextualLabels`: Labels filtrés par notebook actif
|
||||
- `AISuggestions`: Modals pour les suggestions IA
|
||||
|
||||
4. **IA Services:**
|
||||
- `NotebookSuggestionService`: IA pour suggérer un notebook
|
||||
- `LabelSuggestionService`: IA pour suggérer des labels
|
||||
- `BatchOrganizationService`: IA pour organiser en lot
|
||||
- `AutoLabelCreationService`: IA pour créer des labels
|
||||
|
||||
5. **Performance:**
|
||||
- Index sur `Note.userId + Note.notebookId`
|
||||
- Cache des suggestions IA (Redis ou in-memory)
|
||||
- Virtual scrolling pour les notebooks avec 100+ notes
|
||||
|
||||
---
|
||||
|
||||
## ✅ Checklist de Validation
|
||||
|
||||
Avant de passer en développement, confirmer:
|
||||
|
||||
- [ ] Ramez valide l'UX décrite dans ce document
|
||||
- [ ] L'Architecture Team a revu le schéma DB
|
||||
- [ ] L'équipe IA a validé les prompts proposés
|
||||
- [ ] Les risques sont acceptables et des mitigations sont en place
|
||||
- [ ] Le plan de migration est testé sur un dataset de test
|
||||
- [ ] Les mesures de succès (KPIs) sont définies et traçables
|
||||
- [ ] Le wireframe UI est validé par Ramez
|
||||
- [ ] L'implémentation est planifiée sur 8 semaines max
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ PRD COMPLET - Prêt pour Architecture et Wireframes
|
||||
|
||||
**Next Steps:**
|
||||
1. Créer les wireframes UX (Option XW)
|
||||
2. Définir l'architecture technique
|
||||
3. Commencer Phase 1 (MVP)
|
||||
|
||||
---
|
||||
|
||||
*Document créé par Sally (UX Designer) avec Ramez (Product Owner)*
|
||||
*Date: 2026-01-11*
|
||||
*Version: 1.0 - Final*
|
||||
Reference in New Issue
Block a user