feat: hierarchical notebook system - trash, selectors, breadcrumb, sidebar tree
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m9s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m9s
- Schema: soft delete with trashedAt on Notebook model - API: PATCH/GET notebooks support trashedAt filtering with cascade - Sidebar: recursive tree rendering with collapse/expand, visual guides, hover actions - HierarchicalNotebookSelector: portal-based dropdown with search, breadcrumbs, dropUp support - AI chat: context selector with Toutes mes notes + notebook selector - Agent detail: flat selects replaced with HierarchicalNotebookSelector - Breadcrumb: notebook path display on home page - Trash view: card grid with countdown, restore/permanent delete - CSS: design tokens (ink, paper, blueprint, concrete, etc.) - Types: parentId, trashedAt added to Notebook interface
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { motion, AnimatePresence } from 'motion/react'
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
import { useNotebooks } from '@/context/notebooks-context'
|
||||
@@ -15,10 +15,17 @@ export function CreateNotebookDialog({ open, onOpenChange, parentNotebookId }: C
|
||||
const { t } = useLanguage()
|
||||
const { createNotebookOptimistic, notebooks } = useNotebooks()
|
||||
const [name, setName] = useState('')
|
||||
const [selectedParentId, setSelectedParentId] = useState<string | null>(parentNotebookId ?? null)
|
||||
const [selectedParentId, setSelectedParentId] = useState<string | null>(null)
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
|
||||
const rootNotebooks = notebooks.filter(nb => !nb.parentId)
|
||||
const rootNotebooks = notebooks.filter(nb => !nb.parentId && !nb.trashedAt)
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setSelectedParentId(parentNotebookId ?? null)
|
||||
setName('')
|
||||
}
|
||||
}, [open, parentNotebookId])
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
@@ -42,10 +49,12 @@ export function CreateNotebookDialog({ open, onOpenChange, parentNotebookId }: C
|
||||
|
||||
const handleClose = () => {
|
||||
setName('')
|
||||
setSelectedParentId(parentNotebookId ?? null)
|
||||
setSelectedParentId(null)
|
||||
onOpenChange?.(false)
|
||||
}
|
||||
|
||||
const isSubNotebook = !!parentNotebookId
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
@@ -66,10 +75,16 @@ export function CreateNotebookDialog({ open, onOpenChange, parentNotebookId }: C
|
||||
className="relative w-full max-w-md bg-[#F2F0E9] dark:bg-zinc-900 border border-black/10 dark:border-white/10 shadow-2xl rounded-2xl p-8"
|
||||
>
|
||||
<h3 className="text-2xl font-memento-serif font-medium text-foreground mb-2">
|
||||
{t('notebook.createNew') || 'Nouveau carnet'}
|
||||
{isSubNotebook
|
||||
? (t('notebook.createSubNotebook') || 'Nouveau sous-carnet')
|
||||
: (t('notebook.createNew') || 'Nouveau carnet')
|
||||
}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground mb-6 font-light">
|
||||
{t('notebook.createDescription') || 'Donnez un nom à votre nouveau carnet.'}
|
||||
{isSubNotebook && parentNotebookId
|
||||
? `${t('notebook.under') || 'Sous'} ${notebooks.find(nb => nb.id === parentNotebookId)?.name || ''}`
|
||||
: (t('notebook.createDescription') || 'Donnez un nom à votre nouveau carnet.')
|
||||
}
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
@@ -87,7 +102,7 @@ export function CreateNotebookDialog({ open, onOpenChange, parentNotebookId }: C
|
||||
/>
|
||||
</div>
|
||||
|
||||
{!parentNotebookId && rootNotebooks.length > 0 && (
|
||||
{!isSubNotebook && rootNotebooks.length > 0 && (
|
||||
<div>
|
||||
<label className="block text-[11px] uppercase tracking-widest font-bold text-muted-foreground mb-2">
|
||||
{t('notebook.parentNotebook') || 'Carnet parent'}
|
||||
|
||||
Reference in New Issue
Block a user