'use client';
import { useState, useTransition } from 'react';
import { Folder } from '@/services/folders';
import { Tag } from '@/lib/types';
import {
Folder as FolderIcon,
FolderOpen,
Plus,
Edit2,
Trash2,
ChevronRight,
ChevronDown,
} from 'lucide-react';
import { createFolder, updateFolder, deleteFolder } from '@/actions/folders';
import { extractEmojis } from '@/lib/task-emoji';
interface FoldersSidebarProps {
folders: Folder[];
selectedFolderId?: string;
onSelectFolder: (folderId: string | null) => void;
onFoldersChange: () => void;
availableTags: Tag[];
onNoteDrop?: (noteId: string, folderId: string | null) => void;
}
interface FolderItemProps {
folder: Folder;
level: number;
isSelected: boolean;
onSelect: (folderId: string) => void;
onEdit: (folder: Folder) => void;
onDelete: (folderId: string) => void;
availableTags: Tag[];
onNoteDrop?: (noteId: string, folderId: string) => void;
}
function FolderItem({
folder,
level,
isSelected,
onSelect,
onEdit,
onDelete,
availableTags,
onNoteDrop,
}: FolderItemProps) {
const [isExpanded, setIsExpanded] = useState(true);
const [isDragOver, setIsDragOver] = useState(false);
const hasChildren = folder.children && folder.children.length > 0;
const handleEdit = (e: React.MouseEvent) => {
e.stopPropagation();
onEdit(folder);
};
const handleDelete = (e: React.MouseEvent) => {
e.stopPropagation();
onDelete(folder.id);
};
const handleDragOver = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragOver(true);
};
const handleDragLeave = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragOver(false);
};
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragOver(false);
const noteId = e.dataTransfer.getData('noteId');
if (noteId && onNoteDrop) {
onNoteDrop(noteId, folder.id);
}
};
return (
onSelect(folder.id)}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
{hasChildren && (
)}
{isExpanded ? (
) : (
)}
{folder.tagId &&
(() => {
const tag = availableTags.find((t) => t.id === folder.tagId);
if (tag) {
const emojis = extractEmojis(tag.name);
if (emojis.length > 0) {
return (
{emojis[0]}
);
}
}
return null;
})()}
{folder.name}
{folder.notesCount !== undefined && folder.notesCount > 0 && (
{folder.notesCount}
)}
{hasChildren && isExpanded && (
{folder.children!.map((child) => (
))}
)}
);
}
export function FoldersSidebar({
folders,
selectedFolderId,
onSelectFolder,
onFoldersChange,
availableTags,
onNoteDrop,
}: FoldersSidebarProps) {
const [isPending, startTransition] = useTransition();
const [showCreateDialog, setShowCreateDialog] = useState(false);
const [editingFolder, setEditingFolder] = useState(null);
const [folderName, setFolderName] = useState('');
const [selectedTagId, setSelectedTagId] = useState('');
const [isDragOverAll, setIsDragOverAll] = useState(false);
const handleCreateFolder = () => {
setFolderName('');
setSelectedTagId('');
setShowCreateDialog(true);
};
const handleEditFolder = (folder: Folder) => {
setEditingFolder(folder);
setFolderName(folder.name);
setSelectedTagId(folder.tagId || '');
setShowCreateDialog(true);
};
const handleSaveFolder = () => {
if (!folderName.trim()) return;
startTransition(async () => {
if (editingFolder) {
// Update existing folder
const result = await updateFolder(editingFolder.id, {
name: folderName,
tagId: selectedTagId || undefined,
});
if (result.success) {
onFoldersChange();
setShowCreateDialog(false);
setEditingFolder(null);
}
} else {
// Create new folder
const result = await createFolder({
name: folderName,
tagId: selectedTagId || undefined,
});
if (result.success) {
onFoldersChange();
setShowCreateDialog(false);
}
}
});
};
const handleDeleteFolder = (folderId: string) => {
if (!confirm('Êtes-vous sûr de vouloir supprimer ce dossier ?')) return;
startTransition(async () => {
const result = await deleteFolder(folderId);
if (result.success) {
if (selectedFolderId === folderId) {
onSelectFolder(null);
}
onFoldersChange();
}
});
};
return (
{/* Header */}
{/* Folders List */}
{/* All Notes */}
onSelectFolder(null)}
>
Toutes les notes
{/* Uncategorized Notes */}
onSelectFolder('__uncategorized__')}
onDragOver={(e) => {
e.preventDefault();
e.stopPropagation();
setIsDragOverAll(true);
}}
onDragLeave={(e) => {
e.preventDefault();
e.stopPropagation();
setIsDragOverAll(false);
}}
onDrop={(e) => {
e.preventDefault();
e.stopPropagation();
setIsDragOverAll(false);
const noteId = e.dataTransfer.getData('noteId');
if (noteId && onNoteDrop) {
onNoteDrop(noteId, null); // null = retirer du dossier
}
}}
>
Notes non classées
{/* Folders Tree */}
{folders.map((folder) => (
))}
{/* Create/Edit Dialog */}
{showCreateDialog && (
<>
{
setShowCreateDialog(false);
setEditingFolder(null);
}}
/>
{editingFolder ? 'Modifier le dossier' : 'Nouveau dossier'}
>
)}
);
}