feat: add checklist item category sorting

This commit is contained in:
2026-04-11 21:48:37 +03:00
parent 317b17beab
commit f3880cefe0
6 changed files with 39 additions and 5 deletions

View File

@@ -178,7 +178,7 @@ final class ChecklistController extends OCSController {
*
* @param int $houseId House id.
* @param int $listId List id.
* @param string $sortBy Sort mode (custom, newest, oldest, name_asc, name_desc).
* @param string $sortBy Sort mode (custom, newest, oldest, name_asc, name_desc, category).
* @param int<1, 1000> $limit Maximum number of items to return.
* @param int<0, max> $offset Number of items to skip.
*

View File

@@ -26,8 +26,35 @@ class ChecklistItemMapper extends QBMapper {
*/
public function findByList(int $listId, string $sortBy = 'custom'): array {
$qb = $this->db->getQueryBuilder();
$items = $this->getTableName();
if ($sortBy === 'category') {
// Left-join the categories table so items with no category still appear.
// Uncategorized items are grouped separately (sort_uncategorized = 1)
// so they appear after all categorized items regardless of DB null ordering.
$categories = Application::tableName('categories');
$qb->select($items . '.*')
->selectAlias(
$qb->createFunction('CASE WHEN ' . $items . '.category_id IS NULL THEN 1 ELSE 0 END'),
'sort_uncategorized',
)
->from($items)
->leftJoin(
$items,
$categories,
'c',
$qb->expr()->eq($items . '.category_id', 'c.id'),
)
->where($qb->expr()->eq($items . '.list_id', $qb->createNamedParameter($listId, IQueryBuilder::PARAM_INT)))
->orderBy('sort_uncategorized', 'ASC')
->addOrderBy('c.name', 'ASC')
->addOrderBy($items . '.name', 'ASC')
->addOrderBy($items . '.created_at', 'ASC');
return $this->findEntities($qb);
}
$qb->select('*')
->from($this->getTableName())
->from($items)
->where($qb->expr()->eq('list_id', $qb->createNamedParameter($listId, IQueryBuilder::PARAM_INT)));
switch ($sortBy) {

View File

@@ -153,7 +153,7 @@ class PrefsService {
}
public function setChecklistItemSort(string $uid, int $houseId, string $sort): string {
$allowed = ['custom', 'newest', 'oldest', 'name_asc', 'name_desc'];
$allowed = ['custom', 'newest', 'oldest', 'name_asc', 'name_desc', 'category'];
if (!in_array($sort, $allowed, true)) {
$sort = 'custom';
}

View File

@@ -1783,7 +1783,7 @@
{
"name": "sortBy",
"in": "query",
"description": "Sort mode (custom, newest, oldest, name_asc, name_desc).",
"description": "Sort mode (custom, newest, oldest, name_asc, name_desc, category).",
"schema": {
"type": "string",
"default": "custom"

View File

@@ -42,7 +42,13 @@ export async function setLastHouse(houseId: number | null): Promise<void> {
export type PhotoSort = 'custom' | 'newest' | 'oldest' | 'description_asc' | 'description_desc'
export type NoteSort = 'custom' | 'newest' | 'oldest' | 'title_asc' | 'title_desc'
export type ChecklistItemSort = 'custom' | 'newest' | 'oldest' | 'name_asc' | 'name_desc'
export type ChecklistItemSort =
| 'custom'
| 'newest'
| 'oldest'
| 'name_asc'
| 'name_desc'
| 'category'
export interface PhotoSortPrefs {
sort: PhotoSort

View File

@@ -202,6 +202,7 @@ const itemSortOptions: { value: ChecklistItemSort; label: string }[] = [
{ value: 'oldest', label: t('pantry', 'Oldest first') },
{ value: 'name_asc', label: t('pantry', 'Name A\u2013Z') },
{ value: 'name_desc', label: t('pantry', 'Name Z\u2013A') },
{ value: 'category', label: t('pantry', 'Category') },
{ value: 'custom', label: t('pantry', 'Custom') },
]