Skip to content

Commit

Permalink
feat: add spendings per category graphs
Browse files Browse the repository at this point in the history
  • Loading branch information
MegaRedHand committed May 26, 2024
1 parent b7ee262 commit 0751737
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 6 deletions.
19 changes: 19 additions & 0 deletions my-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion my-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^5.0.3",
"vitest": "^1.2.0"
"vitest": "^1.2.0",
"chart.js": "^4.0.0"
},
"type": "module",
"dependencies": {
Expand Down
1 change: 0 additions & 1 deletion my-app/src/lib/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,5 @@ export const categoryService = {
data.id > 0
? put(`category/${data.id}`, data, getAuthHeader(cookies))
: post('category', data, getAuthHeader(cookies)),
get: (id: Id, cookies: Cookies) => get(`category/${id}`, getAuthHeader(cookies)),
list: (groupId: Id, cookies: Cookies) => get(`category/${groupId}`, getAuthHeader(cookies))
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const load: PageServerLoad = async ({ params, url, cookies }) => {
const group_id = url.searchParams.get('groupId') || '';
const id = Number(params.id) || 0;
const category: Category = id
? await categoryService.get(id, cookies)
? await categoryService.list(id, cookies)
: { id: 0, group_id, name: '', description: '', strategy: '' };
const groups: Group[] = await groupService.list(cookies);
return { category, groups };
Expand Down
26 changes: 26 additions & 0 deletions my-app/src/routes/groups/graphs/[[id=integer]]/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { categoryService, groupService, spendingService } from '$lib/server/api';
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params, cookies }) => {
const id = Number(params.id) || 0;
const group: Group = id
? await groupService.get(id, cookies)
: { name: '', description: '', id: 0, owner_id: 0, is_archived: false };
const categories = await categoryService.list(id, cookies);
const spendings = await spendingService.list(id, cookies);
const graphData = computePerCategorySpending(categories, spendings);
return { group, graphData };
};

function computePerCategorySpending(categories: Category[], spendings: Spending[]) {
const categoryMap = new Map<string, number>(categories.map((category) => [category.name, 0]));
spendings.forEach(({ amount }) => {
const randomChoice = Math.floor(Math.random() * categories.length);
const categoryName = categories[randomChoice].name;
const acc = categoryMap.get(categoryName)!;
categoryMap.set(categoryName, acc + amount);
});
const labels = Array.from(categoryMap.keys());
const values = Array.from(categoryMap.values());
return { labels, values };
}
53 changes: 53 additions & 0 deletions my-app/src/routes/groups/graphs/[[id=integer]]/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<script lang="ts">
import { title } from '$lib';
import type { PageData } from './$types';
import type { Action } from 'svelte/action';
import { Chart } from 'chart.js/auto';
export let data: PageData;
export const loadGraph: Action<HTMLCanvasElement> = (canvas) => {
const { labels, values } = data?.graphData;
const label = 'Gastos por categoría';
// NOTE: this is to have each bar be a different color
const datasets = values.map((v, i) => {
let data = Array(values.length).fill(0);
data[i] = v;
return { label, data };
});
const chart = new Chart(canvas, {
type: 'bar',
options: {
plugins: {
legend: { display: false },
colors: { enabled: true, forceOverride: true }
},
scales: { x: { stacked: true }, y: { stacked: true } }
},
data: { labels, datasets }
});
return { destroy: () => chart.destroy() };
};
</script>

<svelte:head>
<title>{title} - Gráficos de finanzas</title>
</svelte:head>

<nav aria-label="breadcrumb">
<ul>
<li><a href="/groups">Grupos</a></li>
<li><a href="/groups/movements/{data.group.id}">{data.group.name}</a></li>
<li>Gráficos de finanzas</li>
</ul>
</nav>

<header class="row">
<div>
<h2>Gráficos de finanzas</h2>
<p>{data.group.description}</p>
</div>
</header>

<div style="width: 600px;"><canvas use:loadGraph></canvas></div>
3 changes: 2 additions & 1 deletion my-app/src/routes/groups/movements/[id=integer]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<header class="row">
<div>
<h2>Moovimietos</h2>
<h2>Moovimientos</h2>
<p>{data.group.description}</p>
</div>
<div class="row">
Expand All @@ -31,6 +31,7 @@
<summary role="button" class="outline">Resumenes</summary>
<ul>
<li><a href="/groups/balance/{data.group.id}">Estado de cuenta grupal</a></li>
<li><a href="/groups/graphs/{data.group.id}">Gráficos de finanzas</a></li>
</ul>
</details>
<details class="dropdown" style="margin-left: 10px">
Expand Down
4 changes: 2 additions & 2 deletions my-app/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ declare global {
is_archived: boolean;
};
type Category = {
id: Id;
group_id: string; // ?
// NOTE: [name, group_id] is primary key
name: string;
group_id: string;
description: string;
strategy: string;
};
Expand Down

0 comments on commit 0751737

Please sign in to comment.