diff options
| author | Adam Soltys <[email protected]> | 2022-09-26 23:56:19 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2022-09-26 23:56:49 -0700 |
| commit | 66a6935a7050be9490780102bd80205f7c1ff6c3 (patch) | |
| tree | 30102e141a37d75dbe60e5ee1d7ecbb1e4165b1d /src | |
| parent | bc8e1f7a365b16b7d5fe5a77fcc0754b13a40d0c (diff) | |
| download | coinos-ui-66a6935a7050be9490780102bd80205f7c1ff6c3.tar.gz coinos-ui-66a6935a7050be9490780102bd80205f7c1ff6c3.zip | |
tip refactoring
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Tip.svelte | 212 | ||||
| -rw-r--r-- | src/components/index.js | 1 | ||||
| -rw-r--r-- | src/lib/utils.js | 5 | ||||
| -rw-r--r-- | src/routes/invoice/+server.js | 17 | ||||
| -rw-r--r-- | src/routes/invoice/[id]/+page.svelte | 221 | ||||
| -rw-r--r-- | src/routes/invoice/[id]/paid/+page.svelte | 4 |
6 files changed, 241 insertions, 219 deletions
diff --git a/src/components/Tip.svelte b/src/components/Tip.svelte new file mode 100644 index 00000000..44728326 --- /dev/null +++ b/src/components/Tip.svelte @@ -0,0 +1,212 @@ +<script> + import { Icon } from '$comp'; + import { t } from '$lib/translations'; + import { f, post, s } from '$lib/utils'; + import { tick } from 'svelte'; + import { goto } from '$app/navigation'; + + export let amountFiat, + showCustomAmount, + showMobileTip, + tipPercent, + tipAmount, + amount, + currency, + tip, + prompt, + rate, + text, + username; + + const tipAmounts = ['None', '10%', '15%', '20%']; + + let customInput; + let customTipAmount; + + let apply = async () => { + if (customTipAmount > 0) { + tipPercent = (customTipAmount / amountFiat) * 100; + console.log('TIP PERCENT', tipPercent); + update(); + showMobileTip = false; + showCustomAmount = false; + } + }; + + let update = async () => { + await tick(); + let { uuid } = await post(`/invoice`, { + amount: parseInt(amount + tip), + prompt, + rate, + tip, + text, + user: { username } + }); + + goto(`/invoice/${uuid}`); + }; + + const handleCustomTipAmount = (e) => { + tipPercent = 0; + customTipAmount = e.target.value; + }; + + const handleMobileClose = () => { + tipPercent = 0; + if (customInput) { + customInput.value = ''; + } + customTipAmount = 0; + tipAmount = 0; + showMobileTip = false; + showCustomAmount = false; + }; + + const handleSlide = (e) => { + customTipAmount = ''; + if (customInput) { + customInput.value = ''; + } + tipPercent = e.target.value; + + clearTimeout(timeout); + timeout = setTimeout(update, 100); + }; + + const handleTipButtonClick = (amount) => { + customTipAmount = ''; + if (customInput) { + customInput.value = ''; + } + + if (amount === 'None') { + tipPercent = 0; + } else { + tipPercent = parseInt(amount.slice(0, 2)); + } + showMobileTip = false; + update(); + }; +</script> + +<div + class="w-[100%] md:w-auto absolute {showMobileTip + ? 'bottom-0' + : '-top-full'} bg-white p-6 md:p-0 rounded-t-3xl md:rounded-none left-0 md:static text-center space-y-5" +> + <div class="flex justify-end items-center"> + <button class="block md:hidden bg-primary rounded-full p-2" on:click={handleMobileClose} + ><Icon icon="close" /></button + > + <button + class="hidden {showCustomAmount ? 'md:block' : ''}" + on:click={() => (showCustomAmount = false)} + ><Icon icon="close" style="hover:opacity-80" /></button + > + </div> + <h1 class="hidden md:block text-4xl font-semibold">{$t('invoice.addTipq')}</h1> + {#if !showCustomAmount} + <div> + <span class="font-semibold mr-1">{f(tipAmount, currency)}</span><span + class="text-secondary font-semibold text-sm">{`(${s(tip)} SAT)`}</span + > + <span class="block text-secondary text-sm">{Math.round(tipPercent)}%</span> + </div> + + <input + id="slider" + type="range" + min="0" + max="100" + value={tipPercent} + class="px-2 py-0" + on:input={handleSlide} + on:change={() => (showMobileTip = false)} + /> + {/if} + <div> + {#if !showCustomAmount} + {#each tipAmounts as amount} + <button + class="bg-black text-white md:text-black md:bg-primary md:hover:bg-black md:hover:text-white w-16 md:w-20 py-3 m-1 rounded-2xl font-semibold {customTipAmount + ? '' + : Math.round(tipPercent) === parseInt(amount.slice(0, 2)) || + (!tipPercent && amount === 'None') + ? '!bg-black !text-white' + : ''}" + on:click={() => handleTipButtonClick(amount)}>{amount}</button + > + {/each} + {/if} + {#if showCustomAmount} + <div class="relative"> + <span + class="absolute top-[18px] left-5 font-semibold {!customTipAmount + ? 'opacity-50' + : 'opacity-100'}">$</span + > + <input + bind:this={customInput} + type="number" + on:input={(e) => handleCustomTipAmount(e)} + class="pl-10" + placeholder="Other" + /> + <button + class="w-full mt-2 bg-black text-white font-semibold py-3 px-7 rounded-2xl {!customTipAmount + ? 'opacity-50' + : 'opacity-100 hover:opacity-80'}" + disabled={!customTipAmount} + on:click={apply}>Apply</button + > + <!-- found missing translation ---> + </div> + {:else} + <div> + <button + class="w-full md:w-auto mt-2 bg-black md:bg-primary text-white md:text-black md:hover:bg-black md:hover:text-white font-semibold py-3 px-7 rounded-2xl" + on:click={() => (showCustomAmount = true)}>Custom amount</button + > + </div> + {/if} + </div> +</div> + +<div + class="hidden md:block h-[1px] lg:h-[600px] w-full lg:w-[1px] bg-lightgrey rounded-xl" + id="section-divider" +/> + +<style> + #slider { + -webkit-appearance: none; + width: 100%; + height: 6px; + border-radius: 5px; + background: #eaecef; + outline: none; + } + + #slider:active { + background-color: black; + } + + #slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 25px; + height: 25px; + border-radius: 50%; + background: black; + cursor: pointer; + } + + #slider::-moz-range-thumb { + width: 25px; + height: 25px; + border-radius: 50%; + background: black; + cursor: pointer; + } +</style> diff --git a/src/components/index.js b/src/components/index.js index 35f7f737..1a673737 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -17,3 +17,4 @@ export { default as Footer } from './Footer.svelte'; export { default as Toggle } from './Toggle.svelte'; export { default as LocationsMap } from './LocationsMap.svelte'; export { default as Qr } from './Qr.svelte'; +export { default as Tip } from './Tip.svelte'; diff --git a/src/lib/utils.js b/src/lib/utils.js index 80419a45..7c05e7c3 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -137,3 +137,8 @@ export const f = (s, currency) => .replace('CA', ''); export const s = (s) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(s); + +export const toggleFullscreen = (el) => + document.fullscreenElement + ? document.exitFullscreen() + : el.requestFullscreen().catch(console.log); diff --git a/src/routes/invoice/+server.js b/src/routes/invoice/+server.js index d9a9739c..759c9315 100644 --- a/src/routes/invoice/+server.js +++ b/src/routes/invoice/+server.js @@ -1,15 +1,7 @@ import { auth, get, post } from '$lib/utils'; export async function POST({ request, parent }) { - let { - amount, - currency, - network = 'lightning', - prompt, - rate, - tip, - username - } = await request.json(); + let { amount, currency, network = 'lightning', prompt, rate, tip, user } = await request.json(); let invoice = { amount, currency, network, prompt, rate, tip }; if (network === 'lightning') { @@ -18,8 +10,7 @@ export async function POST({ request, parent }) { invoice.address = (await get('/address?network=bitcoin&type=bech32')).address; } - return new Response( - JSON.stringify(await post('/invoice', { invoice, user: { username } }, auth(request))), - { headers: { 'content-type': 'application/json' } } - ); + return new Response(JSON.stringify(await post('/invoice', { invoice, user }, auth(request))), { + headers: { 'content-type': 'application/json' } + }); } diff --git a/src/routes/invoice/[id]/+page.svelte b/src/routes/invoice/[id]/+page.svelte index 60257ab7..0fa34430 100644 --- a/src/routes/invoice/[id]/+page.svelte +++ b/src/routes/invoice/[id]/+page.svelte @@ -1,10 +1,9 @@ <script> - import { copy, f, get, post, reverseFormat, s } from '$lib/utils'; + import { copy, f, get, reverseFormat, s, toggleFullscreen } from '$lib/utils'; import { browser } from '$app/environment'; import { invoices, user } from '$lib/store'; - import { Icon, Image, Qr } from '$comp'; + import { Icon, Image, Qr, Tip } from '$comp'; import { goto } from '$app/navigation'; - import { onMount, tick } from 'svelte'; import { t } from '$lib/translations'; export let data; @@ -21,6 +20,7 @@ } = invoice; let showCustomAmount = false; + let showMobileTip = false; let image = '/images/invoice.svg'; let qr; @@ -52,97 +52,14 @@ $: tipAmount = ((tip * rate) / 100000000).toFixed(2); - let apply = async () => { - if (customTipAmount > 0) { - tipPercent = (customTipAmount / amountFiat) * 100; - update(); - showMobileTip = false; - showCustomAmount = false; - } - }; - - let update = async () => { - await tick(); - let { uuid } = await post(`/invoice`, { - amount: parseInt(amount + tip), - prompt, - rate, - tip, - text, - username - }); - - goto(`/invoice/${uuid}`); - }; - const amountFormatted = s(amount); $: invoiceAmountFiatFormatted = f(amountFiat, currency); - let customTipAmount; - - const tipAmounts = ['None', '10%', '15%', '20%']; - let timeout; - const handleSlide = (e) => { - customTipAmount = ''; - if (customInput) { - customInput.value = ''; - } - tipPercent = e.target.value; - - clearTimeout(timeout); - timeout = setTimeout(update, 100); - }; - - const handleTipButtonClick = (amount) => { - customTipAmount = ''; - if (customInput) { - customInput.value = ''; - } - - if (amount === 'None') { - tipPercent = 0; - } else { - tipPercent = parseInt(amount.slice(0, 2)); - } - showMobileTip = false; - update(); - }; - - const handleCustomTipAmount = (e) => { - tipPercent = 0; - customTipAmount = e.target.value; - }; - - let showMobileTip = false; - const handleBackButton = () => { goto(`/${username}/receive`); }; - - const handleMobileClose = () => { - tipPercent = 0; - if (customInput) { - customInput.value = ''; - } - customTipAmount = 0; - tipAmount = 0; - showMobileTip = false; - showCustomAmount = false; - }; - - let customInput; - - function toggleFullscreen() { - if (!document.fullscreenElement) { - qr.requestFullscreen().catch((err) => { - alert(`Error attempting to enable fullscreen mode: ${err.message} (${err.name})`); - }); - } else { - document.exitFullscreen(); - } - } </script> <div class:full-shadow={showMobileTip}> @@ -160,92 +77,19 @@ class="block lg:flex justify-center items-center space-y-10 lg:space-y-0 space-x-0 lg:space-x-24" > {#if invoice.prompt} - <div - class="w-[100%] md:w-auto absolute {showMobileTip - ? 'bottom-0' - : '-top-full'} bg-white p-6 md:p-0 rounded-t-3xl md:rounded-none left-0 md:static text-center space-y-5" - > - <div class="flex justify-end items-center"> - <button class="block md:hidden bg-primary rounded-full p-2" on:click={handleMobileClose} - ><Icon icon="close" /></button - > - <button - class="hidden {showCustomAmount ? 'md:block' : ''}" - on:click={() => (showCustomAmount = false)} - ><Icon icon="close" style="hover:opacity-80" /></button - > - </div> - <h1 class="hidden md:block text-4xl font-semibold">{$t('invoice.addTipq')}</h1> - {#if !showCustomAmount} - <div> - <span class="font-semibold mr-1">{f(tipAmount, currency)}</span><span - class="text-secondary font-semibold text-sm">{`(${s(tip)} SAT)`}</span - > - <span class="block text-secondary text-sm">{Math.round(tipPercent)}%</span> - </div> - - <input - id="slider" - type="range" - min="0" - max="100" - value={tipPercent} - class="px-2 py-0" - on:input={handleSlide} - on:change={() => (showMobileTip = false)} - /> - {/if} - <div> - {#if !showCustomAmount} - {#each tipAmounts as amount} - <button - class="bg-black text-white md:text-black md:bg-primary md:hover:bg-black md:hover:text-white w-16 md:w-20 py-3 m-1 rounded-2xl font-semibold {customTipAmount - ? '' - : Math.round(tipPercent) === parseInt(amount.slice(0, 2)) || - (!tipPercent && amount === 'None') - ? '!bg-black !text-white' - : ''}" - on:click={() => handleTipButtonClick(amount)}>{amount}</button - > - {/each} - {/if} - {#if showCustomAmount} - <div class="relative"> - <span - class="absolute top-[18px] left-5 font-semibold {!customTipAmount - ? 'opacity-50' - : 'opacity-100'}">$</span - > - <input - bind:this={customInput} - type="number" - on:input={(e) => handleCustomTipAmount(e)} - class="pl-10" - placeholder="Other" - /> - <button - class="w-full mt-2 bg-black text-white font-semibold py-3 px-7 rounded-2xl {!customTipAmount - ? 'opacity-50' - : 'opacity-100 hover:opacity-80'}" - disabled={!customTipAmount} - on:click={apply}>Apply</button - > - <!-- found missing translation ---> - </div> - {:else} - <div> - <button - class="w-full md:w-auto mt-2 bg-black md:bg-primary text-white md:text-black md:hover:bg-black md:hover:text-white font-semibold py-3 px-7 rounded-2xl" - on:click={() => (showCustomAmount = true)}>Custom amount</button - > - </div> - {/if} - </div> - </div> - - <div - class="hidden md:block h-[1px] lg:h-[600px] w-full lg:w-[1px] bg-lightgrey rounded-xl" - id="section-divider" + <Tip + bind:amountFiat + bind:showCustomAmount + bind:showMobileTip + bind:tipPercent + bind:tipAmount + bind:amount + bind:tip + bind:rate + bind:prompt + bind:text + bind:currency + bind:username /> {/if} @@ -291,7 +135,7 @@ <div> <button class="border border-lightgrey rounded-md p-2 mx-2 hover:opacity-80" - on:click={toggleFullscreen}><Icon icon="expand" /></button + on:click={() => toggleFullscreen(qr)}><Icon icon="expand" /></button > <button class="border border-lightgrey rounded-md p-2 mx-2 hover:opacity-80" @@ -333,37 +177,6 @@ </div> <style> - #slider { - -webkit-appearance: none; - width: 100%; - height: 6px; - border-radius: 5px; - background: #eaecef; - outline: none; - } - - #slider:active { - background-color: black; - } - - #slider::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 25px; - height: 25px; - border-radius: 50%; - background: black; - cursor: pointer; - } - - #slider::-moz-range-thumb { - width: 25px; - height: 25px; - border-radius: 50%; - background: black; - cursor: pointer; - } - input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { -webkit-appearance: none; diff --git a/src/routes/invoice/[id]/paid/+page.svelte b/src/routes/invoice/[id]/paid/+page.svelte index 04568297..0fc09170 100644 --- a/src/routes/invoice/[id]/paid/+page.svelte +++ b/src/routes/invoice/[id]/paid/+page.svelte @@ -9,9 +9,9 @@ export let data; let { invoice } = data; - let { amount, rate } = invoice; + let { amount, rate } = invoice; - toast.pop(0); + toast.pop(0); $: amountFiat = parseFloat(((amount * rate) / 100000000).toFixed(2)); |
