p2p/src/lib/tableParams.ts
Bhanu Prakash Sai Potteri f5bc1fa119 feat: rebuild the UI on Tailwind v4 + shadcn/ui
Migrates Tailwind v3 -> v4 (CSS-first, theme tokens for brand, workflow
states and charts) and adds 23 shadcn/ui components on Radix.

- lib/workflow.ts is now the single source of truth for state name, colour,
  icon and available actions; "Financial Review" is the canonical served
  name, with "Finance Review" kept as an alias so those rows stop falling
  through to the unstyled fallback and dropping out of every count
- record view: TanStack Table with server-side sort/paginate, company column
  with initials avatar, page totals, density and a URL-synced query state
- dashboard: one cached analytics fetch shared by tiles and charts, donut +
  aging + vendor spend, click-to-filter
- detail view: rebuilt against the live detailview payload — restores the PO
  number and payment terms that the old key heuristics silently dropped,
  parses match_summary into a 3-way-match checklist, and separates the
  department's and reviewer's own words from AI-generated content
- form modal on Radix Dialog (focus trap, scroll lock, escape handling)
2026-07-29 19:47:59 +05:30

51 lines
1.5 KiB
TypeScript

// Shared URL state for the record view.
//
// Table sort/page/search/filters used to live in component state, so a refresh
// or a shared link lost the user's view entirely. These parsers put it in the
// query string instead, which also lets the dashboard tiles act as filters —
// a tile writes `status`, the table reads it.
import {
parseAsArrayOf,
parseAsInteger,
parseAsString,
parseAsStringLiteral,
} from "nuqs";
export const DENSITIES = ["compact", "regular", "relaxed"] as const;
export type Density = (typeof DENSITIES)[number];
/** Row heights per density — the 40/48/56px convention. */
export const DENSITY_ROW: Record<Density, string> = {
compact: "h-10",
regular: "h-12",
relaxed: "h-14",
};
export const DENSITY_CELL: Record<Density, string> = {
compact: "py-1.5",
regular: "py-3",
relaxed: "py-4",
};
export const tableParams = {
q: parseAsString.withDefault(""),
page: parseAsInteger.withDefault(1),
limit: parseAsInteger.withDefault(10),
sort: parseAsString.withDefault(""),
dir: parseAsStringLiteral(["asc", "desc"] as const).withDefault("desc"),
/** Workflow state names, matching `current_state_name`. */
status: parseAsArrayOf(parseAsString).withDefault([]),
density: parseAsStringLiteral(DENSITIES).withDefault("regular"),
};
/**
* Keep the URL short: nuqs omits any value equal to its default, and history
* is replaced rather than pushed so filtering doesn't fill the back button.
*/
export const tableParamsOptions = {
history: "replace" as const,
clearOnDefault: true,
shallow: true,
};