Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,8 @@
"extends": [
"plugin:storybook/recommended"
]
},
"dependencies": {
"react-icons": "^5.5.0"
}
Comment on lines +63 to 65
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt this be dev-dependency?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, updating

}
41 changes: 41 additions & 0 deletions src/TableContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { createContext, useContext } from "react";
import { MRT_ColumnDef, MRT_RowData, MRT_TableInstance, useMaterialReactTable } from "material-react-table";
import { MaterialReactTableProps } from "material-react-table";

// Create context with a type that can be cast to any table instance
export const SmartMRTContext = createContext<any>(null);

export const useTableContext = <T extends MRT_RowData>(): MRT_TableInstance<T> => {
const context = useContext(SmartMRTContext);
if (!context) {
throw new Error('useTableContext must be used within a TableContextProvider');
}
return context as MRT_TableInstance<T>;
}

export const TableContextProvider = <T extends MRT_RowData>({
children,
tableProps,
table
}: {
children: React.ReactNode,
tableProps: Omit<MaterialReactTableProps<T>, 'columns' | 'data'> & {
columns: MRT_ColumnDef<T>[];
data: T[];
},
table?: MRT_TableInstance<T>
Comment on lines +22 to +26
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its either of both right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, updating

}) => {
const { columns, data, ...tablePropsWithoutColumnsAndData } = tableProps;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove columns, data, seperately?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changing

const tableInstance = table || useMaterialReactTable<T>({
columns,
data,
globalFilterModeOptions: ['fuzzy', 'startsWith'],
...tablePropsWithoutColumnsAndData
});

return (
<SmartMRTContext.Provider value={{...tableInstance}}>
{children}
</SmartMRTContext.Provider>
);
}
36 changes: 18 additions & 18 deletions src/components/smart_report/smart_report.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { MaterialReactTableProps, MRT_RowData } from "material-react-table";
import { SmartReportMRT } from "../smart_report_mrt";

import { MaterialReactTableProps, MRT_RowData, MRT_ColumnDef, MRT_TableInstance } from "material-react-table";
import { TableContextProvider } from "../../TableContextProvider";
import { SmartReportMRT } from "../smart_report_mrt/smart_report_mrt";
type SmartReportProps<T extends MRT_RowData> = {
children: React.ReactNode;
tableProps?: never;
} | {
children?: never;
tableProps: MaterialReactTableProps<T>;
tableProps: Omit<MaterialReactTableProps<T>, 'columns' | 'data'> & {
columns: MRT_ColumnDef<T>[];
data: T[];
};
table?: MRT_TableInstance<T>;
}

export const SmartReport = <T extends MRT_RowData>({children, tableProps}:SmartReportProps<T>) => {
if (children) {
return <>{children}</>;
}

if (!tableProps) {
return null;
}
export const SmartReport = <T extends MRT_RowData>({
tableProps,
table
}: SmartReportProps<T>) => {

return <SmartReportMRT {...tableProps} />;
}
return (
<TableContextProvider tableProps={tableProps} table={table}>
<SmartReportMRT />
</TableContextProvider>
);
};
136 changes: 136 additions & 0 deletions src/components/smart_report_mrt/smart_mrt.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* --- Responsive Table CSS --- */

.responsive-card-table {
width: 100%;
border-collapse: collapse;
}

/* Default Table Cell Padding (Example) */
.responsive-card-table th,
.responsive-card-table td {
padding: 8px 12px; /* Adjust to match default MRT/MUI padding */
text-align: left;
border-bottom: 1px solid #ddd; /* Default row separator */
}
.responsive-card-table th {
font-weight: bold;
}
/* Remove bottom border from last row */
.responsive-card-table tr:last-child td {
border-bottom: none;
}


/* --- Mobile Card View (Default Responsive) --- */
/* @media screen and (max-width: 767px) { */

/* Hide header by default in mobile */
.responsive-card-table:not(.force-table-view) thead {
display: none;
}

/* Apply card styles only when NOT forced into table view */
.responsive-card-table:not(.force-table-view) {
border: none;
box-shadow: none;
}

.responsive-card-table:not(.force-table-view) tbody,
.responsive-card-table:not(.force-table-view) tr,
.responsive-card-table:not(.force-table-view) td {
display: block;
width: 100% !important;
box-sizing: border-box;
}

.responsive-card-table:not(.force-table-view) tr {
margin-bottom: 1.5rem;
border: 1px solid #ddd;
border-radius: 5px;
overflow: hidden;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
background-color: #fff;
}

.responsive-card-table:not(.force-table-view) tr.MuiTableRow-root {
background-color: transparent;
}


.responsive-card-table:not(.force-table-view) td {
text-align: right;
padding-left: 50%;
padding-top: 10px;
padding-bottom: 10px;
position: relative;
border: none;
border-bottom: 1px solid #eee;
min-height: 30px;
display: flex;
align-items: center;
justify-content: flex-end;
}

