web: round values and add average
This commit is contained in:
@@ -57,7 +57,7 @@ export function ReportBarChart({ data }: ReportBarChartProps) {
|
|||||||
footer: (info) => info.column.id,
|
footer: (info) => info.column.id,
|
||||||
size: width ? width * 0.3 : undefined,
|
size: width ? width * 0.3 : undefined,
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor((row) => row.totalCount, {
|
columnHelper.accessor((row) => row.metrics.total, {
|
||||||
id: 'totalCount',
|
id: 'totalCount',
|
||||||
cell: (info) => (
|
cell: (info) => (
|
||||||
<div className="text-right font-medium">{info.getValue()}</div>
|
<div className="text-right font-medium">{info.getValue()}</div>
|
||||||
@@ -67,7 +67,7 @@ export function ReportBarChart({ data }: ReportBarChartProps) {
|
|||||||
size: width ? width * 0.1 : undefined,
|
size: width ? width * 0.1 : undefined,
|
||||||
enableSorting: true,
|
enableSorting: true,
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor((row) => row.totalCount, {
|
columnHelper.accessor((row) => row.metrics.total, {
|
||||||
id: 'graph',
|
id: 'graph',
|
||||||
cell: (info) => (
|
cell: (info) => (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ export function ReportTable({
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className={cn('w-max', row)}>
|
<div className={cn('w-max', row)}>
|
||||||
<div className={cn(header, value, cell, total)}>Total</div>
|
<div className={cn(header, value, cell, total)}>Total</div>
|
||||||
|
<div className={cn(header, value, cell, total)}>Average</div>
|
||||||
{data.series[0]?.data.map((serie) => (
|
{data.series[0]?.data.map((serie) => (
|
||||||
<div
|
<div
|
||||||
key={serie.date.toString()}
|
key={serie.date.toString()}
|
||||||
@@ -112,7 +113,10 @@ export function ReportTable({
|
|||||||
return (
|
return (
|
||||||
<div className={cn('w-max', row)} key={serie.name}>
|
<div className={cn('w-max', row)} key={serie.name}>
|
||||||
<div className={cn(header, value, cell, total)}>
|
<div className={cn(header, value, cell, total)}>
|
||||||
{serie.totalCount}
|
{serie.metrics.total}
|
||||||
|
</div>
|
||||||
|
<div className={cn(header, value, cell, total)}>
|
||||||
|
{serie.metrics.average}
|
||||||
</div>
|
</div>
|
||||||
{serie.data.map((item) => {
|
{serie.data.map((item) => {
|
||||||
return (
|
return (
|
||||||
@@ -127,9 +131,13 @@ export function ReportTable({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div>Summary</div>
|
<div>Total</div>
|
||||||
<div>
|
<div>
|
||||||
{data.series.reduce((acc, serie) => serie.totalCount + acc, 0)}
|
{data.series.reduce((acc, serie) => serie.metrics.total + acc, 0)}
|
||||||
|
</div>
|
||||||
|
<div>Average</div>
|
||||||
|
<div>
|
||||||
|
{data.series.reduce((acc, serie) => serie.metrics.average + acc, 0)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import type {
|
|||||||
IInterval,
|
IInterval,
|
||||||
} from '@/types';
|
} from '@/types';
|
||||||
import { getDaysOldDate } from '@/utils/date';
|
import { getDaysOldDate } from '@/utils/date';
|
||||||
|
import { average, isFloat, round, sum } from '@/utils/math';
|
||||||
import { toDots } from '@/utils/object';
|
import { toDots } from '@/utils/object';
|
||||||
import { zChartInputWithDates } from '@/utils/validation';
|
import { zChartInputWithDates } from '@/utils/validation';
|
||||||
import { last, pipe, sort, uniq } from 'ramda';
|
import { last, pipe, sort, uniq } from 'ramda';
|
||||||
@@ -141,13 +142,13 @@ export const chartRouter = createTRPCRouter({
|
|||||||
const sumB = b.data.reduce((acc, item) => acc + item.count, 0);
|
const sumB = b.data.reduce((acc, item) => acc + item.count, 0);
|
||||||
return sumB - sumA;
|
return sumB - sumA;
|
||||||
} else {
|
} else {
|
||||||
return b.totalCount - a.totalCount;
|
return b.metrics.total - a.metrics.total;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
highest: sorted[0]?.totalCount ?? 0,
|
highest: sorted[0]?.metrics.total ?? 0,
|
||||||
lowest: last(sorted)?.totalCount ?? 0,
|
lowest: last(sorted)?.metrics.total ?? 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -155,9 +156,9 @@ export const chartRouter = createTRPCRouter({
|
|||||||
series.reduce(
|
series.reduce(
|
||||||
(acc, item) => {
|
(acc, item) => {
|
||||||
if (acc[item.event.id]) {
|
if (acc[item.event.id]) {
|
||||||
acc[item.event.id] += item.totalCount;
|
acc[item.event.id] += item.metrics.total;
|
||||||
} else {
|
} else {
|
||||||
acc[item.event.id] = item.totalCount;
|
acc[item.event.id] = item.metrics.total;
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
@@ -215,14 +216,6 @@ function getEventLegend(event: IChartEvent) {
|
|||||||
return `${event.name} (${event.id})`;
|
return `${event.name} (${event.id})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTotalCount(arr: ResultItem[]) {
|
|
||||||
return arr.reduce((acc, item) => acc + item.count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFloat(n: number) {
|
|
||||||
return n % 1 !== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDatesFromRange(range: IChartRange) {
|
function getDatesFromRange(range: IChartRange) {
|
||||||
if (range === 0) {
|
if (range === 0) {
|
||||||
const startDate = new Date();
|
const startDate = new Date();
|
||||||
@@ -488,14 +481,17 @@ async function getChartData({
|
|||||||
id: event.id,
|
id: event.id,
|
||||||
name: event.name,
|
name: event.name,
|
||||||
},
|
},
|
||||||
totalCount: getTotalCount(data),
|
metrics: {
|
||||||
|
total: sum(data.map((item) => item.count)),
|
||||||
|
average: round(average(data.map((item) => item.count))),
|
||||||
|
},
|
||||||
data:
|
data:
|
||||||
chartType === 'linear'
|
chartType === 'linear'
|
||||||
? fillEmptySpotsInTimeline(data, interval, startDate, endDate).map(
|
? fillEmptySpotsInTimeline(data, interval, startDate, endDate).map(
|
||||||
(item) => {
|
(item) => {
|
||||||
return {
|
return {
|
||||||
label: legend,
|
label: legend,
|
||||||
count: item.count,
|
count: round(item.count),
|
||||||
date: new Date(item.date).toISOString(),
|
date: new Date(item.date).toISOString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
12
apps/web/src/utils/math.ts
Normal file
12
apps/web/src/utils/math.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export const round = (num: number, decimals = 2) => {
|
||||||
|
const factor = Math.pow(10, decimals);
|
||||||
|
return Math.round((num + Number.EPSILON) * factor) / factor;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const average = (arr: number[]) =>
|
||||||
|
arr.reduce((p, c) => p + c, 0) / arr.length;
|
||||||
|
|
||||||
|
export const sum = (arr: number[]) =>
|
||||||
|
round(arr.reduce((acc, item) => acc + item, 0));
|
||||||
|
|
||||||
|
export const isFloat = (n: number) => n % 1 !== 0;
|
||||||
Reference in New Issue
Block a user