Files
firefly-ui/src/lib/components/Amount.svelte
T
hh 2231c08eee feat: show every amount in one currency, chosen in the header, $ toggles it
A selector in the header and the palette's Currency group pick the
currency, the primary one by default; the choice persists between pages
and $ switches it on and off. Rates come from Firefly's exchange rates,
then from the owner's own transactions with a foreign amount, walking
through other currencies when there is no direct pair. Amount converts
with a ≈ and keeps the original in its title; Money sums several
currencies into one converted amount.
2026-10-16 18:15:53 +00:00

63 lines
1.4 KiB
Svelte

<script lang="ts">
import { formatMoney, type Money, toNumber } from "#lib/format.js";
import { display } from "#lib/money/display.svelte.js";
export type Tone = "income" | "expense" | "transfer" | "neutral" | "auto";
let {
amount,
code,
symbol,
decimals,
tone = "auto",
signed = false,
approx = false,
exact = false,
class: className = "",
}: Money & {
tone?: Tone;
signed?: boolean;
approx?: boolean;
exact?: boolean;
class?: string;
} = $props();
const value = $derived(toNumber(amount));
const converted = $derived(
exact || !code || code === display.code
? null
: display.convert(value, code)
);
const original = $derived(
formatMoney({ amount, code, decimals, symbol }, signed)
);
const shown = $derived(
converted === null
? original
: formatMoney({ ...display.target, amount: converted }, signed)
);
const resolved = $derived.by(() => {
if (tone !== "auto") {
return tone;
}
if (value > 0) {
return "income";
}
return value < 0 ? "expense" : "neutral";
});
const color = $derived(
{
expense: "text-expense",
income: "text-income",
neutral: "text-cladd-fg-softer",
transfer: "text-transfer",
}[resolved]
);
</script>
<span
class="num font-medium {color} {className}"
title={converted === null ? undefined : original}
>{approx || converted !== null ? "≈" : ""}{shown}</span
>