233 lines
7.1 KiB
TypeScript
233 lines
7.1 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import Box from '@mui/material/Box';
|
||
import Button from '@mui/material/Button';
|
||
import AddIcon from '@mui/icons-material/Add';
|
||
import EditIcon from '@mui/icons-material/Edit';
|
||
import DeleteIcon from '@mui/icons-material/DeleteOutlined';
|
||
import SaveIcon from '@mui/icons-material/Save';
|
||
import CancelIcon from '@mui/icons-material/Close';
|
||
import {
|
||
GridRowsProp,
|
||
GridRowModesModel,
|
||
GridRowModes,
|
||
DataGrid,
|
||
GridColDef,
|
||
GridToolbarContainer,
|
||
GridActionsCellItem,
|
||
GridEventListener,
|
||
GridRowId,
|
||
GridRowModel,
|
||
GridRowEditStopReasons,
|
||
GridSlots,
|
||
} from '@mui/x-data-grid';
|
||
|
||
interface EditToolbarProps {
|
||
setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void
|
||
setRowModesModel: (
|
||
newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
|
||
) => void
|
||
columns: GridColDef[]
|
||
autoComplete?: React.ReactElement | null
|
||
}
|
||
|
||
function EditToolbar(props: EditToolbarProps) {
|
||
const { setRows, setRowModesModel, columns, autoComplete } = props
|
||
|
||
const handleClick = () => {
|
||
const id = Date.now().toString(36)
|
||
const newValues: any = {}
|
||
|
||
columns.forEach(column => {
|
||
if (column.type === 'number') {
|
||
newValues[column.field] = 0
|
||
} else if (column.type === 'string') {
|
||
newValues[column.field] = ''
|
||
} else if (column.type === 'boolean') {
|
||
newValues[column.field] = false
|
||
} else {
|
||
newValues[column.field] = undefined
|
||
}
|
||
|
||
if (column.field === 'region_id') {
|
||
// column.valueGetter = (value: any) => {
|
||
// console.log(value)
|
||
// }
|
||
}
|
||
})
|
||
|
||
setRows((oldRows) => [...oldRows, { id, ...newValues, isNew: true }]);
|
||
setRowModesModel((oldModel) => ({
|
||
...oldModel,
|
||
[id]: { mode: GridRowModes.Edit, fieldToFocus: columns[0].field },
|
||
}))
|
||
};
|
||
|
||
return (
|
||
<GridToolbarContainer sx={{ px: '16px', py: '16px' }}>
|
||
{autoComplete &&
|
||
<Box sx={{ flexGrow: '1' }}>
|
||
{autoComplete}
|
||
</Box>
|
||
}
|
||
|
||
<Button color="primary" startIcon={<AddIcon />} onClick={handleClick}>
|
||
Добавить
|
||
</Button>
|
||
</GridToolbarContainer>
|
||
);
|
||
}
|
||
|
||
interface DataGridProps {
|
||
initialRows: GridRowsProp;
|
||
columns: GridColDef[];
|
||
actions: boolean;
|
||
onRowClick: GridEventListener<"rowClick">;
|
||
onSave: any;
|
||
onDelete: any;
|
||
autoComplete?: React.ReactElement | null;
|
||
loading: boolean;
|
||
}
|
||
|
||
export default function FullFeaturedCrudGrid({
|
||
initialRows,
|
||
columns,
|
||
actions = false,
|
||
//onRowClick,
|
||
onSave,
|
||
onDelete,
|
||
autoComplete,
|
||
loading
|
||
}: DataGridProps) {
|
||
const [rows, setRows] = useState(initialRows);
|
||
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
|
||
|
||
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
|
||
if (params.reason === GridRowEditStopReasons.rowFocusOut) {
|
||
event.defaultMuiPrevented = true;
|
||
}
|
||
};
|
||
|
||
const handleEditClick = (id: GridRowId) => () => {
|
||
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } });
|
||
};
|
||
|
||
const handleSaveClick = (id: GridRowId) => () => {
|
||
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } });
|
||
onSave?.(id)
|
||
};
|
||
|
||
const handleDeleteClick = (id: GridRowId) => () => {
|
||
setRows(rows.filter((row) => row.id !== id));
|
||
onDelete?.(id)
|
||
};
|
||
|
||
const handleCancelClick = (id: GridRowId) => () => {
|
||
setRowModesModel({
|
||
...rowModesModel,
|
||
[id]: { mode: GridRowModes.View, ignoreModifications: true },
|
||
});
|
||
|
||
const editedRow = rows.find((row) => row.id === id);
|
||
if (editedRow!.isNew) {
|
||
setRows(rows.filter((row) => row.id !== id));
|
||
}
|
||
};
|
||
|
||
const processRowUpdate = (newRow: GridRowModel) => {
|
||
const updatedRow = { ...newRow, isNew: false };
|
||
setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
|
||
return updatedRow;
|
||
};
|
||
|
||
const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => {
|
||
setRowModesModel(newRowModesModel);
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (initialRows) {
|
||
setRows(initialRows)
|
||
}
|
||
}, [initialRows])
|
||
|
||
const actionColumns: GridColDef[] = [
|
||
{
|
||
field: 'actions',
|
||
type: 'actions',
|
||
headerName: 'Действия',
|
||
width: 100,
|
||
cellClassName: 'actions',
|
||
getActions: ({ id }) => {
|
||
const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
|
||
|
||
if (isInEditMode) {
|
||
return [
|
||
<GridActionsCellItem
|
||
icon={<SaveIcon />}
|
||
label="Save"
|
||
sx={{
|
||
color: 'primary.main',
|
||
}}
|
||
onClick={handleSaveClick(id)}
|
||
/>,
|
||
<GridActionsCellItem
|
||
icon={<CancelIcon />}
|
||
label="Cancel"
|
||
className="textPrimary"
|
||
onClick={handleCancelClick(id)}
|
||
color="inherit"
|
||
/>,
|
||
];
|
||
}
|
||
|
||
return [
|
||
<GridActionsCellItem
|
||
icon={<EditIcon />}
|
||
label="Edit"
|
||
className="textPrimary"
|
||
onClick={handleEditClick(id)}
|
||
color="inherit"
|
||
/>,
|
||
<GridActionsCellItem
|
||
icon={<DeleteIcon />}
|
||
label="Delete"
|
||
onClick={handleDeleteClick(id)}
|
||
color="inherit"
|
||
/>,
|
||
];
|
||
},
|
||
}
|
||
]
|
||
|
||
return (
|
||
<Box
|
||
sx={{
|
||
height: 500,
|
||
width: '100%',
|
||
'& .actions': {
|
||
color: 'text.secondary',
|
||
},
|
||
'& .textPrimary': {
|
||
color: 'text.primary',
|
||
},
|
||
}}
|
||
>
|
||
<DataGrid
|
||
loading={loading}
|
||
rows={rows || []}
|
||
columns={actions ? [...columns, ...actionColumns] : columns}
|
||
editMode="row"
|
||
rowModesModel={rowModesModel}
|
||
//onRowClick={onRowClick}
|
||
onRowModesModelChange={handleRowModesModelChange}
|
||
onRowEditStop={handleRowEditStop}
|
||
processRowUpdate={processRowUpdate}
|
||
slots={{
|
||
toolbar: EditToolbar as GridSlots['toolbar'],
|
||
}}
|
||
slotProps={{
|
||
toolbar: { setRows, setRowModesModel, columns, autoComplete },
|
||
}}
|
||
/>
|
||
</Box>
|
||
);
|
||
} |