Files
stack/apps/web/src/lib/api/layouts.ts
Jason Woltje c694db5d8c feat(web): migrate dashboard to WidgetGrid with layout persistence
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>
2026-02-23 18:43:11 -06:00

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);
}