diff --git a/apps/web/src/data/ledgers.ts b/apps/web/src/data/ledgers.ts index ade960b..557c9ee 100644 --- a/apps/web/src/data/ledgers.ts +++ b/apps/web/src/data/ledgers.ts @@ -1,4 +1,4 @@ -import { ledgerThemeAccents, type CurrencyCode, type LedgerThemeId } from "@cents/domain"; +import { ledgerThemeAccents, type CurrencyCode, type LedgerAmountDisplayMode, type LedgerThemeId } from "@cents/domain"; export const ledgerThemes: ReadonlyArray<{ id: LedgerThemeId; @@ -30,6 +30,7 @@ export type LedgerRecord = { color: string; theme: LedgerThemeId; defaultCurrency: CurrencyCode; + amountDisplay: LedgerAmountDisplayMode; createdAt: string; updatedAt: string; archivedAt: string | null; @@ -40,7 +41,7 @@ export type LedgerRecord = { export type UserPreference = { id: string; userId: string; - key: "currentLedgerId"; + key: "currentLedgerId" | "ledgerAmountDisplay"; value: string; updatedAt: string; }; @@ -49,6 +50,10 @@ export function currentLedgerPreferenceId(userId: string) { return `${userId}:currentLedgerId`; } +export function ledgerAmountDisplayPreferenceId(userId: string, ledgerId: string) { + return `${userId}:ledgerAmountDisplay:${ledgerId}`; +} + export function createDefaultLedgers(): LedgerRecord[] { const now = new Date().toISOString(); return [ @@ -58,6 +63,7 @@ export function createDefaultLedgers(): LedgerRecord[] { color: "#087f72", theme: "jade", defaultCurrency: "CNY", + amountDisplay: "base", createdAt: now, updatedAt: now, archivedAt: null, @@ -69,6 +75,7 @@ export function createDefaultLedgers(): LedgerRecord[] { color: "#3478e5", theme: "ocean", defaultCurrency: "CNY", + amountDisplay: "base", createdAt: now, updatedAt: now, archivedAt: null, diff --git a/apps/web/src/stores/ledgers.ts b/apps/web/src/stores/ledgers.ts index 37bcc84..a4bcab8 100644 --- a/apps/web/src/stores/ledgers.ts +++ b/apps/web/src/stores/ledgers.ts @@ -1,7 +1,8 @@ import { defineStore } from "pinia"; import { apiRequest } from "../data/api"; import { db } from "../data/db"; -import { currentLedgerPreferenceId, type LedgerRecord, type UserPreference } from "../data/ledgers"; +import { currentLedgerPreferenceId, ledgerAmountDisplayPreferenceId, type LedgerRecord, type UserPreference } from "../data/ledgers"; +import type { LedgerAmountDisplayMode } from "@cents/domain"; import { useAuthStore } from "./auth"; export type LedgerMember = { @@ -39,7 +40,18 @@ export const useLedgerStore = defineStore("ledgers", { const auth = useAuthStore(); if (!auth.user) return; const result = await apiRequest<{ ledgers: LedgerRecord[] }>("/api/ledgers"); - const serverLedgers = result.ledgers.map((ledger) => ({ ...ledger })); + const displayPreferences = await db.userPreferences + .where("userId") + .equals(auth.user.id) + .filter((preference) => preference.key === "ledgerAmountDisplay") + .toArray(); + const displayByLedger = new Map( + displayPreferences.map((preference) => [preference.id.split(":").at(-1), preference.value as LedgerAmountDisplayMode]), + ); + const serverLedgers = result.ledgers.map((ledger) => ({ + ...ledger, + amountDisplay: displayByLedger.get(ledger.id) ?? "base", + })); this.ledgers = serverLedgers; const allowedIds = new Set(this.ledgers.map((ledger) => ledger.id)); @@ -118,8 +130,22 @@ export const useLedgerStore = defineStore("ledgers", { await this.setCurrentLedger(result.ledger.id); return result.ledger; }, - async updateLedger(input: Pick) { - await apiRequest(`/api/ledgers/${encodeURIComponent(input.id)}`, { method: "PATCH", body: input }); + async updateLedger(input: Pick & { amountDisplay?: LedgerAmountDisplayMode }) { + const { amountDisplay, ...serverInput } = input; + await apiRequest(`/api/ledgers/${encodeURIComponent(input.id)}`, { method: "PATCH", body: serverInput }); + if (amountDisplay) { + const auth = useAuthStore(); + if (auth.user) { + const preference: UserPreference = { + id: ledgerAmountDisplayPreferenceId(auth.user.id, input.id), + userId: auth.user.id, + key: "ledgerAmountDisplay", + value: amountDisplay, + updatedAt: new Date().toISOString(), + }; + await db.userPreferences.put(preference); + } + } await this.reloadLedgers(); return this.ledgers.find((ledger) => ledger.id === input.id)!; }, diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index 399094a..9723c8a 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -92,35 +92,11 @@ input:focus-visible { .top-actions { display: grid; - grid-template-columns: 56px minmax(0, 1fr) auto; + grid-template-columns: 56px 1fr 40px; align-items: center; gap: 10px; } -.header-right-actions { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 6px; -} - -.currency-display-button { - width: 34px; - height: 34px; - display: inline-grid; - place-items: center; - border: 1px solid rgba(255, 255, 255, 0.28); - border-radius: 7px; - padding: 0; - background: rgba(0, 0, 0, 0.12); - color: rgba(255, 255, 255, 0.82); -} - -.currency-display-button.active { - background: rgba(255, 255, 255, 0.2); - color: #ffffff; -} - .participant-avatars { width: 56px; height: 40px; diff --git a/apps/web/src/views/LedgerSettingsView.vue b/apps/web/src/views/LedgerSettingsView.vue index 1b1192c..45cf766 100644 --- a/apps/web/src/views/LedgerSettingsView.vue +++ b/apps/web/src/views/LedgerSettingsView.vue @@ -1,5 +1,5 @@