Explorar el Código

Use dynamic rowId to prevent timesheet/leave id clash

tags/Baseline_30082024_FRONTEND_UAT
Wayne hace 1 año
padre
commit
7ca124444c
Se han modificado 1 ficheros con 36 adiciones y 23 borrados
  1. +36
    -23
      src/components/TimeLeaveModal/TimeLeaveInputTable.tsx

+ 36
- 23
src/components/TimeLeaveModal/TimeLeaveInputTable.tsx Ver fichero

@@ -9,6 +9,7 @@ import {
GridRenderCellParams,
GridRenderEditCellParams,
GridRowId,
GridRowIdGetter,
GridRowModel,
GridRowModes,
GridRowModesModel,
@@ -69,15 +70,15 @@ export type TimeLeaveRow = Partial<
>;

class ProcessRowUpdateError extends Error {
public readonly rowId: GridRowId;
public readonly row: TimeLeaveRow;
public readonly errors: TimeEntryError | LeaveEntryError | undefined;
constructor(
rowId: GridRowId,
row: TimeLeaveRow,
message?: string,
errors?: TimeEntryError | LeaveEntryError,
) {
super(message);
this.rowId = rowId;
this.row = row;
this.errors = errors;

Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
@@ -135,19 +136,28 @@ const TimeLeaveInputTable: React.FC<Props> = ({
useFormContext<RecordTimeLeaveInput>();
const currentEntries = getValues(day);

const getRowId = useCallback<GridRowIdGetter<TimeLeaveRow>>(
(row) => `${row.type}-${row.id}`,
[],
);

const [entries, setEntries] = useState<TimeLeaveRow[]>(currentEntries || []);

const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});

const apiRef = useGridApiRef();
const addRow = useCallback(() => {
const id = Date.now();
setEntries((e) => [...e, { id, _isNew: true, type: "timeEntry" }]);
const type = "timeEntry" as const;
const newEntry = { id: Date.now(), _isNew: true, type };
setEntries((e) => [...e, newEntry]);
setRowModesModel((model) => ({
...model,
[id]: { mode: GridRowModes.Edit, fieldToFocus: "projectId" },
[getRowId(newEntry)]: {
mode: GridRowModes.Edit,
fieldToFocus: "projectId",
},
}));
}, []);
}, [getRowId]);

const validateRow = useCallback(
(row: TimeLeaveRow) => {
@@ -186,25 +196,25 @@ const TimeLeaveInputTable: React.FC<Props> = ({
}));
const editedRow = entries.find((entry) => entry.id === id);
if (editedRow?._isNew) {
setEntries((es) => es.filter((e) => e.id !== id));
setEntries((es) => es.filter((e) => getRowId(e) !== id));
} else {
setEntries((es) =>
es.map((e) =>
e.id === id
getRowId(e) === id
? { ...e, _error: undefined, _isPlanned: undefined }
: e,
),
);
}
},
[entries],
[entries, getRowId],
);

const handleDelete = useCallback(
(id: GridRowId) => () => {
setEntries((es) => es.filter((e) => e.id !== id));
setEntries((es) => es.filter((e) => getRowId(e) !== id));
},
[],
[getRowId],
);

const handleSave = useCallback(
@@ -218,10 +228,17 @@ const TimeLeaveInputTable: React.FC<Props> = ({
);

const processRowUpdate = useCallback(
(newRow: GridRowModel<TimeLeaveRow>) => {
(
newRow: GridRowModel<TimeLeaveRow>,
originalRow: GridRowModel<TimeLeaveRow>,
) => {
const errors = validateRow(newRow);
if (errors) {
throw new ProcessRowUpdateError(newRow.id!, "validation error", errors);
throw new ProcessRowUpdateError(
originalRow,
"validation error",
errors,
);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -242,24 +259,19 @@ const TimeLeaveInputTable: React.FC<Props> = ({
_isPlanned: newIsPlanned,
} satisfies TimeLeaveRow;
setEntries((es) =>
es.map((e) => (e.id === rowToSave.id ? rowToSave : e)),
es.map((e) => (getRowId(e) === getRowId(originalRow) ? rowToSave : e)),
);
return rowToSave;
},
[validateRow, verifyIsPlanned],
[validateRow, verifyIsPlanned, getRowId],
);

const onProcessRowUpdateError = useCallback(
(updateError: ProcessRowUpdateError) => {
const errors = updateError.errors;
const rowId = updateError.rowId;
const oldRow = updateError.row;

apiRef.current.updateRows([
{
id: rowId,
_error: errors,
},
]);
apiRef.current.updateRows([{ ...oldRow, _error: errors }]);
},
[apiRef],
);
@@ -685,6 +697,7 @@ const TimeLeaveInputTable: React.FC<Props> = ({
return (
<>
<StyledDataGrid
getRowId={getRowId}
apiRef={apiRef}
autoHeight
sx={{


Cargando…
Cancelar
Guardar