fix(budgets,tags,piggy-banks,dashboard): live buttons that answer in place, lucide icons, mobile wrapping

This commit is contained in:
hh committed 2026-10-16 04:26:07 +00:00
1 parent aba2509399
commit f3a603648e
10 files changed
+102 -71

No files matched your search

@@ -133,7 +133,12 @@
async function create(event: SubmitEvent) {
event.preventDefault();
const name = newName.trim();
if (!name || creating) {
if (creating) {
return;
}
if (!name) {
createError = "Type a name first";
createInput?.focus();
return;
}
creating = true;
@@ -333,12 +338,12 @@
{/if}
{#if !extra && row.lines.length < enabled.length}
<button
class="ml-auto text-[11px] text-cladd-fg-softer hover:text-brand max-sm:hidden"
class="ml-auto inline-flex items-center gap-0.5 text-[11px] text-cladd-fg-softer hover:text-brand max-sm:hidden"
onclick={() => startAdding(row)}
title="Budget an amount in another currency (a)"
type="button"
>
+ currency
<Plus class="size-3" />currency
</button>
{/if}
</div>
@@ -453,23 +458,30 @@
</tr>
{/each}
{/each}
<tr class="border-cladd-outline border-t bg-cladd-surface-next/40">
<td class="px-3 py-1.5 sm:whitespace-nowrap">
<a class="text-brand italic hover:underline" href={noBudgetHref}
>Expenses without a budget</a
>
{#if query.data?.noBudgetCount}
<span class="ml-1.5 text-[12px] text-cladd-fg-soft"
>{query.data.noBudgetCount}
transactions</span
>
{/if}
<tr
class="border-cladd-outline border-t bg-cladd-surface-next/40 max-sm:hidden"
>
<td class="whitespace-nowrap px-3 py-1.5">
{@render noBudgetLabel()}
</td>
<td></td>
<td class="px-3 py-1.5 text-right">
<MoneyList sums={query.data?.noBudget ?? []} />
</td>
<td class="max-sm:hidden" colspan="2"></td>
<td colspan="2"></td>
</tr>
<tr
class="border-cladd-outline border-t bg-cladd-surface-next/40 sm:hidden"
>
<td class="px-3 py-1.5" colspan="3">
<div class="flex items-start justify-between gap-3">
<div>{@render noBudgetLabel()}</div>
<MoneyList
class="flex-col items-end"
sums={query.data?.noBudget ?? []}
/>
</div>
</td>
</tr>
</tbody>
{/snippet}
@@ -481,13 +493,12 @@
<input
aria-label="New budget name"
class="cladd-cut cladd-focusable-input h-7 w-64 min-w-0 flex-1 rounded-cladd-sm px-2 text-[13px] sm:flex-none"
oninput={() => (createError = "")}
placeholder="New budget name (c)"
bind:this={createInput}
bind:value={newName}
>
<Button disabled={creating || !newName.trim()} size="sm" type="submit"
>Create</Button
>
<Button disabled={creating} size="sm" type="submit">Create</Button>
{#if createError}
<span class="text-expense">{createError}</span>
{/if}
@@ -495,6 +506,18 @@
{/snippet}
</Box>
{#snippet noBudgetLabel()}
<a class="text-brand italic hover:underline" href={noBudgetHref}
>Expenses without a budget</a
>
{#if query.data?.noBudgetCount}
<span class="ml-1.5 whitespace-nowrap text-[12px] text-cladd-fg-soft"
>{query.data.noBudgetCount}
transactions</span
>
{/if}
{/snippet}
{#if inactive.length > 0}
<Box class="mt-4" title="Inactive budgets">
<p class="text-[13px]">
+8 -4
View File
@@ -115,7 +115,12 @@
async function create(event: SubmitEvent) {
event.preventDefault();
const name = newName.trim();
if (!name || creating) {
if (creating) {
return;
}
if (!name) {
createError = "Type a name first";
createInput?.focus();
return;
}
creating = true;
@@ -326,13 +331,12 @@
<input
aria-label="New category name"
class="cladd-cut cladd-focusable-input h-7 w-64 rounded-cladd-sm px-2 text-[13px]"
oninput={() => (createError = "")}
placeholder="New category name (c)"
bind:this={createInput}
bind:value={newName}
>
<Button disabled={creating || !newName.trim()} size="sm" type="submit"
>Create</Button
>
<Button disabled={creating} size="sm" type="submit">Create</Button>
{#if createError}
<span class="text-expense">{createError}</span>
{/if}
+2 -22
View File
@@ -19,7 +19,6 @@
import { errorText } from "#lib/components/misc/action.svelte.js";
import MoneyEditor from "#lib/components/piggy-banks/MoneyEditor.svelte";
import {
limit,
type Mode,
piggyMoney,
rooms,
@@ -67,19 +66,6 @@
.map((p) => piggyMoney(p.attributes, p.attributes[field]))
);
const canAdd = (p: Item<PiggyBank>) =>
(p.attributes.accounts ?? []).some(
(a) =>
limit(
p.attributes,
a.account_id ?? "",
"add",
room.get(a.account_id ?? "")
) > 0
);
const canRemove = (p: Item<PiggyBank>) =>
toNumber(p.attributes.current_amount) > 0;
function startMoney(p: Item<PiggyBank> | undefined, mode: Mode): void {
if (p) {
nav.cursor = rows.indexOf(p);
@@ -294,7 +280,6 @@
size: "icon-xs",
variant: "ghost",
})}
disabled={!canRemove(item)}
onclick={() => startMoney(item, "remove")}
title="Remove money (-)"
type="button"
@@ -329,7 +314,6 @@
size: "icon-xs",
variant: "ghost",
})}
disabled={!canAdd(item)}
onclick={() => startMoney(item, "add")}
title="Add money (+)"
type="button"
@@ -391,14 +375,10 @@
onSelect={() => goto(`/piggy-banks/edit/${target.id}`)}
>Edit</ContextMenuItem
>
<ContextMenuItem
disabled={!canAdd(target)}
onSelect={() => startMoney(target, "add")}
<ContextMenuItem onSelect={() => startMoney(target, "add")}
>Add money</ContextMenuItem
>
<ContextMenuItem
disabled={!canRemove(target)}
onSelect={() => startMoney(target, "remove")}
<ContextMenuItem onSelect={() => startMoney(target, "remove")}
>Remove money</ContextMenuItem
>
<ContextMenuSeparator />
@@ -345,7 +345,6 @@
</button>
<button
class={buttonVariants({ size: "sm", variant: "outline" })}
disabled={toNumber(piggy.current_amount) <= 0}
onclick={() => setMode("remove")}
type="button"
>
@@ -118,10 +118,12 @@
</Field>
</div>
{#snippet footer()}
<Button disabled={save.busy || locked} size="sm" type="submit">
{item ? "Update link type" : "Store new link type"}
</Button>
<Status action={save} />
{#if !locked}
<Button disabled={save.busy} size="sm" type="submit">
{item ? "Update link type" : "Store new link type"}
</Button>
<Status action={save} />
{/if}
{#if item && !locked}
<span class="ml-auto flex items-center gap-2">
<Status action={removal} busy="Deleting" />
+8 -4
View File
@@ -130,7 +130,12 @@
async function create(event: SubmitEvent) {
event.preventDefault();
const tag = newTag.trim();
if (!tag || creating) {
if (creating) {
return;
}
if (!tag) {
createError = "Type a tag first";
createInput?.focus();
return;
}
creating = true;
@@ -446,13 +451,12 @@
<input
aria-label="New tag"
class="cladd-cut cladd-focusable-input h-7 w-64 rounded-cladd-sm px-2 text-[13px]"
oninput={() => (createError = "")}
placeholder="New tag, parent/child works (c)"
bind:this={createInput}
bind:value={newTag}
>
<Button disabled={creating || !newTag.trim()} size="sm" type="submit"
>Create</Button
>
<Button disabled={creating} size="sm" type="submit">Create</Button>
{#if createError}
<span class="text-expense">{createError}</span>
{/if}