diff --git a/packages/com.sncommunity.advanced-checklist/src/common/utils.test.ts b/packages/com.sncommunity.advanced-checklist/src/common/utils.test.ts index e63bacb9..85460efc 100644 --- a/packages/com.sncommunity.advanced-checklist/src/common/utils.test.ts +++ b/packages/com.sncommunity.advanced-checklist/src/common/utils.test.ts @@ -7,6 +7,7 @@ import { getPlainPreview, getTaskArrayFromGroupedTasks, groupTasksByCompletedStatus, + reorderTasksWithinSection, parseMarkdownTasks, truncateText, } from './utils' @@ -118,6 +119,36 @@ describe('groupTasksByCompletedStatus', () => { }) }) +describe('reorderTasksWithinSection', () => { + const createdAt = new Date().toISOString() + + it('should reorder open tasks without moving completed tasks in the array', () => { + const tasks: TaskModel[] = [ + { id: 'completed-1', description: 'Done A', completed: true, createdAt }, + { id: 'open-1', description: 'Open A', completed: false, createdAt }, + { id: 'open-2', description: 'Open B', completed: false, createdAt }, + { id: 'completed-2', description: 'Done B', completed: true, createdAt }, + ] + + const reordered = reorderTasksWithinSection(tasks, 'open-tasks', 0, 1) + + expect(reordered.map((task) => task.id)).toEqual(['completed-1', 'open-2', 'open-1', 'completed-2']) + }) + + it('should reorder completed tasks without moving open tasks in the array', () => { + const tasks: TaskModel[] = [ + { id: 'open-1', description: 'Open A', completed: false, createdAt }, + { id: 'completed-1', description: 'Done A', completed: true, createdAt }, + { id: 'completed-2', description: 'Done B', completed: true, createdAt }, + { id: 'open-2', description: 'Open B', completed: false, createdAt }, + ] + + const reordered = reorderTasksWithinSection(tasks, 'completed-tasks', 0, 1) + + expect(reordered.map((task) => task.id)).toEqual(['open-1', 'completed-2', 'completed-1', 'open-2']) + }) +}) + describe('getTaskArrayFromGroupedTasks', () => { it('should return an array of tasks', () => { const workTasks = [ diff --git a/packages/com.sncommunity.advanced-checklist/src/common/utils.ts b/packages/com.sncommunity.advanced-checklist/src/common/utils.ts index 6846183d..d0568bfa 100644 --- a/packages/com.sncommunity.advanced-checklist/src/common/utils.ts +++ b/packages/com.sncommunity.advanced-checklist/src/common/utils.ts @@ -35,6 +35,24 @@ export function groupTasksByCompletedStatus(tasks: TaskModel[]) { } } +export function taskMatchesSection(task: TaskModel, sectionId: string): boolean { + return sectionId === 'completed-tasks' ? task.completed === true : !task.completed +} + +export function reorderTasksWithinSection( + tasks: TaskModel[], + sectionId: string, + fromIndex: number, + toIndex: number, +): TaskModel[] { + const matchesSection = (task: TaskModel) => taskMatchesSection(task, sectionId) + const sectionTasks = tasks.filter(matchesSection) + const reorderedSection = arrayMoveImmutable(sectionTasks, fromIndex, toIndex) + + let sectionIndex = 0 + return tasks.map((task) => (matchesSection(task) ? reorderedSection[sectionIndex++] : task)) +} + export function getTaskArrayFromGroupedTasks(groupedTasks: GroupModel[]): TaskModel[] { let taskArray: TaskModel[] = [] diff --git a/packages/com.sncommunity.advanced-checklist/src/features/tasks/TaskSectionList.tsx b/packages/com.sncommunity.advanced-checklist/src/features/tasks/TaskSectionList.tsx index 05e14800..fd30aae2 100644 --- a/packages/com.sncommunity.advanced-checklist/src/features/tasks/TaskSectionList.tsx +++ b/packages/com.sncommunity.advanced-checklist/src/features/tasks/TaskSectionList.tsx @@ -31,9 +31,12 @@ const TaskSectionList: React.FC = ({ group }) => { return } + const sectionId = source.droppableId.replace(/-droppable$/, '') + dispatch( tasksReordered({ groupName: group.name, + sectionId, swapTaskIndex: source.index, withTaskIndex: destination.index, isSameSection: source.droppableId === destination.droppableId, diff --git a/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.test.ts b/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.test.ts index b70190db..50c89be9 100644 --- a/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.test.ts +++ b/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.test.ts @@ -739,6 +739,7 @@ it('should handle adding an existing task group', () => { }) it('should handle reordering tasks from the same section', () => { + const createdAt = new Date().toISOString() const previousState: TasksState = { schemaVersion: '1.0.0', defaultSections: [], @@ -747,22 +748,28 @@ it('should handle reordering tasks from the same section', () => { name: 'Test', tasks: [ { - id: 'some-id', - description: 'A simple task', + id: 'completed-1', + description: 'A completed task', completed: true, - createdAt: new Date().toISOString(), + createdAt, }, { - id: 'another-id', - description: 'Another simple task', + id: 'open-1', + description: 'First open task', completed: false, - createdAt: new Date().toISOString(), + createdAt, }, { - id: 'yet-another-id', - description: 'Yet another simple task', + id: 'open-2', + description: 'Second open task', + completed: false, + createdAt, + }, + { + id: 'completed-2', + description: 'Another completed task', completed: true, - createdAt: new Date().toISOString(), + createdAt, }, ], }, @@ -774,6 +781,7 @@ it('should handle reordering tasks from the same section', () => { previousState, tasksReordered({ groupName: 'Test', + sectionId: 'open-tasks', swapTaskIndex: 0, withTaskIndex: 1, isSameSection: true, @@ -787,20 +795,26 @@ it('should handle reordering tasks from the same section', () => { name: 'Test', tasks: [ { - id: 'another-id', - description: 'Another simple task', + id: 'completed-1', + description: 'A completed task', + completed: true, + createdAt: expect.any(String), + }, + { + id: 'open-2', + description: 'Second open task', completed: false, createdAt: expect.any(String), }, { - id: 'some-id', - description: 'A simple task', - completed: true, + id: 'open-1', + description: 'First open task', + completed: false, createdAt: expect.any(String), }, { - id: 'yet-another-id', - description: 'Yet another simple task', + id: 'completed-2', + description: 'Another completed task', completed: true, createdAt: expect.any(String), }, @@ -846,6 +860,7 @@ it('should handle reordering tasks from different sections', () => { previousState, tasksReordered({ groupName: 'Test', + sectionId: 'open-tasks', swapTaskIndex: 0, withTaskIndex: 1, isSameSection: false, diff --git a/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.ts b/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.ts index af8dc50f..6d6794fc 100644 --- a/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.ts +++ b/packages/com.sncommunity.advanced-checklist/src/features/tasks/tasks-slice.ts @@ -1,5 +1,5 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { arrayDefault, arrayMoveImmutable, isJsonString, parseMarkdownTasks } from '../../common/utils' +import { arrayDefault, arrayMoveImmutable, isJsonString, parseMarkdownTasks, reorderTasksWithinSection } from '../../common/utils' export const LATEST_SCHEMA_VERSION = '1.0.0' export const DEFAULT_SECTIONS: SectionModel[] = [ @@ -148,12 +148,13 @@ const tasksSlice = createSlice({ state, action: PayloadAction<{ groupName: string + sectionId: string swapTaskIndex: number withTaskIndex: number isSameSection: boolean }>, ) { - const { groupName, swapTaskIndex, withTaskIndex, isSameSection } = action.payload + const { groupName, sectionId, swapTaskIndex, withTaskIndex, isSameSection } = action.payload if (!isSameSection) { return } @@ -161,7 +162,7 @@ const tasksSlice = createSlice({ if (!group) { return } - group.tasks = arrayMoveImmutable(group.tasks, swapTaskIndex, withTaskIndex) + group.tasks = reorderTasksWithinSection(group.tasks, sectionId, swapTaskIndex, withTaskIndex) }, tasksGroupAdded( state,