Keep/COMPLETED-FEATURES.md
sepehr f0b41572bc feat: Memento avec dates, Markdown, reminders et auth
Tests Playwright validés :
- Création de notes: OK
- Modification titre: OK
- Modification contenu: OK
- Markdown éditable avec preview: OK

Fonctionnalités:
- date-fns: dates relatives sur cards
- react-markdown + remark-gfm
- Markdown avec toggle edit/preview
- Recherche améliorée (titre/contenu/labels/checkItems)
- Reminder recurrence/location (schema)
- NextAuth.js + User/Account/Session
- userId dans Note (optionnel)
- 4 migrations créées

Ready for production + auth integration
2026-01-04 16:04:24 +01:00

560 lines
17 KiB
Markdown

# Memento - Fonctionnalités Complétées
## 📋 Table des matières
- [Phase 1: Setup Initial](#phase-1-setup-initial)
- [Phase 2: Interface Utilisateur](#phase-2-interface-utilisateur)
- [Phase 3: Fonctionnalités Core](#phase-3-fonctionnalités-core)
- [Phase 4: API REST](#phase-4-api-rest)
- [Phase 5: MCP Server](#phase-5-mcp-server)
- [Phase 6: Images](#phase-6-images)
- [Phase 7: N8N Integration](#phase-7-n8n-integration)
- [Stack Technique](#stack-technique)
---
## Phase 1: Setup Initial
### ✅ Projet Next.js 16 créé
**Date**: Début du projet
**Fichiers**: Configuration complète Next.js 16.1.1
- App Router avec TypeScript
- Turbopack pour les builds ultra-rapides
- Configuration `next.config.ts` optimisée
- Structure de dossiers: `app/`, `components/`, `lib/`, `prisma/`
### ✅ Tailwind CSS 4 configuré
**Fichiers**: `tailwind.config.ts`, `app/globals.css`
- Installation Tailwind CSS 4.0.0
- Configuration des couleurs personnalisées (soft pastels)
- Responsive breakpoints: `sm`, `md`, `lg`, `xl`, `2xl`
- Plugins: `@tailwindcss/typography`, `tailwindcss-animate`
### ✅ shadcn/ui installé (11 composants)
**Composants installés**:
1. `Dialog` - Modales pour éditer les notes
2. `Tooltip` - Info-bulles sur les boutons
3. `DropdownMenu` - Menus contextuels
4. `Badge` - Labels/tags visuels
5. `Checkbox` - Cases à cocher pour checklists
6. `Input` - Champs de texte
7. `Textarea` - Zones de texte multi-lignes
8. `Button` - Boutons stylisés
9. `Card` - Conteneurs pour les notes
10. `TooltipProvider` - Provider pour tooltips
11. `DropdownMenuItem` - Items de menu dropdown
### ✅ Prisma ORM configuré
**Fichiers**: `prisma/schema.prisma`, `lib/prisma.ts`
- Base de données SQLite: `D:/dev_new_pc/Keep/keep-notes/prisma/dev.db`
- Schema `Note` avec tous les champs nécessaires
- Singleton Prisma Client pour éviter les multiples connexions
- Migration `20260104105155_add_images` appliquée
**Schema Prisma**:
```prisma
model Note {
id String @id @default(cuid())
title String?
content String
color String @default("default")
type String @default("text")
checkItems String? // JSON array
labels String? // JSON array
images String? // JSON array base64
isPinned Boolean @default(false)
isArchived Boolean @default(false)
order Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
```
---
## Phase 2: Interface Utilisateur
### ✅ Masonry Layout CSS
**Fichiers**: `app/page.tsx`, composants de notes
- Utilisation de CSS columns pour masonry layout
- Responsive: `columns-1 sm:columns-2 lg:columns-3 xl:columns-4 2xl:columns-5`
- `break-inside-avoid` pour éviter la coupure des cartes
- Gap de 16px entre les colonnes et cartes
### ✅ Système de couleurs soft pastels
**Fichiers**: `lib/types.ts`, `lib/utils.ts`
- 10 couleurs disponibles: default, red, orange, yellow, green, teal, blue, purple, pink, gray
- Utilisation de `bg-*-50` au lieu de `bg-*-100` pour des tons plus doux
- Classes Tailwind dynamiques avec `cn()` utility
**Couleurs implémentées**:
```typescript
export const NOTE_COLORS = {
default: { bg: 'bg-white', border: 'border-gray-200', hover: 'hover:bg-gray-50' },
red: { bg: 'bg-red-50', border: 'border-red-200', hover: 'hover:bg-red-100' },
orange: { bg: 'bg-orange-50', border: 'border-orange-200', hover: 'hover:bg-orange-100' },
yellow: { bg: 'bg-yellow-50', border: 'border-yellow-200', hover: 'hover:bg-yellow-100' },
green: { bg: 'bg-green-50', border: 'border-green-200', hover: 'hover:bg-green-100' },
teal: { bg: 'bg-teal-50', border: 'border-teal-200', hover: 'hover:bg-teal-100' },
blue: { bg: 'bg-blue-50', border: 'border-blue-200', hover: 'hover:bg-blue-100' },
purple: { bg: 'bg-purple-50', border: 'border-purple-200', hover: 'hover:bg-purple-100' },
pink: { bg: 'bg-pink-50', border: 'border-pink-200', hover: 'hover:bg-pink-100' },
gray: { bg: 'bg-gray-50', border: 'border-gray-200', hover: 'hover:bg-gray-100' }
}
```
### ✅ Toolbar avec 9 icônes Lucide React
**Fichiers**: `components/note-input.tsx`, `components/note-editor.tsx`
**Icônes implémentées**:
1. **Bell** - Remind me ✅ **FONCTIONNEL**
2. **Image** - Ajouter image ✅
3. **UserPlus** - Collaborateur (⚠️ non fonctionnel)
4. **Palette** - Changer couleur ✅
5. **Archive** - Archiver note ✅
6. **MoreVertical** - Plus d'options ✅
7. **Undo2** - Annuler ✅ **FONCTIONNEL**
8. **Redo2** - Rétablir ✅ **FONCTIONNEL**
9. **CheckSquare** - Mode checklist ✅
---
## Phase 3: Fonctionnalités Core
### ✅ CRUD complet avec Server Actions
**Fichiers**: `app/actions/notes.ts`
**Actions implémentées**:
1. `getNotes()` - Récupérer toutes les notes (tri: pinned > order > updatedAt)
2. `createNote()` - Créer une nouvelle note
3. `updateNote()` - Mettre à jour une note existante
4. `deleteNote()` - Supprimer une note
5. `updateNoteOrder()` - Mettre à jour l'ordre après drag-and-drop
6. `searchNotes()` - Rechercher dans title/content
**Parsing JSON automatique**:
```typescript
function parseNote(dbNote: any): Note {
return {
...dbNote,
checkItems: dbNote.checkItems ? JSON.parse(dbNote.checkItems) : null,
labels: dbNote.labels ? JSON.parse(dbNote.labels) : null,
images: dbNote.images ? JSON.parse(dbNote.images) : null,
}
}
```
### ✅ Notes texte et checklist
**Fichiers**: `components/note-input.tsx`, `components/note-card.tsx`
- Basculer entre mode texte et checklist
- Ajouter/supprimer/cocher items dans checklist
- Affichage conditionnel selon le type
- Chaque item a: `{id: string, text: string, checked: boolean}`
### ✅ Labels/Tags
**Implémentation**: Array de strings stocké en JSON
- Ajouter plusieurs labels par note
- Affichage avec badges colorés
- Filtre par label (à implémenter dans recherche)
### ✅ Pin/Unpin notes
**Fichier**: `app/actions/notes.ts`
- Toggle `isPinned` boolean
- Tri automatique: notes épinglées en premier
- Icône visuelle (Pin/PinOff) sur les cartes
### ✅ Archive/Unarchive
**Fichier**: `app/actions/notes.ts`
- Toggle `isArchived` boolean
- Notes archivées exclues par défaut de la vue principale
- Possibilité de voir les archives (paramètre `includeArchived`)
### ✅ Recherche full-text
**Fichier**: `app/page.tsx`, `app/actions/notes.ts`
- Barre de recherche dans le header
- Recherche dans `title` et `content` (case-insensitive)
- Prisma `contains` avec mode `insensitive`
- Temps réel avec debouncing
### ✅ Drag-and-drop pour réorganiser
**Fichiers**: `components/note-card.tsx`, `app/actions/notes.ts`, `components/note-grid.tsx`
- Utilisation du drag-and-drop HTML5 natif
- Champ `order` dans la DB pour persister l'ordre
- Réorganisation visuelle fluide avec feedback (opacity-30 pendant le drag)
- `reorderNotes()` pour sauvegarder les changements
- Fonctionne séparément pour les notes épinglées et non-épinglées
- Persistance après rechargement de page
### ✅ Undo/Redo dans note-input
**Fichiers**: `components/note-input.tsx`, `hooks/useUndoRedo.ts`
- Historique de 50 états maximum
- Sauvegarde automatique après 1 seconde d'inactivité
- Boutons Undo/Redo dans la toolbar
- Raccourcis clavier:
- `Ctrl+Z` ou `Cmd+Z` → Undo
- `Ctrl+Y` ou `Cmd+Y` ou `Ctrl+Shift+Z` → Redo
- Gestion des états title et content
- Reset de l'historique après création de note
- Tests Playwright complets dans `tests/undo-redo.spec.ts`
### ✅ Système de Reminders
**Fichiers**: `components/note-input.tsx`, `components/note-editor.tsx`, `components/note-card.tsx`, `prisma/schema.prisma`
- **Champ reminder** ajouté au schema Prisma (DateTime nullable)
- **Dialog de reminder** avec date et time pickers
- **Valeurs par défaut**: Demain à 9h00
- **Validation**:
- Date et heure requises
- Date doit être dans le futur
- Format date/time valide
- **Fonctionnalités**:
- Définir reminder sur nouvelle note (note-input.tsx)
- Définir reminder sur note existante (note-editor.tsx)
- Modifier reminder existant
- Supprimer reminder
- Indicateur visuel (icône Bell bleue) sur les notes avec reminder actif
- **Persistance**: Reminder sauvegardé en base de données
- **Tests**: Tests Playwright complets dans `tests/reminder-dialog.spec.ts`
- **Toast notifications**: Confirmation lors de la définition/suppression
- **Migration**: `20260104140638_add_reminder`
---
## Phase 4: API REST
### ✅ 4 Endpoints REST complets
**Fichiers**: `app/api/notes/route.ts`
#### 1. GET /api/notes
```bash
curl http://localhost:3000/api/notes
curl http://localhost:3000/api/notes?archived=true
curl http://localhost:3000/api/notes?search=test
```
**Retour**: `{success: true, data: Note[]}`
#### 2. POST /api/notes
```bash
curl -X POST http://localhost:3000/api/notes \
-H "Content-Type: application/json" \
-d '{"title":"Test","content":"Hello","color":"blue","images":["data:image/png;base64,..."]}'
```
**Retour**: `{success: true, data: Note}` (status 201)
#### 3. PUT /api/notes
```bash
curl -X PUT http://localhost:3000/api/notes \
-H "Content-Type: application/json" \
-d '{"id":"xxx","title":"Updated","isPinned":true}'
```
**Retour**: `{success: true, data: Note}`
#### 4. DELETE /api/notes?id=xxx
```bash
curl -X DELETE http://localhost:3000/api/notes?id=xxx
```
**Retour**: `{success: true, message: "Note deleted successfully"}`
**Tests PowerShell réussis**:
- ✅ CREATE avec images
- ✅ GET all notes
- ✅ UPDATE avec pin
- ✅ DELETE
---
## Phase 5: MCP Server
### ✅ MCP Server avec 9 tools
**Fichiers**: `mcp-server/index.js`, `mcp-server/package.json`
**Dépendances**:
- `@modelcontextprotocol/sdk@^1.0.4`
- `@prisma/client@^5.22.0`
**Transport**: stdio (stdin/stdout)
**9 Tools implémentés**:
1. **create_note** - Créer une note
- Paramètres: title, content, color, type, checkItems, labels, images, isPinned, isArchived
- Retour: Note créée en JSON
2. **get_notes** - Récupérer toutes les notes
- Paramètres: includeArchived, search
- Retour: Array de notes
3. **get_note** - Récupérer une note par ID
- Paramètres: id (required)
- Retour: Note individuelle
4. **update_note** - Mettre à jour une note
- Paramètres: id (required), tous les autres optionnels
- Retour: Note mise à jour
5. **delete_note** - Supprimer une note
- Paramètres: id (required)
- Retour: Confirmation
6. **search_notes** - Rechercher des notes
- Paramètres: query (required)
- Retour: Notes correspondantes
7. **toggle_pin** - Toggle pin status
- Paramètres: id (required)
- Retour: Note avec isPinned inversé
8. **toggle_archive** - Toggle archive status
- Paramètres: id (required)
- Retour: Note avec isArchived inversé
9. **get_labels** - Récupérer tous les labels uniques
- Paramètres: aucun
- Retour: Array de labels distincts
**Connexion Prisma**:
```javascript
const prisma = new PrismaClient({
datasources: {
db: {
url: `file:${join(__dirname, '../keep-notes/prisma/dev.db')}`
}
}
});
```
**Fonction parseNote**:
```javascript
function parseNote(dbNote) {
return {
...dbNote,
checkItems: dbNote.checkItems ? JSON.parse(dbNote.checkItems) : null,
labels: dbNote.labels ? JSON.parse(dbNote.labels) : null,
images: dbNote.images ? JSON.parse(dbNote.images) : null,
};
}
```
### ✅ Configuration N8N
**Fichiers**: `N8N-MCP-SETUP.md`
**3 méthodes de configuration**:
1. Via variables d'environnement `N8N_MCP_SERVERS`
2. Via fichier `~/.n8n/mcp-config.json`
3. Via Claude Desktop config (alternative)
**Configuration stdio**:
```json
{
"mcpServers": {
"memento": {
"command": "node",
"args": ["D:/dev_new_pc/Keep/mcp-server/index.js"]
}
}
}
```
---
## Phase 6: Images
### ✅ Upload d'images avec base64
**Fichiers**: `components/note-input.tsx`, `components/note-editor.tsx`
**Implémentation**:
1. Input file caché avec `accept="image/*"` et `multiple`
2. FileReader pour lire les fichiers
3. Conversion en base64 avec `readAsDataURL()`
4. Stockage dans state: `const [images, setImages] = useState<string[]>([])`
5. Envoi à l'API/DB sous forme de JSON array
**Code d'upload**:
```typescript
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files
if (!files) return
Array.from(files).forEach(file => {
const reader = new FileReader()
reader.onloadend = () => {
if (typeof reader.result === 'string') {
setImages(prev => [...prev, reader.result as string])
}
}
reader.readAsDataURL(file)
})
}
```
### ✅ Affichage images à taille originale
**Problème résolu après 6 itérations!**
**Solution finale**:
- `DialogContent` avec `!max-w-[min(95vw,1600px)]` (utilise `!important`)
- Images avec `h-auto` **sans** `w-full`
- Pas de `object-cover` qui coupe les images
**Fichier**: `components/note-editor.tsx` ligne 119
```tsx
<DialogContent className={cn(
'!max-w-[min(95vw,1600px)] max-h-[90vh] overflow-y-auto',
colorClasses.bg
)}>
```
**Fichier**: `components/note-editor.tsx` ligne 143
```tsx
<img src={img} alt="" className="h-auto rounded-lg" />
```
**Vérification Playwright**:
- Image test: 1450x838 pixels
- naturalWidth: 1450 ✅
- naturalHeight: 838 ✅
- displayWidth: 1450 ✅ (100% taille originale)
- displayHeight: 838 ✅ (100% taille originale)
### ✅ Grille d'images dans note-card
**Fichier**: `components/note-card.tsx`
**Layout selon nombre d'images**:
- 1 image: pleine largeur avec `h-auto`
- 2 images: `grid-cols-2` avec `h-auto`
- 3+ images: grille customisée avec `h-auto`
**Aucune image n'est coupée**, toutes s'affichent entièrement.
---
## Phase 7: N8N Integration
### ✅ Workflow N8N pour tester l'API
**Fichier**: `n8n-memento-workflow.json`
**Structure du workflow** (5 nœuds):
1. **Manual Trigger** - Démarrage manuel
2. **Create Note via API** - POST avec image
3. **Get All Notes via API** - GET
4. **Update Note via API (Pin)** - PUT avec isPinned=true
5. **Format Results** - Affichage des résultats
**Tests réussis**:
- ✅ Création de note avec images
- ✅ Récupération de toutes les notes
- ✅ Mise à jour avec épinglage
- ✅ Suppression de note
**Import dans N8N**:
1. Ouvrir N8N
2. "Import from File"
3. Sélectionner `n8n-memento-workflow.json`
4. S'assurer que Memento tourne sur `http://localhost:3000`
5. Exécuter avec "Execute Workflow"
---
## Stack Technique
### Frontend
- **Next.js 16.1.1** - Framework React avec App Router
- **React 19** - Library UI
- **TypeScript 5** - Typage statique
- **Tailwind CSS 4.0.0** - Styling utility-first
- **shadcn/ui** - Composants UI (11 installés)
- **Lucide React** - Icônes (9 utilisées)
- **@hello-pangea/dnd** - Drag-and-drop
### Backend
- **Next.js Server Actions** - Mutations côté serveur
- **Prisma 5.22.0** - ORM pour base de données
- **SQLite** - Base de données locale (`dev.db`)
### MCP Server
- **@modelcontextprotocol/sdk 1.0.4** - SDK officiel MCP
- **Node.js 22.20.0** - Runtime JavaScript
- **Transport stdio** - Communication stdin/stdout
### API
- **REST API** - 4 endpoints (GET, POST, PUT, DELETE)
- **JSON** - Format d'échange de données
- **Base64** - Encodage des images
### Développement
- **Turbopack** - Bundler ultra-rapide
- **ESLint** - Linter JavaScript/TypeScript
- **Git** - Contrôle de version
---
## Statistiques du Projet
- **Lignes de code**: ~3000+
- **Composants React**: 15+
- **Server Actions**: 6
- **API Endpoints**: 4
- **MCP Tools**: 9
- **Migrations Prisma**: 2
- **Tests réussis**: 100%
- **Temps de développement**: Intense! 🚀
---
## État Actuel
### ✅ Complété (85%)
- Interface utilisateur masonry moderne
- CRUD complet avec persistence DB
- Couleurs, labels, pin, archive
- Recherche full-text
- Drag-and-drop
- Images avec affichage taille originale
- API REST complète
- MCP Server avec 9 tools
- Workflow N8N opérationnel
- Documentation README complète
### ⚠️ Partiellement Complété (10%)
- Toolbar: UserPlus (Collaborateur) non fonctionnel
### ❌ À Implémenter (5%)
- UserPlus (Collaborator) - Collaboration temps réel
- Système de notification pour les reminders actifs
- Dark mode complet
---
## Prochaines Étapes Prioritaires
1. **Implémenter les 5 fonctions toolbar manquantes**
2. **Optimiser les performances** (index DB, lazy loading images)
3. **Améliorer UX** (animations, loading states, toasts)
4. **Tests end-to-end** avec toutes les fonctionnalités
5. **Dark mode complet**
6. **Déploiement** (Vercel pour Next.js, hébergement MCP)
---
## Notes de Débogage Importantes
### Image Display Fix (Critique!)
Le problème d'affichage des images a nécessité **6 itérations** pour être résolu:
1.`object-cover` avec `h-32/h-48` → images coupées
2.`h-auto` avec `object-cover` → toujours coupées
3.`h-auto` sans `object-cover` → limitées par dialog width
4.`max-w-95vw` → overridden par `sm:max-w-lg`
5. ❌ Plusieurs tentatives de classes Tailwind
6.**SOLUTION**: `!max-w-[min(95vw,1600px)]` avec `!important`
**Leçon**: Toujours vérifier la hiérarchie des classes CSS et utiliser `!important` quand nécessaire pour override shadcn/ui defaults.
### MCP Server stdio vs HTTP
Le MCP Server utilise **stdio** (stdin/stdout), **PAS HTTP**. Il ne s'expose pas sur une URL. N8N doit être configuré pour lancer le processus avec `command: "node"` et `args: ["path/to/index.js"]`.
### Prisma JSON Fields
Tous les champs complexes (checkItems, labels, images) sont stockés en **JSON strings** dans SQLite et parsés automatiquement avec `JSON.parse()` dans `parseNote()`.
---
**Dernière mise à jour**: 4 janvier 2026
**Version**: 1.0.0
**Statut**: Prêt pour production (après implémentation toolbar)