From 02429f81cc7f6e5fbad97f0229dbcf458cc6939c Mon Sep 17 00:00:00 2001 From: Anurag Patil Date: Sun, 18 Feb 2024 23:48:58 +0530 Subject: [PATCH 1/5] feat: initialise a new totals tab with basic UI --- src/app/groups/[groupId]/group-tabs.tsx | 1 + src/app/groups/[groupId]/total-your-share.tsx | 36 +++++++++ .../groups/[groupId]/total-your-spending.tsx | 36 +++++++++ .../[groupId]/totals-group-spending.tsx | 14 ++++ src/app/groups/[groupId]/totals/page.tsx | 78 +++++++++++++++++++ src/lib/totals.ts | 46 +++++++++++ 6 files changed, 211 insertions(+) create mode 100644 src/app/groups/[groupId]/total-your-share.tsx create mode 100644 src/app/groups/[groupId]/total-your-spending.tsx create mode 100644 src/app/groups/[groupId]/totals-group-spending.tsx create mode 100644 src/app/groups/[groupId]/totals/page.tsx create mode 100644 src/lib/totals.ts diff --git a/src/app/groups/[groupId]/group-tabs.tsx b/src/app/groups/[groupId]/group-tabs.tsx index bd603cca..dcaf0541 100644 --- a/src/app/groups/[groupId]/group-tabs.tsx +++ b/src/app/groups/[groupId]/group-tabs.tsx @@ -23,6 +23,7 @@ export function GroupTabs({ groupId }: Props) { Expenses Balances + Totals Settings diff --git a/src/app/groups/[groupId]/total-your-share.tsx b/src/app/groups/[groupId]/total-your-share.tsx new file mode 100644 index 00000000..542f1168 --- /dev/null +++ b/src/app/groups/[groupId]/total-your-share.tsx @@ -0,0 +1,36 @@ +'use client' +import { formatCurrency } from '@/lib/utils' +import { getGroup, getGroupExpenses } from '@/lib/api' +import { getTotalActiveUserShare } from '@/lib/totals' +import { useEffect, useState } from 'react' + + +type Props = { + group: NonNullable>> + expenses: NonNullable>> +} + +export function TotalsYourShare({ group, expenses }: Props) { + + const [activeUser, setActiveUser] = useState('') + + useEffect(() => { + const activeUser = localStorage.getItem(`${group.id}-activeUser`) + if (activeUser) setActiveUser(activeUser) + + }, [group, expenses]) + + const totalActiveUserShare = getTotalActiveUserShare(activeUser, expenses) + const currency = group.currency + + return activeUser === '' ? + ( +
+ 'No active user set!!' +
+ ) : ( +
+ {formatCurrency(currency, totalActiveUserShare)} +
+ ) +} \ No newline at end of file diff --git a/src/app/groups/[groupId]/total-your-spending.tsx b/src/app/groups/[groupId]/total-your-spending.tsx new file mode 100644 index 00000000..5ef7bf09 --- /dev/null +++ b/src/app/groups/[groupId]/total-your-spending.tsx @@ -0,0 +1,36 @@ +'use client' +import { formatCurrency } from '@/lib/utils' +import { getGroup, getGroupExpenses } from '@/lib/api' +import { getTotalActiveUserPaidFor } from '@/lib/totals' +import { useEffect, useState } from 'react' + + +type Props = { + group: NonNullable>> + expenses: NonNullable>> +} + +export function TotalsYourSpendings({ group, expenses }: Props) { + + const [activeUser, setActiveUser] = useState('') + + useEffect(() => { + const activeUser = localStorage.getItem(`${group.id}-activeUser`) + if (activeUser) setActiveUser(activeUser) + + }, [group, expenses]) + + const totalYourSpendings = getTotalActiveUserPaidFor(activeUser, expenses) + const currency = group.currency + + return activeUser === '' ? + ( +
+ 'No active user set!!' +
+ ) : ( +
+ {formatCurrency(currency, totalYourSpendings)} +
+ ) +} \ No newline at end of file diff --git a/src/app/groups/[groupId]/totals-group-spending.tsx b/src/app/groups/[groupId]/totals-group-spending.tsx new file mode 100644 index 00000000..fc4791ca --- /dev/null +++ b/src/app/groups/[groupId]/totals-group-spending.tsx @@ -0,0 +1,14 @@ +import { formatCurrency } from '@/lib/utils' + +type Props = { + totalGroupSpendings: number + currency: string +} + +export function TotalsGroupSpending({ totalGroupSpendings, currency }: Props) { + return ( +
+ {formatCurrency(currency, totalGroupSpendings)} +
+ ) +} \ No newline at end of file diff --git a/src/app/groups/[groupId]/totals/page.tsx b/src/app/groups/[groupId]/totals/page.tsx new file mode 100644 index 00000000..c01ae9b1 --- /dev/null +++ b/src/app/groups/[groupId]/totals/page.tsx @@ -0,0 +1,78 @@ +import { cached } from '@/app/cached-functions' +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card' +import { getGroupExpenses } from '@/lib/api' +import { Metadata } from 'next' +import { notFound } from 'next/navigation' +import { TotalsGroupSpending } from '@/app/groups/[groupId]/totals-group-spending' +import { getTotalGroupSpending } from '@/lib/totals' +import { TotalsYourSpendings } from '@/app/groups/[groupId]/total-your-spending' +import { TotalsYourShare } from '@/app/groups/[groupId]/total-your-share' + +export const metadata: Metadata = { + title: 'Totals', +} + +export default async function TotalsPage({ + params: { groupId }, +}: { + params: { groupId: string } +}) { + const group = await cached.getGroup(groupId) + if (!group) notFound() + + const expenses = await getGroupExpenses(groupId) + const totalGroupSpendings = getTotalGroupSpending(expenses) + + return ( + <> + + + Total group spending + + Combined amount of all expenses recorded by the members + + + + + + + + + Total you paid for + + Total amount of money that you have paid on behalf of the group + + + + + + + + + Your total share + + Total amount of money that you are responsible for paying + + + + + + + + ) +} diff --git a/src/lib/totals.ts b/src/lib/totals.ts new file mode 100644 index 00000000..3baa4d00 --- /dev/null +++ b/src/lib/totals.ts @@ -0,0 +1,46 @@ +import { getGroupExpenses } from "@/lib/api"; +import { match } from 'ts-pattern' + +export function getTotalGroupSpending(expenses: NonNullable>>): number { + return expenses.reduce((total, expense) => (!expense.isReimbursement ? total + expense.amount : total + 0), 0) +} + +export function getTotalActiveUserPaidFor(activeUserId: string | null, expenses: NonNullable>>): number { + return expenses.reduce((total, expense) => (expense.paidBy.id === activeUserId ? total + expense.amount : total + 0),0) +} + +export function getTotalActiveUserShare(activeUserId: string | null, expenses: NonNullable>>): number { + let total = 0; + + expenses.forEach(expense => { + const paidFors = expense.paidFor; + const userPaidFor = paidFors.find(paidFor => paidFor.participantId === activeUserId); + + if (!userPaidFor) { + // If the active user is not involved in the expense, skip it + return; + } + + switch (expense.splitMode) { + case 'EVENLY': + // Divide the total expense evenly among all participants + total += expense.amount / paidFors.length; + break; + case 'BY_AMOUNT': + // Directly add the user's share if the split mode is BY_AMOUNT + total += userPaidFor.shares; + break; + case 'BY_PERCENTAGE': + // Calculate the user's share based on their percentage of the total expense + total += (expense.amount * userPaidFor.shares) / 10000; // Assuming shares are out of 10000 for percentage + break; + case 'BY_SHARES': + // Calculate the user's share based on their shares relative to the total shares + const totalShares = paidFors.reduce((sum, paidFor) => sum + paidFor.shares, 0); + total += (expense.amount * userPaidFor.shares) / totalShares; + break; + } + }); + + return parseFloat(total.toFixed(2)); +} \ No newline at end of file From 74b1b31c851d0d43867d946c6b4eabe85d001a89 Mon Sep 17 00:00:00 2001 From: Anurag Patil Date: Wed, 21 Feb 2024 08:05:22 +0530 Subject: [PATCH 2/5] fix: update group tabs and add stats page --- src/app/groups/[groupId]/group-tabs.tsx | 2 +- .../[groupId]/{totals => stats}/page.tsx | 30 ++++--------------- .../[groupId]/totals-group-spending.tsx | 11 +++++-- ...l-your-share.tsx => totals-your-share.tsx} | 26 ++++++++-------- ...-spending.tsx => totals-your-spending.tsx} | 26 ++++++++-------- 5 files changed, 43 insertions(+), 52 deletions(-) rename src/app/groups/[groupId]/{totals => stats}/page.tsx (62%) rename src/app/groups/[groupId]/{total-your-share.tsx => totals-your-share.tsx} (56%) rename src/app/groups/[groupId]/{total-your-spending.tsx => totals-your-spending.tsx} (56%) diff --git a/src/app/groups/[groupId]/group-tabs.tsx b/src/app/groups/[groupId]/group-tabs.tsx index dcaf0541..d7a0876f 100644 --- a/src/app/groups/[groupId]/group-tabs.tsx +++ b/src/app/groups/[groupId]/group-tabs.tsx @@ -23,7 +23,7 @@ export function GroupTabs({ groupId }: Props) { Expenses Balances - Totals + Stats Settings diff --git a/src/app/groups/[groupId]/totals/page.tsx b/src/app/groups/[groupId]/stats/page.tsx similarity index 62% rename from src/app/groups/[groupId]/totals/page.tsx rename to src/app/groups/[groupId]/stats/page.tsx index c01ae9b1..dccc98ba 100644 --- a/src/app/groups/[groupId]/totals/page.tsx +++ b/src/app/groups/[groupId]/stats/page.tsx @@ -11,8 +11,9 @@ import { Metadata } from 'next' import { notFound } from 'next/navigation' import { TotalsGroupSpending } from '@/app/groups/[groupId]/totals-group-spending' import { getTotalGroupSpending } from '@/lib/totals' -import { TotalsYourSpendings } from '@/app/groups/[groupId]/total-your-spending' -import { TotalsYourShare } from '@/app/groups/[groupId]/total-your-share' +import { TotalsYourSpendings } from '@/app/groups/[groupId]/totals-your-spending' +import { TotalsYourShare } from '@/app/groups/[groupId]/totals-your-share' +import { Space } from 'lucide-react' export const metadata: Metadata = { title: 'Totals', @@ -33,9 +34,9 @@ export default async function TotalsPage({ <> - Total group spending + Totals - Combined amount of all expenses recorded by the members + Spending summary of the entire group @@ -43,36 +44,17 @@ export default async function TotalsPage({ totalGroupSpendings={totalGroupSpendings} currency={group.currency} /> - - - - - Total you paid for - - Total amount of money that you have paid on behalf of the group - - - - - - - - Your total share - - Total amount of money that you are responsible for paying - - - + ) } diff --git a/src/app/groups/[groupId]/totals-group-spending.tsx b/src/app/groups/[groupId]/totals-group-spending.tsx index fc4791ca..3c022361 100644 --- a/src/app/groups/[groupId]/totals-group-spending.tsx +++ b/src/app/groups/[groupId]/totals-group-spending.tsx @@ -7,8 +7,13 @@ type Props = { export function TotalsGroupSpending({ totalGroupSpendings, currency }: Props) { return ( -
- {formatCurrency(currency, totalGroupSpendings)} -
+ <> +
+ Total group spendings +
+
+ {formatCurrency(currency, totalGroupSpendings)} +
+ ) } \ No newline at end of file diff --git a/src/app/groups/[groupId]/total-your-share.tsx b/src/app/groups/[groupId]/totals-your-share.tsx similarity index 56% rename from src/app/groups/[groupId]/total-your-share.tsx rename to src/app/groups/[groupId]/totals-your-share.tsx index 542f1168..e2f4bd52 100644 --- a/src/app/groups/[groupId]/total-your-share.tsx +++ b/src/app/groups/[groupId]/totals-your-share.tsx @@ -16,21 +16,23 @@ export function TotalsYourShare({ group, expenses }: Props) { useEffect(() => { const activeUser = localStorage.getItem(`${group.id}-activeUser`) - if (activeUser) setActiveUser(activeUser) + if (activeUser) setActiveUser(activeUser) - }, [group, expenses]) + }, [group, expenses]) - const totalActiveUserShare = getTotalActiveUserShare(activeUser, expenses) + const totalActiveUserShare = (activeUser === '' || activeUser === 'None') ? 0 : getTotalActiveUserShare(activeUser, expenses) const currency = group.currency - return activeUser === '' ? - ( -
- 'No active user set!!' -
- ) : ( -
- {formatCurrency(currency, totalActiveUserShare)} -
+ return ( + <> +
+ Your total share + +
+
+ {formatCurrency(currency, totalActiveUserShare)} +
+ + ) } \ No newline at end of file diff --git a/src/app/groups/[groupId]/total-your-spending.tsx b/src/app/groups/[groupId]/totals-your-spending.tsx similarity index 56% rename from src/app/groups/[groupId]/total-your-spending.tsx rename to src/app/groups/[groupId]/totals-your-spending.tsx index 5ef7bf09..d6158b05 100644 --- a/src/app/groups/[groupId]/total-your-spending.tsx +++ b/src/app/groups/[groupId]/totals-your-spending.tsx @@ -16,21 +16,23 @@ export function TotalsYourSpendings({ group, expenses }: Props) { useEffect(() => { const activeUser = localStorage.getItem(`${group.id}-activeUser`) - if (activeUser) setActiveUser(activeUser) + if (activeUser) setActiveUser(activeUser) - }, [group, expenses]) + }, [group, expenses]) - const totalYourSpendings = getTotalActiveUserPaidFor(activeUser, expenses) + const totalYourSpendings = (activeUser === '' || activeUser === 'None') ? 0 : getTotalActiveUserPaidFor(activeUser, expenses) const currency = group.currency - return activeUser === '' ? - ( -
- 'No active user set!!' -
- ) : ( -
- {formatCurrency(currency, totalYourSpendings)} -
+ return ( + <> +
+ Total you paid for +
+ +
+ {formatCurrency(currency, totalYourSpendings)} +
+ + ) } \ No newline at end of file From dc6c0742e323ec2f38ad08ae25ca7e349c24b419 Mon Sep 17 00:00:00 2001 From: Anurag Patil Date: Wed, 21 Feb 2024 08:13:52 +0530 Subject: [PATCH 3/5] fix: styling within the new elements --- src/app/groups/[groupId]/stats/page.tsx | 2 +- src/app/groups/[groupId]/totals-group-spending.tsx | 6 +++--- src/app/groups/[groupId]/totals-your-share.tsx | 6 +++--- src/app/groups/[groupId]/totals-your-spending.tsx | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/app/groups/[groupId]/stats/page.tsx b/src/app/groups/[groupId]/stats/page.tsx index dccc98ba..67be52b0 100644 --- a/src/app/groups/[groupId]/stats/page.tsx +++ b/src/app/groups/[groupId]/stats/page.tsx @@ -39,7 +39,7 @@ export default async function TotalsPage({ Spending summary of the entire group - + -
+
+
Total group spendings
{formatCurrency(currency, totalGroupSpendings)}
- +
) } \ No newline at end of file diff --git a/src/app/groups/[groupId]/totals-your-share.tsx b/src/app/groups/[groupId]/totals-your-share.tsx index e2f4bd52..d4502151 100644 --- a/src/app/groups/[groupId]/totals-your-share.tsx +++ b/src/app/groups/[groupId]/totals-your-share.tsx @@ -24,15 +24,15 @@ export function TotalsYourShare({ group, expenses }: Props) { const currency = group.currency return ( - <> -
+
+
Your total share
{formatCurrency(currency, totalActiveUserShare)}
- +
) } \ No newline at end of file diff --git a/src/app/groups/[groupId]/totals-your-spending.tsx b/src/app/groups/[groupId]/totals-your-spending.tsx index d6158b05..504ddf09 100644 --- a/src/app/groups/[groupId]/totals-your-spending.tsx +++ b/src/app/groups/[groupId]/totals-your-spending.tsx @@ -24,15 +24,15 @@ export function TotalsYourSpendings({ group, expenses }: Props) { const currency = group.currency return ( - <> -
+
+
Total you paid for
{formatCurrency(currency, totalYourSpendings)}
- +
) } \ No newline at end of file From 48441524d74ba0d62ded0f3a1daa212f7012e02c Mon Sep 17 00:00:00 2001 From: Sebastien Castiel Date: Wed, 28 Feb 2024 10:35:19 -0500 Subject: [PATCH 4/5] Prettier --- src/app/groups/[groupId]/stats/page.tsx | 32 +++---- .../[groupId]/totals-group-spending.tsx | 24 +++-- .../groups/[groupId]/totals-your-share.tsx | 54 +++++------ .../groups/[groupId]/totals-your-spending.tsx | 55 +++++------ src/lib/totals.ts | 94 +++++++++++-------- 5 files changed, 131 insertions(+), 128 deletions(-) diff --git a/src/app/groups/[groupId]/stats/page.tsx b/src/app/groups/[groupId]/stats/page.tsx index 67be52b0..063795a3 100644 --- a/src/app/groups/[groupId]/stats/page.tsx +++ b/src/app/groups/[groupId]/stats/page.tsx @@ -1,4 +1,7 @@ import { cached } from '@/app/cached-functions' +import { TotalsGroupSpending } from '@/app/groups/[groupId]/totals-group-spending' +import { TotalsYourShare } from '@/app/groups/[groupId]/totals-your-share' +import { TotalsYourSpendings } from '@/app/groups/[groupId]/totals-your-spending' import { Card, CardContent, @@ -7,13 +10,9 @@ import { CardTitle, } from '@/components/ui/card' import { getGroupExpenses } from '@/lib/api' +import { getTotalGroupSpending } from '@/lib/totals' import { Metadata } from 'next' import { notFound } from 'next/navigation' -import { TotalsGroupSpending } from '@/app/groups/[groupId]/totals-group-spending' -import { getTotalGroupSpending } from '@/lib/totals' -import { TotalsYourSpendings } from '@/app/groups/[groupId]/totals-your-spending' -import { TotalsYourShare } from '@/app/groups/[groupId]/totals-your-share' -import { Space } from 'lucide-react' export const metadata: Metadata = { title: 'Totals', @@ -36,25 +35,18 @@ export default async function TotalsPage({ Totals - Spending summary of the entire group + Spending summary of the entire group. - - - - + + + + - ) } diff --git a/src/app/groups/[groupId]/totals-group-spending.tsx b/src/app/groups/[groupId]/totals-group-spending.tsx index 5bdea190..3c0c96da 100644 --- a/src/app/groups/[groupId]/totals-group-spending.tsx +++ b/src/app/groups/[groupId]/totals-group-spending.tsx @@ -1,19 +1,17 @@ import { formatCurrency } from '@/lib/utils' type Props = { - totalGroupSpendings: number - currency: string + totalGroupSpendings: number + currency: string } export function TotalsGroupSpending({ totalGroupSpendings, currency }: Props) { - return ( -
-
- Total group spendings -
-
- {formatCurrency(currency, totalGroupSpendings)} -
-
- ) -} \ No newline at end of file + return ( +
+
Total group spendings
+
+ {formatCurrency(currency, totalGroupSpendings)} +
+
+ ) +} diff --git a/src/app/groups/[groupId]/totals-your-share.tsx b/src/app/groups/[groupId]/totals-your-share.tsx index d4502151..3218d6f6 100644 --- a/src/app/groups/[groupId]/totals-your-share.tsx +++ b/src/app/groups/[groupId]/totals-your-share.tsx @@ -1,38 +1,34 @@ 'use client' -import { formatCurrency } from '@/lib/utils' import { getGroup, getGroupExpenses } from '@/lib/api' import { getTotalActiveUserShare } from '@/lib/totals' +import { formatCurrency } from '@/lib/utils' import { useEffect, useState } from 'react' - type Props = { - group: NonNullable>> - expenses: NonNullable>> + group: NonNullable>> + expenses: NonNullable>> } export function TotalsYourShare({ group, expenses }: Props) { - - const [activeUser, setActiveUser] = useState('') - - useEffect(() => { - const activeUser = localStorage.getItem(`${group.id}-activeUser`) - if (activeUser) setActiveUser(activeUser) - - }, [group, expenses]) - - const totalActiveUserShare = (activeUser === '' || activeUser === 'None') ? 0 : getTotalActiveUserShare(activeUser, expenses) - const currency = group.currency - - return ( -
-
- Your total share - -
-
- {formatCurrency(currency, totalActiveUserShare)} -
-
- - ) -} \ No newline at end of file + const [activeUser, setActiveUser] = useState('') + + useEffect(() => { + const activeUser = localStorage.getItem(`${group.id}-activeUser`) + if (activeUser) setActiveUser(activeUser) + }, [group, expenses]) + + const totalActiveUserShare = + activeUser === '' || activeUser === 'None' + ? 0 + : getTotalActiveUserShare(activeUser, expenses) + const currency = group.currency + + return ( +
+
Your total share
+
+ {formatCurrency(currency, totalActiveUserShare)} +
+
+ ) +} diff --git a/src/app/groups/[groupId]/totals-your-spending.tsx b/src/app/groups/[groupId]/totals-your-spending.tsx index 504ddf09..19bdb411 100644 --- a/src/app/groups/[groupId]/totals-your-spending.tsx +++ b/src/app/groups/[groupId]/totals-your-spending.tsx @@ -1,38 +1,35 @@ 'use client' -import { formatCurrency } from '@/lib/utils' import { getGroup, getGroupExpenses } from '@/lib/api' import { getTotalActiveUserPaidFor } from '@/lib/totals' +import { formatCurrency } from '@/lib/utils' import { useEffect, useState } from 'react' - type Props = { - group: NonNullable>> - expenses: NonNullable>> + group: NonNullable>> + expenses: NonNullable>> } export function TotalsYourSpendings({ group, expenses }: Props) { - - const [activeUser, setActiveUser] = useState('') - - useEffect(() => { - const activeUser = localStorage.getItem(`${group.id}-activeUser`) - if (activeUser) setActiveUser(activeUser) - - }, [group, expenses]) - - const totalYourSpendings = (activeUser === '' || activeUser === 'None') ? 0 : getTotalActiveUserPaidFor(activeUser, expenses) - const currency = group.currency - - return ( -
-
- Total you paid for -
- -
- {formatCurrency(currency, totalYourSpendings)} -
-
- - ) -} \ No newline at end of file + const [activeUser, setActiveUser] = useState('') + + useEffect(() => { + const activeUser = localStorage.getItem(`${group.id}-activeUser`) + if (activeUser) setActiveUser(activeUser) + }, [group, expenses]) + + const totalYourSpendings = + activeUser === '' || activeUser === 'None' + ? 0 + : getTotalActiveUserPaidFor(activeUser, expenses) + const currency = group.currency + + return ( +
+
Total you paid for
+ +
+ {formatCurrency(currency, totalYourSpendings)} +
+
+ ) +} diff --git a/src/lib/totals.ts b/src/lib/totals.ts index 3baa4d00..797318c8 100644 --- a/src/lib/totals.ts +++ b/src/lib/totals.ts @@ -1,46 +1,66 @@ -import { getGroupExpenses } from "@/lib/api"; -import { match } from 'ts-pattern' +import { getGroupExpenses } from '@/lib/api' -export function getTotalGroupSpending(expenses: NonNullable>>): number { - return expenses.reduce((total, expense) => (!expense.isReimbursement ? total + expense.amount : total + 0), 0) +export function getTotalGroupSpending( + expenses: NonNullable>>, +): number { + return expenses.reduce( + (total, expense) => + !expense.isReimbursement ? total + expense.amount : total + 0, + 0, + ) } -export function getTotalActiveUserPaidFor(activeUserId: string | null, expenses: NonNullable>>): number { - return expenses.reduce((total, expense) => (expense.paidBy.id === activeUserId ? total + expense.amount : total + 0),0) +export function getTotalActiveUserPaidFor( + activeUserId: string | null, + expenses: NonNullable>>, +): number { + return expenses.reduce( + (total, expense) => + expense.paidBy.id === activeUserId ? total + expense.amount : total + 0, + 0, + ) } -export function getTotalActiveUserShare(activeUserId: string | null, expenses: NonNullable>>): number { - let total = 0; +export function getTotalActiveUserShare( + activeUserId: string | null, + expenses: NonNullable>>, +): number { + let total = 0 - expenses.forEach(expense => { - const paidFors = expense.paidFor; - const userPaidFor = paidFors.find(paidFor => paidFor.participantId === activeUserId); + expenses.forEach((expense) => { + const paidFors = expense.paidFor + const userPaidFor = paidFors.find( + (paidFor) => paidFor.participantId === activeUserId, + ) - if (!userPaidFor) { - // If the active user is not involved in the expense, skip it - return; - } + if (!userPaidFor) { + // If the active user is not involved in the expense, skip it + return + } - switch (expense.splitMode) { - case 'EVENLY': - // Divide the total expense evenly among all participants - total += expense.amount / paidFors.length; - break; - case 'BY_AMOUNT': - // Directly add the user's share if the split mode is BY_AMOUNT - total += userPaidFor.shares; - break; - case 'BY_PERCENTAGE': - // Calculate the user's share based on their percentage of the total expense - total += (expense.amount * userPaidFor.shares) / 10000; // Assuming shares are out of 10000 for percentage - break; - case 'BY_SHARES': - // Calculate the user's share based on their shares relative to the total shares - const totalShares = paidFors.reduce((sum, paidFor) => sum + paidFor.shares, 0); - total += (expense.amount * userPaidFor.shares) / totalShares; - break; - } - }); + switch (expense.splitMode) { + case 'EVENLY': + // Divide the total expense evenly among all participants + total += expense.amount / paidFors.length + break + case 'BY_AMOUNT': + // Directly add the user's share if the split mode is BY_AMOUNT + total += userPaidFor.shares + break + case 'BY_PERCENTAGE': + // Calculate the user's share based on their percentage of the total expense + total += (expense.amount * userPaidFor.shares) / 10000 // Assuming shares are out of 10000 for percentage + break + case 'BY_SHARES': + // Calculate the user's share based on their shares relative to the total shares + const totalShares = paidFors.reduce( + (sum, paidFor) => sum + paidFor.shares, + 0, + ) + total += (expense.amount * userPaidFor.shares) / totalShares + break + } + }) - return parseFloat(total.toFixed(2)); -} \ No newline at end of file + return parseFloat(total.toFixed(2)) +} From 8335aca04a03540b958e70af8d464a3bfab7f198 Mon Sep 17 00:00:00 2001 From: Sebastien Castiel Date: Wed, 28 Feb 2024 10:42:18 -0500 Subject: [PATCH 5/5] Display active user expenses only if active user is set --- src/app/groups/[groupId]/stats/page.tsx | 11 +++--- .../{ => stats}/totals-group-spending.tsx | 0 .../{ => stats}/totals-your-share.tsx | 0 .../{ => stats}/totals-your-spending.tsx | 9 ++--- src/app/groups/[groupId]/stats/totals.tsx | 34 +++++++++++++++++++ src/lib/hooks.ts | 14 ++++++++ 6 files changed, 54 insertions(+), 14 deletions(-) rename src/app/groups/[groupId]/{ => stats}/totals-group-spending.tsx (100%) rename src/app/groups/[groupId]/{ => stats}/totals-your-share.tsx (100%) rename src/app/groups/[groupId]/{ => stats}/totals-your-spending.tsx (75%) create mode 100644 src/app/groups/[groupId]/stats/totals.tsx diff --git a/src/app/groups/[groupId]/stats/page.tsx b/src/app/groups/[groupId]/stats/page.tsx index 063795a3..eb7fa9e2 100644 --- a/src/app/groups/[groupId]/stats/page.tsx +++ b/src/app/groups/[groupId]/stats/page.tsx @@ -1,7 +1,5 @@ import { cached } from '@/app/cached-functions' -import { TotalsGroupSpending } from '@/app/groups/[groupId]/totals-group-spending' -import { TotalsYourShare } from '@/app/groups/[groupId]/totals-your-share' -import { TotalsYourSpendings } from '@/app/groups/[groupId]/totals-your-spending' +import { Totals } from '@/app/groups/[groupId]/stats/totals' import { Card, CardContent, @@ -39,12 +37,11 @@ export default async function TotalsPage({ - - - diff --git a/src/app/groups/[groupId]/totals-group-spending.tsx b/src/app/groups/[groupId]/stats/totals-group-spending.tsx similarity index 100% rename from src/app/groups/[groupId]/totals-group-spending.tsx rename to src/app/groups/[groupId]/stats/totals-group-spending.tsx diff --git a/src/app/groups/[groupId]/totals-your-share.tsx b/src/app/groups/[groupId]/stats/totals-your-share.tsx similarity index 100% rename from src/app/groups/[groupId]/totals-your-share.tsx rename to src/app/groups/[groupId]/stats/totals-your-share.tsx diff --git a/src/app/groups/[groupId]/totals-your-spending.tsx b/src/app/groups/[groupId]/stats/totals-your-spending.tsx similarity index 75% rename from src/app/groups/[groupId]/totals-your-spending.tsx rename to src/app/groups/[groupId]/stats/totals-your-spending.tsx index 19bdb411..f621a41f 100644 --- a/src/app/groups/[groupId]/totals-your-spending.tsx +++ b/src/app/groups/[groupId]/stats/totals-your-spending.tsx @@ -1,8 +1,8 @@ 'use client' import { getGroup, getGroupExpenses } from '@/lib/api' +import { useActiveUser } from '@/lib/hooks' import { getTotalActiveUserPaidFor } from '@/lib/totals' import { formatCurrency } from '@/lib/utils' -import { useEffect, useState } from 'react' type Props = { group: NonNullable>> @@ -10,12 +10,7 @@ type Props = { } export function TotalsYourSpendings({ group, expenses }: Props) { - const [activeUser, setActiveUser] = useState('') - - useEffect(() => { - const activeUser = localStorage.getItem(`${group.id}-activeUser`) - if (activeUser) setActiveUser(activeUser) - }, [group, expenses]) + const activeUser = useActiveUser(group.id) const totalYourSpendings = activeUser === '' || activeUser === 'None' diff --git a/src/app/groups/[groupId]/stats/totals.tsx b/src/app/groups/[groupId]/stats/totals.tsx new file mode 100644 index 00000000..aa320374 --- /dev/null +++ b/src/app/groups/[groupId]/stats/totals.tsx @@ -0,0 +1,34 @@ +'use client' +import { TotalsGroupSpending } from '@/app/groups/[groupId]/stats/totals-group-spending' +import { TotalsYourShare } from '@/app/groups/[groupId]/stats/totals-your-share' +import { TotalsYourSpendings } from '@/app/groups/[groupId]/stats/totals-your-spending' +import { getGroup, getGroupExpenses } from '@/lib/api' +import { useActiveUser } from '@/lib/hooks' + +export function Totals({ + group, + expenses, + totalGroupSpendings, +}: { + group: NonNullable>> + expenses: NonNullable>> + totalGroupSpendings: number +}) { + const activeUser = useActiveUser(group.id) + console.log('activeUser', activeUser) + + return ( + <> + + {activeUser && activeUser !== 'None' && ( + <> + + + + )} + + ) +} diff --git a/src/lib/hooks.ts b/src/lib/hooks.ts index 4d3ad080..490eccf5 100644 --- a/src/lib/hooks.ts +++ b/src/lib/hooks.ts @@ -48,3 +48,17 @@ export function useBaseUrl() { }, []) return baseUrl } + +/** + * @returns The active user, or `null` until it is fetched from local storage + */ +export function useActiveUser(groupId: string) { + const [activeUser, setActiveUser] = useState(null) + + useEffect(() => { + const activeUser = localStorage.getItem(`${groupId}-activeUser`) + if (activeUser) setActiveUser(activeUser) + }, [groupId]) + + return activeUser +}