This repository has been archived on 2024-02-08. You can view files and clone it, but cannot push or open issues or pull requests.
frontend/src/composables/taskList.ts

124 lines
3.1 KiB
TypeScript

import {ref, shallowReactive, watch, computed, type Ref} from 'vue'
import {useRoute} from 'vue-router'
import TaskCollectionService from '@/services/taskCollection'
import type {ITask} from '@/modelTypes/ITask'
import type {IList} from '@/modelTypes/IList'
import type {IParams, OrderBy, SortBy} from '@/types/IParams'
// FIXME: merge with DEFAULT_PARAMS in filters.vue
export const getDefaultParams = () => ({
sortBy: ['position', 'id'],
orderBy: ['asc', 'desc'],
filterBy: ['done'],
filterValue: ['false'],
filterComparator: ['equals'],
filterConcat: 'and',
} as IParams)
type FilterSortOrderMap = Partial<{[key in SortBy]: OrderBy }>
const SORT_BY_DEFAULT: FilterSortOrderMap = {
id: 'desc',
} as const
/**
* This mixin provides a base set of methods and properties to get tasks on a list.
*/
export function useTaskList(listId: Ref<IList['id']>, sortByDefault = SORT_BY_DEFAULT) {
const params = ref({...getDefaultParams()})
const search = ref('')
const page = ref(1)
const sortBy = ref<FilterSortOrderMap>({ ...sortByDefault })
// This makes sure an id sort order is always sorted last.
// When tasks would be sorted first by id and then by whatever else was specified, the id sort takes
// precedence over everything else, making any other sort columns pretty useless.
function formatSortOrder(params: IParams) {
const sortEntries = Object.entries(sortBy.value)
const sortKeys: SortBy[] = []
const orderByValue: OrderBy[] = []
let idFilterValue
sortEntries.forEach(([key, value], index) => {
if (key === 'id') {
idFilterValue = value
sortEntries.splice(index, 1)
return true
}
sortKeys.push(key as SortBy)
orderByValue.push(value)
})
if (idFilterValue) {
sortKeys.push('id')
}
params.sortBy = sortKeys
params.orderBy = orderByValue
return params
}
const getAllTasksParams = computed(() => {
let loadParams = {...params.value}
if (search.value !== '') {
loadParams.s = search.value
}
loadParams = formatSortOrder(loadParams)
return [
{listId: listId.value},
loadParams,
page.value || 1,
]
})
const taskCollectionService = shallowReactive(new TaskCollectionService())
const loading = computed(() => taskCollectionService.loading)
const totalPages = computed(() => taskCollectionService.totalPages)
const tasks = ref<ITask[]>([])
async function loadTasks() {
tasks.value = []
tasks.value = await taskCollectionService.getAll(...getAllTasksParams.value)
return tasks.value
}
const route = useRoute()
watch(() => route.query, (query) => {
const { page: pageQueryValue, search: searchQuery } = query
if (searchQuery !== undefined) {
search.value = searchQuery as string
}
if (pageQueryValue !== undefined) {
page.value = Number(pageQueryValue)
}
}, { immediate: true })
// Only listen for query path changes
watch(() => JSON.stringify(getAllTasksParams.value), (newParams, oldParams) => {
if (oldParams === newParams) {
return
}
loadTasks()
}, { immediate: true })
return {
tasks,
loading,
totalPages,
currentPage: page,
loadTasks,
searchTerm: search,
params,
sortByParam: sortBy,
}
}