Files
monorepo/LCU.WebApps.Operations.IncentiveManager/src/containers/commissions-page/CommissionRatesEditor.tsx
T
2026-03-23 11:21:52 -05:00

140 lines
4.7 KiB
TypeScript

import React from "react";
import { ICommissionRateChange } from "../../shared/models/Commission";
import { IAppState } from "../../store/Store";
import CommissionRatesTable from "../../components/commissions/CommissionRatesTable";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getAllCommissions } from "../../actions/CommissionActions";
import { ICommissionState } from "../../reducers/CommissionReducer";
import CommissionService from "../../shared/services/CommissionService";
import AsyncState from "../../shared/enumerations/AsyncState";
import moment from "moment";
import { SettingsContext } from "../../shared/providers/SettingsProvider";
const CommissionRatesEditor: React.FC = () => {
const dispatch = useDispatch();
const settings = React.useContext(SettingsContext);
const commissionsState = useSelector<IAppState, ICommissionState>(
(state) => state.commissionState
);
const commissions = CommissionService.mapToChange(
commissionsState.commissions.data ?? []
);
const [pendingChanges, setPendingChanges] = useState<
ICommissionRateChange[]
>([]);
const [saveMessage, setSaveMessage] = useState<string>("");
const [submitState, setSubmitState] = useState<AsyncState>(
AsyncState.Inactive
);
const rolesWithCommissions =
settings?.appRoles.filter((role) => role.hasCommissions) ?? [];
const productsWithCommissions =
settings?.productDetails.filter((product) => product.hasCommissions) ??
[];
const isValidChanges = (changes: ICommissionRateChange[]): boolean => {
let isValid = true;
changes.forEach((change) => {
if (!CommissionService.isValidRateChange(change)) {
isValid = false;
}
});
return isValid;
};
const changeRate = (change: ICommissionRateChange) => {
setSubmitState(AsyncState.Inactive);
const changes = [...pendingChanges];
const original = commissions.find(
(com) =>
com.role.name === change.role.name &&
com.product === change.product
);
const index = pendingChanges.findIndex(
(com) =>
com.role.name === change.role.name &&
com.product === change.product
);
if (index < 0) {
changes.push(change); // add new
} else if (original?.ratePerProduct === change.ratePerProduct) {
changes.splice(index, 1); // remove change if it is the same as original value
} else {
changes[index] = { ...changes[index], ...change }; // update already pending change
}
setPendingChanges(changes);
};
const save = async () => {
setSubmitState(AsyncState.Loading);
await CommissionService.setCommissions(pendingChanges).then(
(responseState) => {
setSubmitState(responseState.state);
if (responseState.state === AsyncState.Success) {
setSaveMessage("Changes Saved " + moment().format("LTS"));
setPendingChanges([]);
dispatch(getAllCommissions());
} else {
setSaveMessage(responseState.data ?? "");
}
}
);
};
const canSave = () => {
return (
(submitState === AsyncState.Inactive ||
submitState === AsyncState.Success) &&
isValidChanges(pendingChanges) &&
pendingChanges.length > 0
);
};
return (
<>
<div className="d-flex justify-content-end align-items-center">
<span className="mr-2" data-test="commission-save-span">
{saveMessage}
</span>
<button
data-test="commission-save-btn"
className="btn btn-outline-success my-2"
onClick={save}
type="button"
disabled={!canSave()}
>
Save
</button>
</div>
{commissionsState.commissions.state &&
commissionsState.commissions.data &&
rolesWithCommissions.length &&
productsWithCommissions.length ? (
<CommissionRatesTable
commissions={commissions}
roles={rolesWithCommissions}
products={productsWithCommissions}
onRateChange={changeRate}
/>
) : (
<div data-test="commissions-wait">Please Wait... </div>
)}
</>
);
};
export default CommissionRatesEditor;