Add household privacy mode UI

This commit is contained in:
MOHAN 2026-07-16 23:22:36 +05:30
parent 69a88163dc
commit dada5e7d4f
2 changed files with 70 additions and 0 deletions

View File

@ -0,0 +1,9 @@
import { NextRequest } from "next/server";
import { proxyRequest } from "@/lib/backend";
export async function PATCH(
req: NextRequest,
{ params }: { params: { id: string } }
) {
return proxyRequest(req, `households/${params.id}/privacy`);
}

View File

@ -109,6 +109,11 @@ type HouseholdGoal = {
type DashboardData = { type DashboardData = {
household: Household; household: Household;
members: HouseholdMember[]; members: HouseholdMember[];
privacyMode: {
enabled: boolean;
hideIndividualBalances: boolean;
hideIndividualTransactions: boolean;
};
summary: { summary: {
memberCount: number; memberCount: number;
accountCount: number; accountCount: number;
@ -207,6 +212,7 @@ export default function HouseholdSettingsPage() {
}); });
const [fairSplitResult, setFairSplitResult] = useState<FairSplitResult | null>(null); const [fairSplitResult, setFairSplitResult] = useState<FairSplitResult | null>(null);
const [fairSplitStatus, setFairSplitStatus] = useState(""); const [fairSplitStatus, setFairSplitStatus] = useState("");
const [privacyStatus, setPrivacyStatus] = useState("");
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [status, setStatus] = useState(""); const [status, setStatus] = useState("");
@ -428,6 +434,25 @@ export default function HouseholdSettingsPage() {
await loadInvites(selectedId); await loadInvites(selectedId);
}; };
const updatePrivacyMode = async (enabled: boolean) => {
if (!selectedId) return;
setPrivacyStatus("Updating privacy mode...");
const res = await apiFetch<{ privacyMode: DashboardData["privacyMode"] }>(`/api/households/${selectedId}/privacy`, {
method: "PATCH",
body: JSON.stringify({
enabled,
hideIndividualBalances: true,
hideIndividualTransactions: true,
}),
});
if (res.error) {
setPrivacyStatus(res.error.message ?? "Unable to update privacy mode.");
return;
}
setPrivacyStatus(enabled ? "Privacy mode enabled." : "Privacy mode disabled.");
await loadDashboard(selectedId);
};
const maxCashflow = Math.max( const maxCashflow = Math.max(
1, 1,
...(dashboard?.cashflow ?? []).map((month) => Math.max(month.income, month.expenses)), ...(dashboard?.cashflow ?? []).map((month) => Math.max(month.income, month.expenses)),
@ -564,6 +589,42 @@ export default function HouseholdSettingsPage() {
</div> </div>
</div> </div>
<div className="glass-panel rounded-2xl p-6 shadow-sm">
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Financial independence</p>
<h2 className="mt-2 text-xl font-bold text-foreground">Privacy mode</h2>
<p className="mt-2 max-w-3xl text-sm text-muted-foreground">
When enabled, the shared dashboard only shows joint household accounts and joint transactions. Individual mine/theirs balances and activity stay out of the shared view.
</p>
{privacyStatus ? <p className="mt-2 text-sm text-muted-foreground">{privacyStatus}</p> : null}
</div>
<button
type="button"
onClick={() => updatePrivacyMode(!dashboard.privacyMode.enabled)}
className={`rounded-lg px-4 py-2 text-sm font-bold transition-colors ${
dashboard.privacyMode.enabled
? "border border-border bg-background text-foreground hover:bg-secondary"
: "bg-primary text-primary-foreground hover:bg-primary/90"
}`}
>
{dashboard.privacyMode.enabled ? "Disable privacy mode" : "Enable privacy mode"}
</button>
</div>
{dashboard.privacyMode.enabled ? (
<div className="mt-4 grid gap-3 md:grid-cols-2">
<div className="rounded-xl border border-border bg-background/40 p-4">
<p className="text-sm font-semibold text-foreground">Individual balances hidden</p>
<p className="mt-1 text-xs text-muted-foreground">Mine/theirs account balances are excluded from cards and ownership totals.</p>
</div>
<div className="rounded-xl border border-border bg-background/40 p-4">
<p className="text-sm font-semibold text-foreground">Individual transactions hidden</p>
<p className="mt-1 text-xs text-muted-foreground">Recent transactions and cashflow use joint account activity only.</p>
</div>
</div>
) : null}
</div>
<div className="glass-panel rounded-2xl p-6 shadow-sm"> <div className="glass-panel rounded-2xl p-6 shadow-sm">
<div className="grid gap-6 lg:grid-cols-[0.9fr_1.1fr]"> <div className="grid gap-6 lg:grid-cols-[0.9fr_1.1fr]">
<div> <div>