|
|
|
@@ -3,109 +3,157 @@ import * as React from 'react'; |
|
|
|
import { |
|
|
|
DataGrid, |
|
|
|
GridActionsCellItem, |
|
|
|
GridRowModes, |
|
|
|
GridRowEditStopReasons, |
|
|
|
} from "@mui/x-data-grid"; |
|
|
|
import EditIcon from '@mui/icons-material/Edit'; |
|
|
|
import VisibilityIcon from '@mui/icons-material/Visibility'; |
|
|
|
import DeleteIcon from '@mui/icons-material/Delete'; |
|
|
|
import SaveIcon from '@mui/icons-material/Save'; |
|
|
|
import CancelIcon from '@mui/icons-material/Cancel'; |
|
|
|
import {useContext, useEffect} from "react"; |
|
|
|
import {useNavigate} from "react-router-dom"; |
|
|
|
import {CustomNoRowsOverlay, dateComparator, getDateString} from "../../../utils/CommonFunction"; |
|
|
|
import AbilityContext from "../../../components/AbilityProvider"; |
|
|
|
import {LIONER_BUTTON_THEME} from "../../../themes/colorConst"; |
|
|
|
import {ThemeProvider} from "@emotion/react"; |
|
|
|
import axios from "axios"; // Add this |
|
|
|
import {apiPath} from "../../../auth/utils"; // Add this (same as in index.js) |
|
|
|
|
|
|
|
// ==============================|| Consultant TABLE ||============================== // |
|
|
|
|
|
|
|
export default function ConsultantTable({recordList, applySearch}) { |
|
|
|
const [rows, setRows] = React.useState(recordList); |
|
|
|
const [rowModesModel] = React.useState({}); |
|
|
|
const [rows, setRows] = React.useState([]); |
|
|
|
const [rowModesModel, setRowModesModel] = React.useState({}); |
|
|
|
|
|
|
|
const [isWindowOpen, setIsWindowOpen] = React.useState(false); |
|
|
|
const [recordId, setRecordId] = React.useState(null); |
|
|
|
|
|
|
|
const navigate = useNavigate() |
|
|
|
const ability = useContext(AbilityContext); |
|
|
|
|
|
|
|
const [paginationModel, setPaginationModel] = React.useState({ |
|
|
|
page: 0, |
|
|
|
pageSize:10 |
|
|
|
pageSize: 10 |
|
|
|
}); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
setPaginationModel({page:0,pageSize:10}); |
|
|
|
setRows(recordList); |
|
|
|
setPaginationModel({page: 0, pageSize: 10}); |
|
|
|
// Ensure each row has a unique 'id' field (required by DataGrid) |
|
|
|
setRows(recordList.map(row => ({ ...row, id: row.id || row.someUniqueKey }))); |
|
|
|
}, [recordList]); |
|
|
|
|
|
|
|
const handleRowEditStop = (params, event) => { |
|
|
|
if (params.reason === GridRowEditStopReasons.rowFocusOut) { |
|
|
|
event.defaultMuiPrevented = true; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const handleEditClick = (id) => () => { |
|
|
|
navigate('/consultant/'+ id); |
|
|
|
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } }); |
|
|
|
}; |
|
|
|
|
|
|
|
const handleCloseClick = () => { |
|
|
|
setIsWindowOpen(false); |
|
|
|
setRecordId(null); |
|
|
|
const handleSaveClick = (id) => () => { |
|
|
|
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); |
|
|
|
}; |
|
|
|
|
|
|
|
const handleCloseRefresh = () => { |
|
|
|
setIsWindowOpen(false); |
|
|
|
setRecordId(null); |
|
|
|
applySearch(); |
|
|
|
const handleCancelClick = (id) => () => { |
|
|
|
setRowModesModel({ |
|
|
|
...rowModesModel, |
|
|
|
[id]: { mode: GridRowModes.View, ignoreModifications: true }, |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
const handleDeleteClick = (id) => async () => { |
|
|
|
if (window.confirm("Are you sure you want to delete this consultant? This action cannot be undone.")) { |
|
|
|
try { |
|
|
|
const response = await axios.post(`${apiPath}/consultant/delete`, { id }); |
|
|
|
|
|
|
|
if (response.status === 200 || response.status === 204) { |
|
|
|
applySearch(); // Refresh the table |
|
|
|
} |
|
|
|
} catch (err) { |
|
|
|
console.error("Delete error:", err); |
|
|
|
alert("Failed to delete consultant. Please try again."); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const processRowUpdate = async (newRow) => { |
|
|
|
// Optimistically update UI |
|
|
|
const updatedRow = { ...newRow }; |
|
|
|
|
|
|
|
try { |
|
|
|
const response = await axios.post(`${apiPath}/consultant/save`, newRow); |
|
|
|
if (response.status === 200) { |
|
|
|
// If backend returns updated data, use it |
|
|
|
return response.data || updatedRow; |
|
|
|
} |
|
|
|
} catch (err) { |
|
|
|
console.error("Save error:", err); |
|
|
|
alert("Failed to save changes. Please try again."); |
|
|
|
// On failure, you could revert, but here we keep the edited value |
|
|
|
} |
|
|
|
|
|
|
|
return updatedRow; |
|
|
|
}; |
|
|
|
|
|
|
|
const columns = [ |
|
|
|
/* |
|
|
|
{ |
|
|
|
field: 'actions', |
|
|
|
type: 'actions', |
|
|
|
headerName: 'Actions', |
|
|
|
// flex: 0.5, |
|
|
|
width: 100, |
|
|
|
cellClassName: 'actions', |
|
|
|
getActions: ({id}) => { |
|
|
|
width: 150, |
|
|
|
getActions: ({ id }) => { |
|
|
|
const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; |
|
|
|
|
|
|
|
if (isInEditMode) { |
|
|
|
return [ |
|
|
|
<ThemeProvider key="save" theme={LIONER_BUTTON_THEME}> |
|
|
|
<GridActionsCellItem |
|
|
|
icon={<SaveIcon />} |
|
|
|
label="Save" |
|
|
|
onClick={handleSaveClick(id)} |
|
|
|
color="save" |
|
|
|
/> |
|
|
|
</ThemeProvider>, |
|
|
|
<ThemeProvider key="cancel" theme={LIONER_BUTTON_THEME}> |
|
|
|
<GridActionsCellItem |
|
|
|
icon={<CancelIcon />} |
|
|
|
label="Cancel" |
|
|
|
onClick={handleCancelClick(id)} |
|
|
|
color="cancel" |
|
|
|
/> |
|
|
|
</ThemeProvider>, |
|
|
|
]; |
|
|
|
} |
|
|
|
|
|
|
|
return [ |
|
|
|
<ThemeProvider key="OutSave" theme={LIONER_BUTTON_THEME}> |
|
|
|
<ThemeProvider key="edit" theme={LIONER_BUTTON_THEME}> |
|
|
|
<GridActionsCellItem |
|
|
|
icon={<EditIcon sx={{fontSize: 25}}/>} |
|
|
|
label="Edit" |
|
|
|
className="textPrimary" |
|
|
|
onClick={handleEditClick(id)} |
|
|
|
color="edit" |
|
|
|
// disabled={'true'} |
|
|
|
// disabled={!ability.can('VIEW','DASHBOARD')} |
|
|
|
/> |
|
|
|
</ThemeProvider> |
|
|
|
] |
|
|
|
</ThemeProvider>, |
|
|
|
<ThemeProvider key="delete" theme={LIONER_BUTTON_THEME}> |
|
|
|
<GridActionsCellItem |
|
|
|
icon={<DeleteIcon />} |
|
|
|
label="Delete" |
|
|
|
onClick={handleDeleteClick(id)} |
|
|
|
color="error" // Use "error" if no 'delete' color defined |
|
|
|
/> |
|
|
|
</ThemeProvider>, |
|
|
|
]; |
|
|
|
}, |
|
|
|
}, |
|
|
|
*/ |
|
|
|
// { |
|
|
|
// id: 'title', |
|
|
|
// field: 'title', |
|
|
|
// headerName: 'Title', |
|
|
|
// // sortComparator: dateComparator, |
|
|
|
// flex: 0.75, |
|
|
|
// renderCell: (params) => ( |
|
|
|
// <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}> |
|
|
|
// {params.value} |
|
|
|
// </div> |
|
|
|
// // <div> |
|
|
|
// // {getDateString(params.row.pdfFrom,false)} |
|
|
|
// // </div> |
|
|
|
// ), |
|
|
|
// }, |
|
|
|
{ |
|
|
|
id: 'name', |
|
|
|
field: 'name', |
|
|
|
headerName: 'Name', |
|
|
|
flex: 2, |
|
|
|
renderCell: (params) => { |
|
|
|
return ( |
|
|
|
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}> |
|
|
|
{params.value} |
|
|
|
</div> |
|
|
|
); |
|
|
|
} |
|
|
|
editable: true, // Enables inline editing |
|
|
|
renderCell: (params) => ( |
|
|
|
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}> |
|
|
|
{params.value} |
|
|
|
</div> |
|
|
|
), |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'createDate', |
|
|
|
field: 'createDate', |
|
|
|
headerName: 'Create Datetime', |
|
|
|
flex: 1, |
|
|
|
@@ -116,29 +164,26 @@ export default function ConsultantTable({recordList, applySearch}) { |
|
|
|
</div> |
|
|
|
), |
|
|
|
}, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
return ( |
|
|
|
<div> |
|
|
|
<div style={{ width: '100%' }}> |
|
|
|
<DataGrid |
|
|
|
rows={rows} |
|
|
|
columns={columns} |
|
|
|
columnHeaderHeight={45} |
|
|
|
editMode="row" |
|
|
|
//autoPageSize |
|
|
|
rowModesModel={rowModesModel} |
|
|
|
onRowModesModelChange={setRowModesModel} |
|
|
|
onRowEditStop={handleRowEditStop} |
|
|
|
processRowUpdate={processRowUpdate} |
|
|
|
onProcessRowUpdateError={(error) => console.error(error)} |
|
|
|
getRowHeight={() => 'auto'} |
|
|
|
paginationModel={paginationModel} |
|
|
|
onPaginationModelChange={setPaginationModel} |
|
|
|
slots={{ |
|
|
|
noRowsOverlay: () => ( |
|
|
|
CustomNoRowsOverlay() |
|
|
|
) |
|
|
|
}} |
|
|
|
slots={{ noRowsOverlay: CustomNoRowsOverlay }} |
|
|
|
pageSizeOptions={[10]} |
|
|
|
autoHeight |
|
|
|
/> |
|
|
|
</div> |
|
|
|
); |
|
|
|
} |
|
|
|
} |