feat/build-branch #3

Merged
Mitchell merged 4 commits from feat/build-branch into main 2025-11-25 11:42:56 +01:00
3 changed files with 120 additions and 15 deletions
Showing only changes of commit d9485bcf2e - Show all commits

View File

@ -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

View File

@ -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
}

View File

@ -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;