- Archive dormant apps (daemon, desktop, native, tui) and superseded packages/server into repos/ for reference - Archive 21 dead web components (chat page shell, work-os cluster, strays) into repos/web/; keep reused message-rendering primitives in components/chat - Merge @code/work-os into @code/primitives; work.ts absorbed via ./work subpath and barrel export; update all four importers - Add docs/futures.md tracking audio/video (blocked at Flue + provider), web layout cleanup, and message rendering quality - Repoint dev:zopu script to @code/agents (the live Flue server) - Note repos/ reference-code convention in AGENTS.md
72 lines
2.5 KiB
TypeScript
72 lines
2.5 KiB
TypeScript
import { Radio } from "lucide-react";
|
|
|
|
import type { SignalItem } from "@/hooks/work-os/use-work-os";
|
|
import { formatRelativeTime } from "@/lib/work-os/work-unit-projection";
|
|
|
|
interface SignalsPanelProps {
|
|
readonly signals: readonly SignalItem[];
|
|
readonly loading: boolean;
|
|
}
|
|
|
|
export const SignalsPanel = ({ loading, signals }: SignalsPanelProps) => {
|
|
if (loading) {
|
|
return (
|
|
<section className="rounded-2xl border border-border/30 bg-card/30 p-4">
|
|
<div className="mb-3 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
<Radio className="size-3" />
|
|
Signals
|
|
</div>
|
|
<p className="text-xs text-muted-foreground">Loading signals…</p>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
if (signals.length === 0) {
|
|
return (
|
|
<section className="rounded-2xl border border-border/30 bg-card/30 p-4">
|
|
<div className="mb-3 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
<Radio className="size-3" />
|
|
Signals
|
|
</div>
|
|
<p className="text-xs text-muted-foreground">
|
|
No Signals detected for this project yet.
|
|
</p>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<section className="rounded-2xl border border-border/30 bg-card/30 p-4">
|
|
<div className="mb-3 flex items-center justify-between gap-2">
|
|
<div className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
<Radio className="size-3" />
|
|
Signals
|
|
</div>
|
|
<span className="text-[10px] text-muted-foreground/60">
|
|
{signals.length} total
|
|
</span>
|
|
</div>
|
|
<div className="space-y-3">
|
|
{signals.map((signal) => (
|
|
<div
|
|
className="rounded-xl border border-border/20 bg-background/30 p-3"
|
|
key={`${signal.title}-${signal.createdAt}`}
|
|
>
|
|
<p className="text-sm font-medium">{signal.title}</p>
|
|
<p className="mt-1 line-clamp-2 text-xs leading-5 text-muted-foreground">
|
|
{signal.summary}
|
|
</p>
|
|
<div className="mt-2 flex items-center gap-3 text-[10px] text-muted-foreground/60">
|
|
<span>
|
|
{signal.sourceCount} source
|
|
{signal.sourceCount === 1 ? "" : "s"}
|
|
</span>
|
|
<span>{formatRelativeTime(signal.createdAt)}</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|