feat: expenses in statistics
This commit is contained in:
@@ -6,6 +6,7 @@ export type ProfitChartDataItem = {
|
|||||||
date: string;
|
date: string;
|
||||||
revenue: number;
|
revenue: number;
|
||||||
profit: number;
|
profit: number;
|
||||||
|
expenses: number;
|
||||||
dealsCount: number;
|
dealsCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type ProfitTableDataItem = {
|
|||||||
groupedValue: (string | number);
|
groupedValue: (string | number);
|
||||||
revenue: number;
|
revenue: number;
|
||||||
profit: number;
|
profit: number;
|
||||||
|
expenses?: (number | null);
|
||||||
dealsCount: number;
|
dealsCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export const ProfitChart = () => {
|
|||||||
[
|
[
|
||||||
{ name: "profit", label: "Прибыль", color: "indigo.6" },
|
{ name: "profit", label: "Прибыль", color: "indigo.6" },
|
||||||
{ name: "revenue", label: "Выручка", color: "teal.6" },
|
{ name: "revenue", label: "Выручка", color: "teal.6" },
|
||||||
|
{ name: "expenses", label: "Расходы", color: "red.6" },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ name: "dealsCount", label: "Количество сделок", color: "indigo.6" },
|
{ name: "dealsCount", label: "Количество сделок", color: "indigo.6" },
|
||||||
@@ -34,6 +35,8 @@ export const ProfitChart = () => {
|
|||||||
|
|
||||||
const units = ["₽", "шт"];
|
const units = ["₽", "шт"];
|
||||||
|
|
||||||
|
const chartSizes = ["42vh", "28vh"];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["profit-chart-container"]}>
|
<div className={styles["profit-chart-container"]}>
|
||||||
<Total profitData={profitData} />
|
<Total profitData={profitData} />
|
||||||
@@ -42,13 +45,13 @@ export const ProfitChart = () => {
|
|||||||
form={form}
|
form={form}
|
||||||
/>
|
/>
|
||||||
<Skeleton visible={isLoading}>
|
<Skeleton visible={isLoading}>
|
||||||
<Stack gap={"xl"}>
|
<Stack gap="20px">
|
||||||
{getChartsSeries.map((series, idx) => {
|
{getChartsSeries.map((series, idx) => {
|
||||||
return (
|
return (
|
||||||
<AreaChart
|
<AreaChart
|
||||||
my={"sm"}
|
my={"sm"}
|
||||||
w={"98%"}
|
w={"98%"}
|
||||||
h={"34vh"}
|
h={chartSizes[idx]}
|
||||||
data={formattedProfitData}
|
data={formattedProfitData}
|
||||||
dataKey="date"
|
dataKey="date"
|
||||||
unit={units[idx]}
|
unit={units[idx]}
|
||||||
|
|||||||
@@ -19,6 +19,28 @@ export const useProfitTableColumns = ({ groupTableBy }: Props) => {
|
|||||||
[GroupStatisticsTable.BY_MANAGERS]: "Менеджер",
|
[GroupStatisticsTable.BY_MANAGERS]: "Менеджер",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getConditionalColumns = (): MRT_ColumnDef<ProfitTableDataItem>[] => {
|
||||||
|
if (groupTableBy === GroupStatisticsTable.BY_DATES) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
accessorKey: "revenue",
|
||||||
|
header: "Выручка",
|
||||||
|
Cell: ({ row }) =>
|
||||||
|
row.original.revenue.toLocaleString("ru-RU") + "₽",
|
||||||
|
size: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "expenses",
|
||||||
|
header: "Расходы",
|
||||||
|
Cell: ({ row }) =>
|
||||||
|
row.original.expenses?.toLocaleString("ru-RU") + "₽",
|
||||||
|
size: 50,
|
||||||
|
}
|
||||||
|
] as MRT_ColumnDef<ProfitTableDataItem>[];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
return useMemo<MRT_ColumnDef<ProfitTableDataItem>[]>(
|
return useMemo<MRT_ColumnDef<ProfitTableDataItem>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -35,13 +57,14 @@ export const useProfitTableColumns = ({ groupTableBy }: Props) => {
|
|||||||
}
|
}
|
||||||
return row.original.groupedValue;
|
return row.original.groupedValue;
|
||||||
},
|
},
|
||||||
size: 60,
|
size: groupTableBy === GroupStatisticsTable.BY_DATES ? 40 : 80,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "dealsCount",
|
accessorKey: "dealsCount",
|
||||||
header: "Кол-во",
|
header: "Кол-во",
|
||||||
size: 40,
|
size: 40,
|
||||||
},
|
},
|
||||||
|
...getConditionalColumns(),
|
||||||
{
|
{
|
||||||
accessorKey: "profit",
|
accessorKey: "profit",
|
||||||
header: "Прибыль",
|
header: "Прибыль",
|
||||||
@@ -49,13 +72,6 @@ export const useProfitTableColumns = ({ groupTableBy }: Props) => {
|
|||||||
row.original.profit.toLocaleString("ru-RU") + "₽",
|
row.original.profit.toLocaleString("ru-RU") + "₽",
|
||||||
size: 50,
|
size: 50,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorKey: "revenue",
|
|
||||||
header: "Выручка",
|
|
||||||
Cell: ({ row }) =>
|
|
||||||
row.original.revenue.toLocaleString("ru-RU") + "₽",
|
|
||||||
size: 50,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
[groupTableBy],
|
[groupTableBy],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,14 +7,18 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const Total = ({ profitData }: Props) => {
|
export const Total = ({ profitData }: Props) => {
|
||||||
const totalProfit = profitData.reduce(
|
|
||||||
(sum, dataItem) => dataItem.profit + sum,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
const totalRevenue = profitData.reduce(
|
const totalRevenue = profitData.reduce(
|
||||||
(sum, dataItem) => dataItem.revenue + sum,
|
(sum, dataItem) => dataItem.revenue + sum,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
const totalExpense = profitData.reduce(
|
||||||
|
(sum, dataItem) => dataItem.expenses + sum,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
const totalProfit = profitData.reduce(
|
||||||
|
(sum, dataItem) => dataItem.profit + sum,
|
||||||
|
0,
|
||||||
|
);
|
||||||
const totalCount = profitData.reduce(
|
const totalCount = profitData.reduce(
|
||||||
(sum, dataItem) => dataItem.dealsCount + sum,
|
(sum, dataItem) => dataItem.dealsCount + sum,
|
||||||
0,
|
0,
|
||||||
@@ -23,15 +27,19 @@ export const Total = ({ profitData }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<PageBlock style={{ padding: "25px", height: "7vh", flexGrow: 0 }}>
|
<PageBlock style={{ padding: "25px", height: "7vh", flexGrow: 0 }}>
|
||||||
<Group gap={2} justify={"space-between"}>
|
<Group gap={2} justify={"space-between"}>
|
||||||
<Center w={"30%"}>
|
<Center w={"24%"}>
|
||||||
<Text>Прибыль: {new Intl.NumberFormat("ru-RU").format(totalProfit)} ₽</Text>
|
|
||||||
</Center>
|
|
||||||
<Divider size={"md"} orientation="vertical" />
|
|
||||||
<Center w={"30%"}>
|
|
||||||
<Text>Выручка: {new Intl.NumberFormat("ru-RU").format(totalRevenue)} ₽</Text>
|
<Text>Выручка: {new Intl.NumberFormat("ru-RU").format(totalRevenue)} ₽</Text>
|
||||||
</Center>
|
</Center>
|
||||||
<Divider size={"md"} orientation="vertical" />
|
<Divider size={"md"} orientation="vertical" />
|
||||||
<Center w={"30%"}>
|
<Center w={"24%"}>
|
||||||
|
<Text>Расходы: {new Intl.NumberFormat("ru-RU").format(totalExpense)} ₽</Text>
|
||||||
|
</Center>
|
||||||
|
<Divider size={"md"} orientation="vertical" />
|
||||||
|
<Center w={"24%"}>
|
||||||
|
<Text>Прибыль: {new Intl.NumberFormat("ru-RU").format(totalProfit)} ₽</Text>
|
||||||
|
</Center>
|
||||||
|
<Divider size={"md"} orientation="vertical" />
|
||||||
|
<Center w={"24%"}>
|
||||||
<Text>Сделок: {new Intl.NumberFormat("ru-RU").format(totalCount)} шт</Text>
|
<Text>Сделок: {new Intl.NumberFormat("ru-RU").format(totalCount)} шт</Text>
|
||||||
</Center>
|
</Center>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
Reference in New Issue
Block a user