sort-priority.ts1.9 KBView on GitHub /**
* Sort-priority helpers.
*
* Sorting a canvas/table is multi-column: every active sort carries a `priority`
* where 0 wins ties first. Activating a sort from a column header (or a column
* popover) means "sort by this now", so the new sort takes priority 0 and every
* other active sort shifts down one slot — it never lands silently at the bottom
* of the list where it has no visible effect.
*
* Pure functions so both the canvas viewConfig writer and the CRMSlice reducer
* can share the same rule.
*/
import type { ColumnSort } from '../store/crmSlice';
/** Anything keyed by column id that carries an optional sort — canvas config or CRM columns. */
type SortCarrier = { sort?: ColumnSort };
/**
* Return a copy of `config` where `columnId` sorts at priority 0 and all other
* active sorts are pushed down one slot (relative order preserved).
*/
export function withTopPrioritySort<T extends SortCarrier>(
config: Record<string, T>,
columnId: string,
sort: Omit<ColumnSort, 'priority'>,
): Record<string, T> {
const next: Record<string, T> = {};
for (const [id, entry] of Object.entries(config)) {
next[id] =
id !== columnId && entry.sort?.active
? { ...entry, sort: { ...entry.sort, priority: entry.sort.priority + 1 } }
: entry;
}
next[columnId] = { ...(next[columnId] ?? ({} as T)), sort: { ...sort, priority: 0 } };
return next;
}
/**
* Renumber active sorts to 0..n-1 following `orderedColumnIds`. Columns absent
* from the list keep whatever they have (inactive sorts carry no priority).
*/
export function withSortOrder<T extends SortCarrier>(
config: Record<string, T>,
orderedColumnIds: string[],
): Record<string, T> {
const next = { ...config };
orderedColumnIds.forEach((id, index) => {
const sort = next[id]?.sort;
if (sort?.active) next[id] = { ...next[id], sort: { ...sort, priority: index } };
});
return next;
}