@rsc-labs/medusa-store-analytics-v2
Version:
Get analytics data about your store
217 lines (216 loc) • 9.95 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { Text, Container, Heading } from "@medusajs/ui";
import { calculateResolution, getChartDateName, getLegendName, compareDatesBasedOnResolutionType, ChartResolutionType, getChartTooltipDate } from "./utils/chartUtils.js";
import { AreaChart, CartesianGrid, XAxis, YAxis, Tooltip, Area, Legend } from "recharts";
import { useState, useEffect } from "react";
import { Box, Grid } from "@mui/material";
const incrementDate = (date, resolutionType) => {
switch (resolutionType) {
case ChartResolutionType.DayMonth:
date.setDate(date.getDate() + 1);
break;
case ChartResolutionType.Month:
date.setMonth(date.getMonth() + 1);
break;
default:
date.setDate(date.getDate() + 1);
}
};
const generateChartData = (data, fromDate, toDate, chartResolutionType, toCompareDate, connectEmptyPointsUsingPreviousValue) => {
const currentData = data.current;
const previousData = data.previous;
const startFromDate = new Date(fromDate);
const offsetTime = toDate.getTime() - (toCompareDate ? toCompareDate.getTime() : fromDate.getTime());
const dataPoints = [];
let currentDataValue;
let previousDataValue;
while (startFromDate.getTime() < toDate.getTime() || compareDatesBasedOnResolutionType(startFromDate, toDate, chartResolutionType)) {
const currentOrder = currentData.find((order) => compareDatesBasedOnResolutionType(new Date(order.date), startFromDate, chartResolutionType));
const offsetDate = new Date(startFromDate);
offsetDate.setTime(offsetDate.getTime() - offsetTime);
const previousOrder = previousData.find((previous) => compareDatesBasedOnResolutionType(new Date(previous.date), offsetDate, chartResolutionType));
if (connectEmptyPointsUsingPreviousValue) {
if (currentOrder) {
currentDataValue = parseInt(currentOrder.value);
}
if (previousOrder) {
previousDataValue = parseInt(previousOrder.value);
}
dataPoints.push({
current: {
date: new Date(startFromDate),
value: currentOrder ? parseInt(currentOrder.value) : currentDataValue ? currentDataValue : void 0
},
previous: {
date: new Date(offsetDate),
value: previousOrder ? parseInt(previousOrder.value) : previousDataValue ? previousDataValue : void 0
}
});
} else {
dataPoints.push({
current: {
date: new Date(startFromDate),
value: currentOrder ? parseInt(currentOrder.value) : 0
},
previous: {
date: new Date(offsetDate),
value: previousOrder ? parseInt(previousOrder.value) : 0
}
});
}
incrementDate(startFromDate, chartResolutionType);
}
if (connectEmptyPointsUsingPreviousValue) {
for (let i = dataPoints.length - 1; i >= 0; i--) {
if (dataPoints[i].current.value === void 0) {
if (dataPoints[dataPoints.length - 1].previous.value) {
dataPoints[i].current.value = dataPoints[dataPoints.length - 1].previous.value;
} else {
dataPoints[i].current.value = 0;
}
}
if (dataPoints[i].previous.value) {
previousDataValue = dataPoints[i].previous.value;
} else {
dataPoints[i].previous.value = previousDataValue;
}
}
}
return dataPoints;
};
const ChartCustomTooltip = ({ active, payload, label, resolutionType }) => {
if (active && payload && payload.length) {
switch (resolutionType) {
case ChartResolutionType.DayMonth:
return /* @__PURE__ */ jsxs(Container, { children: [
/* @__PURE__ */ jsxs(Heading, { level: "h3", style: { color: payload[0].color }, children: [
`${getChartTooltipDate(payload[0].payload.current.date, resolutionType)}`,
" : ",
payload[0].payload.current.value
] }),
payload[1] !== void 0 && /* @__PURE__ */ jsxs(Heading, { level: "h3", style: { color: payload[1].color }, children: [
`${getChartTooltipDate(payload[1].payload.previous.date, resolutionType)}`,
" : ",
payload[1].payload.previous.value
] })
] });
case ChartResolutionType.Month:
return /* @__PURE__ */ jsxs(Container, { children: [
/* @__PURE__ */ jsxs(Heading, { level: "h3", style: { color: payload[0].color }, children: [
`${getChartTooltipDate(payload[0].payload.current.date, resolutionType)}`,
" : ",
payload[0].payload.current.value
] }),
payload[1] !== void 0 && /* @__PURE__ */ jsxs(Heading, { level: "h3", style: { color: payload[1].color }, children: [
`${getChartTooltipDate(payload[1].payload.previous.date, resolutionType)}`,
" : ",
payload[1].payload.previous.value
] })
] });
}
}
return null;
};
const areRangesTheSame = (fromDate, toDate, fromCompareDate, toCompareDate) => {
function isToday(date) {
const today = /* @__PURE__ */ new Date();
today.setHours(0, 0, 0, 0);
const givenDate = new Date(date);
givenDate.setHours(0, 0, 0, 0);
return today.getTime() === givenDate.getTime();
}
if (fromCompareDate) {
const oneDay = 24 * 60 * 60 * 1e3;
if (toCompareDate) {
if (isToday(toDate)) {
const diffBase3 = Math.ceil(Math.abs((toDate.getTime() - fromDate.getTime()) / oneDay));
const diffCompare3 = Math.round(Math.abs((toCompareDate.getTime() - fromCompareDate.getTime()) / oneDay));
return diffBase3 == diffCompare3;
}
const diffBase2 = Math.round(Math.abs((toDate.getTime() - fromDate.getTime()) / oneDay));
const diffCompare2 = Math.round(Math.abs((toCompareDate.getTime() - fromCompareDate.getTime()) / oneDay));
return diffBase2 == diffCompare2;
}
const diffBase = Math.ceil(Math.abs((toDate.getTime() - fromDate.getTime()) / oneDay));
const diffCompare = Math.ceil(Math.abs((Date.now() - fromCompareDate.getTime()) / oneDay));
return diffBase == diffCompare;
}
return true;
};
const ChartCurrentPrevious = ({ rawChartData, fromDate, toDate, fromCompareDate, toCompareDate, compareEnabled, connectEmptyPointsUsingPreviousValue }) => {
const [chartDataPoints, setChartData] = useState([]);
const resolutionType = calculateResolution(fromDate, toDate);
useEffect(() => {
const chartDataPoints2 = generateChartData(
rawChartData,
fromDate,
toDate,
resolutionType,
toCompareDate,
connectEmptyPointsUsingPreviousValue
);
setChartData(chartDataPoints2);
}, [rawChartData, fromDate, toDate]);
if (!areRangesTheSame(fromDate, toDate, fromCompareDate, toCompareDate)) {
const currentPeriodInDays = Math.ceil((toDate.getTime() - fromDate.getTime()) / (24 * 60 * 60 * 1e3));
let precedingPeriodInDays = 0;
if (fromCompareDate) {
if (toCompareDate) {
precedingPeriodInDays = Math.ceil((toCompareDate.getTime() - fromCompareDate.getTime()) / (24 * 60 * 60 * 1e3));
} else {
precedingPeriodInDays = Math.ceil((new Date(Date.now()).getTime() - fromCompareDate.getTime()) / (24 * 60 * 60 * 1e3));
}
}
return /* @__PURE__ */ jsx(
Box,
{
width: 500,
height: 400,
display: "flex",
alignItems: "center",
justifyContent: "center",
children: /* @__PURE__ */ jsxs(Grid, { container: true, direction: "column", justifyContent: "center", alignItems: "center", children: [
/* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Text, { children: "Chart can be shown only for the same length of ranges." }) }),
/* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Text, { children: `You are comparing ${currentPeriodInDays} days to ${precedingPeriodInDays} days` }) })
] })
}
);
}
return /* @__PURE__ */ jsxs(
AreaChart,
{
width: 500,
height: 400,
data: chartDataPoints,
margin: {
top: 20,
right: 0,
left: 0,
bottom: 0
},
children: [
/* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3" }),
/* @__PURE__ */ jsxs("defs", { children: [
/* @__PURE__ */ jsxs("linearGradient", { id: "colorPrevious", x1: "0", y1: "0", x2: "0", y2: "1", children: [
/* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: "#8884d8", stopOpacity: 0.8 }),
/* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: "#8884d8", stopOpacity: 0 })
] }),
/* @__PURE__ */ jsxs("linearGradient", { id: "colorCurrent", x1: "0", y1: "0", x2: "0", y2: "1", children: [
/* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: "#82ca9d", stopOpacity: 0.8 }),
/* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: "#82ca9d", stopOpacity: 0 })
] })
] }),
/* @__PURE__ */ jsx(XAxis, { dataKey: (value) => getChartDateName(value.current.date, resolutionType, fromDate, toDate), minTickGap: 15, interval: "preserveStartEnd" }),
/* @__PURE__ */ jsx(YAxis, {}),
/* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(ChartCustomTooltip, { active: false, payload: [], label: "", resolutionType }) }),
/* @__PURE__ */ jsx(Area, { name: compareEnabled && fromCompareDate ? getLegendName(true) : void 0, type: "monotone", dataKey: "current.value", stroke: "#82ca9d", fillOpacity: 1, fill: "url(#colorCurrent)" }),
compareEnabled && fromCompareDate && /* @__PURE__ */ jsx(Area, { name: getLegendName(false), type: "monotone", dataKey: "previous.value", stroke: "#8884d8", fillOpacity: 1, fill: "url(#colorPrevious)" }),
compareEnabled && fromCompareDate && /* @__PURE__ */ jsx(Legend, { verticalAlign: "bottom", height: 36, iconType: "circle" })
]
}
);
};
export {
ChartCurrentPrevious,
ChartCustomTooltip
};