import { createSelector } from "@reduxjs/toolkit"; import { Box, IconButton, MenuItem, Select } from "@mui/material"; import OpenInNewIcon from "@mui/icons-material/OpenInNew"; import { GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import { RootState } from "@/app/redux/store"; import { TABLE_COLUMNS } from "../constants"; import { selectTransactionStatuses } from "@/app/redux/metadata/selectors"; import { DataRowBase } from "../types"; const TRANSACTION_STATUS_FALLBACK: string[] = [ "pending", "completed", "failed", "inprogress", "error", ]; type SelectorProps = { enableStatusActions: boolean; extraColumns?: string[] | null; showExtraColumns?: boolean; localRows: DataRowBase[]; handleStatusChange: (rowId: number, newStatus: string) => void; }; // ------------------------- // Basic Selectors (props-driven) // ------------------------- const propsEnableStatusActions = (_: RootState, props: SelectorProps) => props.enableStatusActions; const propsExtraColumns = (_: RootState, props: SelectorProps) => props.extraColumns ?? null; const propsShowExtraColumns = (_: RootState, props: SelectorProps) => props.showExtraColumns ?? false; const propsLocalRows = (_: RootState, props: SelectorProps) => props.localRows ?? []; const propsStatusChangeHandler = (_: RootState, props: SelectorProps) => props.handleStatusChange; // ------------------------- // Base Columns // ------------------------- const makeSelectBaseColumns = () => createSelector([propsEnableStatusActions], enableStatusActions => { if (!enableStatusActions) return TABLE_COLUMNS; return [ ...TABLE_COLUMNS, { field: "actions", headerName: "Actions", width: 160, sortable: false, filterable: false, } as GridColDef, ]; }); // ------------------------- // Visible Columns // ------------------------- const makeSelectVisibleColumns = () => createSelector( [makeSelectBaseColumns(), propsExtraColumns, propsShowExtraColumns], (baseColumns, extraColumns, showExtraColumns) => { if (!extraColumns || extraColumns.length === 0) return baseColumns; return showExtraColumns ? baseColumns : baseColumns.filter(col => !extraColumns.includes(col.field)); } ); // ------------------------- // Resolved Statuses (STATE-based) // ------------------------- const makeSelectResolvedStatuses = () => createSelector([selectTransactionStatuses], statuses => statuses.length > 0 ? statuses : TRANSACTION_STATUS_FALLBACK ); // ------------------------- // Enhanced Columns // ------------------------- export const makeSelectEnhancedColumns = () => createSelector( [ makeSelectVisibleColumns(), propsLocalRows, propsStatusChangeHandler, makeSelectResolvedStatuses(), ], ( visibleColumns, localRows, handleStatusChange, resolvedStatusOptions ): GridColDef[] => { return visibleColumns.map(col => { // -------------------------------- // 1. STATUS COLUMN RENDERER // -------------------------------- if (col.field === "status") { return { ...col, renderCell: (params: GridRenderCellParams) => { const value = params.value?.toLowerCase(); let bgColor = "#e0e0e0"; let textColor = "#000"; switch (value) { case "completed": bgColor = "#d0f0c0"; textColor = "#1b5e20"; break; case "pending": bgColor = "#fff4cc"; textColor = "#9e7700"; break; case "inprogress": bgColor = "#cce5ff"; textColor = "#004085"; break; case "error": bgColor = "#ffcdd2"; textColor = "#c62828"; break; } return ( {params.value} ); }, }; } // -------------------------------- // 2. USER ID COLUMN // -------------------------------- if (col.field === "userId") { return { ...col, headerAlign: "center", align: "center", renderCell: (params: GridRenderCellParams) => ( e.stopPropagation()} > {params.value} e.stopPropagation()} > ), }; } // -------------------------------- // 3. ACTIONS COLUMN // -------------------------------- if (col.field === "actions") { return { ...col, renderCell: (params: GridRenderCellParams) => { const currentRow = localRows.find(row => row.id === params.id); const options = currentRow?.options?.map(option => option.value) ?? resolvedStatusOptions; const uniqueOptions = Array.from(new Set(options)); return ( value={currentRow?.status ?? ""} onChange={e => handleStatusChange( params.id as number, e.target.value as string ) } size="small" fullWidth displayEmpty sx={{ "& .MuiOutlinedInput-notchedOutline": { border: "none" }, "& .MuiSelect-select": { py: 0.5 }, }} onClick={e => e.stopPropagation()} > {uniqueOptions.map(option => ( {option} ))} ); }, }; } return col; }); } );