diff --git a/client/src/components/Todo/useTodoList.ts b/client/src/components/Todo/useTodoList.ts
index fea2b5392..86b581dd1 100644
--- a/client/src/components/Todo/useTodoList.ts
+++ b/client/src/components/Todo/useTodoList.ts
@@ -45,6 +45,7 @@ export function useTodoList(tripId: number, items: TodoItem[], addItemSignal: nu
lastHandledAddSignal.current = addItemSignal
}, [addItemSignal])
const [sortByPrio, setSortByPrio] = useState(false)
+ const [sortByDue, setSortByDue] = useState(false)
const [addingCategory, setAddingCategory] = useState(false)
const [newCategoryName, setNewCategoryName] = useState('')
const [members, setMembers] = useState
([])
@@ -86,8 +87,15 @@ export function useTodoList(tripId: number, items: TodoItem[], addItemSignal: nu
const bp = b.priority || 99
return ap - bp
})
+ // Nearest deadline first, undated tasks after all dated ones; ties keep the
+ // manual order, the stable sort leaves them untouched (#2205).
+ else if (sortByDue) result = [...result].sort((a, b) => {
+ if (!a.due_date) return b.due_date ? 1 : 0
+ if (!b.due_date) return -1
+ return a.due_date < b.due_date ? -1 : a.due_date > b.due_date ? 1 : 0
+ })
return result
- }, [items, filter, currentUserId, today, sortByPrio])
+ }, [items, filter, currentUserId, today, sortByPrio, sortByDue])
const selectedItem = items.find(i => i.id === selectedId) || null
const totalCount = items.length
@@ -109,7 +117,7 @@ export function useTodoList(tripId: number, items: TodoItem[], addItemSignal: nu
return {
canEdit, t, formatDate, toggleTodoItem, reorderTodoItems,
isMobile, filter, setFilter, selectedId, setSelectedId,
- isAddingNew, setIsAddingNew, sortByPrio, setSortByPrio,
+ isAddingNew, setIsAddingNew, sortByPrio, setSortByPrio, sortByDue, setSortByDue,
addingCategory, setAddingCategory, newCategoryName, setNewCategoryName,
members, categories, today, filtered, selectedItem,
totalCount, doneCount, overdueCount, myCount,
diff --git a/client/src/mobile/screens/trip/tabs/MTodoListTab.tsx b/client/src/mobile/screens/trip/tabs/MTodoListTab.tsx
index 3e6c750eb..727734642 100644
--- a/client/src/mobile/screens/trip/tabs/MTodoListTab.tsx
+++ b/client/src/mobile/screens/trip/tabs/MTodoListTab.tsx
@@ -36,7 +36,7 @@ export default function MTodoListTab({ planner }: { planner: TripPlanner }) {
const tripMembers = planner.tripMembers
const [active, setActive] = useState({ kind: 'smart', id: 'all' })
- const [sortByPriority, setSortByPriority] = useState(false)
+ const [sortBy, setSortBy] = useState<'priority' | 'due' | null>(null)
const [editingItemId, setEditingItemId] = useState(null)
const [creatingTask, setCreatingTask] = useState(false)
@@ -50,10 +50,10 @@ export default function MTodoListTab({ planner }: { planner: TripPlanner }) {
active.kind === 'category'
? filterTodoItemsByCategory(items, active.name)
: filterTodoItems(items, active.id, currentUserId, today),
- sortByPriority,
+ sortBy,
today,
),
- [items, active, currentUserId, today, sortByPriority],
+ [items, active, currentUserId, today, sortBy],
)
const pct = items.length > 0 ? Math.round((counts.done / items.length) * 100) : 0
@@ -113,13 +113,22 @@ export default function MTodoListTab({ planner }: { planner: TripPlanner }) {
))}
+
{categories.length > 0 && }
{categories.map(cat => (