124 lines
3.1 KiB
TypeScript
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,
|
|
}
|
|
} |