Show the impact of an expense on the active user's balance (#139)

* Add devcontainer configuration for codespace support

* Show the impact of an expense on the active user's balance

* Run prettier

* Put the balance on a different line

---------

Co-authored-by: Sebastien Castiel <sebastien@castiel.me>
This commit is contained in:
dcbr
2024-04-13 19:07:18 +02:00
committed by GitHub
parent 1ad470309b
commit 1cd2b273f9
3 changed files with 78 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
'use client'
import { Money } from '@/components/money'
import { getBalances } from '@/lib/balances'
import { useActiveUser } from '@/lib/hooks'
type Props = {
groupId: string
currency: string
expense: Parameters<typeof getBalances>[0][number]
}
export function ActiveUserBalance({ groupId, currency, expense }: Props) {
const activeUserId = useActiveUser(groupId)
if (activeUserId === null || activeUserId === '' || activeUserId === 'None') {
return null
}
const balances = getBalances([expense])
let fmtBalance = <>You are not involved</>
if (Object.hasOwn(balances, activeUserId)) {
const balance = balances[activeUserId]
let balanceDetail = <></>
if (balance.paid > 0 && balance.paidFor > 0) {
balanceDetail = (
<>
{' ('}
<Money {...{ currency, amount: balance.paid }} />
{' - '}
<Money {...{ currency, amount: balance.paidFor }} />
{')'}
</>
)
}
fmtBalance = (
<>
Your balance:{' '}
<Money {...{ currency, amount: balance.total }} bold colored />
{balanceDetail}
</>
)
}
return <div className="text-xs text-muted-foreground">{fmtBalance}</div>
}

View File

@@ -1,4 +1,5 @@
'use client'
import { ActiveUserBalance } from '@/app/groups/[groupId]/expenses/active-user-balance'
import { CategoryIcon } from '@/app/groups/[groupId]/expenses/category-icon'
import { Button } from '@/components/ui/button'
import { SearchBar } from '@/components/ui/search-bar'
@@ -151,6 +152,9 @@ export function ExpenseList({
</Fragment>
))}
</div>
<div className="text-xs text-muted-foreground">
<ActiveUserBalance {...{ groupId, currency, expense }} />
</div>
</div>
<div className="flex flex-col justify-between items-end">
<div

31
src/components/money.tsx Normal file
View File

@@ -0,0 +1,31 @@
'use client'
import { cn, formatCurrency } from '@/lib/utils'
type Props = {
currency: string
amount: number
bold?: boolean
colored?: boolean
}
export function Money({
currency,
amount,
bold = false,
colored = false,
}: Props) {
return (
<span
className={cn(
colored && amount <= 1
? 'text-red-600'
: colored && amount >= 1
? 'text-green-600'
: '',
bold && 'font-bold',
)}
>
{formatCurrency(currency, amount)}
</span>
)
}