diff --git a/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx b/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx index 6c89515c..37af547a 100644 --- a/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx +++ b/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx @@ -283,6 +283,24 @@ const TaskListV2: React.FC = () => { project_id: urlProjectId, }; + // Update the Redux store immediately for optimistic updates + const currentTask = allTasks.find(task => task.id === taskId); + if (currentTask) { + const updatedTask = { + ...currentTask, + custom_column_values: { + ...currentTask.custom_column_values, + [columnKey]: value, + }, + updated_at: new Date().toISOString(), + }; + + // Import and dispatch the updateTask action + import('@/features/task-management/task-management.slice').then(({ updateTask }) => { + dispatch(updateTask(updatedTask)); + }); + } + if (socket && connected) { socket.emit(SocketEvents.TASK_CUSTOM_COLUMN_UPDATE.toString(), JSON.stringify(body)); } else { @@ -291,7 +309,7 @@ const TaskListV2: React.FC = () => { } catch (error) { console.error('Error updating custom column value:', error); } - }, [urlProjectId, socket, connected]); + }, [urlProjectId, socket, connected, allTasks, dispatch]); // Custom column settings handler const handleCustomColumnSettings = useCallback((columnKey: string) => { @@ -317,11 +335,9 @@ const TaskListV2: React.FC = () => { // The global socket handler will handle the real-time update }, []); - // Handle scroll synchronization + // Handle scroll synchronization - disabled since header is now sticky inside content const handleContentScroll = useCallback(() => { - if (headerScrollRef.current && contentScrollRef.current) { - headerScrollRef.current.scrollLeft = contentScrollRef.current.scrollLeft; - } + // No longer needed since header scrolls naturally with content }, []); // Memoized values for GroupedVirtuoso @@ -454,7 +470,7 @@ const TaskListV2: React.FC = () => { // Render column headers const renderColumnHeaders = useCallback(() => ( -
+
{visibleColumns.map((column, index) => { const columnStyle: ColumnStyle = { @@ -491,7 +507,8 @@ const TaskListV2: React.FC = () => {
); })} -
+ {/* Add Custom Column Button - positioned at the end and scrolls with content */} +
@@ -533,7 +550,7 @@ const TaskListV2: React.FC = () => { onDragOver={handleDragOver} onDragEnd={handleDragEnd} > -
+
{/* Task Filters */}
@@ -544,33 +561,24 @@ const TaskListV2: React.FC = () => { {/* Table Container */}
- {/* Column Headers */} -
-
- {renderColumnHeaders()} -
-
- - {/* Task List Content */} + {/* Task List Content with Sticky Header */}
+ {/* Sticky Column Headers */} +
+ {renderColumnHeaders()} +
!('isAddTaskRow' in item) && !item.parent_task_id) diff --git a/worklenz-frontend/src/components/task-list-v2/components/CustomColumnComponents.tsx b/worklenz-frontend/src/components/task-list-v2/components/CustomColumnComponents.tsx index 8df48ff2..a79839ac 100644 --- a/worklenz-frontend/src/components/task-list-v2/components/CustomColumnComponents.tsx +++ b/worklenz-frontend/src/components/task-list-v2/components/CustomColumnComponents.tsx @@ -284,7 +284,7 @@ export const DateCustomColumnCell: React.FC<{ }; return ( -
+
option.selection_name === customValue); const handleOptionSelect = async (option: any) => { + if (!task.id) return; + + setIsDropdownOpen(false); setIsLoading(true); + try { - if (task.id) { - updateTaskCustomColumnValue(task.id, columnKey, option.selection_name); - } - setIsDropdownOpen(false); - } finally { - // Small delay to show loading state - setTimeout(() => setIsLoading(false), 200); + // Send the update to the server - Redux store will be updated immediately + updateTaskCustomColumnValue(task.id, columnKey, option.selection_name); + + // Short loading state for visual feedback + setTimeout(() => { + setIsLoading(false); + }, 200); + } catch (error) { + console.error('Error updating selection:', error); + setIsLoading(false); } }; @@ -527,7 +534,7 @@ export const SelectionCustomColumnCell: React.FC<{ ); return ( -
+