aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2022-09-26 23:56:19 -0700
committerAdam Soltys <[email protected]>2022-09-26 23:56:49 -0700
commit66a6935a7050be9490780102bd80205f7c1ff6c3 (patch)
tree30102e141a37d75dbe60e5ee1d7ecbb1e4165b1d /src
parentbc8e1f7a365b16b7d5fe5a77fcc0754b13a40d0c (diff)
downloadcoinos-ui-66a6935a7050be9490780102bd80205f7c1ff6c3.tar.gz
coinos-ui-66a6935a7050be9490780102bd80205f7c1ff6c3.zip
tip refactoring
Diffstat (limited to 'src')
-rw-r--r--src/components/Tip.svelte212
-rw-r--r--src/components/index.js1
-rw-r--r--src/lib/utils.js5
-rw-r--r--src/routes/invoice/+server.js17
-rw-r--r--src/routes/invoice/[id]/+page.svelte221
-rw-r--r--src/routes/invoice/[id]/paid/+page.svelte4
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));