diff --git a/src/app/groups/[groupId]/expenses/expense-card.tsx b/src/app/groups/[groupId]/expenses/expense-card.tsx index f4a5f288..239f8fdf 100644 --- a/src/app/groups/[groupId]/expenses/expense-card.tsx +++ b/src/app/groups/[groupId]/expenses/expense-card.tsx @@ -38,7 +38,8 @@ export function ExpenseCard({ expense, currency, groupId }: Props) { {expense.title}
- Paid by {expense.paidBy.name} for{' '} + {expense.amount > 0 ? 'Paid by ' : 'Received by '} + {expense.paidBy.name} for{' '} {expense.paidFor.map((paidFor, index) => ( {index !== 0 && <>, } diff --git a/src/app/groups/[groupId]/stats/totals-group-spending.tsx b/src/app/groups/[groupId]/stats/totals-group-spending.tsx index 3c0c96da..7cb35da6 100644 --- a/src/app/groups/[groupId]/stats/totals-group-spending.tsx +++ b/src/app/groups/[groupId]/stats/totals-group-spending.tsx @@ -6,11 +6,12 @@ type Props = { } export function TotalsGroupSpending({ totalGroupSpendings, currency }: Props) { + const balance = totalGroupSpendings < 0 ? 'earnings' : 'spendings' return (
-
Total group spendings
+
Total group {balance}
- {formatCurrency(currency, totalGroupSpendings)} + {formatCurrency(currency, Math.abs(totalGroupSpendings))}
) diff --git a/src/app/groups/[groupId]/stats/totals-your-share.tsx b/src/app/groups/[groupId]/stats/totals-your-share.tsx index 3218d6f6..3c7b7cb0 100644 --- a/src/app/groups/[groupId]/stats/totals-your-share.tsx +++ b/src/app/groups/[groupId]/stats/totals-your-share.tsx @@ -1,7 +1,7 @@ 'use client' import { getGroup, getGroupExpenses } from '@/lib/api' import { getTotalActiveUserShare } from '@/lib/totals' -import { formatCurrency } from '@/lib/utils' +import { cn, formatCurrency } from '@/lib/utils' import { useEffect, useState } from 'react' type Props = { @@ -26,8 +26,13 @@ export function TotalsYourShare({ group, expenses }: Props) { return (
Your total share
-
- {formatCurrency(currency, totalActiveUserShare)} +
+ {formatCurrency(currency, Math.abs(totalActiveUserShare))}
) diff --git a/src/app/groups/[groupId]/stats/totals-your-spending.tsx b/src/app/groups/[groupId]/stats/totals-your-spending.tsx index f621a41f..137574bc 100644 --- a/src/app/groups/[groupId]/stats/totals-your-spending.tsx +++ b/src/app/groups/[groupId]/stats/totals-your-spending.tsx @@ -2,7 +2,7 @@ import { getGroup, getGroupExpenses } from '@/lib/api' import { useActiveUser } from '@/lib/hooks' import { getTotalActiveUserPaidFor } from '@/lib/totals' -import { formatCurrency } from '@/lib/utils' +import { cn, formatCurrency } from '@/lib/utils' type Props = { group: NonNullable>> @@ -17,13 +17,19 @@ export function TotalsYourSpendings({ group, expenses }: Props) { ? 0 : getTotalActiveUserPaidFor(activeUser, expenses) const currency = group.currency + const balance = totalYourSpendings < 0 ? 'earnings' : 'spendings' return (
-
Total you paid for
+
Your total {balance}
-
- {formatCurrency(currency, totalYourSpendings)} +
+ {formatCurrency(currency, Math.abs(totalYourSpendings))}
) diff --git a/src/components/expense-form.tsx b/src/components/expense-form.tsx index fbc0099e..758e93d1 100644 --- a/src/components/expense-form.tsx +++ b/src/components/expense-form.tsx @@ -64,14 +64,15 @@ export type Props = { const enforceCurrencyPattern = (value: string) => value - // replace first comma with # - .replace(/[.,]/, '#') - // remove all other commas - .replace(/[.,]/g, '') - // change back # to dot - .replace(/#/, '.') - // remove all non-numeric and non-dot characters - .replace(/[^\d.]/g, '') + .replace(/^\s*-/, '_') // replace leading minus with _ + .replace(/[.,]/, '#') // replace first comma with # + .replace(/[-.,]/g, '') // remove other minus and commas characters + .replace(/_/, '-') // change back _ to minus + .replace(/#/, '.') // change back # to dot + .replace(/[^-\d.]/g, '') // remove all non-numeric characters + +const capitalize = (value: string) => + value.charAt(0).toUpperCase() + value.slice(1) const getDefaultSplittingOptions = (group: Props['group']) => { const defaultValue = { @@ -243,14 +244,16 @@ export function ExpenseForm({ return onSubmit(values, activeUserId ?? undefined) } + const [isIncome, setIsIncome] = useState(Number(form.getValues().amount) < 0) + const sExpense = isIncome ? 'income' : 'expense' + const sPaid = isIncome ? 'received' : 'paid' + return (
- - {isCreate ? <>Create expense : <>Edit expense} - + {(isCreate ? 'Create ' : 'Edit ') + sExpense} ( - Expense title + {capitalize(sExpense)} title - Enter a description for the expense. + Enter a description for the {sExpense}. @@ -290,7 +293,7 @@ export function ExpenseForm({ name="expenseDate" render={({ field }) => ( - Expense date + {capitalize(sExpense)} date - Enter the date the expense was made. + Enter the date the {sExpense} was {sPaid}. @@ -319,15 +322,17 @@ export function ExpenseForm({ {group.currency} - onChange(enforceCurrencyPattern(event.target.value)) - } + onChange={(event) => { + const v = enforceCurrencyPattern(event.target.value) + const income = Number(v) < 0 + setIsIncome(income) + if (income) form.setValue('isReimbursement', false) + onChange(v) + }} onFocus={(e) => { // we're adding a small delay to get around safaris issue with onMouseUp deselecting things again const target = e.currentTarget @@ -339,23 +344,25 @@ export function ExpenseForm({
- ( - - - - -
- This is a reimbursement -
-
- )} - /> + {!isIncome && ( + ( + + + + +
+ This is a reimbursement +
+
+ )} + /> + )} )} /> @@ -375,7 +382,7 @@ export function ExpenseForm({ isLoading={isCategoryLoading} /> - Select the expense category. + Select the {sExpense} category. @@ -387,7 +394,7 @@ export function ExpenseForm({ name="paidBy" render={({ field }) => ( - Paid by + {capitalize(sPaid)} by - Select the participant who paid the expense. + Select the participant who {sPaid} the {sExpense}. @@ -428,7 +435,7 @@ export function ExpenseForm({ - Paid for + {capitalize(sPaid)} for