aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsecondl1ght <[email protected]>2022-07-30 06:52:55 -0600
committersecondl1ght <[email protected]>2022-07-30 06:52:55 -0600
commit8851572f78a70c7bd02a3d669dc103459323ed8d (patch)
tree8f2bdce5946ac7a7a81ccdbeaa91191129f39442
parentfac00131fd980db9513143807fe2d823376e9551 (diff)
downloadcoinos-ui-8851572f78a70c7bd02a3d669dc103459323ed8d.tar.gz
coinos-ui-8851572f78a70c7bd02a3d669dc103459323ed8d.zip
add 404 and error page, redirect to login if trying to access w/o user
-rw-r--r--src/components/AppHeader.svelte4
-rw-r--r--src/routes/[...path].svelte16
-rw-r--r--src/routes/__error.svelte16
-rw-r--r--src/routes/invoice/[amount].svelte224
-rw-r--r--src/routes/receive.svelte184
-rw-r--r--static/icons/error.svg3
-rw-r--r--static/icons/info.svg2
-rw-r--r--static/icons/question.svg3
8 files changed, 252 insertions, 200 deletions
diff --git a/src/components/AppHeader.svelte b/src/components/AppHeader.svelte
index 3f8e7e87..6376e27f 100644
--- a/src/components/AppHeader.svelte
+++ b/src/components/AppHeader.svelte
@@ -1,7 +1,7 @@
<script>
// we will want to dynamically use the users avatar on this screen if they have uploaded one
- import { user } from "$lib/store";
+ import { user } from '$lib/store';
import { goto } from '$app/navigation';
import { Icon } from '$comp';
</script>
@@ -15,7 +15,7 @@
><Icon icon="clock" style="mx-auto" /></button
>
<button class="bg-white p-2 rounded-full w-12 h-12"
- ><Icon icon="profile" style="mx-auto" /> {$user.username}</button
+ ><Icon icon="profile" style="mx-auto" /></button
>
<button class="bg-white p-2 rounded-full w-12 h-12"
><Icon icon="menu" style="mx-auto" /></button
diff --git a/src/routes/[...path].svelte b/src/routes/[...path].svelte
new file mode 100644
index 00000000..503316bb
--- /dev/null
+++ b/src/routes/[...path].svelte
@@ -0,0 +1,16 @@
+<script>
+ import { Icon } from '$comp';
+</script>
+
+<div class="flex justify-center items-center mt-20">
+ <div class="space-y-5 text-center">
+ <a href="/">
+ <Icon icon="logo" />
+ </a>
+
+ <Icon icon="question" style="mx-auto w-full" />
+
+ <h1 class="font-bold text-5xl">404</h1>
+ <p>Page not found.</p>
+ </div>
+</div>
diff --git a/src/routes/__error.svelte b/src/routes/__error.svelte
new file mode 100644
index 00000000..6cdeeac7
--- /dev/null
+++ b/src/routes/__error.svelte
@@ -0,0 +1,16 @@
+<script>
+ import { Icon } from '$comp';
+</script>
+
+<div class="flex justify-center items-center mt-20">
+ <div class="space-y-5 text-center">
+ <a href="/">
+ <Icon icon="logo" />
+ </a>
+
+ <Icon icon="error" style="mx-auto w-full" />
+
+ <h1 class="font-bold text-5xl">Error</h1>
+ <p>Please try again or contact support.</p>
+ </div>
+</div>
diff --git a/src/routes/invoice/[amount].svelte b/src/routes/invoice/[amount].svelte
index 4c1ec199..2cf16e37 100644
--- a/src/routes/invoice/[amount].svelte
+++ b/src/routes/invoice/[amount].svelte
@@ -8,6 +8,10 @@
export let text;
export let amount;
+ if (!$user && typeof window !== 'undefined') {
+ window.location = '/login';
+ }
+
let tipPercent = 0;
const setRate = ($invoiceAmountFiat / $invoiceAmount) * 100000000;
@@ -83,131 +87,133 @@
});
</script>
-<button class="ml-5 md:ml-20 mt-5 md:mt-10" on:click={() => goto('/receive')}>
- <Icon icon="arrow-left" style="w-10" />
-</button>
+{#if $user}
+ <button class="ml-5 md:ml-20 mt-5 md:mt-10" on:click={() => goto('/receive')}>
+ <Icon icon="arrow-left" style="w-10" />
+ </button>
-<div class="flex justify-center items-center mb-20 mt-[20px] px-3">
- <div
- class="block lg:flex justify-center items-center space-y-10 lg:space-y-0 space-x-0 lg:space-x-24"
- >
- {#if $invoiceAmount && $invoiceAmountFiat && $rate && text}
- <!-- tipping section -->
- <div class="text-center space-y-5">
- <h1 class="text-4xl font-semibold">Add a tip?</h1>
+ <div class="flex justify-center items-center mb-20 mt-[20px] px-3">
+ <div
+ class="block lg:flex justify-center items-center space-y-10 lg:space-y-0 space-x-0 lg:space-x-24"
+ >
+ {#if $invoiceAmount && $invoiceAmountFiat && $rate && text}
+ <!-- tipping section -->
+ <div class="text-center space-y-5">
+ <h1 class="text-4xl font-semibold">Add a tip?</h1>
- <div>
- <span class="font-semibold mr-1">{tipAmountFormatted}</span><span
- class="text-secondary font-semibold text-sm">{`(${tipAmountSats} SATS)`}</span
- >
- <span class="block text-secondary text-sm">{tipPercent}%</span>
- </div>
+ <div>
+ <span class="font-semibold mr-1">{tipAmountFormatted}</span><span
+ class="text-secondary font-semibold text-sm">{`(${tipAmountSats} SATS)`}</span
+ >
+ <span class="block text-secondary text-sm">{tipPercent}%</span>
+ </div>
- <input
- id="slider"
- type="range"
- min="0"
- max="100"
- value={tipPercent}
- class="px-2"
- on:input={(e) => {
- customTipAmount = '';
- tipPercent = e.target.value;
- }}
- />
+ <input
+ id="slider"
+ type="range"
+ min="0"
+ max="100"
+ value={tipPercent}
+ class="px-2"
+ on:input={(e) => {
+ customTipAmount = '';
+ tipPercent = e.target.value;
+ }}
+ />
- <div>
- {#each tipAmounts as amount}
- <button
- class="bg-primary w-20 py-3 m-1 rounded-2xl font-semibold {tipPercent ===
- amount.slice(0, 2) ||
- ((tipPercent === 0 || tipPercent === '0') && amount === 'None')
- ? '!bg-black text-white'
- : ''}"
- on:click={() => handleTipButtonClick(amount)}>{amount}</button
- >
- {/each}
+ <div>
+ {#each tipAmounts as amount}
+ <button
+ class="bg-primary w-20 py-3 m-1 rounded-2xl font-semibold {tipPercent ===
+ amount.slice(0, 2) ||
+ ((tipPercent === 0 || tipPercent === '0') && amount === 'None')
+ ? '!bg-black text-white'
+ : ''}"
+ on:click={() => handleTipButtonClick(amount)}>{amount}</button
+ >
+ {/each}
- <div class="relative">
- <span
- class="absolute top-[20px] left-5 font-semibold {!customTipAmount
- ? 'opacity-50'
- : 'opacity-100'}">$</span
- >
- <input
- type="number"
- min="0"
- on:input={(e) => handleCustomTipAmount(e)}
- class="bg-primary rounded-2xl py-3 px-10 font-semibold mt-2 mr-1 w-full md:w-auto"
- placeholder="Other"
- />
- <button
- class="w-full md:w-auto mt-2 md:mt-0 bg-black text-white font-semibold py-3 px-7 rounded-2xl {!customTipAmount
- ? 'opacity-50'
- : 'opacity-100'}"
- disabled={!customTipAmount}>Done</button
- >
+ <div class="relative">
+ <span
+ class="absolute top-[20px] left-5 font-semibold {!customTipAmount
+ ? 'opacity-50'
+ : 'opacity-100'}">$</span
+ >
+ <input
+ type="number"
+ min="0"
+ on:input={(e) => handleCustomTipAmount(e)}
+ class="bg-primary rounded-2xl py-3 px-10 font-semibold mt-2 mr-1 w-full md:w-auto"
+ placeholder="Other"
+ />
+ <button
+ class="w-full md:w-auto mt-2 md:mt-0 bg-black text-white font-semibold py-3 px-7 rounded-2xl {!customTipAmount
+ ? 'opacity-50'
+ : 'opacity-100'}"
+ disabled={!customTipAmount}>Done</button
+ >
+ </div>
</div>
</div>
- </div>
-
- <div
- class="h-[1px] lg:h-[600px] w-full lg:w-[1px] bg-lightgrey rounded-xl"
- id="section-divider"
- />
-
- <!-- invoice section -->
- <div class="text-center space-y-5">
- <span class="text-secondary"
- >Scan to pay <span class="text-black font-semibold">insert name here</span></span
- >
<div
- id="qr"
- class="border border-lightgrey rounded-3xl lg:p-5 flex justify-center items-center"
+ class="h-[1px] lg:h-[600px] w-full lg:w-[1px] bg-lightgrey rounded-xl"
+ id="section-divider"
/>
- <div class="px-5 space-y-3">
- <div class="flex justify-between">
- <span class="font-semibold text-sm">Invoice</span>
- <span class="font-semibold text-sm"
- >{invoiceAmountFiatFormatted}
- <span class="text-secondary font-normal">{`(${invoiceAmountFormatted} SATS)`}</span
- ></span
- >
- </div>
+ <!-- invoice section -->
+ <div class="text-center space-y-5">
+ <span class="text-secondary"
+ >Scan to pay <span class="text-black font-semibold">insert name here</span></span
+ >
- <div class="flex justify-between">
- <span class="font-semibold text-sm">Tip</span>
- <span class="font-semibold text-sm"
- >{tipAmountFormatted}
- <span class="text-secondary font-normal">{`(${tipAmountSats} SATS)`}</span></span
- >
- </div>
+ <div
+ id="qr"
+ class="border border-lightgrey rounded-3xl lg:p-5 flex justify-center items-center"
+ />
- <div class="flex justify-between">
- <span class="font-bold">Total</span>
- <span class="font-bold"
- >{totalAmountFormatted}
- <span class="text-secondary font-normal">{`(${totalAmountSats} SATS)`}</span></span
- >
+ <div class="px-5 space-y-3">
+ <div class="flex justify-between">
+ <span class="font-semibold text-sm">Invoice</span>
+ <span class="font-semibold text-sm"
+ >{invoiceAmountFiatFormatted}
+ <span class="text-secondary font-normal">{`(${invoiceAmountFormatted} SATS)`}</span
+ ></span
+ >
+ </div>
+
+ <div class="flex justify-between">
+ <span class="font-semibold text-sm">Tip</span>
+ <span class="font-semibold text-sm"
+ >{tipAmountFormatted}
+ <span class="text-secondary font-normal">{`(${tipAmountSats} SATS)`}</span></span
+ >
+ </div>
+
+ <div class="flex justify-between">
+ <span class="font-bold">Total</span>
+ <span class="font-bold"
+ >{totalAmountFormatted}
+ <span class="text-secondary font-normal">{`(${totalAmountSats} SATS)`}</span></span
+ >
+ </div>
</div>
</div>
- </div>
- {:else}
- <div
- class="w-[94vw] md:w-[375px] h-[381px] md:h-[269px] animate-pulse bg-gray-400 rounded-xl"
- />
- <div
- class="h-[1px] lg:h-[600px] w-full lg:w-[1px] bg-lightgrey rounded-xl"
- id="section-divider"
- />
- <div
- class="w-full md:w-[342px] h-[454px] md:h-[494px] animate-pulse bg-gray-400 rounded-xl"
- />
- {/if}
+ {:else}
+ <div
+ class="w-[94vw] md:w-[375px] h-[381px] md:h-[269px] animate-pulse bg-gray-400 rounded-xl"
+ />
+ <div
+ class="h-[1px] lg:h-[600px] w-full lg:w-[1px] bg-lightgrey rounded-xl"
+ id="section-divider"
+ />
+ <div
+ class="w-full md:w-[342px] h-[454px] md:h-[494px] animate-pulse bg-gray-400 rounded-xl"
+ />
+ {/if}
+ </div>
</div>
-</div>
+{/if}
<style>
#slider {
diff --git a/src/routes/receive.svelte b/src/routes/receive.svelte
index e78934a9..11bafe9a 100644
--- a/src/routes/receive.svelte
+++ b/src/routes/receive.svelte
@@ -2,7 +2,11 @@
// in the future we will want to allow users to set their fiat currency in the settings
import { AppHeader, Icon } from '$comp';
import { goto } from '$app/navigation';
- import { invoiceAmount, invoiceAmountFiat, rate } from '$lib/store';
+ import { invoiceAmount, invoiceAmountFiat, rate, user } from '$lib/store';
+
+ if (!$user && typeof window !== 'undefined') {
+ window.location = '/login';
+ }
let useFiat = true;
let amountFiat = 0;
@@ -78,98 +82,102 @@
};
</script>
-<AppHeader />
+{#if $user}
+ <AppHeader />
-<!-- step 1 input amount and generate QR code -->
-<div class="flex justify-center items-center mt-20 mb-3 px-3">
- {#if $rate}
- <div class="space-y-5">
- <!-- amounts -->
- <div class="text-center">
- <div class="text-5xl md:text-6xl font-semibold tracking-widest mb-1">
- {useFiat ? `$${amountFiat}` : amountSatsFormatted}<span
- class="tracking-normal text-base font-normal">{useFiat ? 'USD' : 'SATS'}</span
+ <!-- step 1 input amount and generate QR code -->
+ <div class="flex justify-center items-center mt-20 mb-3 px-3">
+ {#if $rate}
+ <div class="space-y-5">
+ <!-- amounts -->
+ <div class="text-center">
+ <div class="text-5xl md:text-6xl font-semibold tracking-widest mb-1">
+ {useFiat ? `$${amountFiat}` : amountSatsFormatted}<span
+ class="tracking-normal text-base font-normal">{useFiat ? 'USD' : 'SATS'}</span
+ >
+ </div>
+ <span class="text-secondary mr-1"
+ >{useFiat ? `${amountSatsConverted} SATS` : `${amountFiatConverted} USD`}</span
+ >
+ <button
+ on:click={() => {
+ if (useFiat) {
+ amountSats = (amountFiat / ($rate / 100000000)).toFixed(0).toString();
+ } else {
+ amountFiat =
+ (amountSats * ($rate / 100000000)).toFixed(2) > 0.0
+ ? (amountSats * ($rate / 100000000)).toFixed(2).toString()
+ : 0;
+ }
+ useFiat = !useFiat;
+ }}><Icon icon="swap" style="inline" /></button
>
</div>
- <span class="text-secondary mr-1"
- >{useFiat ? `${amountSatsConverted} SATS` : `${amountFiatConverted} USD`}</span
- >
- <button
- on:click={() => {
- if (useFiat) {
- amountSats = (amountFiat / ($rate / 100000000)).toFixed(0).toString();
- } else {
- amountFiat =
- (amountSats * ($rate / 100000000)).toFixed(2) > 0.0
- ? (amountSats * ($rate / 100000000)).toFixed(2).toString()
- : 0;
- }
- useFiat = !useFiat;
- }}><Icon icon="swap" style="inline" /></button
- >
- </div>
- <!-- error message -->
- {#if message}
- <div
- class="text-orange-500 text-sm text-center font-bold bg-primary p-2 rounded-xl flex justify-center items-center space-x-1"
- >
- <Icon icon="info" style="w-5" />
- <p>{message}</p>
- </div>
- {/if}
+ <!-- error message -->
+ {#if message}
+ <div
+ class="text-orange-500 text-sm text-center font-bold bg-primary p-2 rounded-xl flex justify-center items-center space-x-1"
+ >
+ <Icon icon="info" style="w-5" />
+ <p>{message}</p>
+ </div>
+ {/if}
- <!-- numpad -->
- <div class="grid grid-cols-3 gap-2 w-full md:w-[300px] mx-auto">
- {#each numPad as value}
- {#if value === '<'}
- <button
- class="bg-primary rounded-xl py-4 px-8 font-semibold active:bg-black active:text-white flex justify-center items-center"
- on:click={() => handleInput(value)}
- >
- <svg
- class="w-5"
- width="24"
- height="24"
- viewBox="0 0 24 24"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
+ <!-- numpad -->
+ <div class="grid grid-cols-3 gap-2 w-full md:w-[300px] mx-auto">
+ {#each numPad as value}
+ {#if value === '<'}
+ <button
+ class="bg-primary rounded-xl py-4 px-8 font-semibold active:bg-black active:text-white flex justify-center items-center"
+ on:click={() => handleInput(value)}
>
- <path
- d="M15 19L8 12L15 5"
- stroke="currentColor"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- />
- </svg>
- </button>
- {:else}
- <button
- class="bg-primary rounded-xl py-4 px-8 font-semibold active:bg-black active:text-white"
- on:click={() => handleInput(value)}>{value}</button
- >
- {/if}
- {/each}
- </div>
+ <svg
+ class="w-5"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M15 19L8 12L15 5"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ </svg>
+ </button>
+ {:else}
+ <button
+ class="bg-primary rounded-xl py-4 px-8 font-semibold active:bg-black active:text-white"
+ on:click={() => handleInput(value)}>{value}</button
+ >
+ {/if}
+ {/each}
+ </div>
- <!-- buttons -->
- <div class="space-y-3 w-full md:w-[300px] mx-auto">
- <button
- class="bg-black text-white rounded-xl w-full h-[48px] flex justify-center items-center font-semibold text-sm {$invoiceAmount ===
- 0
- ? 'opacity-50'
- : 'opacity-100'}"
- on:click={() => goto(`/invoice/${$invoiceAmount}`)}
- disabled={$invoiceAmount === 0}><Icon icon="qr" style="mr-2" /> Show QR</button
- >
- <button
- class="bg-primary rounded-xl w-full h-[48px] flex justify-center items-center font-semibold text-sm"
- disabled={true}><Icon icon="send" style="mr-2" /> Send Invoice</button
- >
+ <!-- buttons -->
+ <div class="space-y-3 w-full md:w-[300px] mx-auto">
+ <button
+ class="bg-black text-white rounded-xl w-full h-[48px] flex justify-center items-center font-semibold text-sm {$invoiceAmount ===
+ 0
+ ? 'opacity-50'
+ : 'opacity-100'}"
+ on:click={() => goto(`/invoice/${$invoiceAmount}`)}
+ disabled={$invoiceAmount === 0}><Icon icon="qr" style="mr-2" /> Show QR</button
+ >
+ <button
+ class="bg-primary rounded-xl w-full h-[48px] flex justify-center items-center font-semibold text-sm"
+ disabled={true}><Icon icon="send" style="mr-2" /> Send Invoice</button
+ >
+ </div>
</div>
- </div>
- {:else}
- <div class="w-full md:w-[300px] h-[475px] md:h-[485px] animate-pulse bg-gray-400 rounded-xl" />
- {/if}
-</div>
+ {:else}
+ <div
+ class="w-full md:w-[300px] h-[475px] md:h-[485px] animate-pulse bg-gray-400 rounded-xl"
+ />
+ {/if}
+ </div>
+{/if}
diff --git a/static/icons/error.svg b/static/icons/error.svg
new file mode 100644
index 00000000..7d8269a4
--- /dev/null
+++ b/static/icons/error.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10 14L12 12M12 12L14 10M12 12L10 10M12 12L14 14M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/static/icons/info.svg b/static/icons/info.svg
index 80f33b37..e916f53c 100644
--- a/static/icons/info.svg
+++ b/static/icons/info.svg
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M12 8V12M12 16H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M13 16H12V12H11M12 8H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
diff --git a/static/icons/question.svg b/static/icons/question.svg
new file mode 100644
index 00000000..b7d46339
--- /dev/null
+++ b/static/icons/question.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.22766 9C8.77678 7.83481 10.2584 7 12.0001 7C14.2092 7 16.0001 8.34315 16.0001 10C16.0001 11.3994 14.7224 12.5751 12.9943 12.9066C12.4519 13.0106 12.0001 13.4477 12.0001 14M12 17H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>