diff --git a/.replit b/.replit index ccafaa6..4f7eaad 100644 --- a/.replit +++ b/.replit @@ -19,7 +19,7 @@ localPort = 35345 externalPort = 3002 [[ports]] -localPort = 40293 +localPort = 39333 externalPort = 3001 [[ports]] diff --git a/client/src/components/KanbanBoard.tsx b/client/src/components/KanbanBoard.tsx index 913beaa..0ed76a4 100644 --- a/client/src/components/KanbanBoard.tsx +++ b/client/src/components/KanbanBoard.tsx @@ -7,7 +7,7 @@ import { LayoutGrid, Calendar as CalendarIcon, ChevronLeft, ChevronRight } from import { Task, Label } from '@shared/schema'; import TaskCard from './TaskCard'; import { useQuery } from '@tanstack/react-query'; -import { format, startOfWeek, endOfWeek, startOfMonth, endOfMonth, addWeeks, addMonths, isWithinInterval, addDays, isSameDay, getDaysInMonth } from 'date-fns'; +import { format, startOfWeek, endOfWeek, startOfMonth, endOfMonth, addWeeks, addMonths, isWithinInterval } from 'date-fns'; interface KanbanBoardProps { tasks: Task[]; @@ -78,8 +78,10 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate }: const navigatePeriod = (direction: 'prev' | 'next') => { if (viewMode === 'weekly') { setCurrentDate(addWeeks(currentDate, direction === 'next' ? 1 : -1)); + console.log(`Navigating to week of ${format(addWeeks(currentDate, direction === 'next' ? 1 : -1), 'd.M.yyyy')}`); } else if (viewMode === 'monthly') { setCurrentDate(addMonths(currentDate, direction === 'next' ? 1 : -1)); + console.log(`Navigating to month of ${format(addMonths(currentDate, direction === 'next' ? 1 : -1), 'MMM yyyy')}`); } }; @@ -92,195 +94,6 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate }: return 'All Tasks'; }; - const getTasksForDate = (date: Date) => { - return tasks.filter(task => - task.dueDate && isSameDay(task.dueDate, date) - ); - }; - - const handleDateDrop = (date: Date) => { - if (draggedTask) { - const task = tasks.find(t => t.id === draggedTask); - if (task) { - onTaskUpdate?.(draggedTask, { dueDate: date }); - console.log(`Task ${draggedTask} moved to ${format(date, 'yyyy-MM-dd')}`); - } - setDraggedTask(null); - } - }; - - const renderWeeklyCalendar = () => { - const weekStart = startOfWeek(currentDate); - const dates = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i)); - - return ( -
- {dates.map((date, index) => { - const dayTasks = getTasksForDate(date); - const isToday = isSameDay(date, new Date()); - const isWeekend = date.getDay() === 0 || date.getDay() === 6; - - return ( - handleDateDrop(date)} - data-testid={`calendar-date-${format(date, 'yyyy-MM-dd')}`} - > -
-
- {format(date, 'EEE')} -
-
- {format(date, 'd')} -
-
- -
- {dayTasks.slice(0, 3).map((task) => { - const taskLabel = task.labelId && labels.length > 0 ? labels.find(label => label.id === task.labelId) : null; - - return ( -
handleDragStart(task.id)} - onDragEnd={handleDragEnd} - className={`cursor-move ${draggedTask === task.id ? 'opacity-50' : ''}`} - data-testid={`calendar-task-${task.id}`} - > - -
- {task.title} -
-
-
- ); - })} - - {dayTasks.length > 3 && ( - - +{dayTasks.length - 3} more - - )} -
-
- ); - })} -
- ); - }; - - const renderMonthlyCalendar = () => { - const monthStart = startOfMonth(currentDate); - const monthEnd = endOfMonth(currentDate); - const calendarStart = startOfWeek(monthStart); - const calendarEnd = endOfWeek(monthEnd); - - const dates = []; - let currentDateIterator = calendarStart; - - while (currentDateIterator <= calendarEnd) { - dates.push(currentDateIterator); - currentDateIterator = addDays(currentDateIterator, 1); - } - - return ( -
- {/* Month grid header */} -
- {['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map(day => ( -
- {day} -
- ))} -
- - {/* Month grid */} -
- {dates.map((date, index) => { - const dayTasks = getTasksForDate(date); - const isToday = isSameDay(date, new Date()); - const isCurrentMonth = date >= monthStart && date <= monthEnd; - - return ( - handleDateDrop(date)} - data-testid={`calendar-date-${format(date, 'yyyy-MM-dd')}`} - > -
-
- {format(date, 'd')} -
-
- -
- {dayTasks.slice(0, 2).map((task) => { - const taskLabel = task.labelId && labels.length > 0 ? labels.find(label => label.id === task.labelId) : null; - - return ( -
handleDragStart(task.id)} - onDragEnd={handleDragEnd} - className={`cursor-move ${draggedTask === task.id ? 'opacity-50' : ''}`} - data-testid={`calendar-task-${task.id}`} - > - -
- {task.title} -
-
-
- ); - })} - - {dayTasks.length > 2 && ( - - +{dayTasks.length - 2} - - )} -
-
- ); - })} -
-
- ); - }; return (
@@ -339,8 +152,8 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate }: + {/* All view modes use the same kanban layout, just with different filtering */} - {/* Kanban Columns */}
{columns.map((column) => { const columnTasks = getTasksForColumn(column.status); @@ -402,11 +215,125 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate }: - {renderWeeklyCalendar()} +
+ {columns.map((column) => { + const columnTasks = getTasksForColumn(column.status); + + return ( + handleDrop(column.status)} + data-testid={`column-${column.id}`} + > +
+

+ {column.title} +

+ + {columnTasks.length} + +
+ +
+ {columnTasks.map((task) => ( +
handleDragStart(task.id)} + onDragEnd={handleDragEnd} + className={`cursor-move ${draggedTask === task.id ? 'opacity-50' : ''}`} + > + { + onTaskUpdate?.(task.id, { isTracking: true }); + console.log(`Timer started for ${task.title}`); + }} + onPause={() => { + onTaskUpdate?.(task.id, { isTracking: false }); + console.log(`Timer paused for ${task.title}`); + }} + onEdit={() => { + console.log(`Edit task ${task.title}`); + }} + isDragging={draggedTask === task.id} + /> +
+ ))} + + {columnTasks.length === 0 && ( +
+ No tasks in {column.title.toLowerCase()} for this week +
+ )} +
+
+ ); + })} +
- {renderMonthlyCalendar()} +
+ {columns.map((column) => { + const columnTasks = getTasksForColumn(column.status); + + return ( + handleDrop(column.status)} + data-testid={`column-${column.id}`} + > +
+

+ {column.title} +

+ + {columnTasks.length} + +
+ +
+ {columnTasks.map((task) => ( +
handleDragStart(task.id)} + onDragEnd={handleDragEnd} + className={`cursor-move ${draggedTask === task.id ? 'opacity-50' : ''}`} + > + { + onTaskUpdate?.(task.id, { isTracking: true }); + console.log(`Timer started for ${task.title}`); + }} + onPause={() => { + onTaskUpdate?.(task.id, { isTracking: false }); + console.log(`Timer paused for ${task.title}`); + }} + onEdit={() => { + console.log(`Edit task ${task.title}`); + }} + isDragging={draggedTask === task.id} + /> +
+ ))} + + {columnTasks.length === 0 && ( +
+ No tasks in {column.title.toLowerCase()} for this month +
+ )} +
+
+ ); + })} +