diff --git a/src/app/shared/page.tsx b/src/app/shared/page.tsx index 3850bbc..6f64758 100644 --- a/src/app/shared/page.tsx +++ b/src/app/shared/page.tsx @@ -5,6 +5,7 @@ import { useSharedTransactions, useParticipantBalances, useSettleSplits, + useCreateParticipant, } from "@/lib/hooks"; import type { SharedTransactionRow } from "@/lib/queries"; @@ -12,8 +13,67 @@ function formatDate(d: string) { return new Date(d).toLocaleDateString("en-AU", { day: "numeric", month: "short", year: "numeric" }); } -function formatAmount(n: number) { - return `$${Number(n).toFixed(2)}`; +const SPEND_TYPES = new Set(["debit", "fee", "interest"]); + +function formatAmount(n: number, type?: string) { + const formatted = `$${Number(n).toFixed(2)}`; + return type && !SPEND_TYPES.has(type) ? `+${formatted}` : formatted; +} + +function AddParticipantForm({ onDone }: { onDone: () => void }) { + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [error, setError] = useState(""); + const create = useCreateParticipant(); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + setError(""); + if (!name.trim()) { setError("Name is required"); return; } + try { + await create.mutateAsync({ name: name.trim(), email: email.trim() || undefined }); + onDone(); + } catch (err) { + setError(err instanceof Error ? err.message : "Failed to create"); + } + } + + return ( +
+ ); } export default function SharedPage() { @@ -21,6 +81,7 @@ export default function SharedPage() { const { data: balances = [], isLoading: balLoading } = useParticipantBalances(); const settle = useSettleSplits(); const [settling, setSettling] = useStateLoading balances...
) : ( - others.map((b) => ( -{b.name}
-{b.unsettled_count} unsettled
-{formatAmount(b.total_owed)}
-owes you
+ balances.map((b) => { + const theyOweMe = b.total_owed > 0; + const net = Math.abs(b.total_owed); + return ( +{b.name}
++ {theyOweMe ? `${b.unsettled_count} unsettled` : "you owe"} +
++ ${net.toFixed(2)} +
+{theyOweMe ? "owes you" : "you owe"}
+{tx.effective_merchant || tx.description}
{tx.description}
-