.responsive-card-table:not(.force-table-view) tr td:last-child {
border-bottom: none;
}

.responsive-card-table:not(.force-table-view) td::before {
content: attr(data-label);
position: absolute;
left: 10px;
top: 50%;
transform: translateY(-50%);
width: calc(50% - 20px);
padding-right: 10px;
font-weight: bold;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #555;
}

/* --- Overrides when .force-table-view is active on mobile --- */

/* IMPORTANT: Show header when table view is forced */
.responsive-card-table.force-table-view thead {
display: table-header-group !important; /* Or initial */
}

/* Reset row display */
.responsive-card-table.force-table-view tr {
display: table-row !important;
/* Reset card styles */
margin-bottom: 0 !important;
border: none !important;
border-radius: 0 !important;
box-shadow: none !important;
background-color: transparent !important;
overflow: visible !important;
}

/* Reset cell display and styles */
.responsive-card-table.force-table-view td {
display: table-cell !important;
width: auto !important; /* Allow table layout */
/* Reset card cell styles */
text-align: left !important; /* Default alignment */
padding: 8px 12px !important; /* Restore original padding */
position: static !important;
border: none !important; /* Remove card border */
border-bottom: 1px solid #ddd !important; /* Restore row border */
min-height: auto !important;
}

/* Hide the generated labels when table view is forced */
.responsive-card-table.force-table-view td::before {
display: none !important;
}

/* Ensure last row border is correctly removed in forced table view */
.responsive-card-table.force-table-view tr:last-child td {
border-bottom: none !important;
}

/* } */
39 changes: 26 additions & 13 deletions src/components/smart_report_mrt/smart_report_mrt.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import TableViewIcon from '@mui/icons-material/TableView';
import ViewModuleIcon from '@mui/icons-material/ViewModule';
import { Button } from "@mui/material";
import { MaterialReactTable, MaterialReactTableProps, MRT_RowData } from "material-react-table";
import { MaterialReactTable } from "material-react-table";
import { useState } from "react";
import "./smart_report_mrt.css";
import "./smart_mrt.css";
import { FaFilePdf } from 'react-icons/fa';
import { useTableContext } from '../../TableContextProvider';

/*
TODO: (Responsive Card View)
- Add a field `showInCardView` to the column definition. Default to false.
- Show columns that have `showInCardView` set to true in card view.
- When user toggles visibility of a column in card view, update the `showInCardView` field.
*/
export const SmartReportMRT = <T extends MRT_RowData>(props: MaterialReactTableProps<T>) => {
export const SmartReportMRT = () => {
// Get table instance from context
const table = useTableContext();

// State to control the view mode override. Default to table view on desktop & card view on mobile.
const [forceTableView, setForceTableView] = useState(window.innerWidth >= 500);

return (
<MaterialReactTable
// Add props to the main table element (<table>)
muiTableProps = {{
// Conditionally add the 'force-table-view' class
className: `responsive-card-table ${forceTableView ? 'force-table-view' : ''}`,
sx: {
maxWidth: forceTableView ? '100%' : '500px',
maxWidth: forceTableView ? '100%' : '500px',
}
}}
// Add props to the table body cells (<td>)
Expand All @@ -31,16 +31,29 @@ export const SmartReportMRT = <T extends MRT_RowData>(props: MaterialReactTableP
})}
renderTopToolbar = {() => (
<div className="top-toolbar">
<Button
<Button
onClick={() => setForceTableView(!forceTableView)}
startIcon={forceTableView ? <ViewModuleIcon /> : <TableViewIcon />}
>
{forceTableView ? 'Switch to Card View' : null}
{forceTableView ? 'Card View' : 'Table View'}
</Button>
<Button variant="outlined" style={{ height:'100%'}} startIcon={<FaFilePdf />}>
View PDF
</Button>
</div>
)}

{...props}
// Use table instance from context instead of props
state={table.getState()}
columns={table.options.columns}
data={table.options.data}
enableColumnFilters={table.options.enableColumnFilters}
enableGlobalFilter={table.options.enableGlobalFilter}
enableColumnOrdering={table.options.enableColumnOrdering}
enableGrouping={table.options.enableGrouping}
enablePagination={table.options.enablePagination}
enableSorting={table.options.enableSorting}
// Add more table props as needed
Comment on lines +47 to +56
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What the hell is this!?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passing table = {table} is overriding the pdf button and other props we pass.

This way buttons are showing, but from table actions we can't change table state, it has to be done via api.

How to solve this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passing table = {table} is overriding the pdf button and other props we pass.

This way buttons are showing, but from table actions we can't change table state, it has to be done via api.

How to solve this?

/>
);
};