fix(manacore): show all open tasks in dashboard widget, not just today

The tasks widget only showed tasks with dueDate=today, so tasks without
a date appeared as "no tasks". Now fetches all open tasks via GET /tasks,
sorted by due date (today/overdue first, then future, then no date).

- Add getAllOpenTasks() to todo service
- Update widget to use getAllOpenTasks()
- Show due date label next to task title (with overdue highlighting)
- Update i18n: "Aufgaben heute" → "Aufgaben"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-24 21:22:36 +01:00
parent 04f5afe671
commit 47dbe00d3d
4 changed files with 65 additions and 14 deletions

View file

@ -97,6 +97,30 @@ export const todoService = {
return { data: result.data.tasks || [], error: null };
},
/**
* Get all open tasks sorted by due date (today first, then future, then no date)
*/
async getAllOpenTasks(): Promise<ApiResult<Task[]>> {
const result = await getClient().get<{ tasks: Task[] }>('/tasks');
if (result.error || !result.data) {
return { data: null, error: result.error };
}
const openTasks = (result.data.tasks || []).filter((t) => !t.isCompleted);
// Sort: today/overdue first, then by date ascending, tasks without date last
const now = new Date();
now.setHours(0, 0, 0, 0);
openTasks.sort((a, b) => {
const dateA = a.dueDate ? new Date(a.dueDate).getTime() : Infinity;
const dateB = b.dueDate ? new Date(b.dueDate).getTime() : Infinity;
return dateA - dateB;
});
return { data: openTasks, error: null };
},
/**
* Get upcoming tasks for the next N days
*/

View file

@ -7,9 +7,25 @@
import { _ } from 'svelte-i18n';
import { todoService, type Task } from '$lib/api/services';
import { APP_URLS } from '@manacore/shared-branding';
import { format, isToday, isTomorrow, isPast } from 'date-fns';
import { de } from 'date-fns/locale';
import WidgetSkeleton from '../WidgetSkeleton.svelte';
import WidgetError from '../WidgetError.svelte';
function formatDueDate(dueDate?: string): string | null {
if (!dueDate) return null;
const date = new Date(dueDate);
if (isToday(date)) return 'Heute';
if (isTomorrow(date)) return 'Morgen';
return format(date, 'dd. MMM', { locale: de });
}
function isOverdue(dueDate?: string): boolean {
if (!dueDate) return false;
const date = new Date(dueDate);
return isPast(date) && !isToday(date);
}
let state = $state<'loading' | 'success' | 'error'>('loading');
let data = $state<Task[]>([]);
let error = $state<string | null>(null);
@ -32,7 +48,7 @@
state = 'loading';
retrying = true;
const result = await todoService.getTodayTasks();
const result = await todoService.getAllOpenTasks();
if (result.data) {
data = result.data;
@ -124,13 +140,24 @@
<!-- Content -->
<div class="min-w-0 flex-1">
<p
class="truncate text-sm font-medium {task.isCompleted
? 'text-muted-foreground line-through'
: ''}"
>
{task.title}
</p>
<div class="flex items-center gap-2">
<p
class="truncate text-sm font-medium {task.isCompleted
? 'text-muted-foreground line-through'
: ''}"
>
{task.title}
</p>
{#if formatDueDate(task.dueDate)}
<span
class="flex-shrink-0 text-xs {isOverdue(task.dueDate)
? 'text-red-500'
: 'text-muted-foreground'}"
>
{formatDueDate(task.dueDate)}
</span>
{/if}
</div>
<!-- Meta row: time, subtasks, labels -->
{#if task.dueTime || getSubtaskProgress(task) || (task.labels && task.labels.length > 0)}
<div class="mt-0.5 flex items-center gap-2 text-xs text-muted-foreground">

View file

@ -33,9 +33,9 @@
"empty": "Keine Transaktionen"
},
"tasks_today": {
"title": "Aufgaben heute",
"description": "Deine heutigen Aufgaben",
"empty": "Keine Aufgaben für heute"
"title": "Aufgaben",
"description": "Deine offenen Aufgaben",
"empty": "Keine offenen Aufgaben"
},
"tasks_upcoming": {
"title": "Kommende Aufgaben",

View file

@ -33,9 +33,9 @@
"empty": "No transactions"
},
"tasks_today": {
"title": "Tasks Today",
"description": "Your tasks for today",
"empty": "No tasks for today"
"title": "Tasks",
"description": "Your open tasks",
"empty": "No open tasks"
},
"tasks_upcoming": {
"title": "Upcoming Tasks",