diff --git a/src/components/mui/__tests__/mui-table-editable.test.js b/src/components/mui/__tests__/mui-table-editable.test.js index b14d68e46..497585ba9 100644 --- a/src/components/mui/__tests__/mui-table-editable.test.js +++ b/src/components/mui/__tests__/mui-table-editable.test.js @@ -29,6 +29,23 @@ jest.mock("@mui/material/ButtonBase/TouchRipple", () => ({ default: () => null })); +// TableCell shim to inspect sx prop in tests +jest.mock("@mui/material/TableCell", () => { + const React = require("react"); + return { + __esModule: true, + default: ({ children, sx, ...rest }) => ( + + {children} + + ) + }; +}); + // TablePagination shim jest.mock("@mui/material/TablePagination", () => { const React = require("react"); @@ -145,7 +162,7 @@ const setup = (overrides = {}) => { onPageChange: jest.fn(), onPerPageChange: jest.fn(), onSort: jest.fn(), - options: { sortCol: "name", sortDir: "-1" }, + options: { sortCol: "name", sortDir: -1 }, getName: (item) => item.name, onEdit: jest.fn(), onDelete: jest.fn(), @@ -156,6 +173,17 @@ const setup = (overrides = {}) => { return props; }; +const getCellSx = (cell) => { + const rawSx = cell.getAttribute("data-sx"); + if (!rawSx) return {}; + + try { + return JSON.parse(rawSx); + } catch { + return {}; + } +}; + // ---- Tests ---- describe("MuiTableEditable", () => { test("renders headers and rows", () => { @@ -270,7 +298,7 @@ describe("MuiTableEditable", () => { test("sort click triggers onSort with flipped dir", async () => { const user = userEvent.setup(); - const { onSort } = setup({ options: { sortCol: "name", sortDir: "-1" } }); + const { onSort } = setup({ options: { sortCol: "name", sortDir: -1 } }); // 1) Try our mock's testid first (desc + active when sortDir === "-1") let sortBtn = screen.queryByTestId("sort-label-desc-active"); @@ -295,6 +323,45 @@ describe("MuiTableEditable", () => { expect(onSort).toHaveBeenCalled(); const [colKey, newDir] = onSort.mock.calls[0]; expect(colKey).toBe("name"); - expect(newDir).toBe(1); // "-1" * -1 => 1 + expect(newDir).toBe(1); + }); + + test("applies archived styles to content, edit and delete cells when disableProp matches", () => { + setup({ + options: { sortCol: "name", sortDir: -1, disableProp: "is_archived" }, + data: [ + { id: 1, name: "Alice", role: "Dev", age: 35, is_archived: true }, + { id: 2, name: "Bob", role: "PM", age: 41, is_archived: false } + ], + onArchive: jest.fn() + }); + + const aliceRow = screen.getByText("Alice").closest("tr"); + const cells = within(aliceRow).getAllByTestId("mui-table-cell"); + + const archivedCellIndexes = [0, 1, 2, 3, 5]; + archivedCellIndexes.forEach((index) => { + const sx = getCellSx(cells[index]); + expect(sx.backgroundColor).toBe("background.light"); + expect(sx.color).toBe("text.disabled"); + }); + }); + + test("does not apply archived styles to archive/unarchive action cell", () => { + setup({ + options: { sortCol: "name", sortDir: -1, disableProp: "is_archived" }, + data: [{ id: 1, name: "Alice", role: "Dev", age: 35, is_archived: true }], + onArchive: jest.fn() + }); + + const unarchiveButton = screen.getByRole("button", { + name: "general.unarchive" + }); + const actionCell = unarchiveButton.closest("td"); + const sx = getCellSx(actionCell); + + expect(sx.width).toBe(80); + expect(sx.backgroundColor).toBeUndefined(); + expect(sx.color).toBeUndefined(); }); }); diff --git a/src/components/mui/editable-table/mui-table-editable.js b/src/components/mui/editable-table/mui-table-editable.js index cf42e03ca..47800d68e 100644 --- a/src/components/mui/editable-table/mui-table-editable.js +++ b/src/components/mui/editable-table/mui-table-editable.js @@ -23,6 +23,11 @@ import { } from "../../../utils/constants"; import showConfirmDialog from "../showConfirmDialog"; +const ARCHIVED_CELL_SX = { + backgroundColor: "background.light", + color: "text.disabled" +}; + const validateValue = (value, validation) => { if (!validation) return { isValid: true }; @@ -132,7 +137,7 @@ const MuiTableEditable = ({ onPageChange, onPerPageChange, onSort, - options = { sortCol: "", sortDir: 1 }, + options = { sortCol: "", sortDir: 1, disableProp: null }, getName = (item) => item.name, onEdit, onArchive, @@ -163,6 +168,14 @@ const MuiTableEditable = ({ const { sortCol, sortDir } = options; + const getArchivedCellSx = (row) => + options.disableProp && row[options.disableProp] ? ARCHIVED_CELL_SX : null; + + const getCellSx = (row, baseSx = {}) => ({ + ...baseSx, + ...(getArchivedCellSx(row) || {}) + }); + const handleDelete = async (item) => { const isConfirmed = await showConfirmDialog({ title: T.translate("general.are_you_sure"), @@ -249,17 +262,16 @@ const MuiTableEditable = ({ {/* TABLE BODY */} - {data.map((row, idx) => ( - // eslint-disable-next-line react/no-array-index-key - + {data.map((row) => ( + {columns.map((col) => ( handleCellClick(row.id, col.columnKey)} - sx={{ + sx={getCellSx(row, { cursor: col.editable ? "pointer" : "default", padding: col.editable ? "8px 16px" : undefined // Ensure enough space for the edit icon - }} + })} > {col.editable ? ( ))} {onEdit && ( - + onEdit(row)} size="small" @@ -318,7 +330,7 @@ const MuiTableEditable = ({ )} {onDelete && ( - + handleDelete(row)} size="small" diff --git a/src/components/mui/table/mui-table.js b/src/components/mui/table/mui-table.js index 5f8b9d55b..cc50ee975 100644 --- a/src/components/mui/table/mui-table.js +++ b/src/components/mui/table/mui-table.js @@ -28,6 +28,11 @@ import { import showConfirmDialog from "../showConfirmDialog"; import styles from "./mui-table.module.less"; +const ARCHIVED_CELL_SX = { + backgroundColor: "background.light", + color: "text.disabled" +}; + const MuiTable = ({ columns = [], data = [], @@ -73,6 +78,14 @@ const MuiTable = ({ const { sortCol, sortDir } = options; + const getArchivedCellSx = (row) => + options.disableProp && row[options.disableProp] ? ARCHIVED_CELL_SX : null; + + const getCellSx = (row, baseSx = {}) => ({ + ...baseSx, + ...(getArchivedCellSx(row) || {}) + }); + const handleDelete = async (item) => { const isConfirmed = await showConfirmDialog({ title: deleteDialogTitle || T.translate("general.are_you_sure"), @@ -161,9 +174,8 @@ const MuiTable = ({ {/* TABLE BODY */} - {data.map((row, idx) => ( - // eslint-disable-next-line react/no-array-index-key - + {data.map((row) => ( + {/* Main content columns */} {columns.map((col) => ( {renderCell(row, col)} @@ -189,15 +194,7 @@ const MuiTable = ({ onEdit(row)}> @@ -234,15 +231,7 @@ const MuiTable = ({