feat(dashboard,accounts,charts): v1 dashboard redrawn, account lists and pages, svg chart kit
This commit is contained in:
1 parent
62cd17ecde
commit
9e89829bae
36 files changed
+5678
-16
No files matched your search
@@ -0,0 +1,103 @@
|
||||
<script lang="ts">
|
||||
import { createQuery, keepPreviousData } from "@tanstack/svelte-query";
|
||||
import { showUrl } from "#lib/components/accounts/links.js";
|
||||
import Box from "#lib/components/Box.svelte";
|
||||
import BarChart from "#lib/components/charts/BarChart.svelte";
|
||||
import { tones } from "#lib/components/charts/chart.js";
|
||||
import { toNumber } from "#lib/format.js";
|
||||
import { period } from "#lib/period.svelte.js";
|
||||
import { accountsQuery, byCurrency, money } from "./data.js";
|
||||
|
||||
const liabilities = createQuery(() => ({
|
||||
...accountsQuery("liabilities", period.start, period.end),
|
||||
placeholderData: keepPreviousData,
|
||||
}));
|
||||
|
||||
const groups = $derived(
|
||||
byCurrency(
|
||||
(liabilities.data ?? []).filter(
|
||||
(a) =>
|
||||
a.attributes.liability_type === "debt" &&
|
||||
toNumber(a.attributes.debt_amount) !== 0
|
||||
),
|
||||
(a) => a.attributes.currency_code ?? ""
|
||||
).map(([code, list]) => {
|
||||
const first = list[0].attributes;
|
||||
const format = money({
|
||||
code,
|
||||
decimals: first.currency_decimal_places ?? 2,
|
||||
symbol: first.currency_symbol ?? code,
|
||||
});
|
||||
const bars = list
|
||||
.map((a) => {
|
||||
const due = Math.abs(toNumber(a.attributes.debt_amount));
|
||||
const value =
|
||||
a.attributes.liability_direction === "credit" ? due : -due;
|
||||
return {
|
||||
color: value > 0 ? tones.income : tones.expense,
|
||||
href: showUrl(a.id),
|
||||
key: a.id,
|
||||
label: a.attributes.name,
|
||||
value,
|
||||
};
|
||||
})
|
||||
.sort((x, y) => y.value - x.value);
|
||||
const owed = bars
|
||||
.filter((b) => b.value > 0)
|
||||
.reduce((s, b) => s + b.value, 0);
|
||||
const owe = bars
|
||||
.filter((b) => b.value < 0)
|
||||
.reduce((s, b) => s - b.value, 0);
|
||||
return { bars, code, format, owe, owed };
|
||||
})
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if groups.length > 0}
|
||||
<Box href="/accounts/liabilities" title="Debts with friends">
|
||||
<div
|
||||
class="flex flex-col gap-4 transition-opacity {liabilities.isPlaceholderData
|
||||
? "opacity-60"
|
||||
: ""}"
|
||||
>
|
||||
{#each groups as group (group.code)}
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<div class="flex items-baseline gap-3 text-[12px]">
|
||||
<span
|
||||
class="font-semibold text-[11px] text-cladd-fg-soft tracking-wide"
|
||||
>{group.code}</span
|
||||
>
|
||||
{#if group.owed > 0}
|
||||
<span class="text-cladd-fg-soft"
|
||||
>Owed to me
|
||||
<span class="num text-income"
|
||||
>{group.format(group.owed)}</span
|
||||
></span
|
||||
>
|
||||
{/if}
|
||||
{#if group.owe > 0}
|
||||
<span class="text-cladd-fg-soft"
|
||||
>I owe
|
||||
<span class="num text-expense"
|
||||
>{group.format(group.owe)}</span
|
||||
></span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<BarChart
|
||||
bars={group.bars}
|
||||
format={group.format}
|
||||
label="Debts with friends in {group.code}"
|
||||
labelWidth="minmax(5rem, 9rem)"
|
||||
orientation="horizontal"
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{#snippet footer()}
|
||||
<a class="text-brand hover:underline" href="/accounts/liabilities"
|
||||
>See your liabilities</a
|
||||
>
|
||||
{/snippet}
|
||||
</Box>
|
||||
{/if}
|
||||
Reference in new issue
Block a user