feat(subscriptions): paying card set for several at once and kept in Firefly, quieter table
Each runway line says whether its card came from the last payment or was set by hand; x selects bills and a sets the card for all of them, stored in the Firefly preference ffui_bill_cards so every device sees it. Price change moves to the subscription page, per year turns grey, group sums follow the one-currency mode, key chips fit their buttons and the panels no longer show a focus ring. Linking found payments is y.
This commit is contained in:
1 parent
54895b9305
commit
c610aa58fa
10 files changed
+285
-130
No files matched your search
@@ -24,6 +24,7 @@
|
||||
import Calendar from "./Calendar.svelte";
|
||||
import CardMenu from "./CardMenu.svelte";
|
||||
import Money from "./Money.svelte";
|
||||
import Sums from "./Sums.svelte";
|
||||
|
||||
let {
|
||||
needs,
|
||||
@@ -69,8 +70,20 @@
|
||||
needs.flatMap((n) => n.dues).find((d) => d.bill.id === id)?.bill ?? null;
|
||||
}
|
||||
|
||||
function chosen(due: Due): string {
|
||||
const card = byCurrency && due.card ? `${due.card.name}: ` : "";
|
||||
if (due.manual) {
|
||||
return `${card}set by you`;
|
||||
}
|
||||
if (!due.lastPaid) {
|
||||
return "never paid";
|
||||
}
|
||||
const where = byCurrency ? "" : " here";
|
||||
return `${card}last paid${where} ${formatDate(due.lastPaid, "short")}`;
|
||||
}
|
||||
|
||||
const segment = (on: boolean) =>
|
||||
buttonVariants({ size: "xs", variant: on ? "default" : "outline" });
|
||||
buttonVariants({ size: "sm", variant: on ? "default" : "outline" });
|
||||
</script>
|
||||
|
||||
<section class="cladd-surface cladd-outline mb-3 rounded-cladd-lg">
|
||||
@@ -122,7 +135,7 @@
|
||||
</p>
|
||||
{:else}
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger {oncontextmenu}>
|
||||
<ContextMenuTrigger class="outline-none" {oncontextmenu}>
|
||||
<div
|
||||
class="grid gap-3 p-3 [grid-template-columns:repeat(auto-fill,minmax(16rem,1fr))]"
|
||||
>
|
||||
@@ -143,7 +156,7 @@
|
||||
<div
|
||||
class="font-semibold text-[26px] text-cladd-fg leading-tight"
|
||||
>
|
||||
<Money {...total} />
|
||||
<Money {...total} exact />
|
||||
</div>
|
||||
{/each}
|
||||
{#if need.short && need.currency}
|
||||
@@ -170,28 +183,33 @@
|
||||
{/if}
|
||||
<ul class="mt-2 border-cladd-outline border-t pt-1 text-[12px]">
|
||||
{#each need.dues as due, i (`${due.bill.id}:${due.date}:${i}`)}
|
||||
<li
|
||||
class="flex h-6 items-center gap-2"
|
||||
data-bill={due.bill.id}
|
||||
>
|
||||
<span
|
||||
class="num w-12 shrink-0 {due.overdue
|
||||
? "text-expense"
|
||||
: "text-cladd-fg-soft"}"
|
||||
>{due.overdue
|
||||
? "overdue"
|
||||
: formatDate(due.date, "short")}</span
|
||||
<li class="py-0.5" data-bill={due.bill.id}>
|
||||
<div class="flex h-5 items-center gap-2">
|
||||
<span
|
||||
class="num w-12 shrink-0 {due.overdue
|
||||
? "text-expense"
|
||||
: "text-cladd-fg-soft"}"
|
||||
>{due.overdue
|
||||
? "overdue"
|
||||
: formatDate(due.date, "short")}</span
|
||||
>
|
||||
<a
|
||||
class="min-w-0 flex-1 truncate text-cladd-fg hover:underline"
|
||||
href="/subscriptions/show/{due.bill.id}"
|
||||
>{due.bill.attributes.name}</a
|
||||
>
|
||||
<Money
|
||||
{...due.pay}
|
||||
approx={due.approx}
|
||||
class="font-medium text-cladd-fg"
|
||||
exact
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="truncate ps-14 text-[11px] text-cladd-fg-softer leading-4"
|
||||
>
|
||||
<a
|
||||
class="min-w-0 flex-1 truncate text-cladd-fg hover:underline"
|
||||
href="/subscriptions/show/{due.bill.id}"
|
||||
>{due.bill.attributes.name}</a
|
||||
>
|
||||
<Money
|
||||
{...due.pay}
|
||||
approx={due.approx}
|
||||
class="font-medium text-cladd-fg"
|
||||
/>
|
||||
{chosen(due)}
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
@@ -211,7 +229,7 @@
|
||||
>Edit</ContextMenuItem
|
||||
>
|
||||
<ContextMenuSeparator />
|
||||
<CardMenu billId={target.id} {cards} />
|
||||
<CardMenu billIds={[target.id]} {cards} />
|
||||
{/if}
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
@@ -225,10 +243,7 @@
|
||||
>Annual renewals in {RENEWAL_DAYS} days:</span
|
||||
>
|
||||
<span class="font-semibold text-cladd-fg"
|
||||
>{renewals.length},
|
||||
{#each renewalTotals as total, i (total.code)}
|
||||
{i > 0 ? " + " : ""}<Money {...total} />
|
||||
{/each}</span
|
||||
>{renewals.length}, <Sums inline parts={renewalTotals} /></span
|
||||
>
|
||||
{#each renewals as due (due.bill.id)}
|
||||
<span class="text-cladd-fg-soft"
|
||||
|
||||
Reference in new issue
Block a user