## 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>
190 lines
4.8 KiB
TypeScript
190 lines
4.8 KiB
TypeScript
import { prisma } from '@/lib/prisma'
|
|
import { getAIProvider } from '@/lib/ai/factory'
|
|
|
|
export interface NotebookSummary {
|
|
notebookId: string
|
|
notebookName: string
|
|
notebookIcon: string | null
|
|
summary: string // Markdown formatted summary
|
|
stats: {
|
|
totalNotes: number
|
|
totalLabels: number
|
|
labelsUsed: string[]
|
|
}
|
|
generatedAt: Date
|
|
}
|
|
|
|
/**
|
|
* Service for generating AI-powered notebook summaries
|
|
* (Story 5.6 - IA6)
|
|
*/
|
|
export class NotebookSummaryService {
|
|
/**
|
|
* Generate a summary for a notebook
|
|
* @param notebookId - Notebook ID
|
|
* @param userId - User ID (for authorization)
|
|
* @returns Notebook summary or null
|
|
*/
|
|
async generateSummary(notebookId: string, userId: string): Promise<NotebookSummary | null> {
|
|
// 1. Get notebook with notes and labels
|
|
const notebook = await prisma.notebook.findFirst({
|
|
where: {
|
|
id: notebookId,
|
|
userId,
|
|
},
|
|
include: {
|
|
labels: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
},
|
|
},
|
|
_count: {
|
|
select: { notes: true },
|
|
},
|
|
},
|
|
})
|
|
|
|
if (!notebook) {
|
|
throw new Error('Notebook not found')
|
|
}
|
|
|
|
// Get all notes in this notebook
|
|
const notes = await prisma.note.findMany({
|
|
where: {
|
|
notebookId,
|
|
userId,
|
|
},
|
|
select: {
|
|
id: true,
|
|
title: true,
|
|
content: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
labelRelations: {
|
|
select: {
|
|
name: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
updatedAt: 'desc',
|
|
},
|
|
take: 100, // Limit to 100 most recent notes for summary
|
|
})
|
|
|
|
if (notes.length === 0) {
|
|
return null
|
|
}
|
|
|
|
// 2. Generate summary using AI
|
|
const summary = await this.generateAISummary(notes, notebook)
|
|
|
|
// 3. Get labels used in this notebook
|
|
const labelsUsed = Array.from(
|
|
new Set(
|
|
notes.flatMap(note =>
|
|
note.labelRelations.map(l => l.name)
|
|
)
|
|
)
|
|
)
|
|
|
|
return {
|
|
notebookId: notebook.id,
|
|
notebookName: notebook.name,
|
|
notebookIcon: notebook.icon,
|
|
summary,
|
|
stats: {
|
|
totalNotes: notebook._count.notes,
|
|
totalLabels: notebook.labels.length,
|
|
labelsUsed,
|
|
},
|
|
generatedAt: new Date(),
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Use AI to generate notebook summary
|
|
*/
|
|
private async generateAISummary(notes: any[], notebook: any): Promise<string> {
|
|
// Build notes summary for AI
|
|
const notesSummary = notes
|
|
.map((note, index) => {
|
|
const title = note.title || 'Sans titre'
|
|
const content = note.content.substring(0, 200) // Limit content length
|
|
const labels = note.labelRelations.map((l: any) => l.name).join(', ')
|
|
const date = new Date(note.createdAt).toLocaleDateString('fr-FR')
|
|
|
|
return `[${index + 1}] **${title}** (${date})
|
|
${labels ? `Labels: ${labels}` : ''}
|
|
${content}...`
|
|
})
|
|
.join('\n\n')
|
|
|
|
const prompt = this.buildPrompt(notesSummary, notebook.name)
|
|
|
|
try {
|
|
const provider = getAIProvider()
|
|
const summary = await provider.generateText(prompt)
|
|
return summary.trim()
|
|
} catch (error) {
|
|
console.error('Failed to generate notebook summary:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build prompt for AI (always in French - interface language)
|
|
*/
|
|
private buildPrompt(notesSummary: string, notebookName: string): string {
|
|
return `
|
|
Tu es un assistant qui génère des synthèses structurées de carnets de notes.
|
|
|
|
CARNET: ${notebookName}
|
|
|
|
NOTES DU CARNET:
|
|
${notesSummary}
|
|
|
|
TÂCHE:
|
|
Génère une synthèse structurée et organisée de ce carnet en analysant toutes les notes.
|
|
|
|
FORMAT DE LA RÉPONSE (Markdown avec emojis):
|
|
|
|
# 📊 Synthèse du Carnet ${notebookName}
|
|
|
|
## 🌍 Thèmes Principaux
|
|
• Identifie 3-5 thèmes récurrents ou sujets abordés
|
|
|
|
## 📝 Statistiques
|
|
• Nombre total de notes analysées
|
|
• Principales catégories de contenu
|
|
|
|
## 📅 Éléments Temporels
|
|
• Dates ou périodes importantes mentionnées
|
|
• Événements planifiés vs passés
|
|
|
|
## ⚠️ Points d'Attention / Actions Requises
|
|
• Tâches ou actions identifiées dans les notes
|
|
• Rappels ou échéances importantes
|
|
• Éléments nécessitant une attention particulière
|
|
|
|
## 💡 Insights Clés
|
|
• Résumé des informations les plus importantes
|
|
• Tendances ou patterns observés
|
|
• Connexions entre les différentes notes
|
|
|
|
RÈGLES:
|
|
- Utilise le format Markdown avec emojis comme dans l'exemple
|
|
- Sois concis et organise l'information de manière claire
|
|
- Identifie les vraies tendances, ne pas inventer d'informations
|
|
- Si une section n'est pas pertinente, utilise "N/A" ou omets-la
|
|
- Ton: professionnel mais accessible
|
|
|
|
Ta réponse :
|
|
`.trim()
|
|
}
|
|
}
|
|
|
|
// Export singleton instance
|
|
export const notebookSummaryService = new NotebookSummaryService()
|