javascriptreactjsmantine

How to fix calculation dynamically in Reactjs


When we calculate the distributor's percentage of several records and each value is rounded to 2 decimal places, it may be that the sum of all records is different from 100.00% (example: 99.97%, 100.02%).

However, for the Distributor the important thing is that the sum of all records totals 100%.

When the total record is different from 100%, a "Reach 100%" button must be enabled. Then the BIGGEST records must be adjusted by 0.01% (more or less) until the total value of all records is 100%.

When the sum of records is equal to, for example, 100.05%, 0.01% of the records that received the highest values must be reduced (in this case, 0.01% will be reduced from 5 records that have the highest percentages in the list ).

When the sum of records is equal to, for example, 99.97%, 0.01% of the records that received the highest values must be increased (in this case, 0.01% of 3 records that have the highest percentages in the list will be increased ).

When you do the calculation on the calculator with the Distribution Percentage fields, they are also 99.99% or 100.02%, for example. Adding these calculated data, they also need to reach 100%.

In other words, when you click on the "Reach 100%" button, both the calculations in the Distribution Percentage column and the Total column must reach 100%.

You can test the scenario accordingly by selecting the records.

Can you help me with this calculation? I couldn't solve it at all.

Example in codesandbox: https://codesandbox.io/s/laughing-buck-j4hr87?file=/src/App.js


Solution

  • If i understood your question correctly what you need to do is add a click listener to the button and inside that you can do calculation of what the current difference is. Based on this you can update your calculation until you get 100 percent match.

    Here is an kind of function you need:

    const updateCalculation = (id, amount) => {
        setSelectedDataCalculation((prevCalc) =>
          prevCalc.map((prev) => {
            if (prev.id === id) {
              return {
                ...prev,
                distributionPercentage: prev.distributionPercentage + amount
              };
            }
            return prev;
          })
        );
      };
    
      const reach100 = () => {
        if (selectedDataCalculation.length) {
          const adjustAmount = 0.01;
          let diff = parseFloat((100 - totalPercentage).toFixed(2));
          while (diff !== 0) {
            let maxAmount = 0;
            const maxCalculationId = selectedDataCalculation.reduce((acc, calc) => {
              if (calc.distributionPercentage > maxAmount) {
                maxAmount = calc.distributionPercentage;
                return calc.id;
              }
              return acc;
            }, 0);
    
            if (diff > 0) {
              updateCalculation(maxCalculationId, adjustAmount);
              diff = diff - adjustAmount;
            } else {
              updateCalculation(maxCalculationId, -adjustAmount);
              diff = diff + adjustAmount;
            }
          }
        }
      };
    

    Here you need to add button click event to reach100 function.

    Note: I just wrote this based on scenarios you given. Please test this and alter based on your scenario. This code could have unknown bugs.

    Here is the link with above code added: https://codesandbox.io/s/eager-monad-yvtwkd?file=/src/App.js

    Hope that helps!