Как вернуть сумму месяца на основе дат в JavaScript (React)

Я написал крючок для расчета продаж на основе данных за месяц для диаграммы.

Работает нормально, но я не доволен.

Есть ли другой или простой способ избежать повторения и сделать код чистым и расширяемым?

примечание: я не работаю с компаниями или командами - (самообучение)

Я хочу подсчитать сумму за день в месяце и вернуть новый массив объектов.

Функция:



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
  };
};

Применение:

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

Возвращаться :

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



Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я бы предложил что-то вроде этого:

Создайте объект MonthNames: сопоставление числовых значений месяцев с именами строк.

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'
};

Вместо создания отдельных массивов для каждого месяца и последующего расчета итогов я использовал сокращение, чтобы сгруппировать итоги по месяцам за один проход.

Результатом totalsPerMonths будет объект, ключами которого являются уникальные даты (месяцы), а значениями — общие суммы за каждый месяц.

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

Здесь я извлек числовое значение месяца в строковое имя, используя сопоставление MonthNames.

После сокращения я создал dataVisualizationToChart, перебирая ключи сгруппированного и уменьшенного объекта.

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

Надеюсь, мое решение поможет вам!

Я бы посоветовал вам поработать над проблемами, связанными с массивами и агрегацией результатов, в LeetCode. Это очень помогает при решении подобных задач в будущем!

Используйте Map.groupBy() для группировки по дате, затем суммируйте каждую сумму при сопоставлении с массивом с помощью Array.from(). Вам также не нужен финальный .filter() здесь, поскольку несуществующие месяцы не будут существовать в результирующем массиве, поэтому нет необходимости фильтровать их из результата, как вы это делаете сейчас:

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

См. рабочий пример ниже:

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.info(dataVisualizationToChart);

Другие вопросы по теме