diff --git a/keep-notes/components/create-notebook-dialog.tsx b/keep-notes/components/create-notebook-dialog.tsx index b1e8e5b..003b9c6 100644 --- a/keep-notes/components/create-notebook-dialog.tsx +++ b/keep-notes/components/create-notebook-dialog.tsx @@ -1,7 +1,6 @@ 'use client' import { useState } from 'react' -import { useRouter } from 'next/navigation' import { Plus, X, Folder, Briefcase, FileText, Zap, BarChart3, Globe, Sparkles, Book, Heart, Crown, Music, Building2 } from 'lucide-react' import { Button } from '@/components/ui/button' import { @@ -47,7 +46,6 @@ interface CreateNotebookDialogProps { } export function CreateNotebookDialog({ open, onOpenChange }: CreateNotebookDialogProps) { - const router = useRouter() const { t } = useLanguage() const { createNotebookOptimistic } = useNotebooks() const [name, setName] = useState('') @@ -68,9 +66,8 @@ export function CreateNotebookDialog({ open, onOpenChange }: CreateNotebookDialo icon: selectedIcon, color: selectedColor, }) - // Close dialog — no full page reload needed + // Close dialog — context already updated sidebar state onOpenChange?.(false) - router.refresh() } catch (error) { console.error('Failed to create notebook:', error) } finally { diff --git a/keep-notes/components/delete-notebook-dialog.tsx b/keep-notes/components/delete-notebook-dialog.tsx index da3a4bb..773f187 100644 --- a/keep-notes/components/delete-notebook-dialog.tsx +++ b/keep-notes/components/delete-notebook-dialog.tsx @@ -26,7 +26,6 @@ export function DeleteNotebookDialog({ notebook, open, onOpenChange }: DeleteNot try { await deleteNotebook(notebook.id) onOpenChange(false) - window.location.reload() } catch (error) { // Error already handled in UI } diff --git a/keep-notes/components/edit-notebook-dialog.tsx b/keep-notes/components/edit-notebook-dialog.tsx index 23671cd..e5fcb3c 100644 --- a/keep-notes/components/edit-notebook-dialog.tsx +++ b/keep-notes/components/edit-notebook-dialog.tsx @@ -1,7 +1,6 @@ 'use client' -import { useState } from 'react' -import { useRouter } from 'next/navigation' +import { useState, useEffect } from 'react' import { useLanguage } from '@/lib/i18n' import { Button } from '@/components/ui/button' import { @@ -14,41 +13,36 @@ import { } from '@/components/ui/dialog' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' +import { useNotebooks } from '@/context/notebooks-context' +import { Notebook } from '@/lib/types' interface EditNotebookDialogProps { - notebook: any + notebook: Notebook open: boolean onOpenChange: (open: boolean) => void } export function EditNotebookDialog({ notebook, open, onOpenChange }: EditNotebookDialogProps) { - const router = useRouter() + const { updateNotebook } = useNotebooks() const { t } = useLanguage() const [name, setName] = useState(notebook?.name || '') const [isSubmitting, setIsSubmitting] = useState(false) + useEffect(() => { + if (open) { + setName(notebook?.name || '') + } + }, [open, notebook?.name]) + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() - if (!name.trim()) return - setIsSubmitting(true) - try { - const response = await fetch(`/api/notebooks/${notebook.id}`, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name: name.trim() }), - }) - - if (response.ok) { - onOpenChange(false) - window.location.reload() - } else { - const error = await response.json() - } - } catch (error) { - // Error already handled in UI + await updateNotebook(notebook.id, { name: name.trim() }) + onOpenChange(false) + } catch { + // Error handled in UI } finally { setIsSubmitting(false) } @@ -63,7 +57,6 @@ export function EditNotebookDialog({ notebook, open, onOpenChange }: EditNoteboo {t('notebook.editDescription')} -
@@ -80,7 +73,6 @@ export function EditNotebookDialog({ notebook, open, onOpenChange }: EditNoteboo />
- - - - {onSummary && ( - - - {t('notebook.summary')} - - )} - - - {t('notebook.edit')} + + + + + + {onSummary && ( + + + {t('notebook.summary')} - - {t('notebook.delete')} - - - - + )} + + + {t('notebook.edit')} + + + {t('notebook.delete')} + + + ) } diff --git a/keep-notes/components/notebooks-list.tsx b/keep-notes/components/notebooks-list.tsx index 4dbbc21..c236cb9 100644 --- a/keep-notes/components/notebooks-list.tsx +++ b/keep-notes/components/notebooks-list.tsx @@ -15,6 +15,7 @@ import { EditNotebookDialog } from './edit-notebook-dialog' import { NotebookSummaryDialog } from './notebook-summary-dialog' import { useLanguage } from '@/lib/i18n' import { useLabels } from '@/context/LabelContext' +import { Notebook } from '@/lib/types' // Map icon names to lucide-react components const ICON_MAP: Record = { @@ -35,8 +36,7 @@ const ICON_MAP: Record = { // Function to get icon component by name const getNotebookIcon = (iconName: string) => { - const IconComponent = ICON_MAP[iconName] || Folder - return IconComponent + return ICON_MAP[iconName] || Folder } export function NotebooksList() { @@ -49,9 +49,9 @@ export function NotebooksList() { const { labels } = useLabels() const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false) - const [editingNotebook, setEditingNotebook] = useState(null) - const [deletingNotebook, setDeletingNotebook] = useState(null) - const [summaryNotebook, setSummaryNotebook] = useState(null) + const [editingNotebook, setEditingNotebook] = useState(null) + const [deletingNotebook, setDeletingNotebook] = useState(null) + const [summaryNotebook, setSummaryNotebook] = useState(null) const [expandedNotebook, setExpandedNotebook] = useState(null) const currentNotebookId = searchParams.get('notebook') @@ -140,7 +140,7 @@ export function NotebooksList() { {/* Notebooks Loop */} - {notebooks.map((notebook: any) => { + {notebooks.map((notebook: Notebook) => { const isActive = currentNotebookId === notebook.id const isExpanded = expandedNotebook === notebook.id const isDragOver = dragOverNotebookId === notebook.id @@ -151,39 +151,48 @@ export function NotebooksList() { return (
{isActive ? ( - // Active notebook with expanded labels - STYLE MATCH Sidebar + // Active notebook with expanded labels
handleDrop(e, notebook.id)} onDragOver={(e) => handleDragOver(e, notebook.id)} onDragLeave={handleDragLeave} className={cn( - "flex flex-col mr-2 rounded-r-full overflow-hidden transition-all", + "flex flex-col mr-2 rounded-r-full overflow-hidden transition-all relative", !notebook.color && "bg-primary/10 dark:bg-primary/20", isDragOver && "ring-2 ring-primary ring-dashed" )} style={notebook.color ? { backgroundColor: `${notebook.color}20` } : undefined} > - {/* Header - allow pointer events for expand button */} + {/* Header */}
-
+
{notebook.name}
- +
+ {/* Actions menu for active notebook */} + setEditingNotebook(notebook)} + onDelete={() => setDeletingNotebook(notebook)} + onSummary={() => setSummaryNotebook(notebook)} + /> + +
{/* Contextual Labels Tree */} @@ -221,45 +230,41 @@ export function NotebooksList() { onDragOver={(e) => handleDragOver(e, notebook.id)} onDragLeave={handleDragLeave} className={cn( - "flex items-center group relative", + "flex items-center relative", isDragOver && "ring-2 ring-blue-500 ring-dashed rounded-r-full mr-2" )} > -
- + - {/* Expand button separate from main click */} - -
- - {/* Actions (visible on hover) */} -
+ {/* Actions + expand on the right — always rendered, visible on hover */} +
setEditingNotebook(notebook)} onDelete={() => setDeletingNotebook(notebook)} onSummary={() => setSummaryNotebook(notebook)} /> +
)} @@ -302,7 +307,7 @@ export function NotebooksList() { onOpenChange={(open) => { if (!open) setSummaryNotebook(null) }} - notebookId={summaryNotebook?.id} + notebookId={summaryNotebook?.id ?? null} notebookName={summaryNotebook?.name} /> diff --git a/keep-notes/context/NoteRefreshContext.tsx b/keep-notes/context/NoteRefreshContext.tsx index 320b424..eba3893 100644 --- a/keep-notes/context/NoteRefreshContext.tsx +++ b/keep-notes/context/NoteRefreshContext.tsx @@ -14,7 +14,7 @@ export function NoteRefreshProvider({ children }: { children: React.ReactNode }) const triggerRefresh = useCallback(() => { setRefreshKey(prev => prev + 1) - }, [refreshKey]) + }, []) return ( diff --git a/keep-notes/context/notebooks-context.tsx b/keep-notes/context/notebooks-context.tsx index 8052181..c1f15e9 100644 --- a/keep-notes/context/notebooks-context.tsx +++ b/keep-notes/context/notebooks-context.tsx @@ -40,7 +40,7 @@ export interface NotebooksContextValue { error: string | null // Actions: Notebooks - createNotebookOptimistic: (data: CreateNotebookInput) => Promise + createNotebookOptimistic: (data: CreateNotebookInput) => Promise updateNotebook: (notebookId: string, data: UpdateNotebookInput) => Promise deleteNotebook: (notebookId: string) => Promise updateNotebookOrderOptimistic: (notebookIds: string[]) => Promise @@ -114,7 +114,6 @@ export function NotebooksProvider({ children, initialNotebooks = [] }: Notebooks // ===== ACTIONS: NOTEBOOKS ===== const createNotebookOptimistic = useCallback(async (data: CreateNotebookInput) => { - // Server action sera implémenté plus tard const response = await fetch('/api/notebooks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -125,9 +124,10 @@ export function NotebooksProvider({ children, initialNotebooks = [] }: Notebooks throw new Error('Failed to create notebook') } - const result = await response.json() - return result - }, []) + // Reload notebooks from server to update sidebar state + await loadNotebooks() + triggerRefresh() + }, [loadNotebooks, triggerRefresh]) const updateNotebook = useCallback(async (notebookId: string, data: UpdateNotebookInput) => { const response = await fetch(`/api/notebooks/${notebookId}`, {