Skip to content

Commit 13b89be

Browse files
committed
feat: redesign continue section as compact module with smart filtering
Replace NowWorkingOn and ActiveWorkSection with a single compact ContinueWhereYouLeftOff strip that only surfaces meaningful, user-owned work. Adds useMeaningfulWork hook that filters out system-initiated runs, stale progress, and completed sessions. Mode B detection now uses filtered work instead of raw active state.
1 parent 1a5fa3b commit 13b89be

12 files changed

+523
-691
lines changed

apps/desktop/src/features/dashboard/components/ActiveWorkSection.tsx

Lines changed: 0 additions & 241 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { CornerDownLeftIcon, ArrowRightIcon } from "lucide-react";
2+
import type { MeaningfulWorkItem } from "@/features/dashboard/hooks/useMeaningfulWork";
3+
4+
export interface ContinueWhereYouLeftOffProps {
5+
items: MeaningfulWorkItem[];
6+
onContinue?: (sessionId: string) => void;
7+
onViewResults?: (actionId: string) => void;
8+
}
9+
10+
function formatTimeAgo(ts: number): string {
11+
const diffMs = Date.now() - ts;
12+
const diffMin = Math.floor(diffMs / 60_000);
13+
if (diffMin < 1) return "just now";
14+
if (diffMin < 60) return `${diffMin}m ago`;
15+
const diffHrs = Math.floor(diffMin / 60);
16+
if (diffHrs < 24) return `${diffHrs}h ago`;
17+
const diffDays = Math.floor(diffHrs / 24);
18+
return `${diffDays}d ago`;
19+
}
20+
21+
export function ContinueWhereYouLeftOff({
22+
items,
23+
onContinue,
24+
onViewResults,
25+
}: ContinueWhereYouLeftOffProps) {
26+
if (items.length === 0) return null;
27+
28+
return (
29+
<section className="mb-5 rounded-lg border border-border/20 bg-card/50 px-4 py-3">
30+
{/* Section label */}
31+
<div className="mb-2.5 flex items-center gap-2">
32+
<CornerDownLeftIcon className="size-3 text-primary/60" />
33+
<h2 className="section-label">Continue where you left off</h2>
34+
</div>
35+
36+
{/* Compact item rows */}
37+
<div className="space-y-1">
38+
{items.map((item) => {
39+
const handleClick = () => {
40+
if (item.sessionId && onContinue) {
41+
onContinue(item.sessionId);
42+
} else if (item.actionId && onViewResults) {
43+
onViewResults(item.actionId);
44+
}
45+
};
46+
47+
return (
48+
<button
49+
key={item.id}
50+
type="button"
51+
onClick={handleClick}
52+
className="group flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-white/[0.03]"
53+
>
54+
{/* Status dot */}
55+
<span
56+
className={`size-1.5 shrink-0 rounded-full ${
57+
item.needsInput
58+
? "bg-amber-500"
59+
: "bg-primary/50"
60+
}`}
61+
/>
62+
63+
{/* Title */}
64+
<span className="min-w-0 flex-1 truncate text-[13px] text-foreground">
65+
{item.title}
66+
</span>
67+
68+
{/* Status badge */}
69+
<span
70+
className={`shrink-0 font-mono text-[10px] font-medium uppercase tracking-wider ${
71+
item.needsInput
72+
? "text-amber-500"
73+
: "text-muted-foreground/50"
74+
}`}
75+
>
76+
{item.status}
77+
</span>
78+
79+
{/* Timestamp */}
80+
<span className="shrink-0 font-mono text-[10px] tabular-nums text-muted-foreground/30">
81+
{formatTimeAgo(item.updatedAt)}
82+
</span>
83+
84+
{/* Continue CTA */}
85+
<span className="flex shrink-0 items-center gap-1 text-xs text-muted-foreground/40 transition-colors group-hover:text-primary">
86+
Continue
87+
<ArrowRightIcon className="size-2.5" />
88+
</span>
89+
</button>
90+
);
91+
})}
92+
</div>
93+
</section>
94+
);
95+
}

0 commit comments

Comments
 (0)