feat(web): migrate dashboard to WidgetGrid with layout persistence (#497)
All checks were successful
ci/woodpecker/push/web Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #497.
This commit is contained in:
2026-02-24 00:50:24 +00:00
committed by jason.woltje
parent f9cccd6965
commit cc56f2cbe1
8 changed files with 399 additions and 176 deletions

View File

@@ -0,0 +1,54 @@
/**
* Layout API client — CRUD for user dashboard layouts
*/
import type { UserLayout, WidgetPlacement } from "@mosaic/shared";
import { apiGet, apiPost, apiPatch } from "./client";
export interface CreateLayoutPayload {
name: string;
isDefault?: boolean;
layout: WidgetPlacement[];
metadata?: Record<string, unknown>;
}
export interface UpdateLayoutPayload {
name?: string;
isDefault?: boolean;
layout?: WidgetPlacement[];
metadata?: Record<string, unknown>;
}
/**
* Fetch the user's default layout for the active workspace.
* Returns null if no layout exists (404).
*/
export async function fetchDefaultLayout(workspaceId: string): Promise<UserLayout | null> {
try {
return await apiGet<UserLayout>("/api/layouts/default", workspaceId);
} catch {
// 404 = no layout yet — not an error
return null;
}
}
/**
* Create a new layout.
*/
export async function createLayout(
workspaceId: string,
payload: CreateLayoutPayload
): Promise<UserLayout> {
return apiPost<UserLayout>("/api/layouts", payload, workspaceId);
}
/**
* Update an existing layout (partial patch).
*/
export async function updateLayout(
workspaceId: string,
layoutId: string,
payload: UpdateLayoutPayload
): Promise<UserLayout> {
return apiPatch<UserLayout>(`/api/layouts/${layoutId}`, payload, workspaceId);
}