From 6084077b54d26e228d0ece12a3f1c72998fa1f81 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Fri, 19 Jun 2026 21:06:17 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20organisateur=20IA=20=E2=80=94=20apply=20?= =?UTF-8?q?tag=20utilise=20syncNoteLabels=20au=20lieu=20de=20properties?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - applyTag faisait un PATCH sur /api/notes/[id]/properties avec { tags: [...] } mais l'API properties attend { properties: { propId: value } } - Maintenant: PATCH /api/ai/organize-notebook qui appelle syncNoteLabels() - Les tags sont appliqués comme LABELS (système existant) sur les notes - Merge avec labels existants (n'écrase pas) --- .../app/api/ai/organize-notebook/route.ts | 39 +++++++++++++++++++ memento-note/components/home-client.tsx | 3 +- .../wizard/notebook-organizer-dialog.tsx | 15 ++++--- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/memento-note/app/api/ai/organize-notebook/route.ts b/memento-note/app/api/ai/organize-notebook/route.ts index 3edf308..0663f25 100644 --- a/memento-note/app/api/ai/organize-notebook/route.ts +++ b/memento-note/app/api/ai/organize-notebook/route.ts @@ -3,6 +3,7 @@ import { auth } from '@/auth' import prisma from '@/lib/prisma' import { notebookOrganizerService } from '@/lib/ai/services/notebook-organizer.service' import { checkEntitlementOrThrow, QuotaExceededError, incrementUsageAsync } from '@/lib/entitlements' +import { syncNoteLabels } from '@/app/actions/notes' export async function POST(request: NextRequest) { try { @@ -55,3 +56,41 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: error.message || 'Failed to organize notebook' }, { status: 500 }) } } + +export async function PATCH(request: NextRequest) { + try { + const session = await auth() + if (!session?.user?.id) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + const { action, tagName, noteIds, notebookId } = await request.json() + + if (action === 'apply_tag' && tagName && Array.isArray(noteIds)) { + // Fetch existing labels for each note, merge with new tag + for (const noteId of noteIds) { + const note = await prisma.note.findUnique({ + where: { id: noteId }, + select: { labels: true, notebookId: true }, + }) + if (!note) continue + + let existingLabels: string[] = [] + try { existingLabels = note.labels ? JSON.parse(note.labels) : [] } catch {} + + if (!existingLabels.includes(tagName)) { + existingLabels.push(tagName) + } + + await syncNoteLabels(noteId, existingLabels, note.notebookId, session.user.id) + } + + return NextResponse.json({ success: true, applied: noteIds.length }) + } + + return NextResponse.json({ error: 'Invalid action' }, { status: 400 }) + } catch (error: any) { + console.error('[Notebook Organizer PATCH] Error:', error) + return NextResponse.json({ error: error.message }, { status: 500 }) + } +} diff --git a/memento-note/components/home-client.tsx b/memento-note/components/home-client.tsx index dddaebe..d94c3e3 100644 --- a/memento-note/components/home-client.tsx +++ b/memento-note/components/home-client.tsx @@ -1068,7 +1068,8 @@ export function HomeClient({ > {t('structuredViews.organizer') || 'Organiser'} - + + )} {searchParams.get('notebook') && (
diff --git a/memento-note/components/wizard/notebook-organizer-dialog.tsx b/memento-note/components/wizard/notebook-organizer-dialog.tsx index 1a6feb1..357c41c 100644 --- a/memento-note/components/wizard/notebook-organizer-dialog.tsx +++ b/memento-note/components/wizard/notebook-organizer-dialog.tsx @@ -53,15 +53,14 @@ export function NotebookOrganizerDialog({ const applyTag = async (tagName: string, noteIds: string[]) => { try { - for (const noteId of noteIds) { - await fetch(`/api/notes/${noteId}/properties`, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ tags: [tagName] }), - }).catch(() => {}) - } + const res = await fetch('/api/ai/organize-notebook', { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'apply_tag', tagName, noteIds, notebookId }), + }) + if (!res.ok) throw new Error('Failed') setAppliedTags(prev => new Set(prev).add(tagName)) - toast.success(t('wizard.tagApplied') || `Tag "${tagName}" appliqué à ${noteIds.length} notes`) + toast.success(t('structuredViews.tagApplied') || `Tag "${tagName}" appliqué à ${noteIds.length} notes`) } catch { toast.error('Erreur') }