Skip to content

Commit

Permalink
Fix grouping query and show category totals in a table
Browse files Browse the repository at this point in the history
  • Loading branch information
thaapasa committed Feb 26, 2024
1 parent 03ad106 commit 85363ce
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 23 deletions.
74 changes: 59 additions & 15 deletions src/client/ui/grouping/GroupingCategoryChart.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
import styled from '@emotion/styled';
import * as B from 'baconjs';
import * as React from 'react';
import { Cell, Legend, Pie, PieChart, Tooltip } from 'recharts';
import { Cell, Pie, PieChart, Tooltip } from 'recharts';

import { CategoryMap, ExpenseGroupingCategoryTotal, isDefined, ObjectId } from 'shared/types';
import { Money, MoneyLike } from 'shared/util';
import { categoryMapE, getFullCategoryName } from 'client/data/Categories';

import { getChartColor } from '../chart/ChartColors';
import { formatMoney } from '../chart/Format';
import { colorScheme } from '../Colors';
import { connect } from '../component/BaconConnect';
import { Row } from '../component/Row';
import { Flex } from '../Styles';

interface GroupingCategoryChartProps {
categoryMap: CategoryMap;
totals: ExpenseGroupingCategoryTotal[];
}

interface Data {
name: string;
categoryId: number;
value: MoneyLike;
color: string;
}

const GroupingCategoryChartImpl: React.FC<GroupingCategoryChartProps> = ({
totals,
categoryMap,
}) => {
const data: Data[] = React.useMemo(() => {
const colors = createColorScheme(totals, categoryMap);
const d = totals.map<Data>(t => ({
name: getFullCategoryName(t.categoryId, categoryMap),
categoryId: t.categoryId,
value: Money.from(t.sum).valueOf(),
color: colors[t.categoryId],
}));
d.sort((a, b) => {
const ca = categoryMap[a.categoryId];
Expand All @@ -43,25 +56,56 @@ const GroupingCategoryChartImpl: React.FC<GroupingCategoryChartProps> = ({
return d;
}, [totals, categoryMap]);
if (totals.length < 1) return null;
const colors = createColorScheme(totals, categoryMap);
return (
<PieChart width={450} height={168}>
<Pie data={data} cy="50%" cx="50%" outerRadius={80} dataKey="value">
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={colors[entry.categoryId]} />
<Row>
<Flex />
<PieChart width={168} height={168}>
<Pie data={data} cy="50%" cx="50%" outerRadius={80} dataKey="value">
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
<Tooltip formatter={formatMoney} />
</PieChart>
<CategoryTotalsTable data={data} />
<Flex />
</Row>
);
};

const CategoryTotalsTable: React.FC<{ data: Data[] }> = ({ data }) => {
const total = data.reduce((p, n) => p.plus(n.value), Money.from(0));
return (
<LegendTable>
<tbody>
{data.map((d, i) => (
<tr key={i}>
<td style={{ color: d.color }}>{d.name}</td>
<td>{Money.from(d.value).format()}</td>
</tr>
))}
</Pie>
<Legend layout="vertical" align="right" />
<Tooltip formatter={formatMoney} />
</PieChart>
<tr className="total">
<td>Yhteensä</td>
<td>{total.format()}</td>
</tr>
</tbody>
</LegendTable>
);
};

interface Data {
name: string;
categoryId: number;
value: MoneyLike;
}
const LegendTable = styled('table')`
margin-left: 16px;
& td:last-child {
text-align: right;
padding-left: 32px;
}
& tr.total {
font-weight: bold;
td:first-child {
color: ${colorScheme.secondary.dark};
}
}
`;

function createColorScheme(
totals: ExpenseGroupingCategoryTotal[],
Expand Down
15 changes: 7 additions & 8 deletions src/server/data/grouping/GroupingDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,15 @@ const EXPENSE_SUM_SUBSELECT = /*sql*/ `

const EXPENSE_JOIN_TO_GROUPING = /*sql*/ `
LEFT JOIN categories cat ON (cat.id = e.category_id)
LEFT JOIN expense_grouping_categories egc ON (egc.category_id = cat.id OR egc.category_id = cat.parent_id)
LEFT JOIN expense_groupings eg ON (eg.id = egc.expense_grouping_id)
LEFT JOIN expense_groupings eg ON (
eg.id = $/groupingId/
AND eg.id IN (SELECT expense_grouping_id FROM expense_grouping_categories egc WHERE egc.category_id IN (cat.id, cat.parent_id)
AND (eg.start_date IS NULL OR eg.start_date <= e.date)
AND (eg.end_date IS NULL OR eg.end_date >= e.date)
))
WHERE e.group_id=$/groupId/
AND (
(
e.grouping_id IS NULL
AND egc.expense_grouping_id = $/groupingId/
AND (eg.start_date IS NULL OR eg.start_date <= e.date)
AND (eg.end_date IS NULL OR eg.end_date >= e.date)
)
(e.grouping_id IS NULL AND eg.id = $/groupingId/)
OR (e.grouping_id = $/groupingId/)
)
`;
Expand Down

0 comments on commit 85363ce

Please sign in to comment.