Added progress view and unified terminology around urgency vs time

This commit is contained in:
2026-02-17 18:06:34 -06:00
parent 09240e8f89
commit 1a24165975
4 changed files with 54 additions and 4 deletions
+3
View File
@@ -12,6 +12,7 @@ const MatrixView = lazy(() => import('./views/MatrixView').then(m => ({ default:
const SettingsView = lazy(() => import('./views/SettingsView').then(m => ({ default: m.SettingsView })));
const SnowballView = lazy(() => import('./views/SnowballView').then(m => ({ default: m.SnowballView })));
const DigInView = lazy(() => import('./views/DigInView').then(m => ({ default: m.DigInView })));
const ProgressView = lazy(() => import('./views/ProgressView').then(m => ({ default: m.ProgressView })));
const App: Component = () => {
// Basic routing state
@@ -38,6 +39,7 @@ const App: Component = () => {
import('./views/SettingsView');
import('./views/SnowballView');
import('./views/DigInView');
import('./views/ProgressView');
// Remove splash screen after high priority work is done
const splash = document.getElementById('splash');
@@ -58,6 +60,7 @@ const App: Component = () => {
<Show when={currentView() === "matrix"}><MatrixView /></Show>
<Show when={currentView() === "snowball"}><SnowballView /></Show>
<Show when={currentView() === "dig_in"}><DigInView /></Show>
<Show when={currentView() === "progress"}><ProgressView /></Show>
<Show when={currentView() === "settings"}><SettingsView /></Show>
</Suspense>
</Layout>
+5 -3
View File
@@ -1,5 +1,5 @@
import { type Component, For, Show } from "solid-js";
import { LayoutDashboard, ListTodo, Settings, Clock, ArrowUpCircle, PanelLeftClose, Snowflake, Pickaxe, ChevronDown, Gauge, TrendingUp, Users, Box } from "lucide-solid";
import { LayoutDashboard, ListTodo, Settings, Clock, ArrowUpCircle, PanelLeftClose, Snowflake, Pickaxe, ChevronDown, Gauge, TrendingUp, Users, Box, BarChart3 } from "lucide-solid";
import { cn } from "@/lib/utils";
import { Button } from "./ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
@@ -16,11 +16,12 @@ interface NavItem {
// Desktop nav items (all)
const desktopNavItems: NavItem[] = [
{ icon: ListTodo, label: "Focus", view: "critical" },
{ icon: Clock, label: "Time", view: "urgency" },
{ icon: Clock, label: "Urgency", view: "urgency" },
{ icon: ArrowUpCircle, label: "Priority", view: "priority" },
{ icon: LayoutDashboard, label: "Matrix", view: "matrix" },
{ icon: Snowflake, label: "Snowball", view: "snowball" },
{ icon: Pickaxe, label: "Dig In", view: "dig_in" },
{ icon: BarChart3, label: "Progress", view: "progress" },
];
// Mobile nav groups
@@ -37,13 +38,14 @@ const mobileNavGroups: MobileNavGroup[] = [
{
icon: TrendingUp, label: "Value", items: [
{ icon: ArrowUpCircle, label: "Priority", view: "priority" },
{ icon: Clock, label: "Time", view: "urgency" },
{ icon: Clock, label: "Urgency", view: "urgency" },
]
},
{
icon: Gauge, label: "Flow", items: [
{ icon: Snowflake, label: "Snowball", view: "snowball" },
{ icon: Pickaxe, label: "Dig In", view: "dig_in" },
{ icon: BarChart3, label: "Progress", view: "progress" },
]
},
{ icon: Settings, label: "Settings", view: "settings" },
+1 -1
View File
@@ -205,7 +205,7 @@ export const TaskDetail: Component<TaskDetailProps> = (props) => {
{/* Urgency */}
<div class="flex items-center gap-1 group shrink-0">
<span class="text-[0.625rem] uppercase font-bold tracking-wider text-muted-foreground/70 hidden sm:inline">Time</span>
<span class="text-[0.625rem] uppercase font-bold tracking-wider text-muted-foreground/70 hidden sm:inline">Urgency</span>
<Select<any>
value={currentUrgency()}
onChange={(val: string | null) => val && updateUrgency(val)}
+45
View File
@@ -0,0 +1,45 @@
import { type Component, For, createMemo } from "solid-js";
import { store, getCombinedScore, matchesFilter } from "@/store";
import { TaskCard } from "@/components/TaskCard";
export const ProgressView: Component = () => {
const sortedTasks = createMemo(() => {
return [...store.tasks]
.filter(t => !t.deletedAt && matchesFilter(t))
.sort((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);
});
});
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 gap-3">
<For each={sortedTasks()}>
{(task) => <TaskCard task={task} />}
</For>
</div>
{sortedTasks().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>
);
};