Skip to content

Commit

Permalink
feat: connect balances
Browse files Browse the repository at this point in the history
  • Loading branch information
MegaRedHand committed Jun 2, 2024
1 parent b5b7b7d commit f1f34cb
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 54 deletions.
4 changes: 3 additions & 1 deletion my-app/src/lib/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ export const groupService = {
put(`group/${id}/archive`, undefined!, getAuthHeader(cookies)),
unarchive: (id: Id, cookies: Cookies) =>
put(`group/${id}/unarchive`, undefined!, getAuthHeader(cookies)),
listAllMembers: (id: Id, cookies: Cookies) => get(`group/${id}/member`, getAuthHeader(cookies))
listAllMembers: (id: Id, cookies: Cookies) => get(`group/${id}/member`, getAuthHeader(cookies)),
listAllMemberBalances: (id: Id, cookies: Cookies) =>
get(`group/${id}/balance`, getAuthHeader(cookies))
};
export const spendingService = {
save: (data: Spending, cookies: Cookies) =>
Expand Down
52 changes: 8 additions & 44 deletions my-app/src/routes/groups/balance/[id=integer]/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,21 @@
import { getUserId } from '$lib/auth';
import { groupService, spendingService } from '$lib/server/api';
import { groupService } from '$lib/server/api';
import type { PageServerLoad } from './$types';

type Balance = {
id: number;
email: string;
balance: number;
};

export const load: PageServerLoad = async ({ cookies, params }) => {
const id = Number(params.id);
const group: Group = await groupService.get(id, cookies);
const groupMembers: User[] = await groupService.listAllMembers(id, cookies);
const spendings: Spending[] = await spendingService.list(id, cookies);

const memberBalances = computeBalancesFromSpendings(groupMembers, spendings);
const memberBalances: Balance[] = await groupService.listAllMemberBalances(id, cookies);

const userId = getUserId(cookies);
const userBalance = memberBalances.find(({ id }) => id === userId)!.balance;
const otherBalances = memberBalances.filter(({ id }) => id !== userId);
const userBalance = memberBalances.find(({ user_id }) => user_id === userId)!.current_balance;
const otherBalances = memberBalances.filter(({ user_id }) => user_id !== userId);

let balances;
if (userBalance === 0) {
balances = otherBalances.map((mb) => ({ ...mb, balance: 0 }));
} else {
balances = distributeBalances(otherBalances, userBalance);
}
const balances = otherBalances.map(({ user_id, current_balance }) => {
const email = groupMembers.find(({ id }) => id === user_id)!.email;
return { email, balance: current_balance };
});
return { group, balances, userBalance };
};

function computeBalancesFromSpendings(groupMembers: User[], spendings: Spending[]) {
// TODO: move this computation to backend
const groupSize = groupMembers.length;
return groupMembers.map(({ id, email }) => {
const balance = spendings
.map(({ owner_id, amount }) =>
owner_id === id ? (amount * (groupSize - 1)) / groupSize : -amount / groupSize
)
.reduce((a, b) => a + b, 0);
return { id, email, balance };
});
}

function distributeBalances(memberBalances: Balance[], userBalance: number) {
const sign = Math.sign(userBalance);
const balances = memberBalances.map((mb) => {
if (sign * mb.balance >= 0) {
return { ...mb, balance: 0 };
}
const balanceLeft = userBalance + mb.balance;
userBalance = sign * Math.max(0, sign * balanceLeft);
const memberBalance = sign * balanceLeft < 0 ? mb.balance - balanceLeft : mb.balance;
return { ...mb, balance: memberBalance };
});
return balances;
}
10 changes: 5 additions & 5 deletions my-app/src/routes/groups/balance/[id=integer]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
}
export const personalBalanceTooltip =
data?.userBalance < 0
? 'You owe money'
? 'Les debes dinero'
: data?.userBalance > 0
? 'You are owed money'
: 'You are even';
? 'Te deben dinero'
: 'Están a mano';
export function balanceTooltip(balance: number) {
return balance > 0 ? 'You owe them' : balance < 0 ? 'They owe you' : 'You are even';
return balance > 0 ? 'Le debes dinero' : balance < 0 ? 'Te debe dinero' : 'Están a mano';
}
</script>

Expand All @@ -41,7 +41,7 @@
</header>

<article class="grid">
<p>Your balance</p>
<p>Tu balance</p>
<p class="text-right">
<span style="color: {balanceColor(data?.userBalance)}">{formatMoney(data?.userBalance)}</span>
<span data-tooltip={personalBalanceTooltip} style="border-bottom: 0px">{@html INFO_SVG}</span>
Expand Down
7 changes: 3 additions & 4 deletions my-app/src/routes/invites/send/[[id=integer]]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
import type { PageData } from './$types';
export let data: PageData;
const pageTitle = `Invitar`;
</script>

<svelte:head>
<title>{data.group.name} - {pageTitle}</title>
<title>{data.group.name} - Invitar</title>
</svelte:head>

<nav aria-label="breadcrumb">
<ul>
<li><a href="/groups">Grupos</a></li>
<li>Invitaciones</li>
<li>Enviar</li>
<li><a href="/groups/members/{data.group.id}">Miembros</a></li>
<li>Invitar</li>
</ul>
</nav>

Expand Down
6 changes: 6 additions & 0 deletions my-app/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ declare global {
type AcceptInvite = {
token: string;
};
type Balance = {
id: Id;
user_id: Id;
group_id: Id;
current_balance: number;
};
}

export {};

0 comments on commit f1f34cb

Please sign in to comment.