diff options
| author | Adam Soltys <[email protected]> | 2022-11-06 11:24:36 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2022-11-06 11:24:36 -0800 |
| commit | 1bda2b36e3f7f6c7f7a85647b2bc4ca308012fbe (patch) | |
| tree | 29601126a68556d11e5968d15159b5fc066d2e64 /src | |
| parent | 84e8da3e50ba1a35d254346d8fc92a3795d41670 (diff) | |
| download | coinos-ui-1bda2b36e3f7f6c7f7a85647b2bc4ca308012fbe.tar.gz coinos-ui-1bda2b36e3f7f6c7f7a85647b2bc4ca308012fbe.zip | |
invoice requests
Diffstat (limited to 'src')
18 files changed, 179 insertions, 52 deletions
diff --git a/src/components/Invoice.svelte b/src/components/Invoice.svelte new file mode 100644 index 00000000..4b42f851 --- /dev/null +++ b/src/components/Invoice.svelte @@ -0,0 +1,34 @@ +<script> + import { fly } from 'svelte/transition'; + import { Avatar, Icon } from '$comp'; + import { invoice } from '$lib/store'; + + export let user; +</script> + +{#if $invoice} + <div + class="flex flex-wrap md:flex-nowrap fixed bottom-0 border-t w-full p-4 bg-white z-50" + in:fly + > + <div class="my-auto md:w-1/2"> + <div class="flex"> + <Avatar user={$invoice.user.username} size={12} /> + <h1 class="my-auto"><b>{$invoice.user.username}</b> sent an invoice</h1> + </div> + </div> + <div class="mx-auto my-auto"> + <a href={`/invoice/${$invoice.uuid}`}> + <button class="text-lg rounded-full border py-3 px-7 font-bold hover:opacity-80 w-full"> + Pay + </button> + </a> + </div> + <button + class="absolute right-4 top-4 ml-auto mb-auto rounded-full border font-bold hover:opacity-80 p-3" + on:click={() => ($invoice = undefined)} + > + <Icon icon="close" /> + </button> + </div> +{/if} diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte index b4f2bbbb..de292f2a 100644 --- a/src/components/Numpad.svelte +++ b/src/components/Numpad.svelte @@ -8,7 +8,7 @@ currency, fiat = !amount; - export let amountFiat = amount ? amount * ($selectedRate / sats) : 0; + export let amountFiat = amount ? amount * ($selectedRate / sats) : 0; let amountSats = amount; let loading = false; diff --git a/src/components/Request.svelte b/src/components/Request.svelte index ea314f13..2c87d436 100644 --- a/src/components/Request.svelte +++ b/src/components/Request.svelte @@ -1,10 +1,37 @@ <script> import { fly } from 'svelte/transition'; - import { Avatar } from '$comp'; + import { Avatar, Icon } from '$comp'; import { request } from '$lib/store'; + + export let user; </script> -<div class="fixed bottom-0 h-24 border-t w-full bg-primary" in:fly> - <Avatar user={$request.requester} /> - {$request.requester.username} is requesting an invoice -</div> +{#if $request} + <div + class="flex flex-wrap md:flex-nowrap fixed bottom-0 border-t w-full p-4 bg-white z-50" + in:fly + > + <div class="my-auto md:w-1/2"> + <div class="flex"> + <Avatar user={$request.requester} size={12} /> + <h1 class="my-auto"><b>{$request.requester.username}</b> is ready to pay</h1> + </div> + {#if $request.memo} + <div class="border-l-4 pl-4 my-2">{$request.memo}</div> + {/if} + </div> + <div class="mx-auto my-auto"> + <a href={`/${user.username}/receive`}> + <button class="text-lg rounded-full border py-3 px-7 font-bold hover:opacity-80 w-full"> + Create invoice + </button> + </a> + </div> + <button + class="absolute right-4 top-4 ml-auto mb-auto rounded-full border font-bold hover:opacity-80 p-3" + on:click={() => ($request = undefined)} + > + <Icon icon="close" /> + </button> + </div> +{/if} diff --git a/src/components/index.js b/src/components/index.js index f3d550ec..07b169bb 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,3 +1,4 @@ +export { default as Invoice } from './Invoice.svelte'; export { default as Request } from './Request.svelte'; export { default as Pin } from './Pin.svelte'; export { default as Card } from './Card.svelte'; diff --git a/src/lib/invoice.js b/src/lib/invoice.js index e8a5f615..5bf05d90 100644 --- a/src/lib/invoice.js +++ b/src/lib/invoice.js @@ -5,18 +5,23 @@ export default async ({ cookies, request }) => { let form = await request.formData(); let rates = await get('/rates'); + let requester = form.get('requester'); let invoice = { amount: parseInt(form.get('amount')), tip: parseInt(form.get('tip')), network: 'lightning', prompt: form.get('prompt') === 'true', - rate: parseFloat(form.get('rate')) || rates[form.get('currency')] + rate: parseFloat(form.get('rate')) || rates[form.get('currency')], + requester }; let user = { username: form.get('username') }; let { uuid } = await post('/invoice', { invoice, user }, auth(cookies)); + console.log('R', requester); + + if (requester) return { requester }; if (invoice.prompt) { throw redirect(307, `/invoice/${uuid}/tip`); diff --git a/src/lib/socket.js b/src/lib/socket.js index d3cc40ea..a5784f19 100644 --- a/src/lib/socket.js +++ b/src/lib/socket.js @@ -1,5 +1,5 @@ import { get } from 'svelte/store'; -import { invoices, request, newPayment, last, rate, user } from '$lib/store'; +import { invoices, invoice, request, newPayment, last, rate, user } from '$lib/store'; import { success, sat } from '$lib/utils'; import { env } from '$env/dynamic/public'; @@ -19,6 +19,10 @@ export const messages = (data) => ({ last.set(Date.now()); }, + invoice() { + invoice.set(data); + }, + rate() { rate.set(data); }, diff --git a/src/lib/store.js b/src/lib/store.js index c32ef49b..3faa234b 100644 --- a/src/lib/store.js +++ b/src/lib/store.js @@ -45,3 +45,4 @@ export const bannerUpload = writable(); export const pin = persistSession('pin', undefined, 5 * 60 * 1000); export const last = writable(); export const request = writable(); +export const invoice = writable(); diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 5bfe7712..36e109e0 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -2,11 +2,11 @@ import { SvelteToast } from '@zerodevx/svelte-toast'; import { onDestroy, onMount } from 'svelte'; import { close, connect, send } from '$lib/socket'; - import { last, selectedRate, rate, user, request } from '$lib/store'; + import { last, selectedRate, invoice, rate, user, request } from '$lib/store'; import { page } from '$app/stores'; import { browser } from '$app/environment'; import { goto } from '$app/navigation'; - import { LoadingSplash, Request } from '$comp'; + import { LoadingSplash, Invoice, Request } from '$comp'; import { warning, protectedRoutes } from '$lib/utils'; import { t, locale } from '$lib/translations'; @@ -84,6 +84,10 @@ <slot /> </main> +{#if $invoice} + <Invoice user={u} /> +{/if} + {#if $request} - <Request /> + <Request user={u} /> {/if} diff --git a/src/routes/(app)/[username]/+page.svelte b/src/routes/(app)/[username]/+page.svelte index b9deeb5f..ed11412f 100644 --- a/src/routes/(app)/[username]/+page.svelte +++ b/src/routes/(app)/[username]/+page.svelte @@ -48,15 +48,15 @@ <div> <a href={`/${subject.username}/receive`}> <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"> - Pay + Pay now </button> </a> - <!-- <a href={`/${subject.username}/request`}> --> - <!-- <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2" --> - <!-- >Request an invoice</button --> - <!-- > --> - <!-- </a> --> + <a href={`/${subject.username}/request`}> + <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2" + >Ask to pay</button + > + </a> </div> {/if} </div> diff --git a/src/routes/(app)/[username]/receive/+page.svelte b/src/routes/(app)/[username]/receive/+page.svelte deleted file mode 100644 index 11d3a6db..00000000 --- a/src/routes/(app)/[username]/receive/+page.svelte +++ /dev/null @@ -1,30 +0,0 @@ -<script> - import { Icon, Numpad } from '$comp'; - import { t } from '$lib/translations'; - import { enhance } from '$app/forms'; - - export let data; - let amount; - - let { currency, username } = data.subject; -</script> - -<form method="POST" class="flex justify-center items-center mt-24 mb-3 px-3" use:enhance> - <input type="hidden" name="amount" value={amount} /> - <input type="hidden" name="currency" value={currency} /> - <input type="hidden" name="username" value={username} /> - <input type="hidden" name="prompt" value="true" /> - - <div class="space-y-3 w-full md:w-[300px] mx-auto"> - <Numpad bind:amount bind:currency /> - <button - type="submit" - class="bg-black text-white rounded-xl w-full h-[48px] flex justify-center items-center font-semibold {!amount - ? 'opacity-50' - : 'opacity-100 hover:opacity-80'}" - disabled={!amount} - > - Next - </button> - </div> -</form> diff --git a/src/routes/(app)/[username]/receive/+page.server.js b/src/routes/(app)/[username]/receive/[...recipient]/+page.server.js index 1068f273..1068f273 100644 --- a/src/routes/(app)/[username]/receive/+page.server.js +++ b/src/routes/(app)/[username]/receive/[...recipient]/+page.server.js diff --git a/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte b/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte new file mode 100644 index 00000000..a0f9a1b0 --- /dev/null +++ b/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte @@ -0,0 +1,70 @@ +<script> + import { Avatar, Icon, Numpad } from '$comp'; + import { t } from '$lib/translations'; + import { enhance } from '$app/forms'; + import { page } from '$app/stores'; + import { request } from '$lib/store'; + + export let data; + export let form; + + let req; + + $: load($page); + let load = () => { + if ($request) { + req = { ...$request }; + $request = null; + } + }; + + let amount; + + let { currency, username } = data.subject; + let { user } = data; +</script> + +{#if form} + <div class="container px-4 mt-20 max-w-xl mx-auto space-y-8"> + <div class="text-center mb-8 space-y-5"> + <p class="text-5xl break-words"> + <span class="text-xl md:text-2xl">Invoice sent to</span> + </p> + + <div class="flex p-1 gap-2 justify-center"> + <Avatar user={req.requester} size={'20'} /> + <p class="text-4xl break-words my-auto">{req.requester.username}</p> + </div> + </div> + <a href={`/${user.username}/dashboard`} class="mx-auto"> + <button class="bg-black text-white rounded-2xl w-20 py-3 font-bold hover:opacity-80"> + Done + </button> + </a> + </div> +{:else} + <form method="POST" class="flex justify-center items-center mt-24 mb-3 px-3" use:enhance> + <input type="hidden" name="amount" value={amount} /> + <input type="hidden" name="currency" value={currency} /> + <input type="hidden" name="username" value={username} /> + + {#if req} + <input type="hidden" name="requester" value={req.requester.username} /> + {/if} + + <input type="hidden" name="prompt" value="true" /> + + <div class="space-y-3 w-full md:w-[300px] mx-auto"> + <Numpad bind:amount bind:currency /> + <button + type="submit" + class="bg-black text-white rounded-xl w-full h-[48px] flex justify-center items-center font-semibold {!amount + ? 'opacity-50' + : 'opacity-100 hover:opacity-80'}" + disabled={!amount} + > + Next + </button> + </div> + </form> +{/if} diff --git a/src/routes/(app)/[username]/receive/[network]/[amount]/+page.server.js b/src/routes/(app)/[username]/receive/[network]/[amount]/+page.server.js deleted file mode 100644 index e69de29b..00000000 --- a/src/routes/(app)/[username]/receive/[network]/[amount]/+page.server.js +++ /dev/null diff --git a/src/routes/(app)/[username]/receive/[network]/[amount]/+page.svelte b/src/routes/(app)/[username]/receive/[network]/[amount]/+page.svelte deleted file mode 100644 index 45b983be..00000000 --- a/src/routes/(app)/[username]/receive/[network]/[amount]/+page.svelte +++ /dev/null @@ -1 +0,0 @@ -hi diff --git a/src/routes/(app)/[username]/request/+page.svelte b/src/routes/(app)/[username]/request/+page.svelte index 37fdae96..6e7eb08a 100644 --- a/src/routes/(app)/[username]/request/+page.svelte +++ b/src/routes/(app)/[username]/request/+page.svelte @@ -22,7 +22,7 @@ <textarea name="memo" - placeholder="(Optionally) use this field to describe your order" + placeholder="You can use this field to describe your order" class="w-full p-4 border rounded-xl h-48" /> diff --git a/src/routes/(app)/invoice/[id]/+page.svelte b/src/routes/(app)/invoice/[id]/+page.svelte index 6de55bae..25ebf227 100644 --- a/src/routes/(app)/invoice/[id]/+page.svelte +++ b/src/routes/(app)/invoice/[id]/+page.svelte @@ -3,7 +3,7 @@ import { back, copy, f, get, sat, reverseFormat, s, sats } from '$lib/utils'; import { onMount, onDestroy } from 'svelte'; import { browser } from '$app/environment'; - import { invoices, last } from '$lib/store'; + import { invoice as inv, invoices, last } from '$lib/store'; import { Icon, Heart, Image, Qr } from '$comp'; import { goto } from '$app/navigation'; import { t } from '$lib/translations'; @@ -24,6 +24,8 @@ let tipPercent = 0; let refresh = (data) => { + $inv = null; + ({ invoice, id } = data); ({ amount, diff --git a/src/routes/(app)/invoice/sent/+page.svelte b/src/routes/(app)/invoice/sent/+page.svelte new file mode 100644 index 00000000..c4cbc5bb --- /dev/null +++ b/src/routes/(app)/invoice/sent/+page.svelte @@ -0,0 +1,10 @@ +<script> + import { Avatar, Icon } from '$comp'; + export let user; +</script> + +Invoice sent to +<div class="flex"> + <Avatar user={$request.requester} size={12} /> + <h1 class="my-auto"><b>{$request.requester.username}</b> is ready to pay</h1> +</div> diff --git a/src/routes/(app)/send/[...text]/+page.server.js b/src/routes/(app)/send/[...text]/+page.server.js index 7d2aa8b0..5e274c67 100644 --- a/src/routes/(app)/send/[...text]/+page.server.js +++ b/src/routes/(app)/send/[...text]/+page.server.js @@ -10,7 +10,7 @@ let parse = async (t, r) => { t.startsWith('bitcoin:') && ({ - address: t, + address: t, options: { amount } } = bip21.decode(t)); @@ -46,7 +46,7 @@ let parse = async (t, r) => { } catch (e) { let r = `/send/bitcoin/${t}`; if (amount) r += '/' + amount; - console.log("AM", amount) + console.log('AM', amount); throw redirect(307, r); } |
