59 lines
2.3 KiB
TypeScript
59 lines
2.3 KiB
TypeScript
import { type Component, For, createMemo, onMount } from "solid-js";
|
|
import { store, getCombinedScore, matchesFilter } from "@/store";
|
|
import { TaskCard } from "@/components/TaskCard";
|
|
import { useDelayedSort } from "@/hooks/useDelayedSort";
|
|
import autoAnimate from "@formkit/auto-animate";
|
|
|
|
export const ProgressView: Component = () => {
|
|
const sourceTasks = createMemo(() => store.tasks.filter(t => !t.deletedAt && matchesFilter(t)));
|
|
|
|
const { displayedTasks, shakingTaskIds } = useDelayedSort(
|
|
sourceTasks,
|
|
(a, b) => {
|
|
// 1. Completed tasks at the bottom
|
|
if (a.completed !== b.completed) return a.completed ? 1 : -1;
|
|
|
|
// 2. Sort by Progress (Status) Descending (Highest progress first)
|
|
// Assuming status 0-9 are active states, 10 is completed (handled above)
|
|
if (a.status !== b.status) return b.status - a.status;
|
|
|
|
// 3. Then by Focus Score (Combined Score)
|
|
return getCombinedScore(b) - getCombinedScore(a);
|
|
},
|
|
300
|
|
);
|
|
|
|
let listRef: HTMLDivElement | undefined;
|
|
onMount(() => {
|
|
if (listRef) autoAnimate(listRef, { duration: 300, easing: 'ease-out' });
|
|
});
|
|
|
|
return (
|
|
<div class="space-y-6">
|
|
<header>
|
|
<h2 class="text-3xl font-bold tracking-tight">Progress</h2>
|
|
<p class="text-muted-foreground mt-1 text-lg">Tasks sorted by progress status, then by focus score.</p>
|
|
</header>
|
|
|
|
<div class="grid grid-cols-1 gap-3 w-full" ref={listRef}>
|
|
<For each={displayedTasks()}>
|
|
{(task) => (
|
|
<div class="w-full min-w-0">
|
|
<TaskCard task={task} isShaking={shakingTaskIds().includes(task.id)} />
|
|
</div>
|
|
)}
|
|
</For>
|
|
</div>
|
|
|
|
{displayedTasks().length === 0 && (
|
|
<div class="flex flex-col items-center justify-center py-20 text-center">
|
|
<div class="w-16 h-16 bg-muted rounded-full flex items-center justify-center mb-4">
|
|
<span class="text-2xl">📈</span>
|
|
</div>
|
|
<p class="text-muted-foreground">No tasks found in the current filter.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|