diff --git a/app/components/ModernTaskPanel.tsx b/app/components/ModernTaskPanel.tsx index 074565a..29de9c4 100644 --- a/app/components/ModernTaskPanel.tsx +++ b/app/components/ModernTaskPanel.tsx @@ -36,7 +36,56 @@ const ModernTaskPanel: React.FC = ({ const [isEditorOpen, setIsEditorOpen] = useState(false); const [isAGiXTConfigOpen, setIsAGiXTConfigOpen] = useState(false); const [agixtConfig, setAgixtConfig] = useState({ backendUrl: '', authToken: '' }); - const [currentView, setCurrentView] = useState<'board' | 'matrix'>('board'); + const [layoutSettings, setLayoutSettings] = useState<LayoutSettings>({ + selectedLayout: 'board', + columnVisibility: { + title: true, + description: true, + dueDate: true, + priority: true, + tags: true, + assignees: true, + subtasks: true, + status: true, + }, + }); + const [groupingSettings, setGroupingSettings] = useState<GroupingSettings>({ + groupBy: 'none', + }); + const [layoutSettings, setLayoutSettings] = useState<LayoutSettings>({ + selectedLayout: 'board', + columnVisibility: { + title: true, + description: true, + dueDate: true, + priority: true, + tags: true, + assignees: true, + subtasks: true, + status: true, + }, + }); + const [groupingSettings, setGroupingSettings] = useState<GroupingSettings>({ + groupBy: 'none', + }); + const [isLayoutSettingsOpen, setIsLayoutSettingsOpen] = useState(false); + const [isGroupingSettingsOpen, setIsGroupingSettingsOpen] = useState(false); + const [layoutSettings, setLayoutSettings] = useState<LayoutSettings>({ + selectedLayout: 'board', + columnVisibility: { + title: true, + description: true, + dueDate: true, + priority: true, + tags: true, + assignees: true, + subtasks: true, + status: true, + }, + }); + const [groupingSettings, setGroupingSettings] = useState<GroupingSettings>({ + groupBy: 'none', + }); // Search and filter functionality const { @@ -109,9 +158,25 @@ const ModernTaskPanel: React.FC = ({
- @@ -159,14 +224,14 @@ const ModernTaskPanel: React.FC = ({ To Do - {filteredAndSortedTasks().filter(task => task.status === 'todo').length} tasks + tasks={getGroupedTasks('todo')}
task.status === 'todo')} + tasks={getGroupedTasks('todo')} onUpdateTask={onUpdateTask} onTaskClick={setSelectedTask} onDeleteTask={onDeleteTask} @@ -185,14 +250,14 @@ const ModernTaskPanel: React.FC = ({ In Progress - {filteredAndSortedTasks().filter(task => task.status === 'in-progress').length} tasks + tasks={getGroupedTasks('in-progress')}
task.status === 'in-progress')} + tasks={getGroupedTasks('in-progress')} onUpdateTask={onUpdateTask} onTaskClick={setSelectedTask} onDeleteTask={onDeleteTask} @@ -211,14 +276,14 @@ const ModernTaskPanel: React.FC = ({ Done - {filteredAndSortedTasks().filter(task => task.status === 'done').length} tasks + tasks={getGroupedTasks('done')}
task.status === 'done')} + tasks={getGroupedTasks('done')} onUpdateTask={onUpdateTask} onTaskClick={setSelectedTask} onDeleteTask={onDeleteTask} @@ -230,11 +295,112 @@ const ModernTaskPanel: React.FC = ({
) : ( - + /> + )} + </div> + + {/* Right Sidebar */} + <div className="w-80 space-y-6"> + {agixtConfig.backendUrl && agixtConfig.authToken && ( + <AIAssistantPanel + backendUrl={agixtConfig.backendUrl} + authToken={agixtConfig.authToken} + onTaskSuggestion={(suggestion) => { + const newTask: Task = { + id: Date.now().toString(), + title: suggestion.title || '', + description: suggestion.description || '', + priority: suggestion.priority || 'medium', + status: 'todo', + progress: 0, + createdAt: new Date(), + updatedAt: new Date(), + owner: 'current-user', + collaborators: [], + activityLog: [], + comments: [], + version: 1, + listId: lists[0]?.id || 'default', + }; + onAddTask(newTask); + }} + onTaskOptimization={(taskIds) => { + const optimizedTasks = taskIds + .map(id => tasks.find(t => t.id === id)) + .filter(Boolean) as Task[]; + onReorderTasks(optimizedTasks); + }} + tasks={tasks} + selectedTask={selectedTask} + /> + )} + </div> + </div> + + {/* Modals */} + {isLayoutSettingsOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <LayoutSettingsPanel + layoutSettings={layoutSettings} + onSave={(newSettings) => { + setLayoutSettings(newSettings); + setIsLayoutSettingsOpen(false); + }} + onClose={() => setIsLayoutSettingsOpen(false)} + /> + </div> + )} + + {isGroupingSettingsOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <GroupingSettingsPanel + groupingSettings={groupingSettings} + onSave={(newSettings) => { + setGroupingSettings(newSettings); + setIsGroupingSettingsOpen(false); + }} + onClose={() => setIsGroupingSettingsOpen(false)} + /> + </div> + )} + + {isAGiXTConfigOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <AGiXTConfig + onClose={() => setIsAGiXTConfigOpen(false)} + onSave={(config) => { + setAgixtConfig(config); + setIsAGiXTConfigOpen(false); + }} + /> + </div> + )} + + {isEditorOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <TaskForm + onSubmit={(task) => { + onAddTask(task); + setIsEditorOpen(false); + }} + onCancel={() => setIsEditorOpen(false)} + lists={lists} + /> + </div> + )} + + {selectedTask && ( + <TaskDetailsPanel + task={selectedTask} + onClose={() => setSelectedTask(null)} + onUpdateTask={onUpdateTask} + allTasks={tasks} + className="fixed inset-y-0 right-0 w-[32rem] shadow-xl" + /> )} @@ -315,4 +481,262 @@ const ModernTaskPanel: React.FC = ({ ); }; -export default ModernTaskPanel; \ No newline at end of file +export default ModernTaskPanel; +interface ColumnVisibility { + [key: string]: boolean; + } + + interface LayoutSettings { + selectedLayout: 'board' | 'matrix' | 'list' | 'calendar'; + columnVisibility: ColumnVisibility; + } + + interface GroupingSettings { + groupBy: 'list' | 'tag' | 'project' | 'none'; + } + + onClick={() =>setLayoutSettings({ ...layoutSettings, selectedLayout: layoutSettings.selectedLayout === 'board' ? 'matrix' : 'board' })} + className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors flex items-center space-x-2" + > + <span>{layoutSettings.selectedLayout === 'board' ? '📊 Matrix View' : '📋 Board View'}</span> + </button> + <button + onClick={() =>setIsLayoutSettingsOpen(true)} + className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors flex items-center space-x-2" + > + <span>⚙️ Layout Settings</span> + </button> + <button + onClick={() =>setIsGroupingSettingsOpen(true)} + className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors flex items-center space-x-2" + > + <span>🔀 Grouping Settings</span> + </button> + <button + + {isLayoutSettingsOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <LayoutSettingsPanel + layoutSettings={layoutSettings} + onSave={(newSettings) =>{ + setLayoutSettings(newSettings); + setIsLayoutSettingsOpen(false); + }} + onClose={() =>setIsLayoutSettingsOpen(false)} + /> + </div> + )} + + {isGroupingSettingsOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <GroupingSettingsPanel + groupingSettings={groupingSettings} + onSave={(newSettings) =>{ + setGroupingSettings(newSettings); + setIsGroupingSettingsOpen(false); + }} + onClose={() =>setIsGroupingSettingsOpen(false)} + /> + </div> + )} + + const getGroupedTasks = (status: 'todo' | 'in-progress' | 'done') =>{ + const filteredTasks = filteredAndSortedTasks().filter(task =>task.status === status); + + if (groupingSettings.groupBy === 'none') { + return filteredTasks; + } + + const grouped: { [key: string]: Task[] } = {}; + filteredTasks.forEach(task =>{ + const groupKey = task[groupingSettings.groupBy] || 'Other'; + if (!grouped[groupKey]) { + grouped[groupKey] = []; + } + grouped[groupKey].push(task); + }); + + if (groupingSettings.groupBy === 'list') { + // Sort groups by list order + return Object.entries(grouped) + .sort(([keyA], [keyB]) =>{ + const indexA = lists.findIndex(list =>list.id === keyA); + const indexB = lists.findIndex(list =>list.id === keyB); + return indexA - indexB; + }) + .flatMap(([, tasks]) =>tasks); + } + + return Object.values(grouped).flat(); + }; + + return ( + <div className="min-h-screen bg-[#111111] text-white p-6"> + {/* Top Bar */} + <div className="flex items-center justify-between mb-8 bg-gray-900 p-6 rounded-lg shadow-lg"> + <div className="flex items-center space-x-4"> + <h1 className="text-3xl font-bold bg-gradient-to-r from-indigo-500 to-purple-500 bg-clip-text text-transparent">Task Dashboard</h1> + <div className="flex items-center space-x-2 ml-8"> + <div className="px-3 py-1 bg-gray-800 rounded-lg"> + <span className="text-gray-400 text-sm">Total Tasks: </span> + <span className="text-white font-medium">{tasks.length}</span> + </div> + <div className="px-3 py-1 bg-gray-800 rounded-lg"> + <span className="text-gray-400 text-sm">Active: </span> + <span className="text-white font-medium">{tasks.filter(t => t.status === 'in-progress').length}</span> + </div> + </div> + </div> + <div className="flex items-center space-x-4"> + <button + + interface ColumnVisibility { + [key: string]: boolean; + } + + interface LayoutSettings { + selectedLayout: 'board' | 'matrix' | 'list' | 'calendar'; + columnVisibility: ColumnVisibility; + } + + interface GroupingSettings { + groupBy: 'list' | 'tag' | 'project' | 'none'; + } + + onClick={() =>setLayoutSettings({ ...layoutSettings, selectedLayout: layoutSettings.selectedLayout === 'board' ? 'matrix' : 'board' })} + className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors flex items-center space-x-2" + > + <span>{layoutSettings.selectedLayout === 'board' ? '📊 Matrix View' : '📋 Board View'}</span> + </button> + <button + onClick={() =>setIsLayoutSettingsOpen(true)} + className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors flex items-center space-x-2" + > + <span>⚙️ Layout Settings</span> + </button> + <button + onClick={() =>setIsGroupingSettingsOpen(true)} + className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors flex items-center space-x-2" + > + <span>🔀 Grouping Settings</span> + </button> + <button + + {isLayoutSettingsOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <LayoutSettingsPanel + layoutSettings={layoutSettings} + onSave={(newSettings) =>{ + setLayoutSettings(newSettings); + setIsLayoutSettingsOpen(false); + }} + onClose={() =>setIsLayoutSettingsOpen(false)} + /> + </div> + )} + + {isGroupingSettingsOpen && ( + <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> + <GroupingSettingsPanel + groupingSettings={groupingSettings} + onSave={(newSettings) =>{ + setGroupingSettings(newSettings); + setIsGroupingSettingsOpen(false); + }} + onClose={() =>setIsGroupingSettingsOpen(false)} + /> + </div> + )} + + const getGroupedTasks = (status: 'todo' | 'in-progress' | 'done') =>{ + const filteredTasks = filteredAndSortedTasks().filter(task =>task.status === status); + + if (groupingSettings.groupBy === 'none') { + return filteredTasks; + } + + const grouped: { [key: string]: Task[] } = {}; + filteredTasks.forEach(task =>{ + const groupKey = task[groupingSettings.groupBy] || 'Other'; + if (!grouped[groupKey]) { + grouped[groupKey] = []; + } + grouped[groupKey].push(task); + }); + + if (groupingSettings.groupBy === 'list') { + // Sort groups by list order + return Object.entries(grouped) + .sort(([keyA], [keyB]) =>{ + const indexA = lists.findIndex(list =>list.id === keyA); + const indexB = lists.findIndex(list =>list.id === keyB); + return indexA - indexB; + }) + .flatMap(([, tasks]) =>tasks); + } + + return Object.values(grouped).flat(); + }; + + return ( + <div className="min-h-screen bg-[#111111] text-white p-6"> + {/* Top Bar */} + <div className="flex items-center justify-between mb-8 bg-gray-900 p-6 rounded-lg shadow-lg"> + <div className="flex items-center space-x-4"> + <h1 className="text-3xl font-bold bg-gradient-to-r from-indigo-500 to-purple-500 bg-clip-text text-transparent">Task Dashboard</h1> + <div className="flex items-center space-x-2 ml-8"> + <div className="px-3 py-1 bg-gray-800 rounded-lg"> + <span className="text-gray-400 text-sm">Total Tasks: </span> + <span className="text-white font-medium">{tasks.length}</span> + </div> + <div className="px-3 py-1 bg-gray-800 rounded-lg"> + <span className="text-gray-400 text-sm">Active: </span> + <span className="text-white font-medium">{tasks.filter(t => t.status === 'in-progress').length}</span> + </div> + </div> + </div> + <div className="flex items-center space-x-4"> + <button + + interface ColumnVisibility { + [key: string]: boolean; + } + + interface LayoutSettings { + selectedLayout: 'board' | 'matrix' | 'list' | 'calendar'; + columnVisibility: ColumnVisibility; + } + + interface GroupingSettings { + groupBy: 'list' | 'tag' | 'project' | 'none'; + } + + const getGroupedTasks = (status: 'todo' | 'in-progress' | 'done') => { + const filteredTasks = filteredAndSortedTasks().filter(task => task.status === status); + + if (groupingSettings.groupBy === 'none') { + return filteredTasks; + } + + const grouped: { [key: string]: Task[] } = {}; + filteredTasks.forEach(task => { + const groupKey = task[groupingSettings.groupBy] || 'Other'; + if (!grouped[groupKey]) { + grouped[groupKey] = []; + } + grouped[groupKey].push(task); + }); + + if (groupingSettings.groupBy === 'list') { + // Sort groups by list order + return Object.entries(grouped) + .sort(([keyA], [keyB]) => { + const indexA = lists.findIndex(list => list.id === keyA); + const indexB = lists.findIndex(list => list.id === keyB); + return indexA - indexB; + }) + .flatMap(([, tasks]) => tasks); + } + + return Object.values(grouped).flat(); + };