skip to Main Content

I wrote a hook to calculate sales based on month to set data for chart.

its work fine, but I’m not satisfied.

is there a different or easy way to avoid repeating and make code clean and extendable!

note: I’m not working with companies or team – ( self learning )

i want to calculate the total per day in the month and return new array of objects

Function:



const month = (date) => new Date(date).toLocaleString('default', { month: 'long' });

export const useGetChartData = (orders) => {

  const orderTotal = orders.length
  const orderTotalsArray = orders.map(order => (+order.total) + (+order.total_tax));
  const sumOrders = orderTotalsArray?.reduce((inc, a) => inc + a, 0);
  const getMonthFromDateAndTotals = orders?.map(order => (
    {
      date: (order.date_paid ? month(order.date_paid) : month(order.date_modified)),
      total: +order.total + +order.total_tax
    }));

  const sendToChart = getMonthFromDateAndTotals.filter(o => o.total > 0);
  //filter!
  const January = sendToChart.filter((d) => d.date == 'January')
  const February = sendToChart.filter((d) => d.date == 'February')
  const March = sendToChart.filter((d) => d.date == 'March')
  const April = sendToChart.filter((d) => d.date == 'April')
  const May = sendToChart.filter((d) => d.date == 'May')
  const June = sendToChart.filter((d) => d.date == 'June')
  const July = sendToChart.filter((d) => d.date == 'July')
  const August = sendToChart.filter((d) => d.date == 'August')
  const September = sendToChart.filter((d) => d.date == 'September')
  const October = sendToChart.filter((d) => d.date == 'October')
  const November = sendToChart.filter((d) => d.date == 'November')
  const December = sendToChart.filter((d) => d.date == 'December')
  // 
  const totalsPerMonths = [
    //reduce! 
    { month: 'January', total: January?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'February', total: February?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'March', total: March?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'April', total: April?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'May', total: May?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'June', total: June?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'July', total: July?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'August', total: August?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'September', total: September?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'October', total: October?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'November', total: November?.reduce((inc, a) => inc + a.total, 0) },
    { month: 'December', total: December?.reduce((inc, a) => inc + a.total, 0) },
    // 
  ];

  const dataVisualizationToChart = totalsPerMonths.filter(vd => vd.total > 0);
  return {
    dataVisualizationToChart,
    orderTotal,
    sumOrders
  };
};

usage:

  const { data: orders, isLoading: ordersLoading, errors: orderErrors} = useGetShopData("orders");
  const { dataVisualizationToChart, sumOrders } = useGetChartData(orders)

Return :

{
  "dataVisualizationToChart": [
    {"month": "February","total": 1875.96},
    { "month": "March", "total": 1362.46},
    { "month": "April","total": 66.05000000000004},
  ],
  "orderTotal": 70,
  "sumOrders": 13064
}```



2

Answers


  1. I would suggest something like this:

    Create the monthNames object: Mapping numerical values of months to string names.

    const monthNames = {
    '01': 'January',
    '02': 'February',
    '03': 'March',
    '04': 'April',
    '05': 'May',
    '06': 'June',
    '07': 'July',
    '08': 'August',
    '09': 'September',
    '10': 'October',
    '11': 'November',
    '12': 'December'
    };
    

    Instead of creating individual arrays for each month and then calculating the totals, I used reduce to group totals by month in a single pass.

    The result of totalsPerMonths will be an object where the keys are unique dates (months) and the values are the total sums for each month.

    const totalsPerMonths = sendToChart.reduce((acc, current) => {
        if (!acc[current.date]) {
            acc[current.date] = 0;
        }
        acc[current.date] += current.total;
        return acc;
    }, {});
    

    Here, I extracted the numeric value of the month into a string name using the monthNames mapping.

    After reducing, I constructed the dataVisualizationToChart by iterating over the keys of the grouped and reduced object.

    const dataVisualizationToChart = Object.keys(totalsPerMonths).map(dateStr => {
        const [year, month] = dateStr.split('-');
        return {
            month: monthNames[month],
            total: totalsPerMonths[dateStr]
        };
    });
    

    I hope my solution helps you!

    I’d suggest you work on problems related to arrays and result aggregation on LeetCode. It really helps with solving similar tasks in the future!

    Login or Signup to reply.
  2. Use Map.groupBy() to group by the date, then sum each total when mapping to an array using Array.from(). You also don’t need a final .filter() here as months that don’t exist won’t exist in the resulting array, so no need to filter them out of the result like you’re currently doing:

    const dataVisualizationToChart = Array.from(
      Map.groupBy(sendToChart, order => order.date),
      ([month, totals]) => ({
        month,
        total: totals.reduce((inc, a) => inc + a.total, 0)
      })
    );
    

    See working example below:

    const sendToChart = [ {date: 'January', total: 1}, {date: 'January', total: 2}, {date: 'January', total: 3}, {date: 'February', total: 1}, {date: 'February', total: 1}, {date: 'May', total: 2}, {date: 'May', total: 5}, {date: 'June', total: 1} ];
    
    const dataVisualizationToChart = Array.from(
      Map.groupBy(sendToChart, order => order.date),
      ([month, totals]) => ({
        month,
        total: totals.reduce((inc, a) => inc + a.total, 0)
      })
    );
    
    console.log(dataVisualizationToChart);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search