@rsc-labs/medusa-store-analytics-v2
Version:
Get analytics data about your store
189 lines (182 loc) • 25.3 kB
JavaScript
;
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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