feat: add dashboard ui view

This commit is contained in:
2026-07-14 23:38:54 +05:00
parent cbb97a99ce
commit 4bd3aa0cd1
8 changed files with 747 additions and 30 deletions
+10 -15
View File
@@ -63,25 +63,22 @@ describe("parseDashboardInboundMessage", () => {
it("rejects non-objects", () => {
const result = parseDashboardInboundMessage(null);
expect(result.isErr()).toBe(true);
if (result.isErr()) {
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
}
if (result.isOk()) return;
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
});
it("rejects unknown type", () => {
const result = parseDashboardInboundMessage({ type: "explode" });
expect(result.isErr()).toBe(true);
if (result.isErr()) {
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
}
if (result.isOk()) return;
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
});
it("rejects selectTask without id", () => {
const result = parseDashboardInboundMessage({ type: "selectTask" });
expect(result.isErr()).toBe(true);
if (result.isErr()) {
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
}
if (result.isOk()) return;
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
});
it("rejects setGroupBy with invalid groupBy", () => {
@@ -90,9 +87,8 @@ describe("parseDashboardInboundMessage", () => {
groupBy: "assignee",
});
expect(result.isErr()).toBe(true);
if (result.isErr()) {
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
}
if (result.isOk()) return;
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
});
it("rejects saveDescription with non-string description", () => {
@@ -102,8 +98,7 @@ describe("parseDashboardInboundMessage", () => {
description: 42,
});
expect(result.isErr()).toBe(true);
if (result.isErr()) {
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
}
if (result.isOk()) return;
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
});
});
+17
View File
@@ -0,0 +1,17 @@
import { AppError } from "@/error";
import { Task } from "@/model/task";
import { TaskFilter } from "./filterTasks";
import { GroupBy, TaskGroup } from "./groupTasks";
/** Host → webview messages (presentation payload only). */
export type DashboardOutboundMessage =
| {
type: "state";
filter: TaskFilter;
groupBy: GroupBy;
selectedId: string | undefined;
groups: TaskGroup[];
selected: Task | null;
}
| { type: "error"; error: AppError }
| { type: "saved"; task: Task };