Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #75: add all the components to the Task Panel #76

Merged
merged 2 commits into from
Dec 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 189 additions & 22 deletions app/components/TaskPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
"use client";

import React, { useEffect, useState } from 'react';
import { DragDropContext, DropResult } from '@hello-pangea/dnd';
import ExportMenu from './ExportMenu';
import { TaskList as TaskListComponent } from './TaskList';
import { ThemeProvider, useTheme, ThemeType } from '../hooks/useTheme';
import { useTasks } from '../hooks/useTasks';
import { useSearch } from '../hooks/useSearch';
import SearchBar from './SearchBar';
import { useKeyboardShortcuts } from '../hooks/useKeyboardShortcuts';
import ThemeSelector from './ThemeSelector';
import TaskForm from './TaskForm';
import AIAssistantPanel from './AIAssistantPanel';
import TaskAnalytics from './TaskAnalytics';
import TaskAutomation from './TaskAutomation';
import React, { useEffect, useState } from 'react';
import { DragDropContext, DropResult } from '@hello-pangea/dnd';
import ExportMenu from './ExportMenu';
import React, { useEffect, useState } from 'react';
import { DragDropContext, DropResult } from '@hello-pangea/dnd';
import ExportMenu from './ExportMenu';
Expand All @@ -21,6 +38,9 @@ import { useRouter } from 'next/navigation';
import { Task } from '../types/task';
import { colors } from '../config/colors';
import AGiXTConfig from './AGiXTConfig';
import { WorkspacePanel } from './WorkspacePanel';
import ViewSelector from './ViewSelector';
import { ViewType } from '../types/view';

const defaultTheme: ThemeType = {
primary: colors.primary.DEFAULT,
Expand All @@ -40,7 +60,7 @@ const defaultTheme: ThemeType = {
}
};

