Files
tehran_tala/apps/admin-panel/src/components/x-table/model.ts
T

192 lines
4.8 KiB
TypeScript

/**
* Ported from legacy henza_admin/src/components/x-table/model/{XTbl,Xtc}.js
* and src/table/index.js (ColCreator).
*
* The fluent column API is preserved exactly — `new Xtc(key, title).filterText()
* .renderSlot('x').noSort()` builds the same shape the legacy table schemas used,
* so the 18 schema files port over with only their import path changed.
*
* Legacy had FOUR near-duplicate XTable forks (x-table/, x-table_select/,
* custom-xtable-select/, backup-table/, ~1,300 LOC). Per the agreed decision this
* port keeps ONE — the x-table/ variant, which is the most complete (it is the
* only one with QuerySelectTableFilter).
*/
export type FilterType = 'default' | 'switch' | 'query' | 'date' | 'number' | 'select';
export interface ColumnSlots {
customRender?: string;
filterDropdown?: string;
filterIcon?: string;
}
/** Port of legacy Xtc — one column definition. */
export class Xtc {
key: string;
title: string;
dataIndex: string;
show = true;
/** legacy `__sorter`: sortable unless noSort() was called */
__sorter = true;
filtered = false;
filterType?: FilterType;
filterAction?: string;
/** legacy `filterItems`: a value -> label map for select filters */
filterItems?: Record<string | number, string>;
scopedSlots?: ColumnSlots;
/** legacy filterKey()/master — filter against a different field than dataIndex */
__fkey?: string;
width?: string | number;
constructor(key: string, title: string) {
this.key = key;
this.title = title;
this.dataIndex = key;
}
private __filter() {
this.filtered = true;
if (!this.scopedSlots) this.scopedSlots = {};
this.scopedSlots.filterDropdown = `${this.key}_filterDropdown`;
this.scopedSlots.filterIcon = `${this.key}_filterIcon`;
}
/** legacy filterKey(key) */
filterKey(key: string) {
this.__fkey = key;
return this;
}
/** legacy renderSlot(name) — render this cell through a named slot */
renderSlot(name: string) {
if (!this.scopedSlots) this.scopedSlots = {};
this.scopedSlots.customRender = name;
return this;
}
filterText() {
this.__filter();
this.filterType = 'default';
return this;
}
filterSwitch() {
this.__filter();
this.filterType = 'switch';
return this;
}
filterQuery(action: string) {
this.__filter();
this.filterType = 'query';
this.filterAction = action;
return this;
}
filterDate() {
this.__filter();
this.filterType = 'date';
return this;
}
filterNumber() {
this.__filter();
this.filterType = 'number';
return this;
}
/**
* legacy filterSelect(items) — `items` is an OBJECT MAP of value -> label,
* e.g. { 0: 'معلق', 1: 'ثبت سفارش' }, stored on `filterItems`. The shape is
* kept exactly so the ported table models pass their maps unchanged.
*
* Legacy also permitted calling it with no argument at all (TaminListModel does
* this), which left filterItems undefined and rendered an empty dropdown.
* Preserved: the parameter is optional here too.
*/
filterSelect(items?: Record<string | number, string>) {
this.__filter();
this.filterType = 'select';
this.filterItems = items;
return this;
}
/** legacy noSort() */
noSort() {
this.__sorter = false;
return this;
}
/** legacy hidden() — column exists but starts unchecked in the column picker */
hidden() {
this.show = false;
return this;
}
setWidth(w: string | number) {
this.width = w;
return this;
}
}
export interface DefaultFilter {
field: string;
op: string;
value: unknown;
}
/** Port of legacy XTbl — a table definition: endpoint + title + columns. */
export class XTbl {
url: string;
title: string;
cols: Xtc[] = [];
defaultFilters?: DefaultFilter[];
_hidePagination = false;
_hideSearch = false;
_noFilters = false;
constructor(url: string, title: string) {
this.url = url;
this.title = title;
}
add(col: Xtc) {
this.cols.push(col);
return this;
}
addDefaultFilter(filter: DefaultFilter) {
if (!this.defaultFilters) this.defaultFilters = [];
this.defaultFilters.push(filter);
return this;
}
hidePagination() {
this._hidePagination = true;
return this;
}
/**
* NOTE: legacy's hideSearch() set `_hidePageination` (sic) instead of a search
* flag — a copy-paste bug, so calling it hid PAGINATION, not the search box.
* Fixed here to set the intended flag; no ported schema calls it, so nothing
* changes in behaviour. Recorded in docs/ADMIN-PORT-PLAN.md.
*/
hideSearch() {
this._hideSearch = true;
return this;
}
/** legacy noFilters(): hides the filter bar entirely (walletTbl uses this). */
noFilters() {
this._noFilters = true;
return this;
}
getSortFields() {
return this.cols.filter((c) => c.__sorter);
}
}
export default XTbl;