openreplay/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/ProgressBarChart.tsx
Sudheer Salavadi 488dfcd849
Various improvements in graphs, and analytics pages. (#2908)
* Various improvements Cards, OmniSearch and Cards  Listing

* Improved cards listing page

* Various improvements in product analytics

* Charts UI improvements

* ui crash

* Chart improvements and layout toggling

* Various improvements

* Tooltips

---------

Co-authored-by: nick-delirium <nikita@openreplay.com>
2024-12-24 10:44:24 +01:00

121 lines
No EOL
4 KiB
TypeScript

import React from 'react';
interface Props {
data: { chart: any[], namesMap: string[] };
compData: { chart: any[], namesMap: string[] } | null;
params: any;
colors: any;
onClick?: (event, index) => void;
yaxis?: any;
label?: string;
hideLegend?: boolean;
}
function ProgressBarChart(props: Props) {
const {
data = { chart: [], namesMap: [] },
compData = { chart: [], namesMap: [] },
colors,
onClick = () => null,
label = 'Number of Sessions',
} = props;
const getTotalForSeries = (series: string, isComp: boolean) => {
if (isComp) {
if (!compData) return 0;
return compData.chart.reduce((acc, curr) => acc + curr[series], 0);
}
return data.chart.reduce((acc, curr) => acc + curr[series], 0);
}
const formattedNumber = (num: number) => {
return Intl.NumberFormat().format(num);
}
// Group the data into pairs (original + comparison)
const groupedData: Array<{ original: any, comparison: any }> = [];
for (let i = 0; i < data.namesMap.length; i++) {
if (!data.namesMap[i]) continue;
const original = {
name: data.namesMap[i],
value: getTotalForSeries(data.namesMap[i], false),
isComp: false,
index: i
};
const comparison = compData && compData.namesMap[i] ? {
name: compData.namesMap[i],
value: getTotalForSeries(compData.namesMap[i], true),
isComp: true,
index: i
} : null;
groupedData.push({ original, comparison });
}
// Find highest value among all data points
const highest = groupedData.reduce((acc, curr) => {
const maxInGroup = Math.max(
curr.original.value,
curr.comparison ? curr.comparison.value : 0
);
return Math.max(acc, maxInGroup);
}, 0);
return (
<div className="w-full flex flex-col gap-3 ps-3 justify-center" style={{ height: 240 }}>
{groupedData.map((group, i) => (
<div key={i} className={`flex flex-col ${i < groupedData.length - 1 && group.comparison ? 'border-b border-dashed border-[0,0,0,.15] pb-3' : ''}`}>
<div className="flex items-center">
<div className="flex items-center" style={{ flex: 1 }}>
<div
className="w-4 h-4 rounded-full mr-2"
style={{ backgroundColor: colors[group.original.index] }}
/>
<span>{group.original.name}</span>
</div>
<div className="flex items-center gap-2" style={{ flex: 4 }}>
<div
style={{
height: 8,
borderRadius: 8,
backgroundColor: colors[group.original.index],
width: `${(group.original.value/highest)*100}%`
}}
/>
<div>{formattedNumber(group.original.value)}</div>
</div>
<div style={{ flex: 1 }} />
</div>
{group.comparison && (
<div className="flex items-center">
<div className="invisible flex items-center" style={{ flex: 1 }}>
<div
className="w-4 h-4 rounded-full mr-2"
style={{ backgroundColor: colors[group.comparison.index] }}
/>
<span>{group.comparison.name}</span>
</div>
<div className="flex items-center gap-2" style={{ flex: 4 }}>
<div
style={{
height: 8,
borderRadius: 8,
backgroundImage: `repeating-linear-gradient(45deg, #ffffff 0px, #ffffff 1.5px, ${colors[group.comparison.index]} 1.5px, ${colors[group.comparison.index]} 4.5px)`,
backgroundSize: '20px 20px',
width: `${(group.comparison.value/highest)*100}%`
}}
/>
<div>{formattedNumber(group.comparison.value)}</div>
</div>
<div style={{ flex: 1 }} />
</div>
)}
</div>
))}
</div>
);
}
export default ProgressBarChart;