feat(uat-batch): Group N — dashboard upgrades
N44, N45, N46 from the 2026-05-21 plan.
Shipped:
N44 Pipeline Value tile respects dashboard timeframe. Tile accepts
optional `range` prop and threads it through
/api/v1/dashboard/kpis?range=<slug> + /forecast?range=<slug>.
Service functions accept optional {from,to} bounds and scope
the pipeline-value SQL to interests created within the window.
New parseRangeSlug helper inverts rangeToSlug. Widget registry
forwards the active dashboard range to the tile.
N45 Clients by country widget. New GET
/api/v1/dashboard/clients-by-country groups non-archived
clients by nationality_iso. <ClientsByCountryWidget> renders a
compact ranked list with mini-bars; rows link to
/clients?nationality=<ISO>. Registered as default-visible rail.
N46 Drag-and-drop dashboard widgets. New
preferences.dashboardWidgetOrder?: string[] on user_profiles;
useDashboardWidgets sorts visibleWidgets by the order
(unlisted ids fall through to registry order) and exposes
setOrder(nextOrder) that PATCHes optimistically.
DashboardShell wires @dnd-kit/core + sortable: Rearrange toggle
turns on per-widget grip handles + sortable-context wraps each
group (charts / rails / feed) so drops stay in-group.
PointerSensor 8px activation distance, KeyboardSensor for a11y.
New <SortableWidget> wraps the render — zero footprint when
off.
Verified: tsc clean, vitest 1454/1454.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -202,6 +202,16 @@ export type UserPreferences = {
|
||||
* surfaces it for everyone without a migration. `false` hides it.
|
||||
*/
|
||||
dashboardWidgets?: Record<string, boolean>;
|
||||
/**
|
||||
* Ordered list of widget ids — drives the dashboard render order so a
|
||||
* rep can drag tiles around and have the layout persist. Missing
|
||||
* widgets (ids not in the array) render after the listed ones in
|
||||
* registry order, so adding a new widget always surfaces it without
|
||||
* a migration. Order is scoped per widget group implicitly — the
|
||||
* shell groups by `widget.group` first (chart / rail / feed) then
|
||||
* sorts within the group by this array.
|
||||
*/
|
||||
dashboardWidgetOrder?: string[];
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user