ubiquitous-invention/apps/web/components/ui/skeleton.tsx

14 lines
249 B
TypeScript
Raw Normal View History

feat(web): wire workspace-home dashboard to real tRPC queries Path-A task 2/5. Replaces the hardcoded `stats` (24/8/12) and hardcoded `recent` list on the workspace-home page with real workspace-scoped data. * server/routers/objects.ts: add two new procedures. - `objects.stats` returns { openTasks, containers }. Open-task count treats null status as open; only `done` and `closed` (per packages/shared object-statuses) are terminal. Container count aggregates project + space + group rows. - `objects.listRecent({ limit })` returns the N most-recently-updated rows, descending by updated_at. Excludes archived and excludes `workspace`/`group` from the activity feed (containers clutter "what did I just touch" recency). Both go through workspaceProcedure, so the workspace_id filter comes from the middleware-resolved ctx.workspace.id rather than any user input. * app/(app)/[workspaceSlug]/page.tsx: rewrite to consume the new procedures via @trpc/react-query. Adds: - Skeleton loading state (no flash of zeros). - Empty state with a "New task" CTA on workspaces with no objects. - Real "X ago" labels on the recent feed. - Click-through links from recent rows to /{slug}/{id}. - A locally-mounted CreateObjectDialog instance independent of the global one in AppShell so the empty-state CTA can pre-seed defaultType="task" without coordinating shared state. * components/ui/skeleton.tsx: new (standard shadcn pulse skeleton). Used by the dashboard but reusable across the app. The scaffolded "Due this week" stat is dropped: `objects` has no due_at column and the task explicitly preferred dropping a card to schema-creep. `pnpm lint && pnpm type-check` clean. Closes plans/Plan-daily-driver-finish/Epic-shipping-the-shell/ Task-wire-workspace-home-dashboard.md. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 01:17:29 -04:00
import { cn } from "@/lib/utils";
export function Skeleton({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
);
}