Added more to transaction table perfomrance

This commit is contained in:
Mitchell Magro 2025-11-19 20:42:31 +01:00
parent 4f230fa208
commit d9485bcf2e
3 changed files with 120 additions and 15 deletions

View File

@ -42,25 +42,103 @@ const propsLocalRows = (_: RootState, props: SelectorProps) =>
const propsStatusChangeHandler = (_: RootState, props: SelectorProps) =>
props.handleStatusChange;
// -------------------------
// Helper: Format field name to header name
// -------------------------
/**
* Converts a field name to a readable header name
* e.g., "userId" -> "User ID", "transactionId" -> "Transaction ID"
*/
const formatFieldNameToHeader = (fieldName: string): string => {
// Handle camelCase: insert space before capital letters and capitalize first letter
return fieldName
.replace(/([A-Z])/g, " $1") // Add space before capital letters
.replace(/^./, str => str.toUpperCase()) // Capitalize first letter
.trim();
};
// -------------------------
// Dynamic Columns from Row Data
// -------------------------
const makeSelectDynamicColumns = () =>
createSelector([propsLocalRows], (localRows): GridColDef[] => {
// If no rows, fall back to static columns
if (!localRows || localRows.length === 0) {
return TABLE_COLUMNS;
}
// Get all unique field names from the row data
const fieldSet = new Set<string>();
localRows.forEach(row => {
Object.keys(row).forEach(key => {
if (key !== "options") {
// Exclude internal fields
fieldSet.add(key);
}
});
});
// Build columns from actual row data fields
const dynamicColumns: GridColDef[] = Array.from(fieldSet).map(field => {
// Format field name to readable header
const headerName = formatFieldNameToHeader(field);
// Set default widths based on field type
let width = 150;
if (field.includes("id") || field.includes("Id")) {
width = 180;
} else if (field === "amount" || field === "currency") {
width = 120;
} else if (field === "status") {
width = 120;
} else if (
field.includes("date") ||
field.includes("Date") ||
field === "dateTime" ||
field === "created" ||
field === "modified"
) {
width = 180;
}
return {
field,
headerName,
width,
sortable: true,
filterable: true,
} as GridColDef;
});
return dynamicColumns;
});
// -------------------------
// Base Columns
// -------------------------
const makeSelectBaseColumns = () =>
createSelector([propsEnableStatusActions], enableStatusActions => {
if (!enableStatusActions) return TABLE_COLUMNS;
createSelector(
[makeSelectDynamicColumns(), propsEnableStatusActions],
(dynamicColumns, enableStatusActions) => {
const baseColumns = dynamicColumns;
return [
...TABLE_COLUMNS,
{
field: "actions",
headerName: "Actions",
width: 160,
sortable: false,
filterable: false,
} as GridColDef,
];
});
if (!enableStatusActions) return baseColumns;
return [
...baseColumns,
{
field: "actions",
headerName: "Actions",
width: 160,
sortable: false,
filterable: false,
} as GridColDef,
];
}
);
// -------------------------
// Visible Columns
@ -70,14 +148,17 @@ const makeSelectVisibleColumns = () =>
createSelector(
[makeSelectBaseColumns(), propsExtraColumns, propsShowExtraColumns],
(baseColumns, extraColumns, showExtraColumns) => {
// Columns are already built from row data, so they're all valid
if (!extraColumns || extraColumns.length === 0) return baseColumns;
return showExtraColumns
const visibleColumns = showExtraColumns
? baseColumns
: baseColumns.filter(col => !extraColumns.includes(col.field));
console.log("visibleColumns", visibleColumns);
return visibleColumns;
}
);
// -------------------------
// Resolved Statuses (STATE-based)
// -------------------------
@ -105,6 +186,7 @@ export const makeSelectEnhancedColumns = () =>
handleStatusChange,
resolvedStatusOptions
): GridColDef[] => {
console.log("visibleColumns", visibleColumns);
return visibleColumns.map(col => {
// --------------------------------
// 1. STATUS COLUMN RENDERER

View File

@ -17,3 +17,21 @@ export interface DataRowBase {
status?: string;
options?: { value: string; label: string }[];
}
export interface ITransactions {
id: string;
psp_id: string;
method_id: string;
merchant_id: string;
external_id?: string; // optional: may not always be present
customer?: string; // keep as string unless you provide structure
type?: string;
currency?: string;
amount: number | string; // sometimes APIs return strings for money
status?: string;
notes?: string;
creator?: string;
created: string; // ISO datetime string from API
modifier?: string;
modified?: string; // ISO datetime string or undefined
}

View File

@ -38,3 +38,8 @@ export const selectConditionOperators = (
state: RootState
): Record<string, string> | undefined =>
state.metadata.data?.field_names?.conditions;
export const selectTransactionFieldNames = (
state: RootState
): Record<string, string> | undefined =>
state.metadata.data?.field_names?.transactions;