## 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>
991 lines
34 KiB
Markdown
991 lines
34 KiB
Markdown
# 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*
|