aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2022-10-03 23:13:49 -0700
committerAdam Soltys <[email protected]>2022-10-03 23:13:49 -0700
commit63f1a6780bab85ebb48ca1fc142cc6beaf772faa (patch)
treeb498ac8dd1a8ac5ffd517e6a8050399d9d7a86a1 /src
parent8906099f391acf19f7b8eb91527b027cedd65b5e (diff)
downloadcoinos-ui-63f1a6780bab85ebb48ca1fc142cc6beaf772faa.tar.gz
coinos-ui-63f1a6780bab85ebb48ca1fc142cc6beaf772faa.zip
refactoring
Diffstat (limited to 'src')
-rw-r--r--src/components/AppHeader.svelte49
-rw-r--r--src/components/LandingHeader.svelte9
-rw-r--r--src/components/LandingHero.svelte19
-rw-r--r--src/components/LocationsMap.svelte2
-rw-r--r--src/components/Numpad.svelte11
-rw-r--r--src/components/Qr.svelte19
-rw-r--r--src/components/RegisterOrLogin.svelte20
-rw-r--r--src/lib/parse.js37
-rw-r--r--src/lib/socket.js19
-rw-r--r--src/lib/store.js7
-rw-r--r--src/lib/utils.js8
-rw-r--r--src/locales/en.json2
-rw-r--r--src/routes/+layout.server.js4
-rw-r--r--src/routes/+layout.svelte16
-rw-r--r--src/routes/+page.svelte17
-rw-r--r--src/routes/[username]/+layout.svelte7
-rw-r--r--src/routes/[username]/+page.svelte4
-rw-r--r--src/routes/[username]/customers/+page.svelte5
-rw-r--r--src/routes/[username]/dashboard/+page.svelte4
-rw-r--r--src/routes/[username]/receive/+page.server.js12
-rw-r--r--src/routes/[username]/receive/+page.svelte229
-rw-r--r--src/routes/[username]/settings/+page.svelte4
-rw-r--r--src/routes/[username]/settings/_account.svelte25
-rw-r--r--src/routes/[username]/settings/_pos.svelte1
-rw-r--r--src/routes/[username]/settings/_security.svelte12
-rw-r--r--src/routes/[username]/support/+page.svelte103
-rw-r--r--src/routes/[username]/transactions/[...page]/+page.svelte9
-rw-r--r--src/routes/invoice/+server.js10
-rw-r--r--src/routes/invoice/[id]/+page.svelte20
-rw-r--r--src/routes/login/+page.server.js12
-rw-r--r--src/routes/logout/+page.server.js8
-rw-r--r--src/routes/logout/+page.svelte10
-rw-r--r--src/routes/logout/done/+page.svelte3
-rw-r--r--src/routes/scan/+page.svelte6
-rw-r--r--src/routes/send/+page.server.js2
-rw-r--r--src/routes/send/+page.svelte14
-rw-r--r--src/routes/send/bitcoin/[address]/+page.svelte5
-rw-r--r--src/routes/send/lightning/[payreq]/+page.server.js2
-rw-r--r--src/routes/send/lightning/[payreq]/+page.svelte17
-rw-r--r--src/routes/sent/+page.svelte12
40 files changed, 246 insertions, 529 deletions
diff --git a/src/components/AppHeader.svelte b/src/components/AppHeader.svelte
index 62cfd940..fca11272 100644
--- a/src/components/AppHeader.svelte
+++ b/src/components/AppHeader.svelte
@@ -1,13 +1,16 @@
<script>
import OutClick from 'svelte-outclick';
- import { subject, user, newPayment, colorTheme, tempProfileFiles } from '$lib/store';
+ import { newPayment, colorTheme, tempProfileFiles } from '$lib/store';
import { goto } from '$app/navigation';
import { Icon } from '$comp';
import { t } from '$lib/translations';
import { page } from '$app/stores';
+ export let data;
export let avatarPosition = 'left-[calc(50vw-64px)] bottom-[-64px]';
+ let { subject, user } = data;
+
const menuButtons = [
{ stringID: 'nav.dashboard', icon: 'dash', goto: 'dashboard' },
{ stringID: 'nav.settings', icon: 'settings', goto: 'settings' },
@@ -22,34 +25,34 @@
goto('/logout');
} else {
showMenu = false;
- goto(`/${$user.username + '/' + item}`);
+ goto(`/${user.username + '/' + item}`);
}
};
$: background =
$tempProfileFiles && $tempProfileFiles.banner
? `url(${$tempProfileFiles.banner})`
- : $subject?.banner
- ? `url(/api/public/${$subject.username}-banner.png)`
+ : subject?.banner
+ ? `url(/api/public/${subject.username}-banner.png)`
: undefined;
</script>
<header class="bg-gradient-to-r {$colorTheme} h-[175px] w-full relative" style:background>
<nav class="flex justify-end items-center space-x-4 p-5">
- {#if $user}
- <a href={`/${$user.username}/receive`}>
+ {#if user}
+ <a href={`/${user.username}/receive`}>
<button
class="bg-white p-2 rounded-full w-12 h-12 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${$user.username}/receive`
+ .url.pathname === `/${user.username}/receive`
? 'opacity-100'
: 'opacity-70 hover:opacity-80'}"
><Icon icon="numpad" style="mx-auto" />
</button>
</a>
- <a href={`/${$user.username}/transactions`}>
+ <a href={`/${user.username}/transactions`}>
<button
class="bg-white p-2 rounded-full w-12 h-12 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${$user.username}/transactions`
+ .url.pathname === `/${user.username}/transactions`
? 'opacity-100'
: 'opacity-70 hover:opacity-80'} relative"
><Icon icon="clock" style="mx-auto" />
@@ -65,10 +68,10 @@
{/if}
</button>
</a>
- <a href={`/${$user.username}`}>
+ <a href={`/${user.username}`}>
<button
class="bg-white p-2 rounded-full w-12 h-12 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${$user.username}`
+ .url.pathname === `/${user.username}`
? 'opacity-100'
: 'opacity-70 hover:opacity-80'}"
><Icon icon="profile" style="mx-auto" />
@@ -78,9 +81,9 @@
<OutClick on:outclick={() => (showMenu = false)}>
<button
class="bg-white p-2 rounded-full w-12 h-12 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${$user.username}/dashboard` ||
- $page.url.pathname === `/${$user.username}/settings` ||
- $page.url.pathname === `/${$user.username}/support`
+ .url.pathname === `/${user.username}/dashboard` ||
+ $page.url.pathname === `/${user.username}/settings` ||
+ $page.url.pathname === `/${user.username}/support`
? 'opacity-100'
: `opacity-70 hover:opacity-80 ${showMenu ? 'opacity-80' : ''}`}"
on:click={() => (showMenu = !showMenu)}
@@ -114,18 +117,18 @@
</a>
{/if}
</nav>
- {#if $subject?.profile}
+ {#if subject?.profile}
<div
class="absolute top-[111px] {avatarPosition} rounded-full border-4 border-white overflow-hidden w-32 h-32"
>
- <a href={`/${$subject.username}`}>
- <img
- src={$tempProfileFiles && $tempProfileFiles.profile
- ? $tempProfileFiles.profile
- : `/api/public/${$subject.username}-profile.png`}
- class="w-full h-full object-cover object-center overflow-hidden"
- />
- </a>
+ <a href={`/${subject.username}`}>
+ <img
+ src={$tempProfileFiles && $tempProfileFiles.profile
+ ? $tempProfileFiles.profile
+ : `/api/public/${subject.username}-profile.png`}
+ class="w-full h-full object-cover object-center overflow-hidden"
+ />
+ </a>
</div>
{:else}
<div
diff --git a/src/components/LandingHeader.svelte b/src/components/LandingHeader.svelte
index adeac98e..1f12e049 100644
--- a/src/components/LandingHeader.svelte
+++ b/src/components/LandingHeader.svelte
@@ -2,7 +2,6 @@
import { goto } from '$app/navigation';
import { scroll } from '$lib/utils';
import { Icon } from '$comp';
- import { user } from '$lib/store';
import { t } from '$lib/translations';
export let howItWorks;
@@ -32,7 +31,7 @@
>
<button class="hover:opacity-80" on:click={() => scroll(faq)}>{$t('faq.header')}</button>
<button class="hover:opacity-80" on:click={() => scroll(about)}>{$t('about.header')}</button>
- {#if !$user}
+ {#if !user}
<button
class="border rounded-full px-6 py-2 font-bold hover:opacity-80"
on:click={() => goto('/register')}
@@ -47,7 +46,7 @@
{:else}
<button
class="border rounded-full px-6 py-2 font-bold"
- on:click={() => goto(`/${$user.username}/dashboard`)}
+ on:click={() => goto(`/${user.username}/dashboard`)}
>{$t('nav.account')}
</button>
<button
@@ -80,7 +79,7 @@
<button on:click={() => mobileMenuButtonClick(about)} class="block"
>{$t('about.header')}</button
>
- {#if !$user}
+ {#if !user}
<button
class="border rounded-full px-6 py-2 font-bold block w-full"
on:click={() => goto('/register')}
@@ -95,7 +94,7 @@
{:else}
<button
class="border rounded-full px-6 py-2 font-bold block"
- on:click={() => goto(`/${$user.username}/dashboard`)}
+ on:click={() => goto(`/${user.username}/dashboard`)}
>{$t('nav.account')}
</button>
<button
diff --git a/src/components/LandingHero.svelte b/src/components/LandingHero.svelte
index 466a6194..74c192fb 100644
--- a/src/components/LandingHero.svelte
+++ b/src/components/LandingHero.svelte
@@ -1,8 +1,9 @@
<script>
import { goto } from '$app/navigation';
import { Icon, Image } from '$comp';
- import { user } from '$lib/store';
import { t } from '$lib/translations';
+
+ export let user;
</script>
<div class="mt-[96.88px] md:mt-0">
@@ -22,18 +23,18 @@
>
{$t('landing.subheader')}
</h2>
- {#if !$user}
+ {#if !user}
<div class="flex justify-center">
- <button
- class="bg-black text-white border rounded-full px-6 py-2 font-bold hover:opacity-80"
- on:click={() => goto('/register')}
- >
- {$t('nav.startInSeconds')}
- </button>
+ <a href="/register">
+ <button
+ class="bg-black text-white border rounded-full px-6 py-2 font-bold hover:opacity-80"
+ >
+ {$t('nav.startInSeconds')}
+ </button>
+ </a>
</div>
{/if}
</div>
- <!-- hero image -->
<Image image="hero-image" style="w-full md:w-2/3 max-w-5xl mx-auto mt-20" />
</div>
diff --git a/src/components/LocationsMap.svelte b/src/components/LocationsMap.svelte
index 8a8599c4..6d0b086e 100644
--- a/src/components/LocationsMap.svelte
+++ b/src/components/LocationsMap.svelte
@@ -77,7 +77,7 @@
locations.forEach(({ lat, lng, info }) => {
let marker = L.marker([lat, lng]);
- marker.bindPopup(info);
+ marker.bindPopup(info);
markers.addLayer(marker);
});
diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte
index 3555688c..9de4a0dc 100644
--- a/src/components/Numpad.svelte
+++ b/src/components/Numpad.svelte
@@ -1,6 +1,6 @@
<script>
import { Left, Icon } from '$comp';
- import { selectedRate, user } from '$lib/store';
+ import { selectedRate } from '$lib/store';
import { f, s, post, warning, sats } from '$lib/utils';
import { t } from '$lib/translations';
@@ -32,7 +32,7 @@
$: amountSatsFormatted = s(amountSats);
- $: amountFiatConverted = f(amountSats * ($selectedRate / sats), $user.currency);
+ $: amountFiatConverted = f(amountSats * ($selectedRate / sats), currency);
$: amountSatsConverted = s(amountFiat / ($selectedRate / sats));
@@ -90,13 +90,14 @@
<div class="text-center">
<div class="text-5xl md:text-6xl font-semibold tracking-widest mb-1">
{useFiat ? `${symbol}${amountFiat}` : amountSatsFormatted}<span
- class="tracking-normal text-base font-normal">{useFiat ? $user.currency : 'SAT'}</span
+ class="tracking-normal text-base font-normal">{useFiat ? currency : 'SAT'}</span
>
</div>
<span class="text-secondary mr-1"
>{useFiat ? `${amountSatsConverted} SAT` : amountFiatConverted}</span
>
<button
+ type="button"
on:click={() => {
if (useFiat) {
amountSats = parseInt((amountFiat / ($selectedRate / sats)).toFixed(0));
@@ -115,13 +116,15 @@
{#each numPad as value}
{#if value === '<'}
<button
+ type="button"
class="bg-primary rounded-xl py-4 px-8 font-semibold active:bg-black active:text-white flex justify-center items-center hover:opacity-80"
on:click={() => handleInput(value)}
>
- <Left />
+ <Left />
</button>
{:else}
<button
+ type="button"
class="bg-primary rounded-xl py-4 px-8 font-semibold active:bg-black active:text-white hover:opacity-80"
on:click={() => handleInput(value)}>{value}</button
>
diff --git a/src/components/Qr.svelte b/src/components/Qr.svelte
index 35146ec3..988faf25 100644
--- a/src/components/Qr.svelte
+++ b/src/components/Qr.svelte
@@ -1,17 +1,20 @@
<script>
+ import screenfull from 'screenfull';
import { browser } from '$app/environment';
import { onMount } from 'svelte';
import { copy } from '$lib/utils';
export let image, text, qr, disabled;
+ let toggle = () => screenfull.toggle(qr.firstChild);
+
$: update(text);
- let update = async (text) => {
+ let update = async (text, fullscreen) => {
if (!(browser && text)) return;
let { default: QRCodeStyling } = await import('qr-code-styling');
const qrCode = new QRCodeStyling({
- width: window.screen.width < 640 ? 250 : 300,
+ width: 300,
type: 'canvas',
data: text,
backgroundOptions: {
@@ -35,22 +38,14 @@
};
</script>
-<div
- bind:this={qr}
- on:click={() => {
- if (!disabled) copy(text);
- }}
-/>
+<div bind:this={qr} on:click={toggle} />
<style>
div {
- @apply px-5
- md:px-0
- w-[300px]
+ @apply w-[300px]
h-[300px]
rounded-3xl
block
- md:flex
justify-center
items-center
cursor-pointer
diff --git a/src/components/RegisterOrLogin.svelte b/src/components/RegisterOrLogin.svelte
index 8f10fadd..de886314 100644
--- a/src/components/RegisterOrLogin.svelte
+++ b/src/components/RegisterOrLogin.svelte
@@ -1,14 +1,11 @@
<script>
- import { browser } from '$app/environment';
- import { page } from '$app/stores';
- import { tick } from 'svelte';
+ import { enhance } from '$app/forms';
import { Icon } from '$comp';
- import { focus, post, failure } from '$lib/utils';
- import { redirect, user, token } from '$lib/store';
- import { auth } from '$lib/socket';
- import { goto } from '$app/navigation';
+ import { focus } from '$lib/utils';
+ import { redirect } from '$lib/store';
import { t } from '$lib/translations';
+ export let form;
export let pageID;
let username,
@@ -22,9 +19,6 @@
register: '/register',
signIn: '/login'
}[pageID];
-
- // TODO: move to server side
- $: if (browser && $user) goto(`/${$user.username}/receive`);
</script>
<div class="pt-10">
@@ -38,7 +32,11 @@
<div class="shadow-xl rounded-3xl p-10 pb-12 space-y-5 w-full mx-5 md:mx-0 md:w-[400px]">
<h1 class="text-2xl font-bold text-center">{$t('login.' + pageID)}</h1>
- <form class="space-y-5" {action} method="POST">
+ {#if form?.error}
+ Login failed
+ {/if}
+
+ <form class="space-y-5" {action} method="POST" use:enhance>
{#if $redirect}
<input type="hidden" name="redirect" value={$redirect} />
{/if}
diff --git a/src/lib/parse.js b/src/lib/parse.js
index 95d0a8b6..e69de29b 100644
--- a/src/lib/parse.js
+++ b/src/lib/parse.js
@@ -1,37 +0,0 @@
-// import bolt11 from 'bolt11';
-import validate from 'bitcoin-address-validation';
-import bip21 from 'bip21';
-import { get } from '$lib/utils';
-import { goto } from '$app/navigation';
-
-let debounce;
-export default async (t) => {
- if (!t) return;
- console.log('parsing');
-
- // lightning
- if (t.startsWith('ln')) {
- goto(`/send/lightning/${t}`);
- }
-
- // bitcoin
- if (validate(t)) {
- console.log('bitcoin');
- goto(`/send/bitcoin/${t}`);
- }
-
- // ln address
- if (t.includes('@') && t.includes('.')) {
- console.log('ln address');
- let [name, domain] = t.split('@');
- try {
- clearTimeout(debounce);
- await new Promise((r) => (debounce = setTimeout(r, 1500)));
- let lnurl = await get(`/encode?domain=${domain}&name=${name}`);
- console.log('lnurl', lnurl);
- } catch (e) {}
- }
-
- // user
- console.log('username');
-};
diff --git a/src/lib/socket.js b/src/lib/socket.js
index ed3fa02e..dac2935e 100644
--- a/src/lib/socket.js
+++ b/src/lib/socket.js
@@ -1,16 +1,13 @@
import { get } from 'svelte/store';
-import { rate, user, token, invoices, newPayment } from '$lib/store';
+import { invoices, newPayment, rate } from '$lib/store';
import { success } from '$lib/utils';
import { env } from '$env/dynamic/public';
const socketUrl = env.PUBLIC_SOCKET;
-let interval, socket;
+let interval, socket, token;
-export const auth = () => {
- let t = get(token);
- if (t) send('login', t);
-};
+export const auth = () => token && send('login', token);
export const send = (type, data) => {
socket?.readyState === 1 && socket.send(JSON.stringify({ type, data }));
@@ -31,11 +28,7 @@ export const messages = (data) => ({
}
},
- connected: auth,
-
- login() {
- user.set(data);
- }
+ connected: auth
});
const initialReconnectDelay = 1000;
@@ -43,7 +36,9 @@ const maxReconnectDelay = 16000;
let currentReconnectDelay = initialReconnectDelay;
-export function connect() {
+export function connect(t) {
+ token = t;
+
clearInterval(interval);
if (socket) return auth();
diff --git a/src/lib/store.js b/src/lib/store.js
index e7228158..c64ad39f 100644
--- a/src/lib/store.js
+++ b/src/lib/store.js
@@ -27,14 +27,9 @@ const persistLocal = (key, defaultValue) => {
return s;
};
-export const rate = writable();
export const redirect = writable();
-export const rates = writable();
+export const rate = writable();
export const selectedRate = writable();
-export const user = writable();
-export const subject = writable();
-export const invoiceAmount = writable();
-export const invoiceAmountFiat = writable();
export const token = persistSession('token');
export const invoices = writable({});
export const newPayment = persistLocal('newPayment');
diff --git a/src/lib/utils.js b/src/lib/utils.js
index a7d0adaa..a4c77d58 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -109,11 +109,14 @@ export const info = (m) => {
export const login = async (user, cookies) => {
let maxAge = 30 * 24 * 60 * 60;
let { token } = await post('/login', user);
+ console.log('logged in', token);
let expires = new Date();
expires.setSeconds(expires.getSeconds() + maxAge);
+ console.log('cs');
cookies.set('token', token, { path: '/' });
+ console.log('bs');
};
export const auth = (cookies) => ({ authorization: `Bearer ${cookies.get('token')}` });
@@ -128,11 +131,6 @@ export const f = (s, currency) =>
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);
-
export const sats = 100000000;
export const back = () => {
diff --git a/src/locales/en.json b/src/locales/en.json
index 8ed35f47..1d1a9749 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -152,7 +152,7 @@
"settings": "Settings",
"support": "Support"
},
- "newSiteHeader": "Welcome to the <a href=\"/news\" class=\"underline underline-offset-4 text-black hover:opacity-80\" >new and improved coinos</a>, focused on merchant adoption! Looking for the old coinos? Visit <a href=\"https://classic.coinos.io\" class=\"underline underline-offset-4 text-black hover:opacity-80\">classic.coinos.io</a>.",
+ "newSiteHeader": "Welcome to the <a href=\"/news\" class=\"underline underline-offset-4 text-black hover:opacity-80\" >new and improved coinos</a>, focused on merchant adoption! Looking for the old coinos? Visit <a href=\"https://classic.coinos.io\" class=\"underline underline-offset-4 text-black hover:opacity-80\">classic.coinos.io</a>.",
"news": {
"header": "News",
"subheader": "Latest Updates",
diff --git a/src/routes/+layout.server.js b/src/routes/+layout.server.js
index f5fa1059..4beaad93 100644
--- a/src/routes/+layout.server.js
+++ b/src/routes/+layout.server.js
@@ -16,7 +16,7 @@ export async function load({ cookies, request, url, params }) {
subject = await get(`/users/${params.username}`);
}
- if (token) {
+ if (token && token !== 'undefined') {
try {
user = await get('/me', { accept: 'application/json', authorization: `Bearer ${token}` });
} catch (e) {
@@ -36,7 +36,7 @@ export async function load({ cookies, request, url, params }) {
}
}
- let rate = await get('/rate');
+ let rate = await get('/rate');
rates = await get('/rates');
return { subject, user, token, rate, rates };
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index f3a03440..118caa48 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -3,7 +3,7 @@
import '../app.css';
import { onMount } from 'svelte';
import { connect } from '$lib/socket';
- import { user, subject, token, rate, rates, selectedRate } from '$lib/store';
+ import { selectedRate, rate } from '$lib/store';
import { page } from '$app/stores';
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
@@ -14,14 +14,10 @@
const localeLocalStorageKey = 'sveltekit-i18n-locale';
export let data;
+ let { user, rate: r, token, rates } = data;
+ $rate = r;
- $: $subject = data.subject;
- $: $token = data.token;
- $: $user = data.user;
- $: $rate = data.rate;
-
- $rates = data.rates;
- $: $selectedRate = data.user && $rate * (data.rates[data.user.currency] / data.rates.USD);
+ $: $selectedRate = user && $rate * (rates[user.currency] / rates.USD);
onMount(() => {
let localStorageLocale = localStorage.getItem(localeLocalStorageKey);
@@ -32,13 +28,13 @@
});
if (protectedRoutes.find((p) => $page.url.pathname.match(p))) {
- if (!$token) {
+ if (!token) {
goto('/login');
warning($t('error.signIn'));
}
}
- connect();
+ connect(token);
});
</script>
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index d7df57d8..872348fd 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -12,6 +12,9 @@
import { t } from '$lib/translations';
+ export let data;
+ let { user } = data;
+
let howItWorks;
let faq;
let about;
@@ -28,24 +31,20 @@
<!-- banner -->
<div class="mt-[101.7px] md:mt-0 w-full text-center py-4 border border-b-black text-secondary">
<p>
- {@html $t('newSiteHeader')}
+ {@html $t('newSiteHeader')}
</p>
</div>
-<LandingHeader {howItWorks} {faq} {about} />
+<LandingHeader {howItWorks} {faq} {about} {user} />
<main class="space-y-40 py-20 md:py-32 lg:py-36 xl:py-40 px-5 md:px-0">
- <!-- hero -->
- <LandingHero />
-
- <!-- landing info 1 -->
+ <LandingHero {user} />
<LandingInfoCard
image="lightning-qr"
title={$t('landing.info1.title')}
description={$t('landing.info1.description')}
/>
- <!-- landing info 2 -->
<LandingInfoCard image="phone-checkout" title={$t('landing.info2.title')} order="reverse">
{$t('landing.info2.description1')}
<br /><br />
@@ -54,7 +53,6 @@
{@html $t('landing.info2.description3')}
</LandingInfoCard>
- <!-- landing info 3 -->
<div>
<LandingInfoCard
image="customize"
@@ -64,7 +62,6 @@
<div bind:this={howItWorks} />
</div>
- <!-- how it works -->
<div>
<h3 class="text-5xl font-medium mb-10 text-center">{$t('howItWorks.header')}</h3>
<div class="grid lg:grid-cols-3 space-y-10 lg:space-y-0 text-center">
@@ -75,7 +72,6 @@
<div bind:this={faq} />
</div>
- <!-- faq -->
<div>
<div class="space-y-10">
<h3 class="text-5xl font-medium text-center">{$t('faq.header')}</h3>
@@ -86,7 +82,6 @@
<div bind:this={about} />
</div>
- <!-- about -->
<div>
<About />
</div>
diff --git a/src/routes/[username]/+layout.svelte b/src/routes/[username]/+layout.svelte
new file mode 100644
index 00000000..b2efa894
--- /dev/null
+++ b/src/routes/[username]/+layout.svelte
@@ -0,0 +1,7 @@
+<script>
+ import { AppHeader } from '$comp';
+ export let data;
+</script>
+
+<AppHeader {data} />
+<slot />
diff --git a/src/routes/[username]/+page.svelte b/src/routes/[username]/+page.svelte
index d1b6d223..5eab4ad2 100644
--- a/src/routes/[username]/+page.svelte
+++ b/src/routes/[username]/+page.svelte
@@ -1,7 +1,7 @@
<script>
import { browser } from '$app/environment';
import { onMount } from 'svelte';
- import { AppHeader, Icon, PageNotFound } from '$comp';
+ import { Icon, PageNotFound } from '$comp';
import { subject, user } from '$lib/store';
import { copy } from '$lib/utils';
import { t } from '$lib/translations';
@@ -35,8 +35,6 @@
let followed = false;
</script>
-<AppHeader />
-
<div class="flex xl:block justify-center items-center my-20 px-3">
<div class="space-y-10 xl:space-y-0">
<div class="xl:ml-[calc(15vw-64px)] space-y-2 w-full md:w-72">
diff --git a/src/routes/[username]/customers/+page.svelte b/src/routes/[username]/customers/+page.svelte
index 1935b156..e69de29b 100644
--- a/src/routes/[username]/customers/+page.svelte
+++ b/src/routes/[username]/customers/+page.svelte
@@ -1,5 +0,0 @@
-<script>
- import { AppHeader } from '$comp';
-</script>
-
-<AppHeader />
diff --git a/src/routes/[username]/dashboard/+page.svelte b/src/routes/[username]/dashboard/+page.svelte
index 1e55867d..c017fdc0 100644
--- a/src/routes/[username]/dashboard/+page.svelte
+++ b/src/routes/[username]/dashboard/+page.svelte
@@ -1,7 +1,7 @@
<script>
import { f, s, post, failure, sats } from '$lib/utils';
import { tick } from 'svelte';
- import { AppHeader, Icon } from '$comp';
+ import { Icon } from '$comp';
import { rate, selectedRate } from '$lib/store';
import { goto } from '$app/navigation';
import { t } from '$lib/translations';
@@ -43,8 +43,6 @@
$: accountBalanceSats = s(user.account.balance);
</script>
-<AppHeader avatarPosition="left-[calc(50vw-64px)] lg:left-[calc(15vw-64px)]" />
-
<div class="text-center mx-auto lg:text-left lg:mx-0 lg:ml-[calc(15vw-64px)] mt-20 w-full md:w-72">
<h2 class="text-3xl font-semibold">{user.username}</h2>
diff --git a/src/routes/[username]/receive/+page.server.js b/src/routes/[username]/receive/+page.server.js
new file mode 100644
index 00000000..8d523213
--- /dev/null
+++ b/src/routes/[username]/receive/+page.server.js
@@ -0,0 +1,12 @@
+import { auth, post } from '$lib/utils';
+
+export const actions = {
+ default: async ({ cookies, request, parent }) => {
+ let { rate, user } = await parent();
+ let invoice = Object.fromEntries(await request.formData());
+ invoice.rate = rate;
+
+ let { uuid } = await post('/invoice', { invoice, user }, auth(cookies));
+ throw redirect(303, `/invoice/${uuid}`);
+ }
+};
diff --git a/src/routes/[username]/receive/+page.svelte b/src/routes/[username]/receive/+page.svelte
index f79e2df5..3c65279d 100644
--- a/src/routes/[username]/receive/+page.svelte
+++ b/src/routes/[username]/receive/+page.svelte
@@ -1,216 +1,29 @@
<script>
- import { AppHeader, Icon } from '$comp';
- import { goto } from '$app/navigation';
- import { invoiceAmount, invoiceAmountFiat, selectedRate, user } from '$lib/store';
- import { f, s, post, warning, sats } from '$lib/utils';
- import { page } from '$app/stores';
+ import { Icon, Numpad } from '$comp';
import { t } from '$lib/translations';
+ import { enhance } from '$app/forms';
- let useFiat = true;
- let amountFiat = 0;
- let amountSats = 0;
- let loading = false;
+ export let data;
+ let amount;
- $: amount = parseInt(useFiat ? Math.round(amountFiat / ($selectedRate / sats)) : amountSats);
-
- $: $invoiceAmount = parseInt(!amountSats ? amountFiat / ($selectedRate / sats) : amountSats);
-
- $: $invoiceAmountFiat = parseInt(
- amountFiat === 0 ? amountSats * ($selectedRate / sats) : amountFiat
- );
-
- $: amountSatsFormatted = s(amountSats);
-
- $: amountFiatConverted = f(amountSats * ($selectedRate / sats), $user.currency);
-
- $: amountSatsConverted = s(amountFiat / ($selectedRate / sats));
-
- const numPad = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '0', '<'];
-
- const handleInput = (value) => {
- if (useFiat) {
- if (amountFiat === 0 && value !== '.' && value !== '<' && value !== '0') {
- amountFiat = value;
- } else if ((amountFiat === 0 || amountFiat === '0') && value === '0') {
- return;
- } else if (amountFiat === 0 && value === '.') {
- amountFiat = '0.';
- } else if (amountFiat !== 0 && amountFiat.includes('.') && value === '.') {
- return;
- } else if (value === '<') {
- if (amountFiat !== 0) {
- amountFiat = amountFiat.slice(0, amountFiat.length - 1);
- if (amountFiat.length === 0) {
- amountFiat = 0;
- amountSats = 0;
- }
- }
- } else if (value !== '.' && value !== '<' && parseInt(amountFiat + value) > $selectedRate) {
- warning($t('user.receive.lessThan1BTCWarning'));
- } else if (amountFiat !== 0 && amountFiat.match(/\.../)) {
- return;
- } else {
- amountFiat = amountFiat + value;
- }
- } else {
- if (value === '.') {
- return;
- } else if (!amountSats && value !== '<' && value !== '0') {
- amountSats = parseInt(value);
- } else if (value === '<') {
- if (amountSats !== 0) {
- amountSats = Math.floor(amountSats / 10);
- if (amountSats.length === 0) {
- amountSats = 0;
- amountFiat = 0;
- }
- }
- } else if (value !== '<' && parseInt(amountSats + value) > sats) {
- warning($t('user.receive.lessThan1BTCWarning'));
- } else {
- amountSats = parseInt(amountSats + value);
- }
- }
- };
-
- let submit = async () => {
- loading = true;
- let { uuid } = await post('/invoice', {
- amount,
- rate: $selectedRate,
- prompt: true,
- username: $page.params.username
- });
- goto(`/invoice/${uuid}`);
- };
+ let { currency } = data.user;
</script>
-{#if $user}
- <AppHeader />
-
- <div class="flex justify-center items-center mt-24 mb-3 px-3">
- {#if $selectedRate}
- <div class="space-y-5">
- <!-- amounts -->
- <div class="text-center">
- <div class="text-5xl md:text-6xl font-semibold tracking-widest mb-1">
- {useFiat
- ? `${
- $user.currency === 'USD' ||
- $user.currency === 'CAD' ||
- $user.currency === 'AUD' ||
- $user.currency === 'NZD' ||
- $user.currency === 'MXN' ||
- $user.currency === 'BRL' ||
- $user.currency === 'HKD' ||
- $user.currency === 'TWD'
- ? '$'
- : $user.currency === 'JPY' || $user.currency === 'CNY'
- ? '¥'
- : $user.currency === 'GBP'
- ? '£'
- : $user.currency === 'EUR'
- ? '€'
- : $user.currency === 'KRW'
- ? '₩'
- : ''
- }${amountFiat}`
- : amountSatsFormatted}<span class="tracking-normal text-base font-normal"
- >{useFiat ? $user.currency : 'SAT'}</span
- >
- </div>
- <span class="text-secondary mr-1"
- >{useFiat ? `${amountSatsConverted} SAT` : amountFiatConverted}</span
- >
- <button
- on:click={() => {
- if (useFiat) {
- amountSats = parseInt((amountFiat / ($selectedRate / sats)).toFixed(0));
- } else {
- amountFiat =
- (amountSats * ($selectedRate / sats)).toFixed(2) > 0.0
- ? (amountSats * ($selectedRate / sats)).toFixed(2)
- : 0;
- }
- useFiat = !useFiat;
- }}><Icon icon="swap" style="inline hover:opacity-80" /></button
- >
- </div>
-
- <!-- 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 hover:opacity-80"
- 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"
- >
- <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 hover:opacity-80"
- on:click={() => handleInput(value)}>{value}</button
- >
- {/if}
- {/each}
- </div>
+<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="prompt" value="true" />
- <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 {$invoiceAmount ===
- 0 || loading
- ? 'opacity-50'
- : 'opacity-100 hover:opacity-80'}"
- on:click={submit}
- disabled={$invoiceAmount === 0 || loading}
- >
- {#if loading}
- <svg
- class="mx-auto h-6 w-6 animate-spin text-white"
- xmlns="http://www.w3.org/2000/svg"
- fill="none"
- viewBox="0 0 24 24"
- >
- <circle
- class="opacity-25"
- cx="12"
- cy="12"
- r="10"
- stroke="currentColor"
- stroke-width="4"
- />
- <path
- class="opacity-75"
- fill="currentColor"
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
- />
- </svg>
- {:else}
- <Icon icon="qr" style="mr-2" /> {$t('user.receive.showQR')}
- {/if}
- </button>
- </div>
- </div>
- {:else}
- <div
- class="w-full md:w-[300px] h-[475px] md:h-[485px] animate-pulse bg-gray-400 rounded-xl"
- />
- {/if}
+ <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}
+ >
+ <Icon icon="qr" style="mr-2" />
+ {$t('user.receive.showQR')}
+ </button>
</div>
-{/if}
+</form>
diff --git a/src/routes/[username]/settings/+page.svelte b/src/routes/[username]/settings/+page.svelte
index 978f537a..410ed1bf 100644
--- a/src/routes/[username]/settings/+page.svelte
+++ b/src/routes/[username]/settings/+page.svelte
@@ -3,7 +3,7 @@
import Pos from './_pos.svelte';
import Security from './_security.svelte';
- import { AppHeader, Icon } from '$comp';
+ import { Icon } from '$comp';
import { t } from '$lib/translations';
import { failure, success, put } from '$lib/utils';
import { user, avatarUpload, bannerUpload } from '$lib/store';
@@ -35,8 +35,6 @@
};
</script>
-<AppHeader />
-
<form on:submit|preventDefault={save} class="mb-[154px]">
<div class="mt-24 mb-20 px-3 md:px-0 w-full md:w-[400px] mx-auto space-y-8">
<h1 class="text-center text-3xl md:text-4xl font-semibold mb-10">
diff --git a/src/routes/[username]/settings/_account.svelte b/src/routes/[username]/settings/_account.svelte
index ff7676f4..8a20df43 100644
--- a/src/routes/[username]/settings/_account.svelte
+++ b/src/routes/[username]/settings/_account.svelte
@@ -1,13 +1,6 @@
<script>
import { tick } from 'svelte';
- import {
- user,
- colorTheme,
- rates,
- tempProfileFiles,
- avatarUpload,
- bannerUpload
- } from '$lib/store';
+ import { colorTheme, tempProfileFiles, avatarUpload, bannerUpload } from '$lib/store';
import { Icon, Toggle, LocaleSelector } from '$comp';
import { t } from '$lib/translations';
import { upload } from '$lib/upload';
@@ -58,7 +51,7 @@
}
};
- $: $user.password = $user.confirm = password;
+ $: user.password = user.confirm = password;
</script>
<div>
@@ -69,13 +62,13 @@
<!-- TODO
<div>
<label for="email" class="font-bold mb-1 block">{$t('user.settings.email')}</label>
- <input type="email" name="email" bind:value={$user.email} />
+ <input type="email" name="email" bind:value={user.email} />
</div> -->
<!-- TODO fix breaking changes when user updates this field -->
<div>
<label for="username" class="font-bold mb-1 block">{$t('user.settings.username')}</label>
- <input disabled type="text" name="username" bind:value={$user.username} />
+ <input disabled type="text" name="username" bind:value={user.username} />
</div>
<div class="relative">
@@ -96,7 +89,7 @@
<div>
<label for="address" class="font-bold mb-1 block">{$t('user.settings.businessAddress')}</label>
- <input type="text" name="address" bind:value={$user.address} />
+ <input type="text" name="address" bind:value={user.address} />
</div>
<!-- TODO -->
@@ -133,13 +126,13 @@
class="absolute w-full h-full object-cover object-center visible overflow-hidden"
/>
</div>
- {:else if $user.profile}
+ {:else if user.profile}
<div
class="relative rounded-full overflow-hidden text-center w-20 h-20 my-auto hover:opacity-80 cursor-pointer"
on:click={() => select('profile')}
>
<img
- src={`/api/public/${$user.username}-profile.png`}
+ src={`/api/public/${user.username}-profile.png`}
class="absolute w-full h-full object-cover object-center visible overflow-hidden"
/>
</div>
@@ -183,9 +176,9 @@
class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80"
on:click={() => select('banner')}
/>
- {:else if $user.banner}
+ {:else if user.banner}
<img
- src={`/api/public/${$user.username}-banner.png`}
+ src={`/api/public/${user.username}-banner.png`}
class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80"
on:click={() => select('banner')}
/>
diff --git a/src/routes/[username]/settings/_pos.svelte b/src/routes/[username]/settings/_pos.svelte
index 3310e426..edf54d91 100644
--- a/src/routes/[username]/settings/_pos.svelte
+++ b/src/routes/[username]/settings/_pos.svelte
@@ -1,5 +1,4 @@
<script>
- import { rates, user } from '$lib/store';
import { Icon, Toggle } from '$comp';
import { t } from '$lib/translations';
import { success, failure, put } from '$lib/utils';
diff --git a/src/routes/[username]/settings/_security.svelte b/src/routes/[username]/settings/_security.svelte
index 1b8fb125..3c0009dc 100644
--- a/src/routes/[username]/settings/_security.svelte
+++ b/src/routes/[username]/settings/_security.svelte
@@ -32,7 +32,7 @@
if (setting2fa && token.length === 6) {
await put('/enable2fa', { token });
success('2FA enabled');
- $user.twofa = 1;
+ user.twofa = 1;
toggleEnabling();
}
} catch (e) {
@@ -46,7 +46,7 @@
if (disabling2fa && token.length === 6) {
await put('/disable2fa', { token });
success('2FA disabled');
- $user.twofa = 0;
+ user.twofa = 0;
toggleDisabling();
}
} catch (e) {
@@ -54,7 +54,7 @@
}
};
- $: otpUri = `otpauth://totp/coinos:${$user.username}?secret=${$user.otpsecret}&period=30&digits=6&algorithm=SHA1&issuer=coinos`;
+ $: otpUri = `otpauth://totp/coinos:${user.username}?secret=${user.otpsecret}&period=30&digits=6&algorithm=SHA1&issuer=coinos`;
</script>
<!-- TODO
@@ -66,7 +66,7 @@
{#if settingPin}
<div class="flex my-4">
<div class="mx-auto">
- <Pincode bind:code bind:value={$user.pin} bind:this={pinInput}>
+ <Pincode bind:code bind:value={user.pin} bind:this={pinInput}>
<PincodeInput />
<PincodeInput />
<PincodeInput />
@@ -110,7 +110,7 @@
<div class="text-center my-4">
{$t('user.settings.accountId')}<br />
- <b>{$user.otpsecret}</b>
+ <b>{user.otpsecret}</b>
</div>
<div class="text-center my-4">
@@ -136,7 +136,7 @@
<PincodeInput />
</Pincode>
</div>
- {:else if $user.twofa}
+ {:else if user.twofa}
<button type="button" class="primary" on:click={toggleDisabling}>
<Icon icon="mobile" style="mr-1" />
{$t('user.settings.twofaDisable')}
diff --git a/src/routes/[username]/support/+page.svelte b/src/routes/[username]/support/+page.svelte
index 663ba8a6..796f72ec 100644
--- a/src/routes/[username]/support/+page.svelte
+++ b/src/routes/[username]/support/+page.svelte
@@ -1,65 +1,58 @@
<script>
- // this needs to be hooked up to the backend
- import { AppHeader } from '$comp';
- import { user } from '$lib/store';
import { t } from '$lib/translations';
let email;
let message;
</script>
-{#if $user}
- <AppHeader />
+<div class="mt-24 mb-20">
+ <h1 class="text-center text-3xl md:text-4xl font-semibold mb-10">
+ {$t('user.support.header')}
+ </h1>
- <div class="mt-24 mb-20">
- <h1 class="text-center text-3xl md:text-4xl font-semibold mb-10">
- {$t('user.support.header')}
- </h1>
+ <form class="space-y-5 mx-auto w-11/12 md:w-[350px]">
+ <div>
+ <label for="email" class="font-semibold">{$t('user.support.email')}</label>
+ <input
+ class="block border rounded-xl p-2 w-full"
+ type="email"
+ name="email"
+ bind:value={email}
+ required
+ />
+ </div>
- <form class="space-y-5 mx-auto w-11/12 md:w-[350px]">
- <div>
- <label for="email" class="font-semibold">{$t('user.support.email')}</label>
- <input
- class="block border rounded-xl p-2 w-full"
- type="email"
- name="email"
- bind:value={email}
- required
- />
- </div>
+ <div>
+ <label for="account" class="font-semibold">{$t('user.support.accountName')}</label>
+ <input
+ class="block border rounded-xl p-2 w-full"
+ type="text"
+ name="account"
+ required
+ disabled
+ value={user.username}
+ />
+ </div>
- <div>
- <label for="account" class="font-semibold">{$t('user.support.accountName')}</label>
- <input
- class="block border rounded-xl p-2 w-full"
- type="text"
- name="account"
- required
- disabled
- value={$user.username}
- />
- </div>
+ <div>
+ <label for="message" class="font-semibold">{$t('user.support.message')}</label>
+ <textarea
+ rows={5}
+ class="block border rounded-xl p-2 w-full"
+ type="text"
+ name="message"
+ bind:value={message}
+ required
+ />
+ </div>
- <div>
- <label for="message" class="font-semibold">{$t('user.support.message')}</label>
- <textarea
- rows={5}
- class="block border rounded-xl p-2 w-full"
- type="text"
- name="message"
- bind:value={message}
- required
- />
- </div>
-
- <button
- disabled={!email || !message}
- class="{!email || !message
- ? 'opacity-50'
- : 'opacity-100'} bg-black text-white font-bold rounded-xl py-3 w-full mx-auto {email &&
- message
- ? 'hover:opacity-80'
- : ''}">{$t('user.support.send')}</button
- >
- </form>
- </div>
-{/if}
+ <button
+ disabled={!email || !message}
+ class="{!email || !message
+ ? 'opacity-50'
+ : 'opacity-100'} bg-black text-white font-bold rounded-xl py-3 w-full mx-auto {email &&
+ message
+ ? 'hover:opacity-80'
+ : ''}">{$t('user.support.send')}</button
+ >
+ </form>
+</div>
diff --git a/src/routes/[username]/transactions/[...page]/+page.svelte b/src/routes/[username]/transactions/[...page]/+page.svelte
index a3e6850a..223418a3 100644
--- a/src/routes/[username]/transactions/[...page]/+page.svelte
+++ b/src/routes/[username]/transactions/[...page]/+page.svelte
@@ -1,5 +1,4 @@
<script>
- import { AppHeader } from '$comp';
import { newPayment } from '$lib/store';
import { t } from '$lib/translations';
import { f, s, sats } from '$lib/utils';
@@ -15,8 +14,6 @@
$: data && ({ page, pages, total, transactions } = data);
</script>
-<AppHeader />
-
<div class="mt-24 mb-20">
<h1 class="px-3 md:px-0 text-center text-3xl md:text-4xl font-semibold mb-10">
{$t('user.transactions.header')}
@@ -27,7 +24,9 @@
{#if pages.length > 1}
{#each pages as _, i}
<a href={`/${user.username}/transactions/${i + 1}`} class:active={page === i + 1}>
- <div class="border py-2 px-4 rounded-full border-2 w-12 h-12 hover:opacity-80 mr-1 text-center my-auto">
+ <div
+ class="border py-2 px-4 rounded-full border-2 w-12 h-12 hover:opacity-80 mr-1 text-center my-auto"
+ >
{i + 1}
</div>
</a>
@@ -76,6 +75,6 @@
<style>
.active div {
- @apply bg-gray-100;
+ @apply bg-gray-100;
}
</style>
diff --git a/src/routes/invoice/+server.js b/src/routes/invoice/+server.js
index 5b2f2b39..e69de29b 100644
--- a/src/routes/invoice/+server.js
+++ b/src/routes/invoice/+server.js
@@ -1,10 +0,0 @@
-import { auth, get, post } from '$lib/utils';
-
-export async function POST({ cookies, request }) {
- let { amount, currency, network = 'lightning', prompt, rate, tip, user } = await request.json();
- let invoice = { amount, currency, network, prompt, rate, tip };
-
- return new Response(JSON.stringify(await post('/invoice', { invoice, user }, auth(cookies))), {
- headers: { 'content-type': 'application/json' }
- });
-}
diff --git a/src/routes/invoice/[id]/+page.svelte b/src/routes/invoice/[id]/+page.svelte
index 7ff63862..9e0f9654 100644
--- a/src/routes/invoice/[id]/+page.svelte
+++ b/src/routes/invoice/[id]/+page.svelte
@@ -1,14 +1,14 @@
<script>
- import { copy, f, get, reverseFormat, s, toggleFullscreen, sats } from '$lib/utils';
+ import { copy, f, get, reverseFormat, s, sats } from '$lib/utils';
import { browser } from '$app/environment';
- import { invoices, user } from '$lib/store';
+ import { invoices } from '$lib/store';
import { Icon, Heart, Image, Qr, Tip } from '$comp';
import { goto } from '$app/navigation';
import { t } from '$lib/translations';
export let data;
$: refresh(data);
- let { invoice, id } = data;
+ let { invoice, id, user } = data;
let {
amount,
rate,
@@ -25,6 +25,8 @@
let qr;
let tipPercent = 0;
+ let fullscreen;
+
let refresh = (data) => {
({ invoice, id } = data);
({
@@ -57,7 +59,7 @@
<div class:full-shadow={showMobileTip}>
<button
class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80"
- class:invisible={!$user}
+ class:invisible={!user}
disabled={showMobileTip}
on:click={() => goto(`/${username}/receive`)}
>
@@ -109,12 +111,10 @@
<div>
<button
- class="border border-lightgrey rounded-md p-2 mx-2 hover:opacity-80"
- on:click={() => toggleFullscreen(qr)}><Icon icon="expand" /></button
- >
- <button
- class="border border-lightgrey rounded-md p-2 mx-2 hover:opacity-80"
- on:click={() => copy(text)}><Icon icon="copy" /></button
+ class="flex rounded-full border py-2 px-5 font-bold hover:opacity-80 mb-2 mx-auto"
+ on:click={() => copy(text)}
+ ><Icon icon="copy" style="mr-1" />
+ <div>Copy</div></button
>
</div>
diff --git a/src/routes/login/+page.server.js b/src/routes/login/+page.server.js
index 28f72712..28a5d78a 100644
--- a/src/routes/login/+page.server.js
+++ b/src/routes/login/+page.server.js
@@ -1,11 +1,15 @@
-import { redirect } from '@sveltejs/kit';
+import { invalid, redirect } from '@sveltejs/kit';
import { login } from '$lib/utils';
export const actions = {
default: async ({ cookies, request }) => {
let user = Object.fromEntries(await request.formData());
- await login(user, cookies);
-
- throw redirect(303, `/${user.username}/dashboard`);
+ try {
+ await login(user, cookies);
+ throw redirect(303, `/${user.username}/dashboard`);
+ } catch (e) {
+ console.log('OW');
+ return invalid(403, { error: 'Login failed' });
+ }
}
};
diff --git a/src/routes/logout/+page.server.js b/src/routes/logout/+page.server.js
index 6d863cb1..d51dcfbc 100644
--- a/src/routes/logout/+page.server.js
+++ b/src/routes/logout/+page.server.js
@@ -2,12 +2,12 @@ import { redirect } from '@sveltejs/kit';
import cookie from 'cookie';
const opts = {
- expires: new Date(0),
+ expires: new Date(0),
path: '/'
};
export async function load({ cookies }) {
- cookies.set('token', '', opts);
- cookies.set('refresh_token', '', opts);
- throw redirect(302, '/logout/done');
+ cookies.set('token', '', opts);
+ cookies.set('refresh_token', '', opts);
+ throw redirect(303, '/logout/done');
}
diff --git a/src/routes/logout/+page.svelte b/src/routes/logout/+page.svelte
index 5fd88bec..e69de29b 100644
--- a/src/routes/logout/+page.svelte
+++ b/src/routes/logout/+page.svelte
@@ -1,10 +0,0 @@
-<script>
- import { onMount } from 'svelte';
- import { browser } from '$app/environment';
- import { user, token } from '$lib/store';
-
- onMount(() => {
- $user = null;
- $token = null;
- });
-</script>
diff --git a/src/routes/logout/done/+page.svelte b/src/routes/logout/done/+page.svelte
index 50fb766e..47d48c54 100644
--- a/src/routes/logout/done/+page.svelte
+++ b/src/routes/logout/done/+page.svelte
@@ -1,12 +1,9 @@
<script>
import { onMount } from 'svelte';
- import { user, token } from '$lib/store';
import { goto } from '$app/navigation';
import { close } from '$lib/socket';
onMount(() => {
- $token = null;
- $user = null;
close();
goto('/');
});
diff --git a/src/routes/scan/+page.svelte b/src/routes/scan/+page.svelte
index 0acebb26..3e024bc8 100644
--- a/src/routes/scan/+page.svelte
+++ b/src/routes/scan/+page.svelte
@@ -17,9 +17,9 @@
</button>
<div class="flex w-full mb-4 px-4">
- <div class="bg-black mx-auto rounded-3xl">
- <video bind:this={vid} class="border-4 rounded-3xl border-black md:max-w-[600px]" />
- </div>
+ <div class="bg-black mx-auto rounded-3xl">
+ <video bind:this={vid} class="border-4 rounded-3xl border-black md:max-w-[600px]" />
+ </div>
</div>
<div class="flex w-full">
diff --git a/src/routes/send/+page.server.js b/src/routes/send/+page.server.js
index 837060f2..d0fefdee 100644
--- a/src/routes/send/+page.server.js
+++ b/src/routes/send/+page.server.js
@@ -1,7 +1,7 @@
import validate from 'bitcoin-address-validation';
import bip21 from 'bip21';
import { get } from '$lib/utils';
-import { invalid, redirect } from "@sveltejs/kit";
+import { invalid, redirect } from '@sveltejs/kit';
export const actions = {
default: async ({ request }) => {
diff --git a/src/routes/send/+page.svelte b/src/routes/send/+page.svelte
index 8963345a..8a695ac6 100644
--- a/src/routes/send/+page.svelte
+++ b/src/routes/send/+page.svelte
@@ -1,16 +1,16 @@
<script>
+ import { enhance } from '$app/forms';
import { onMount } from 'svelte';
import { browser } from '$app/environment';
import { t } from '$lib/translations';
- import { AppHeader, Icon, Spinner } from '$comp';
+ import { Icon, Spinner } from '$comp';
import { back, failure } from '$lib/utils';
export let form;
let el;
let placeholder = 'Address, Invoice, Username';
- let text = placeholder,
- loading;
+ let text = placeholder;
let focus = () => text === placeholder && (text = '');
let keypress = (e) => e.key === 'Enter' && e.preventDefault() && el.submit();
@@ -26,7 +26,7 @@
<Icon icon="arrow-left" style="w-10" />
</button>
-<form method="POST" class="container px-4 mt-20 max-w-xl mx-auto" bind:this={el}>
+<form method="POST" class="container px-4 mt-20 max-w-xl mx-auto" bind:this={el} use:enhance>
<div class="mb-2">
<label for="invoice" class="font-bold mb-1 block">Destination</label>
<input type="hidden" name="text" bind:value={text} />
@@ -70,11 +70,7 @@
? 'opacity-50'
: 'opacity-100 hover:opacity-80'} bg-black text-white border rounded-full px-6 py-2 font-bold"
>
- {#if loading}
- <Spinner />
- {:else}
- Next
- {/if}
+ Next
</button>
</div>
</form>
diff --git a/src/routes/send/bitcoin/[address]/+page.svelte b/src/routes/send/bitcoin/[address]/+page.svelte
index 2b472124..2de624ce 100644
--- a/src/routes/send/bitcoin/[address]/+page.svelte
+++ b/src/routes/send/bitcoin/[address]/+page.svelte
@@ -1,5 +1,6 @@
<script>
- import { AppHeader, Icon, Numpad, Spinner } from '$comp';
+ import { enhance } from '$app/forms';
+ import { Icon, Numpad, Spinner } from '$comp';
import { page } from '$app/stores';
import { back } from '$lib/utils';
export let data;
@@ -20,7 +21,7 @@
</div>
<Numpad bind:amount {currency} />
- <form method="POST">
+ <form method="POST" use:enhance>
<input name="address" value={address} type="hidden" />
<input name="amount" value={amount} type="hidden" />
<div class="flex w-full">
diff --git a/src/routes/send/lightning/[payreq]/+page.server.js b/src/routes/send/lightning/[payreq]/+page.server.js
index 885222c1..f17d6a60 100644
--- a/src/routes/send/lightning/[payreq]/+page.server.js
+++ b/src/routes/send/lightning/[payreq]/+page.server.js
@@ -8,7 +8,7 @@ export async function load({ params }) {
export const actions = {
default: async ({ cookies, request }) => {
let body = Object.fromEntries(await request.formData());
- let { amount, confirmed } = body;
+ let { amount, confirmed } = body;
if (!confirmed) {
return invalid(403, { amount, confirm: true });
diff --git a/src/routes/send/lightning/[payreq]/+page.svelte b/src/routes/send/lightning/[payreq]/+page.svelte
index a2a07a98..65e8989e 100644
--- a/src/routes/send/lightning/[payreq]/+page.svelte
+++ b/src/routes/send/lightning/[payreq]/+page.svelte
@@ -1,5 +1,6 @@
<script>
- import { AppHeader, Icon, Numpad, Spinner } from '$comp';
+ import { enhance } from '$app/forms';
+ import { Icon, Numpad, Spinner } from '$comp';
import { page } from '$app/stores';
import { back, s } from '$lib/utils';
export let data;
@@ -9,9 +10,7 @@
let { alias } = data;
let { currency } = data.user;
- let amount = form?.amount || data.amount;
-
- let loading;
+ let amount = form?.amount || data.amount;
</script>
<button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={back}>
@@ -30,21 +29,17 @@
<Numpad bind:amount {currency} />
{/if}
- <form method="POST">
+ <form method="POST" use:enhance>
<input name="payreq" value={payreq} type="hidden" />
<input name="amount" value={amount} type="hidden" />
- <input name="confirmed" value={form?.confirm} type="hidden" />
+ <input name="confirmed" value={form?.confirm} type="hidden" />
<div class="flex w-full">
<button
type="submit"
class="opacity-100 hover:opacity-80'} rounded-2xl border py-3 font-bold mx-auto mt-2 bg-black text-white px-4 w-24"
>
- {#if loading}
- <Spinner />
- {:else}
- Send
- {/if}
+ Send
</button>
</div>
</form>
diff --git a/src/routes/sent/+page.svelte b/src/routes/sent/+page.svelte
index de61fd41..95bce839 100644
--- a/src/routes/sent/+page.svelte
+++ b/src/routes/sent/+page.svelte
@@ -14,11 +14,9 @@
<Icon icon="check" style="mx-auto" />
</div>
<h1 class="text-3xl md:text-4xl font-bold mb-6">{$t('invoice.paymentSuccessful')}</h1>
- <a href={`/${user.username}/transactions`}>
- <button
- class="bg-black text-white rounded-2xl w-20 py-3 font-bold hover:opacity-80"
- >
- {$t('invoice.done')}
- </button>
- </a>
+ <a href={`/${user.username}/transactions`}>
+ <button class="bg-black text-white rounded-2xl w-20 py-3 font-bold hover:opacity-80">
+ {$t('invoice.done')}
+ </button>
+ </a>
</div>