const TaskPanel: React.FC = () => {
const TaskPanel: React.FC = () =>{
const [mounted, setMounted] = useState(false);
const [isInitialized, setIsInitialized] = useState(false);
const [error, setError] = useState<string | null>(null);
Expand All @@ -53,12 +73,13 @@ const TaskPanel: React.FC = () => {
const [isAGiXTConfigOpen, setIsAGiXTConfigOpen] = useState(false);
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
const [agixtConfig, setAgixtConfig] = useState({ backendUrl: '', authToken: '' });

const [currentView, setCurrentView] = useState<ViewType>('board');

const { tasks, addTask, updateTask, deleteTask, reorderTasks, lists } = useTasks({
remoteEnabled: false,
userId: 'anonymous'
});

const {
searchTerm,
setSearchTerm,
Expand Down Expand Up @@ -101,36 +122,36 @@ useEffect(() =>{
}, [token, noAuth]);

useKeyboardShortcuts({
onNewTask: () => setIsEditorOpen(true),
onSearch: () => document.getElementById('search-input')?.focus(),
onToggleView: () => {},
onDelete: () => {},
onDeleteTask: () => {}
onNewTask: () =>setIsEditorOpen(true),
onSearch: () =>document.getElementById('search-input')?.focus(),
onToggleView: () =>{},
onDelete: () =>{},
onDeleteTask: () =>{}
});

const onDragEnd = (result: DropResult) => {
const onDragEnd = (result: DropResult) =>{
if (!result.destination) return;

const sourceStatus = result.source.droppableId;
const destinationStatus = result.destination.droppableId;
const taskId = result.draggableId;

if (sourceStatus === destinationStatus) {
const listTasks = tasks.filter(t => t.status === sourceStatus);
const listTasks = tasks.filter(t =>t.status === sourceStatus);
const [movedTask] = listTasks.splice(result.source.index, 1);
listTasks.splice(result.destination.index, 0, movedTask);

const updatedTasks = tasks.map(t => {
const updatedTasks = tasks.map(t =>{
if (t.status === sourceStatus) {
const reorderedTask = listTasks.find(rt => rt.id === t.id);
const reorderedTask = listTasks.find(rt =>rt.id === t.id);
return reorderedTask || t;
}
return t;
});

reorderTasks(updatedTasks);
} else {
const task = tasks.find(t => t.id === taskId);
const task = tasks.find(t =>t.id === taskId);
if (!task) return;

const updatedTask = {
Expand All @@ -142,7 +163,7 @@ useEffect(() =>{
}
};

const handleTaskSuggestion = (taskSuggestion: Partial<Task>) => {
const handleTaskSuggestion = (taskSuggestion: Partial<Task>) =>{
const newTask: Task = {
id: Date.now().toString(),
title: taskSuggestion.title || '',
Expand All @@ -162,18 +183,164 @@ useEffect(() =>{
addTask(newTask);
};

const handleTaskOptimization = (taskIds: string[]) => {
const optimizedTasks = taskIds.map(id => tasks.find(t => t.id === id)).filter(Boolean) as Task[];
const handleTaskOptimization = (taskIds: string[]) =>{
const optimizedTasks = taskIds.map(id =>tasks.find(t =>t.id === id)).filter(Boolean) as Task[];
reorderTasks(optimizedTasks);
};

if (!mounted || !isInitialized) {
return (
<div className="flex items-center justify-center h-screen bg-[#111111] text-white">
<div className="text-center">
<div className="text-lg mb-2">Loading Task Panel...</div>
<div className="text-sm text-gray-400">Please wait while we set things up</div>
</div>
return (<div className="flex items-center justify-center h-screen bg-[#111111] text-white"><div className="text-center"><div className="text-lg mb-2">Loading Task Panel...</div><div className="text-sm text-gray-400">Please wait while we set things up</div></div></div>);
}

if (error) {
return (<div className="flex items-center justify-center h-screen bg-[#111111] text-white"><div className="text-center"><div className="text-lg mb-2 text-red-500">Error Loading Task Panel</div><div className="text-sm text-gray-400">{error}</div></div></div>);
}

return (<ThemeProvider value={{ theme, setTheme }}><div className="min-h-screen bg-[#111111] text-white p-4"><div className="flex"><div className="flex-1 max-w-7xl mx-auto"><header className="mb-8"><div className="flex justify-between items-center mb-4"><h1 className="text-2xl font-bold">Task Panel</h1><div className="flex items-center space-x-4"><ThemeSelector currentTheme={theme} onThemeChange={setTheme} /><button
onClick={() =>setIsAGiXTConfigOpen(true)}
className="px-4 py-2 bg-gray-600 hover:bg-gray-700 rounded-lg transition-colors"
>AGiXT Config</button><button
onClick={() =>setIsEditorOpen(true)}
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 rounded-lg transition-colors"
>New Task</button></div></div>{isAGiXTConfigOpen && (<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"><div className="bg-gray-800 p-6 rounded-lg w-full max-w-2xl mx-4"><AGiXTConfig
onClose={() =>setIsAGiXTConfigOpen(false)}
onSave={(config) =>{
setAgixtConfig(config);
setIsAGiXTConfigOpen(false);
}}
/></div></div>)}<SearchBar
searchTerm={searchTerm}
onSearchChange={setSearchTerm}
sortBy={sortBy}
onSortChange={setSortBy}
filterPriority={filterPriority}
onFilterChange={setFilterPriority}
/></header><WorkspacePanel /><div className="space-y-6 mb-8"><div className="grid grid-cols-1 md:grid-cols-2 gap-6"><TaskAnalytics tasks={tasks} /><TaskAutomation tasks={tasks} onUpdateTask={updateTask} /></div><TaskDependencyGraph
tasks={tasks}
onTaskClick={setSelectedTask}
/></div><DragDropContext onDragEnd={onDragEnd}><main className="grid grid-cols-1 md:grid-cols-3 gap-6"><div className="bg-gray-800 rounded-lg p-4"><h2 className="text-xl font-semibold mb-4">To Do</h2><TaskListComponent
droppableId="todo"
tasks={filteredAndSortedTasks().filter(task =>task.status === 'todo')}
onUpdateTask={updateTask}
onTaskClick={(task) =>setSelectedTask(task)}
onDeleteTask={(task) =>deleteTask(task.id)}
onReorderTasks={reorderTasks}
listId="default"
/></div><div className="bg-gray-800 rounded-lg p-4"><h2 className="text-xl font-semibold mb-4">In Progress</h2><TaskListComponent
droppableId="in-progress"
tasks={filteredAndSortedTasks().filter(task =>task.status === 'in-progress')}
onUpdateTask={updateTask}
onTaskClick={(task) =>setSelectedTask(task)}
onDeleteTask={(task) =>deleteTask(task.id)}
onReorderTasks={reorderTasks}
listId="default"
/></div><div className="bg-gray-800 rounded-lg p-4"><h2 className="text-xl font-semibold mb-4">Done</h2><TaskListComponent
droppableId="done"
tasks={filteredAndSortedTasks().filter(task =>task.status === 'done')}
onUpdateTask={updateTask}
onTaskClick={(task) =>setSelectedTask(task)}
onDeleteTask={(task) =>deleteTask(task.id)}
onReorderTasks={reorderTasks}
listId="default"
/></div></main></DragDropContext>{isEditorOpen && (<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"><div className="bg-gray-800 p-6 rounded-lg w-full max-w-2xl mx-4"><TaskForm
onSubmit={(task) =>{
addTask(task);
setIsEditorOpen(false);
}}
onCancel={() =>setIsEditorOpen(false)}
lists={lists}
/></div></div>)}</div><div className="flex flex-col">{agixtConfig.backendUrl && agixtConfig.authToken && (<AIAssistantPanel
backendUrl={agixtConfig.backendUrl}
authToken={agixtConfig.authToken}
onTaskSuggestion={handleTaskSuggestion}
onTaskOptimization={handleTaskOptimization}
tasks={tasks}
selectedTask={selectedTask}
className="ml-4"
/>)}{selectedTask && (<TaskDetailsPanel
task={selectedTask}
onClose={() =>setSelectedTask(null)}
onUpdateTask={updateTask}
allTasks={tasks}
className="ml-4 mt-4"
/>)}</div></div></div></ThemeProvider>);
};

export default TaskPanel;
}

return (<ThemeProvider value={{ theme, setTheme }}><div className="min-h-screen bg-[#111111] text-white p-4"><div className="flex"><div className="flex-1 max-w-7xl mx-auto"><header className="mb-8"><div className="flex justify-between items-center mb-4"><h1 className="text-2xl font-bold">Task Panel</h1><div className="flex items-center space-x-4"><ThemeSelector currentTheme={theme} onThemeChange={setTheme} /><button
onClick={() =>setIsAGiXTConfigOpen(true)}
className="px-4 py-2 bg-gray-600 hover:bg-gray-700 rounded-lg transition-colors"
>AGiXT Config</button><button
onClick={() =>setIsEditorOpen(true)}
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 rounded-lg transition-colors"
>New Task</button></div></div>{isAGiXTConfigOpen && (<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"><div className="bg-gray-800 p-6 rounded-lg w-full max-w-2xl mx-4"><AGiXTConfig
onClose={() =>setIsAGiXTConfigOpen(false)}
onSave={(config) =>{
setAgixtConfig(config);
setIsAGiXTConfigOpen(false);
}}
/></div></div>)}<SearchBar
searchTerm={searchTerm}
onSearchChange={setSearchTerm}
sortBy={sortBy}
onSortChange={setSortBy}
filterPriority={filterPriority}
onFilterChange={setFilterPriority}
/></header><div className="space-y-6 mb-8"><div className="grid grid-cols-1 md:grid-cols-2 gap-6"><TaskAnalytics tasks={tasks} /><TaskAutomation tasks={tasks} onUpdateTask={updateTask} /></div><TaskDependencyGraph
tasks={tasks}
onTaskClick={setSelectedTask}
/></div><DragDropContext onDragEnd={onDragEnd}><main className="grid grid-cols-1 md:grid-cols-3 gap-6"><div className="bg-gray-800 rounded-lg p-4"><h2 className="text-xl font-semibold mb-4">To Do</h2><TaskListComponent
droppableId="todo"
tasks={filteredAndSortedTasks().filter(task =>task.status === 'todo')}
onUpdateTask={updateTask}
onTaskClick={(task) =>setSelectedTask(task)}
onDeleteTask={(task) =>deleteTask(task.id)}
onReorderTasks={reorderTasks}
listId="default"
/></div><div className="bg-gray-800 rounded-lg p-4"><h2 className="text-xl font-semibold mb-4">In Progress</h2><TaskListComponent
droppableId="in-progress"
tasks={filteredAndSortedTasks().filter(task =>task.status === 'in-progress')}
onUpdateTask={updateTask}
onTaskClick={(task) =>setSelectedTask(task)}
onDeleteTask={(task) =>deleteTask(task.id)}
onReorderTasks={reorderTasks}
listId="default"
/></div><div className="bg-gray-800 rounded-lg p-4"><h2 className="text-xl font-semibold mb-4">Done</h2><TaskListComponent
droppableId="done"
tasks={filteredAndSortedTasks().filter(task =>task.status === 'done')}
onUpdateTask={updateTask}
onTaskClick={(task) =>setSelectedTask(task)}
onDeleteTask={(task) =>deleteTask(task.id)}
onReorderTasks={reorderTasks}
listId="default"
/></div></main></DragDropContext>{isEditorOpen && (<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"><div className="bg-gray-800 p-6 rounded-lg w-full max-w-2xl mx-4"><TaskForm
onSubmit={(task) =>{
addTask(task);
setIsEditorOpen(false);
}}
onCancel={() =>setIsEditorOpen(false)}
lists={lists}
/></div></div>)}</div><div className="flex flex-col">{agixtConfig.backendUrl && agixtConfig.authToken && (<AIAssistantPanel
backendUrl={agixtConfig.backendUrl}
authToken={agixtConfig.authToken}
onTaskSuggestion={handleTaskSuggestion}
onTaskOptimization={handleTaskOptimization}
tasks={tasks}
selectedTask={selectedTask}
className="ml-4"
/>)}
{selectedTask && (<TaskDetailsPanel
task={selectedTask}
onClose={() =>setSelectedTask(null)}
onUpdateTask={updateTask}
allTasks={tasks}
className="ml-4 mt-4"
/>)}</div></div></div></ThemeProvider>);
};

export default TaskPanel;
</div>
);
}
Expand Down
Loading