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 StatusChangeHandler = (rowId: number, newStatus: string) => void; const selectEnableStatusActions = ( _state: RootState, enableStatusActions: boolean ) => enableStatusActions; const selectExtraColumns = ( _state: RootState, _enableStatusActions: boolean, extraColumns?: string[] | null ) => extraColumns ?? null; const selectShowExtraColumns = ( _state: RootState, _enableStatusActions: boolean, _extraColumns?: string[] | null, showExtraColumns = false ) => showExtraColumns; const selectLocalRows = ( _state: RootState, _enableStatusActions: boolean, _extraColumns?: string[] | null, _showExtraColumns?: boolean, localRows?: DataRowBase[] ) => localRows ?? []; const noopStatusChangeHandler: StatusChangeHandler = () => {}; const selectStatusChangeHandler = ( _state: RootState, _enableStatusActions: boolean, _extraColumns?: string[] | null, _showExtraColumns?: boolean, _localRows?: DataRowBase[], handleStatusChange?: StatusChangeHandler ) => handleStatusChange ?? noopStatusChangeHandler; export const selectBaseColumns = createSelector( [selectEnableStatusActions], enableStatusActions => { if (!enableStatusActions) { return TABLE_COLUMNS; } return [ ...TABLE_COLUMNS, { field: "actions", headerName: "Actions", width: 160, sortable: false, filterable: false, } as GridColDef, ]; } ); export const selectVisibleColumns = createSelector( [selectBaseColumns, selectExtraColumns, selectShowExtraColumns], (baseColumns, extraColumns, showExtraColumns) => { if (!extraColumns || extraColumns.length === 0) { return baseColumns; } return showExtraColumns ? baseColumns : baseColumns.filter(col => !extraColumns.includes(col.field)); } ); export const selectResolvedTransactionStatuses = createSelector( [selectTransactionStatuses], statuses => (statuses.length > 0 ? statuses : TRANSACTION_STATUS_FALLBACK) ); export const selectEnhancedColumns = createSelector( [ selectVisibleColumns, selectLocalRows, selectStatusChangeHandler, selectResolvedTransactionStatuses, ], ( visibleColumns, localRows, handleStatusChange, resolvedStatusOptions ): GridColDef[] => { return visibleColumns.map(col => { 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} ); }, }; } if (col.field === "userId") { return { ...col, headerAlign: "center", align: "center", renderCell: (params: GridRenderCellParams) => ( e.stopPropagation()} > {params.value} e.stopPropagation()} > ), }; } 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: string[] = 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; }) as GridColDef[]; } );