UNPKG

@rsc-labs/medusa-store-analytics

Version:
169 lines (161 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChartCurrentPrevious = exports.ChartCustomTooltip = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); /* * Copyright 2024 RSC-Labs, https://rsoftcon.com/ * * MIT License * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const ui_1 = require("@medusajs/ui"); const chartUtils_1 = require("./utils/chartUtils"); const recharts_1 = require("recharts"); const react_1 = require("react"); const material_1 = require("@mui/material"); const incrementDate = (date, resolutionType) => { switch (resolutionType) { case chartUtils_1.ChartResolutionType.DayMonth: date.setDate(date.getDate() + 1); break; case chartUtils_1.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() || (0, chartUtils_1.compareDatesBasedOnResolutionType)(startFromDate, toDate, chartResolutionType)) { const currentOrder = currentData.find(order => (0, chartUtils_1.compareDatesBasedOnResolutionType)(new Date(order.date), startFromDate, chartResolutionType)); const offsetDate = new Date(startFromDate); offsetDate.setTime(offsetDate.getTime() - offsetTime); const previousOrder = previousData.find(previous => (0, chartUtils_1.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 : undefined), }, previous: { date: new Date(offsetDate), value: previousOrder ? parseInt(previousOrder.value) : (previousDataValue ? previousDataValue : undefined), } }); } 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 === undefined) { 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 chartUtils_1.ChartResolutionType.DayMonth: return ((0, jsx_runtime_1.jsxs)(ui_1.Container, { children: [(0, jsx_runtime_1.jsxs)(ui_1.Heading, { level: "h3", style: { color: payload[0].color }, children: [`${(0, chartUtils_1.getChartTooltipDate)(payload[0].payload.current.date, resolutionType)}`, " : ", payload[0].payload.current.value] }), payload[1] !== undefined && (0, jsx_runtime_1.jsxs)(ui_1.Heading, { level: "h3", style: { color: payload[1].color }, children: [`${(0, chartUtils_1.getChartTooltipDate)(payload[1].payload.previous.date, resolutionType)}`, " : ", payload[1].payload.previous.value] })] })); case chartUtils_1.ChartResolutionType.Month: return ((0, jsx_runtime_1.jsxs)(ui_1.Container, { children: [(0, jsx_runtime_1.jsxs)(ui_1.Heading, { level: "h3", style: { color: payload[0].color }, children: [`${(0, chartUtils_1.getChartTooltipDate)(payload[0].payload.current.date, resolutionType)}`, " : ", payload[0].payload.current.value] }), payload[1] !== undefined && (0, jsx_runtime_1.jsxs)(ui_1.Heading, { level: "h3", style: { color: payload[1].color }, children: [`${(0, chartUtils_1.getChartTooltipDate)(payload[1].payload.previous.date, resolutionType)}`, " : ", payload[1].payload.previous.value] })] })); } } return null; }; exports.ChartCustomTooltip = ChartCustomTooltip; /* toDate is inclusive. It means that: fromDate: "2024-04-24" toDate: "2024-04-30" Analytics shall include `toDate` so it takes 7 days (including 2024-04-30) fromCompareDate: "2024-04-17" toCompareDate: "2024-04-24" Analytics shall compare to 7 days excluding 2024-04-24 (e.g. 2024-04-30 is compared to 2024-04-23, not 2024-04-24). toDate is inclusive to cover "today" date - so we need to cover situation when someone wants to see everything until now. We cannot use 2024-05-01 because then it is taken as day to show, while we want to show maximum 2024-04-30. toCompareDate is exclusive because backend is using fetches like created_at < toCompareDate, so it does not cover data at toCompareDate Comparison then we will have following algorithm: 1) Take "toDate", remove "time" part and add whole day. 2) Take times in milis from every date and compare. */ const areRangesTheSame = (fromDate, toDate, fromCompareDate, toCompareDate) => { if (fromCompareDate) { const oneDay = 24 * 60 * 60 * 1000; if (toCompareDate) { // Math.ceil is used to round the day to larger value for taking the whole day for comparison const diffBase = Math.ceil(Math.abs((toDate.getTime() - fromDate.getTime()) / oneDay)); const diffCompare = Math.ceil(Math.abs((toCompareDate.getTime() - fromCompareDate.getTime()) / oneDay)); return (diffBase == diffCompare); } 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] = (0, react_1.useState)([]); const resolutionType = (0, chartUtils_1.calculateResolution)(fromDate, toDate); (0, react_1.useEffect)(() => { const chartDataPoints = generateChartData(rawChartData, fromDate, toDate, resolutionType, toCompareDate, connectEmptyPointsUsingPreviousValue); setChartData(chartDataPoints); }, [rawChartData, fromDate, toDate]); if (!areRangesTheSame(fromDate, toDate, fromCompareDate, toCompareDate)) { const currentPeriodInDays = Math.ceil((toDate.getTime() - fromDate.getTime()) / (24 * 60 * 60 * 1000)); const precedingPeriodInDays = Math.ceil((toCompareDate.getTime() - fromCompareDate.getTime()) / (24 * 60 * 60 * 1000)); return ((0, jsx_runtime_1.jsx)(material_1.Box, { width: 500, height: 400, display: "flex", alignItems: "center", justifyContent: "center", children: (0, jsx_runtime_1.jsxs)(material_1.Grid, { container: true, direction: 'column', justifyContent: 'center', alignItems: 'center', children: [(0, jsx_runtime_1.jsx)(material_1.Grid, { item: true, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Chart can be shown only for the same length of ranges." }) }), (0, jsx_runtime_1.jsx)(material_1.Grid, { item: true, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: `You are comparing ${currentPeriodInDays} days to ${precedingPeriodInDays} days` }) })] }) })); } return ((0, jsx_runtime_1.jsxs)(recharts_1.AreaChart, { width: 500, height: 400, data: chartDataPoints, margin: { top: 20, right: 0, left: 0, bottom: 0, }, children: [(0, jsx_runtime_1.jsx)(recharts_1.CartesianGrid, { strokeDasharray: "3 3" }), (0, jsx_runtime_1.jsxs)("defs", { children: [(0, jsx_runtime_1.jsxs)("linearGradient", { id: "colorPrevious", x1: "0", y1: "0", x2: "0", y2: "1", children: [(0, jsx_runtime_1.jsx)("stop", { offset: "5%", stopColor: "#8884d8", stopOpacity: 0.8 }), (0, jsx_runtime_1.jsx)("stop", { offset: "95%", stopColor: "#8884d8", stopOpacity: 0 })] }), (0, jsx_runtime_1.jsxs)("linearGradient", { id: "colorCurrent", x1: "0", y1: "0", x2: "0", y2: "1", children: [(0, jsx_runtime_1.jsx)("stop", { offset: "5%", stopColor: "#82ca9d", stopOpacity: 0.8 }), (0, jsx_runtime_1.jsx)("stop", { offset: "95%", stopColor: "#82ca9d", stopOpacity: 0 })] })] }), (0, jsx_runtime_1.jsx)(recharts_1.XAxis, { dataKey: (value) => (0, chartUtils_1.getChartDateName)(value.current.date, resolutionType, fromDate, toDate), minTickGap: 15, interval: 'preserveStartEnd' }), (0, jsx_runtime_1.jsx)(recharts_1.YAxis, {}), (0, jsx_runtime_1.jsx)(recharts_1.Tooltip, { content: (0, jsx_runtime_1.jsx)(exports.ChartCustomTooltip, { active: false, payload: [], label: "", resolutionType: resolutionType }) }), (0, jsx_runtime_1.jsx)(recharts_1.Area, { name: (compareEnabled && fromCompareDate) ? (0, chartUtils_1.getLegendName)(true) : undefined, type: "monotone", dataKey: "current.value", stroke: "#82ca9d", fillOpacity: 1, fill: "url(#colorCurrent)" }), (compareEnabled && fromCompareDate) && (0, jsx_runtime_1.jsx)(recharts_1.Area, { name: (0, chartUtils_1.getLegendName)(false), type: "monotone", dataKey: "previous.value", stroke: "#8884d8", fillOpacity: 1, fill: "url(#colorPrevious)" }), (compareEnabled && fromCompareDate) && (0, jsx_runtime_1.jsx)(recharts_1.Legend, { verticalAlign: "bottom", height: 36, iconType: "circle" })] })); }; exports.ChartCurrentPrevious = ChartCurrentPrevious;