aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2025-01-15 15:37:19 -0800
committerAdam Soltys <[email protected]>2025-01-15 15:37:19 -0800
commit0a69cf4077363c56e6e5e1b8c8857c2d25e3986a (patch)
tree70648825da0e86cdb76decf44023b71a696b3b36 /src
parent97f9c4f245fb90df5c8048ac5a9e62208e37c484 (diff)
downloadcoinos-ui-0a69cf4077363c56e6e5e1b8c8857c2d25e3986a.tar.gz
coinos-ui-0a69cf4077363c56e6e5e1b8c8857c2d25e3986a.zip
invoice type selection
Diffstat (limited to 'src')
-rw-r--r--src/components/InvoiceActions.svelte84
-rw-r--r--src/components/InvoiceTypes.svelte185
-rw-r--r--src/components/SetType.svelte37
-rw-r--r--src/routes/(app)/[username]/receive/+page.svelte30
-rw-r--r--src/routes/(app)/invoice/[id]/+page.svelte34
5 files changed, 274 insertions, 96 deletions
diff --git a/src/components/InvoiceActions.svelte b/src/components/InvoiceActions.svelte
index c0f8f572..0f500fe6 100644
--- a/src/components/InvoiceActions.svelte
+++ b/src/components/InvoiceActions.svelte
@@ -1,4 +1,6 @@
<script>
+ import { goto } from "$app/navigation";
+ import InvoiceTypes from "$comp/InvoiceTypes.svelte";
let {
user,
invoice,
@@ -8,39 +10,72 @@
type,
showQr = $bindable(),
txt,
+ setAmount,
+ newAmount = $bindable(),
+ toggleType,
toggleAmount,
+ setType,
toggleMemo,
} = $props();
</script>
<div class="text-secondary space-y-2 text-xl pt-2">
- <button type="button" class="btn" onclick={() => copy(txt)}>
- <iconify-icon noobserver icon="ph:copy-bold" width="32"></iconify-icon>
- <div class="my-auto">
- {t("payments.copy")}
- </div>
- </button>
+ <InvoiceTypes
+ {invoice}
+ {user}
+ {toggleType}
+ bind:newAmount
+ {setAmount}
+ {setType}
+ t={$t}
+ activeOnly={true}
+ />
+
+ <div class="flex flex-wrap gap-2 justify-around text-secondary w-full">
+ <button type="button" class="btn !w-auto grow" onclick={() => copy(txt)}>
+ <iconify-icon noobserver icon="ph:copy-bold" width="32"></iconify-icon>
+ <div class="my-auto">
+ {t("payments.copy")}
+ </div>
+ </button>
- {#if user?.id === invoice?.user?.id}
- <button class="btn" onclick={toggleAmount}>
- <iconify-icon noobserver icon="ph:pencil-simple-bold" width="32"></iconify-icon>
- <div class="my-auto">{t("payments.setAmount")}</div>
+ <button class="btn grow !w-auto" onclick={() => goto("/receive")}>
+ <iconify-icon noobserver icon="ph:clipboard-text-bold" width="32"
+ ></iconify-icon>
+ <div class="my-auto text-lg">{t("user.send.paste")}</div>
</button>
- {:else}
- <a href={link} class="block">
- <button class="btn">
- <iconify-icon noobserver icon="ph:wallet-bold" width="32"></iconify-icon>
- <div class="my-auto">{t("payments.openLink")}</div>
+
+ <button class="btn grow !w-auto" onclick={() => goto("/scan")}>
+ <iconify-icon noobserver icon="ph:camera-bold" width="32"></iconify-icon>
+ <div class="my-auto text-lg">{t("user.send.scan")}</div>
+ </button>
+ </div>
+
+ <div class="flex flex-wrap gap-2 justify-around text-secondary w-full">
+ {#if user?.id === invoice?.user?.id}
+ <button class="btn grow !w-auto" onclick={toggleAmount}>
+ <iconify-icon noobserver icon="ph:pencil-simple-bold" width="32"
+ ></iconify-icon>
+ <div class="my-auto">{t("payments.setAmount")}</div>
</button>
- </a>
- {/if}
+ {:else}
+ <a href={link} class="block">
+ <button class="btn grow !w-auto">
+ <iconify-icon noobserver icon="ph:wallet-bold" width="32"
+ ></iconify-icon>
+ <div class="my-auto">{t("payments.openLink")}</div>
+ </button>
+ </a>
+ {/if}
- <button class="btn" onclick={toggleMemo}>
- <iconify-icon noobserver icon="ph:chat-centered-text-bold" width="32"></iconify-icon>
- <div class="my-auto">
- {t("invoice.setMemo")}
- </div>
- </button>
+ <button class="btn grow !w-auto" onclick={toggleMemo}>
+ <iconify-icon noobserver icon="ph:chat-centered-text-bold" width="32"
+ ></iconify-icon>
+ <div class="my-auto">
+ {t("invoice.setMemo")}
+ </div>
+ </button>
+ </div>
{#if txt.length > 120}
<div class="w-full flex justify-center gap-2 flex-wrap">
@@ -49,7 +84,8 @@
<iconify-icon noobserver icon="ph:text-align-center-bold" width="32"
></iconify-icon>
{:else}
- <iconify-icon noobserver icon="ph:qr-code-bold" width="32"></iconify-icon>
+ <iconify-icon noobserver icon="ph:qr-code-bold" width="32"
+ ></iconify-icon>
{/if}
<div class="my-auto">
{showQr ? t("payments.showText") : t("payments.showQr")}
diff --git a/src/components/InvoiceTypes.svelte b/src/components/InvoiceTypes.svelte
index c4d7fa77..0829fc82 100644
--- a/src/components/InvoiceTypes.svelte
+++ b/src/components/InvoiceTypes.svelte
@@ -1,79 +1,133 @@
<script>
import { types } from "$lib/utils";
- import { goto } from "$app/navigation";
import { page } from "$app/stores";
- let { aid, invoice, user, type, t, setType } = $props();
+ import { amountPrompt } from "$lib/store";
+ let {
+ newAmount = $bindable(),
+ invoice,
+ user,
+ t,
+ toggleType,
+ setAmount,
+ setType,
+ activeOnly,
+ } = $props();
+
+ let { aid, address_type, type } = $derived(invoice);
</script>
{#if invoice.uid === aid}
- <div class="grid grid-cols-2 gap-2 justify-around text-secondary">
- <button
- class="btn flex-nowrap"
- class:bg-base-300={type === types.lightning}
- class:text-secondary={type === types.lightning}
- onclick={() => setType(types.lightning)}
- >
- <div
- class="bg-black rounded-full w-8 h-8 items-center justify-center flex"
- >
- <div class="m-auto">
- <iconify-icon
- noobserver
- icon="ph:lightning-fill"
- class="text-yellow-300 text-2xl"
- ></iconify-icon>
- </div>
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.lightning &&
+ $page.url.pathname.includes("/receive")}
+ class:text-secondary={type === types.lightning &&
+ $page.url.pathname.includes("/receive")}
+ class:hidden={activeOnly &&
+ (type !== types.lightning || !$page.url.pathname.includes("/receive"))}
+ onclick={() => {
+ if (activeOnly) toggleType();
+ else {
+ $amountPrompt = false;
+ newAmount = undefined;
+ setType(types.lightning);
+ }
+ }}
+ >
+ <div class="bg-black rounded-full w-8 h-8 items-center justify-center flex">
+ <div class="m-auto">
+ <iconify-icon
+ noobserver
+ icon="ph:lightning-fill"
+ class="text-yellow-300 text-2xl"
+ ></iconify-icon>
</div>
- <div class="my-auto text-lg">Lightning</div>
- </button>
+ </div>
+ <div class="my-auto text-lg">LNURL</div>
+ </button>
- <button
- class="btn flex-nowrap"
- class:bg-base-300={type === types.ecash}
- class:text-secondary={type === types.ecash}
- onclick={() => setType(types.ecash)}
- >
- <img src="/images/cash.png" class="w-8 my-auto" />
- <div class="my-auto text-lg">Ecash</div>
- </button>
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.ecash}
+ class:text-secondary={type === types.ecash}
+ class:hidden={activeOnly && type !== types.ecash}
+ onclick={() => (activeOnly ? toggleType() : setType(types.ecash))}
+ >
+ <img src="/images/cash.png" class="w-8 my-auto" />
+ <div class="my-auto text-lg">Ecash</div>
+ </button>
- <button
- class="btn flex-nowrap"
- class:bg-base-300={type === types.bitcoin}
- class:text-secondary={type === types.bitcoin}
- onclick={() => setType(types.bitcoin)}
- >
- <img src="/images/bitcoin.svg" class="w-8" alt="Bitcoin" />
- <div class="my-auto text-lg">Bitcoin</div>
- </button>
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.bitcoin && address_type === "bech32"}
+ class:text-secondary={type === types.bitcoin && address_type === "bech32"}
+ class:hidden={activeOnly &&
+ (type !== types.bitcoin || address_type !== "bech32")}
+ onclick={() => (activeOnly ? toggleType() : setType(types.bitcoin))}
+ >
+ <img src="/images/bitcoin.svg" class="w-8" alt="Bitcoin" />
+ <div class="my-auto text-lg">Segwit</div>
+ </button>
- <button
- class="btn flex-nowrap"
- class:bg-base-300={type === types.liquid}
- class:text-secondary={type === types.liquid}
- onclick={() => setType(types.liquid)}
- >
- <img src="/images/liquid.svg" class="w-8" alt="Liquid" />
- <div class="my-auto text-lg">Liquid</div>
- </button>
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.liquid}
+ class:text-secondary={type === types.liquid}
+ class:hidden={activeOnly && type !== types.liquid}
+ onclick={() => (activeOnly ? toggleType() : setType(types.liquid))}
+ >
+ <img src="/images/liquid.svg" class="w-8" alt="Liquid" />
+ <div class="my-auto text-lg">Liquid</div>
+ </button>
- <button class="btn flex-nowrap" onclick={() => goto("/scan")}>
- <iconify-icon noobserver icon="ph:camera-bold" width="32"></iconify-icon>
- <div class="my-auto text-lg">{t("user.send.scan")}</div>
- </button>
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.lightning &&
+ !$page.url.pathname.includes("/receive")}
+ class:text-secondary={type === types.lightning &&
+ !$page.url.pathname.includes("/receive")}
+ class:hidden={activeOnly &&
+ (type !== types.lightning || $page.url.pathname.includes("/receive"))}
+ onclick={() => {
+ if (activeOnly) toggleType();
+ else {
+ $amountPrompt = false;
+ newAmount = 0;
+ setType(types.lightning);
+ }
+ }}
+ >
+ <div class="bg-black rounded-full w-8 h-8 items-center justify-center flex">
+ <div class="m-auto">
+ <iconify-icon
+ noobserver
+ icon="ph:lightning-fill"
+ class="text-yellow-300 text-2xl"
+ ></iconify-icon>
+ </div>
+ </div>
+ <div class="my-auto text-lg">Bolt 11</div>
+ </button>
- <button class="btn flex-nowrap" onclick={() => goto("/receive")}>
- <iconify-icon noobserver icon="ph:clipboard-text-bold" width="32"
- ></iconify-icon>
- <div class="my-auto text-lg">{t("user.send.paste")}</div>
- </button>
- </div>
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.bitcoin && address_type !== "legacy"}
+ class:text-secondary={type === types.bitcoin && address_type !== "legacy"}
+ class:hidden={activeOnly &&
+ (type !== types.bitcoin || address_type !== "legacy")}
+ onclick={() =>
+ activeOnly ? toggleType() : setType(types.bitcoin, "legacy")}
+ >
+ <img src="/images/bitcoin.svg" class="w-8" alt="Bitcoin" />
+ <div class="my-auto text-lg">Legacy</div>
+ </button>
<button
class="btn flex-nowrap"
class:bg-base-300={type === types.bolt12}
class:text-secondary={type === types.bolt12}
- onclick={() => setType(types.bolt12)}
+ class:hidden={activeOnly && type !== types.bolt12}
+ onclick={() => (activeOnly ? toggleType() : setType(types.bolt12))}
>
<div class="bg-black rounded-full w-8 h-8 items-center justify-center flex">
<div class="m-auto">
@@ -86,4 +140,17 @@
</div>
<div class="my-auto text-lg">Bolt 12</div>
</button>
+
+ <button
+ class="btn flex-nowrap"
+ class:bg-base-300={type === types.bitcoin}
+ class:text-secondary={type === types.bitcoin}
+ class:hidden={activeOnly &&
+ (type !== types.bitcoin || address_type !== "bech32m")}
+ onclick={() =>
+ activeOnly ? toggleType() : setType(types.bitcoin, "bech32m")}
+ >
+ <img src="/images/bitcoin.svg" class="w-8" alt="Bitcoin" />
+ <div class="my-auto text-lg">Taproot</div>
+ </button>
{/if}
diff --git a/src/components/SetType.svelte b/src/components/SetType.svelte
new file mode 100644
index 00000000..7e80d0bc
--- /dev/null
+++ b/src/components/SetType.svelte
@@ -0,0 +1,37 @@
+<script>
+ import InvoiceTypes from "$comp/InvoiceTypes.svelte";
+ import { focus } from "$lib/utils";
+
+ let {
+ newAmount = $bindable(),
+ invoice,
+ user,
+ submit = $bindable(),
+ settingType,
+ setAmount,
+ setType,
+ toggleType,
+ t,
+ } = $props();
+
+ let { aid, type } = $derived(invoice);
+</script>
+
+{#if settingType}
+ <div
+ class="fixed inset-0 bg-base-100 bg-opacity-90 overflow-y-auto h-full w-full z-50"
+ >
+ <div
+ class="relative mx-auto p-12 max-w-xl shadow-lg rounded-md bg-base-100 space-y-2"
+ >
+ <InvoiceTypes
+ bind:newAmount
+ {setAmount}
+ {invoice}
+ {user}
+ {setType}
+ t={$t}
+ />
+ </div>
+ </div>
+{/if}
diff --git a/src/routes/(app)/[username]/receive/+page.svelte b/src/routes/(app)/[username]/receive/+page.svelte
index e02d6651..887e9680 100644
--- a/src/routes/(app)/[username]/receive/+page.svelte
+++ b/src/routes/(app)/[username]/receive/+page.svelte
@@ -22,6 +22,7 @@
import InvoiceTypes from "$comp/InvoiceTypes.svelte";
import SetAmount from "$comp/SetAmount.svelte";
import SetMemo from "$comp/SetMemo.svelte";
+ import SetType from "$comp/SetType.svelte";
import { t } from "$lib/translations";
import { goto, invalidate } from "$app/navigation";
import { page } from "$app/stores";
@@ -68,20 +69,24 @@
}
};
+ let settingType = $state();
+ let toggleType = () => (settingType = !settingType);
let setType = async (type, address_type) => {
$showQr = true;
- if (type === types.lightning && !amount)
+ if (type === types.lightning && !amount && typeof newAmount === "undefined")
goto(`/${username}/receive`, { invalidateAll: true, noScroll: true });
else {
+ if (typeof newAmount !== "undefined") invoice.amount = newAmount;
invoice.address_type = address_type;
invoice.type = type;
await update();
}
+ settingType = false;
};
let setAmount = async (e) => {
- e.preventDefault();
- e.stopPropagation();
+ e?.preventDefault();
+ e?.stopPropagation();
settingAmount = false;
@@ -142,6 +147,10 @@
/>
<InvoiceActions
+ bind:newAmount
+ {setAmount}
+ {toggleType}
+ {setType}
{toggleAmount}
{toggleMemo}
{user}
@@ -153,8 +162,6 @@
{txt}
t={$t}
/>
-
- <InvoiceTypes {aid} {invoice} {user} {type} {setType} t={$t} />
</div>
<SetAmount
@@ -170,3 +177,16 @@
/>
<SetMemo bind:memo {settingMemo} {setMemo} {toggleMemo} t={$t} />
+
+<SetType
+ {aid}
+ {invoice}
+ {user}
+ {type}
+ {settingType}
+ {setType}
+ {toggleType}
+ t={$t}
+ bind:newAmount
+ {setAmount}
+/>
diff --git a/src/routes/(app)/invoice/[id]/+page.svelte b/src/routes/(app)/invoice/[id]/+page.svelte
index fdb180ef..4c5c3b50 100644
--- a/src/routes/(app)/invoice/[id]/+page.svelte
+++ b/src/routes/(app)/invoice/[id]/+page.svelte
@@ -20,9 +20,9 @@
import Avatar from "$comp/Avatar.svelte";
import InvoiceData from "$comp/InvoiceData.svelte";
import InvoiceActions from "$comp/InvoiceActions.svelte";
- import InvoiceTypes from "$comp/InvoiceTypes.svelte";
import SetAmount from "$comp/SetAmount.svelte";
import SetMemo from "$comp/SetMemo.svelte";
+ import SetType from "$comp/SetType.svelte";
import { t } from "$lib/translations";
import { goto, invalidate } from "$app/navigation";
@@ -85,23 +85,28 @@
}
};
- let setType = async (type) => {
+ let settingType = $state();
+ let toggleType = () => (settingType = !settingType);
+ let setType = async (type, address_type) => {
$showQr = true;
- if (type === types.lightning && !amount)
+ if (type === types.lightning && !amount && typeof newAmount === "undefined")
goto(`/${username}/receive`, { invalidateAll: true, noScroll: true });
else {
+ if (typeof newAmount !== "undefined") invoice.amount = newAmount;
+ invoice.address_type = address_type;
invoice.type = type;
await update();
}
+ settingType = false;
};
let newAmount = $state(0);
let settingAmount = $state();
- let toggleAmount = $state(() => (settingAmount = !settingAmount));
+ let toggleAmount = () => (settingAmount = !settingAmount);
let setAmount = async (e) => {
- e.preventDefault();
- e.stopPropagation();
+ e?.preventDefault();
+ e?.stopPropagation();
settingAmount = false;
@@ -153,6 +158,9 @@
/>
<InvoiceActions
+ bind:newAmount
+ {setAmount}
+ {toggleType}
{toggleAmount}
{toggleMemo}
{user}
@@ -164,8 +172,6 @@
t={$t}
bind:showQr={$showQr}
/>
-
- <InvoiceTypes {aid} {invoice} {user} {type} {setType} t={$t} />
</div>
<SetAmount
@@ -182,3 +188,15 @@
/>
<SetMemo bind:memo {settingMemo} {setMemo} {toggleMemo} t={$t} />
+
+<SetType
+ bind:newAmount
+ {setAmount}
+ {invoice}
+ {user}
+ {type}
+ {settingType}
+ {setType}
+ {toggleType}
+ t={$t}
+/>