Replace the hardcoded dashboard layout with the WidgetGrid system. The dashboard now loads/saves user layouts via the UserLayout API and creates a default layout on first visit with all 7 widgets. Changes: - Add layout API client (fetchDefaultLayout, createLayout, updateLayout) - Add default layout constant with 7-widget arrangement (12-col grid) - Update BaseWidget + WidgetGrid to use CSS variables for theme compat - Add responsive container width measurement via ResizeObserver - Rewrite dashboard page to use WidgetGrid with edit mode toggle - Update all tests for the new dashboard architecture Ref: #488 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
/**
|
|
* 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);
|
|
}
|