1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
import React, { useState } from 'react';
import { Folder, FileText, Archive, ChevronLeft, ChevronRight, Trash2, MessageSquare } from 'lucide-react';
import useFlowStore from '../store/flowStore';
interface LeftSidebarProps {
isOpen: boolean;
onToggle: () => void;
}
const LeftSidebar: React.FC<LeftSidebarProps> = ({ isOpen, onToggle }) => {
const [activeTab, setActiveTab] = useState<'project' | 'files' | 'archive'>('project');
const { archivedNodes, removeFromArchive, createNodeFromArchive } = useFlowStore();
const handleDragStart = (e: React.DragEvent, archiveId: string) => {
e.dataTransfer.setData('archiveId', archiveId);
e.dataTransfer.effectAllowed = 'copy';
};
if (!isOpen) {
return (
<div className="border-r border-gray-200 h-screen bg-white flex flex-col items-center py-4 w-12 z-10 transition-all duration-300">
<button
onClick={onToggle}
className="p-2 hover:bg-gray-100 rounded mb-4"
title="Expand"
>
<ChevronRight size={20} className="text-gray-500" />
</button>
{/* Icons when collapsed */}
<div className="flex flex-col gap-4">
<Folder size={20} className={activeTab === 'project' ? "text-blue-500" : "text-gray-400"} />
<FileText size={20} className={activeTab === 'files' ? "text-blue-500" : "text-gray-400"} />
<Archive size={20} className={activeTab === 'archive' ? "text-blue-500" : "text-gray-400"} />
</div>
</div>
);
}
return (
<div className="w-64 border-r border-gray-200 h-screen flex flex-col bg-white shadow-xl z-10 transition-all duration-300">
{/* Header */}
<div className="p-3 border-b border-gray-200 flex justify-between items-center bg-gray-50">
<h2 className="font-bold text-sm text-gray-700 uppercase">Workspace</h2>
<button
onClick={onToggle}
className="p-1 hover:bg-gray-200 rounded"
>
<ChevronLeft size={16} className="text-gray-500" />
</button>
</div>
{/* Tabs */}
<div className="flex border-b border-gray-200">
<button
onClick={() => setActiveTab('project')}
className={`flex-1 p-3 text-xs flex justify-center items-center gap-2 ${activeTab === 'project' ? 'border-b-2 border-blue-500 text-blue-600 font-medium' : 'text-gray-600 hover:bg-gray-50'}`}
>
<Folder size={14} /> Project
</button>
<button
onClick={() => setActiveTab('files')}
className={`flex-1 p-3 text-xs flex justify-center items-center gap-2 ${activeTab === 'files' ? 'border-b-2 border-blue-500 text-blue-600 font-medium' : 'text-gray-600 hover:bg-gray-50'}`}
>
<FileText size={14} /> Files
</button>
<button
onClick={() => setActiveTab('archive')}
className={`flex-1 p-3 text-xs flex justify-center items-center gap-2 ${activeTab === 'archive' ? 'border-b-2 border-blue-500 text-blue-600 font-medium' : 'text-gray-600 hover:bg-gray-50'}`}
>
<Archive size={14} /> Archive
</button>
</div>
{/* Content Area */}
<div className="flex-1 overflow-y-auto p-4 text-sm text-gray-500">
{activeTab === 'project' && (
<div className="flex flex-col items-center justify-center h-full opacity-50">
<Folder size={48} className="mb-2" />
<p>Project settings coming soon</p>
</div>
)}
{activeTab === 'files' && (
<div className="flex flex-col items-center justify-center h-full opacity-50">
<FileText size={48} className="mb-2" />
<p>File manager coming soon</p>
</div>
)}
{activeTab === 'archive' && (
<div className="space-y-2">
{archivedNodes.length === 0 ? (
<div className="flex flex-col items-center justify-center h-40 opacity-50">
<Archive size={32} className="mb-2" />
<p className="text-xs text-center">
No archived nodes.<br/>
Right-click a node → "Add to Archive"
</p>
</div>
) : (
<>
<p className="text-xs text-gray-400 mb-2">Drag to canvas to create a copy</p>
{archivedNodes.map((archived) => (
<div
key={archived.id}
draggable
onDragStart={(e) => handleDragStart(e, archived.id)}
className="p-2 bg-gray-50 border border-gray-200 rounded-md cursor-grab hover:bg-gray-100 hover:border-gray-300 transition-colors group"
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<MessageSquare size={14} className="text-gray-500" />
<span className="text-sm font-medium truncate max-w-[140px]">{archived.label}</span>
</div>
<button
onClick={() => removeFromArchive(archived.id)}
className="opacity-0 group-hover:opacity-100 p-1 hover:bg-red-100 rounded text-gray-400 hover:text-red-500 transition-all"
title="Remove from archive"
>
<Trash2 size={12} />
</button>
</div>
<div className="text-[10px] text-gray-400 mt-1">{archived.model}</div>
</div>
))}
</>
)}
</div>
)}
</div>
</div>
);
};
export default LeftSidebar;
|