diff --git a/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.test.ts b/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.test.ts index 119e8a86..bf4442cf 100644 --- a/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.test.ts +++ b/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.test.ts @@ -87,4 +87,32 @@ describe('TimeTrackerProjectTaskDropdown', () => { expect(wrapper.emitted('changed')?.at(-1)).toEqual(['', null]); }); + + it("keeps a project's tasks visible when the search term matches the project name", async () => { + const project = { + id: 'p-dummy', + name: 'dummy', + color: '#fff', + client_id: null, + is_archived: false, + } as unknown as Project; + const tasks = [ + { id: 't-1', name: 'design', project_id: 'p-dummy', is_done: false }, + { id: 't-2', name: 'build', project_id: 'p-dummy', is_done: false }, + ] as unknown as Task[]; + + const wrapper = mountDropdown({ projects: [project], tasks }); + await nextTick(); + await nextTick(); + + const searchInput = wrapper.find('[data-testid="client_dropdown_search"]'); + await searchInput.setValue('dummy'); + await nextTick(); + + // project itself shows up + expect(wrapper.find('[data-project-id="p-dummy"]').exists()).toBe(true); + // and its tasks are still available even though they don't match "dummy": + // the task expander keeps showing all of the project's tasks + expect(wrapper.text()).toContain('2 Tasks'); + }); }); diff --git a/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue b/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue index 9238a5be..54388aad 100644 --- a/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue +++ b/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue @@ -251,23 +251,26 @@ function updateFilteredResults() { const projectTasks = tasksByProject.value.get(filterProject.id) ?? []; - const filteredTasks = projectTasks.filter((filterTask) => { - return ( - filterTask.name.toLowerCase().includes(searchTerm) && - (!filterTask.is_done || filterTask.id === task.value) - ); + // tasks that should be selectable regardless of the search term + // (open tasks, plus the currently selected one even if it's done) + const availableTasks = projectTasks.filter((filterTask) => { + return !filterTask.is_done || filterTask.id === task.value; + }); + + const filteredTasks = availableTasks.filter((filterTask) => { + return filterTask.name.toLowerCase().includes(searchTerm); }); if ( (projectNameIncludesSearchTerm || clientNameIncludesSearchTerm) && (!filterProject.is_archived || project.value === filterProject.id) ) { - // search term matches project name + // search term matches project (or client) name: show all the tasks addProjectToFilterObject( tempFilteredClients, groupIndexByKey, filterProject, - filteredTasks, + availableTasks, false ); } else if (filteredTasks.length > 0 && !filterProject.is_archived) {