feat/build-branch #3
@ -42,25 +42,103 @@ const propsLocalRows = (_: RootState, props: SelectorProps) =>
|
|||||||
const propsStatusChangeHandler = (_: RootState, props: SelectorProps) =>
|
const propsStatusChangeHandler = (_: RootState, props: SelectorProps) =>
|
||||||
props.handleStatusChange;
|
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
|
// Base Columns
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
||||||
const makeSelectBaseColumns = () =>
|
const makeSelectBaseColumns = () =>
|
||||||
createSelector([propsEnableStatusActions], enableStatusActions => {
|
createSelector(
|
||||||
if (!enableStatusActions) return TABLE_COLUMNS;
|
[makeSelectDynamicColumns(), propsEnableStatusActions],
|
||||||
|
(dynamicColumns, enableStatusActions) => {
|
||||||
|
const baseColumns = dynamicColumns;
|
||||||
|
|
||||||
return [
|
if (!enableStatusActions) return baseColumns;
|
||||||
...TABLE_COLUMNS,
|
|
||||||
{
|
return [
|
||||||
field: "actions",
|
...baseColumns,
|
||||||
headerName: "Actions",
|
{
|
||||||
width: 160,
|
field: "actions",
|
||||||
sortable: false,
|
headerName: "Actions",
|
||||||
filterable: false,
|
width: 160,
|
||||||
} as GridColDef,
|
sortable: false,
|
||||||
];
|
filterable: false,
|
||||||
});
|
} as GridColDef,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
// Visible Columns
|
// Visible Columns
|
||||||
@ -70,14 +148,17 @@ const makeSelectVisibleColumns = () =>
|
|||||||
createSelector(
|
createSelector(
|
||||||
[makeSelectBaseColumns(), propsExtraColumns, propsShowExtraColumns],
|
[makeSelectBaseColumns(), propsExtraColumns, propsShowExtraColumns],
|
||||||
(baseColumns, extraColumns, showExtraColumns) => {
|
(baseColumns, extraColumns, showExtraColumns) => {
|
||||||
|
// Columns are already built from row data, so they're all valid
|
||||||
if (!extraColumns || extraColumns.length === 0) return baseColumns;
|
if (!extraColumns || extraColumns.length === 0) return baseColumns;
|
||||||
|
|
||||||
return showExtraColumns
|
const visibleColumns = showExtraColumns
|
||||||
? baseColumns
|
? baseColumns
|
||||||
: baseColumns.filter(col => !extraColumns.includes(col.field));
|
: baseColumns.filter(col => !extraColumns.includes(col.field));
|
||||||
|
|
||||||
|
console.log("visibleColumns", visibleColumns);
|
||||||
|
return visibleColumns;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
// Resolved Statuses (STATE-based)
|
// Resolved Statuses (STATE-based)
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@ -105,6 +186,7 @@ export const makeSelectEnhancedColumns = () =>
|
|||||||
handleStatusChange,
|
handleStatusChange,
|
||||||
resolvedStatusOptions
|
resolvedStatusOptions
|
||||||
): GridColDef[] => {
|
): GridColDef[] => {
|
||||||
|
console.log("visibleColumns", visibleColumns);
|
||||||
return visibleColumns.map(col => {
|
return visibleColumns.map(col => {
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
// 1. STATUS COLUMN RENDERER
|
// 1. STATUS COLUMN RENDERER
|
||||||
|
|||||||
@ -17,3 +17,21 @@ export interface DataRowBase {
|
|||||||
status?: string;
|
status?: string;
|
||||||
options?: { value: string; label: 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
|
||||||
|
}
|
||||||
|
|||||||
@ -38,3 +38,8 @@ export const selectConditionOperators = (
|
|||||||
state: RootState
|
state: RootState
|
||||||
): Record<string, string> | undefined =>
|
): Record<string, string> | undefined =>
|
||||||
state.metadata.data?.field_names?.conditions;
|
state.metadata.data?.field_names?.conditions;
|
||||||
|
|
||||||
|
export const selectTransactionFieldNames = (
|
||||||
|
state: RootState
|
||||||
|
): Record<string, string> | undefined =>
|
||||||
|
state.metadata.data?.field_names?.transactions;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user