UNPKG

@rsc-labs/medusa-store-analytics-v2

Version:
189 lines (182 loc) 25.3 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) => { function isToday(date) { const today = 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 * 1000; if (toCompareDate) { // Cover situation when toDate is today so gives jsut couple of hours while we need the whole day. if (isToday(toDate)) { const diffBase = Math.ceil(Math.abs((toDate.getTime() - fromDate.getTime()) / oneDay)); const diffCompare = Math.round(Math.abs((toCompareDate.getTime() - fromCompareDate.getTime()) / oneDay)); return (diffBase == diffCompare); } const diffBase = Math.round(Math.abs((toDate.getTime() - fromDate.getTime()) / oneDay)); const diffCompare = Math.round(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)); let precedingPeriodInDays = 0; if (fromCompareDate) { if (toCompareDate) { precedingPeriodInDays = Math.ceil((toCompareDate.getTime() - fromCompareDate.getTime()) / (24 * 60 * 60 * 1000)); } else { precedingPeriodInDays = Math.ceil((new Date(Date.now()).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; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQtY29tcG9uZW50cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy91aS1jb21wb25lbnRzL2NvbW1vbi9jaGFydC1jb21wb25lbnRzLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUE7Ozs7Ozs7Ozs7R0FVRztBQUVILHFDQUF3RDtBQUN4RCxtREFBdUs7QUFDdkssdUNBQXdGO0FBQ3hGLGlDQUE0QztBQUM1Qyw0Q0FBMEM7QUF3QjFDLE1BQU0sYUFBYSxHQUFHLENBQUMsSUFBVSxFQUFFLGNBQW1DLEVBQUUsRUFBRTtJQUN4RSxRQUFRLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssZ0NBQW1CLENBQUMsUUFBUTtZQUMvQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNqQyxNQUFNO1FBQ1IsS0FBSyxnQ0FBbUIsQ0FBQyxLQUFLO1lBQzVCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ25DLE1BQU07UUFDUjtZQUNFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLGlCQUFpQixHQUFHLENBQ3hCLElBQW1CLEVBQ25CLFFBQWMsRUFDZCxNQUFZLEVBQ1osbUJBQXdDLEVBQ3hDLGFBQW9CLEVBQ3BCLG9DQUE4QyxFQUMzQixFQUFFO0lBRXJCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDakMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUVuQyxNQUFNLGFBQWEsR0FBRyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsT0FBTyxF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