From 1f63848ca9fb01336f04b41434de1cc06a5b3d93 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 10 Sep 2024 20:39:47 -0700 Subject: move routes --- src/components/Account.svelte | 9 +- src/components/AppHeader.svelte | 25 +- src/components/Invoice.svelte | 2 +- src/components/Items.svelte | 51 ++- src/components/LandingHeader.svelte | 6 +- src/components/LocationsMap.svelte | 12 +- src/components/Request.svelte | 2 +- src/lib/invoice.ts | 6 +- src/locales/en.json | 2 + src/routes/(app)/+error.svelte | 38 --- src/routes/(app)/+layout.server.ts | 24 +- src/routes/(app)/+layout.svelte | 3 + .../(app)/[username]/(profile)/+layout.svelte | 2 +- src/routes/(app)/[username]/(profile)/+page.svelte | 18 +- src/routes/(app)/[username]/+layout.server.ts | 12 +- src/routes/(app)/[username]/+layout.svelte | 2 - .../payments/[...page]/+page.server.ts | 28 -- .../[...account]/payments/[...page]/+page.svelte | 315 ------------------ .../[...account]/payments/[...page]/+server.ts | 18 -- .../receive/[...param]/+page.server.ts | 29 -- .../[...account]/receive/[...param]/+page.svelte | 116 ------- .../(app)/[username]/account/setup/+page.svelte | 64 ---- .../[username]/account/setup/step2/+page.svelte | 52 --- .../(app)/[username]/address/+page.server.ts | 9 - src/routes/(app)/[username]/address/+page.svelte | 0 .../(app)/[username]/card/[serial]/+page.server.ts | 16 - .../(app)/[username]/card/[serial]/+page.svelte | 36 --- src/routes/(app)/[username]/customers/+page.svelte | 0 src/routes/(app)/[username]/funds/+page.server.ts | 0 src/routes/(app)/[username]/funds/+page.svelte | 52 --- src/routes/(app)/[username]/generate/+page.svelte | 60 ---- src/routes/(app)/[username]/generate/+server.ts | 12 - src/routes/(app)/[username]/invoice/+server.ts | 7 - .../[username]/invoice/[id]/+layout.server.ts | 39 --- .../(app)/[username]/invoice/[id]/+layout.svelte | 1 - .../(app)/[username]/invoice/[id]/+page.server.ts | 5 - .../(app)/[username]/invoice/[id]/+page.svelte | 344 -------------------- .../[username]/invoice/[id]/memo/+page.server.ts | 13 - .../[username]/invoice/[id]/memo/+page.svelte | 95 ------ .../[username]/invoice/[id]/paid/+page.svelte | 85 ----- .../[username]/invoice/[id]/tip/+page.server.ts | 12 - .../(app)/[username]/invoice/[id]/tip/+page.svelte | 209 ------------ .../(app)/[username]/invoice/sent/+page.svelte | 11 - .../(app)/[username]/items/[id]/+page.server.ts | 21 -- .../(app)/[username]/items/[id]/+page.svelte | 18 -- .../(app)/[username]/items/create/+page.server.ts | 16 - .../(app)/[username]/items/create/+page.svelte | 19 -- src/routes/(app)/[username]/map/+page.server.ts | 12 - src/routes/(app)/[username]/map/+page.svelte | 8 - .../(app)/[username]/messages/+page.server.ts | 42 --- src/routes/(app)/[username]/messages/+page.svelte | 92 ------ .../messages/[recipient]/+page.server.ts | 24 -- .../[username]/messages/[recipient]/+page.svelte | 191 ----------- src/routes/(app)/[username]/reset/+server.ts | 10 - .../[username]/settings/[...tab]/+page.server.ts | 34 -- .../[username]/settings/[...tab]/+page.svelte | 257 --------------- .../[username]/settings/[...tab]/_account.svelte | 190 ----------- .../(app)/[username]/settings/[...tab]/_pos.svelte | 238 -------------- .../[username]/settings/[...tab]/_security.svelte | 321 ------------------- .../[username]/settings/[...tab]/_shopify.svelte | 92 ------ .../(app)/[username]/verify/[code]/+page.server.ts | 14 - .../(app)/[username]/verify/[code]/+page.svelte | 35 -- src/routes/(app)/account/setup/+page.svelte | 64 ++++ src/routes/(app)/account/setup/step2/+page.svelte | 52 +++ src/routes/(app)/admin/+page.svelte | 2 +- .../(app)/ecash/[id]/[...version]/+layout.svelte | 1 - src/routes/(app)/fund/[id]/+page.server.ts | 2 +- src/routes/(app)/fund/[id]/sweep/+page.svelte | 2 +- src/routes/(app)/generate/+page.svelte | 60 ++++ src/routes/(app)/generate/+server.ts | 12 + src/routes/(app)/invoice/+page.server.ts | 29 ++ src/routes/(app)/invoice/+page.svelte | 0 src/routes/(app)/invoice/+server.ts | 7 + src/routes/(app)/invoice/[id]/+layout.server.ts | 36 +++ src/routes/(app)/invoice/[id]/+layout.svelte | 1 + src/routes/(app)/invoice/[id]/+page.server.ts | 5 + src/routes/(app)/invoice/[id]/+page.svelte | 351 +++++++++++++++++++++ src/routes/(app)/invoice/[id]/memo/+page.server.ts | 13 + src/routes/(app)/invoice/[id]/memo/+page.svelte | 95 ++++++ src/routes/(app)/invoice/[id]/paid/+page.svelte | 85 +++++ src/routes/(app)/invoice/[id]/tip/+page.server.ts | 12 + src/routes/(app)/invoice/[id]/tip/+page.svelte | 209 ++++++++++++ src/routes/(app)/invoice/sent/+page.svelte | 11 + src/routes/(app)/items/[id]/+page.server.ts | 21 ++ src/routes/(app)/items/[id]/+page.svelte | 18 ++ src/routes/(app)/items/create/+page.server.ts | 16 + src/routes/(app)/items/create/+page.svelte | 19 ++ src/routes/(app)/ln/[lnurl]/+page.server.ts | 2 +- src/routes/(app)/ln/withdrawal/sent/+page.svelte | 2 +- src/routes/(app)/login/+page.server.ts | 29 -- src/routes/(app)/login/+page.svelte | 188 ----------- src/routes/(app)/messages/+page.server.ts | 42 +++ src/routes/(app)/messages/+page.svelte | 92 ++++++ .../(app)/messages/[recipient]/+page.server.ts | 24 ++ src/routes/(app)/messages/[recipient]/+page.svelte | 191 +++++++++++ .../pay/[username]/[...amount]/+page.server.ts | 2 +- .../(app)/pay/[username]/[...amount]/+page.svelte | 5 +- src/routes/(app)/payment/[id]/+page.svelte | 2 +- .../(app)/payments/[...page]/+page.server.ts | 28 ++ src/routes/(app)/payments/[...page]/+page.svelte | 315 ++++++++++++++++++ src/routes/(app)/payments/[...page]/+server.ts | 18 ++ src/routes/(app)/receive/[...token]/+page.svelte | 2 - src/routes/(app)/register/+page.server.ts | 41 --- src/routes/(app)/register/+page.svelte | 314 ------------------ src/routes/(app)/send/[...text]/+page.svelte | 2 - src/routes/(app)/send/invoice/[id]/+page.server.ts | 6 +- src/routes/(app)/send/invoice/[id]/+page.svelte | 4 +- src/routes/(app)/sent/+page.svelte | 2 +- src/routes/(app)/settings/[...tab]/+page.server.ts | 34 ++ src/routes/(app)/settings/[...tab]/+page.svelte | 257 +++++++++++++++ src/routes/(app)/settings/[...tab]/_account.svelte | 190 +++++++++++ src/routes/(app)/settings/[...tab]/_pos.svelte | 238 ++++++++++++++ .../(app)/settings/[...tab]/_security.svelte | 321 +++++++++++++++++++ src/routes/(app)/settings/[...tab]/_shopify.svelte | 92 ++++++ src/routes/(app)/support/+page.svelte | 139 -------- src/routes/(app)/support/+server.ts | 9 - src/routes/(app)/verify/[code]/+page.server.ts | 14 + src/routes/(app)/verify/[code]/+page.svelte | 35 ++ src/routes/(static)/+layout.svelte | 2 +- src/routes/(static)/login/+page.server.ts | 29 ++ src/routes/(static)/login/+page.svelte | 171 ++++++++++ src/routes/(static)/register/+page.server.ts | 41 +++ src/routes/(static)/register/+page.svelte | 292 +++++++++++++++++ src/routes/(static)/support/+page.svelte | 134 ++++++++ src/routes/(static)/support/+server.ts | 9 + src/routes/+error.svelte | 38 +++ src/routes/start/+server.ts | 2 +- 127 files changed, 3855 insertions(+), 4102 deletions(-) delete mode 100644 src/routes/(app)/+error.svelte delete mode 100644 src/routes/(app)/[username]/[...account]/payments/[...page]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/[...account]/payments/[...page]/+page.svelte delete mode 100644 src/routes/(app)/[username]/[...account]/payments/[...page]/+server.ts delete mode 100644 src/routes/(app)/[username]/[...account]/receive/[...param]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/[...account]/receive/[...param]/+page.svelte delete mode 100644 src/routes/(app)/[username]/account/setup/+page.svelte delete mode 100644 src/routes/(app)/[username]/account/setup/step2/+page.svelte delete mode 100644 src/routes/(app)/[username]/address/+page.server.ts delete mode 100644 src/routes/(app)/[username]/address/+page.svelte delete mode 100644 src/routes/(app)/[username]/card/[serial]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/card/[serial]/+page.svelte delete mode 100644 src/routes/(app)/[username]/customers/+page.svelte delete mode 100644 src/routes/(app)/[username]/funds/+page.server.ts delete mode 100644 src/routes/(app)/[username]/funds/+page.svelte delete mode 100644 src/routes/(app)/[username]/generate/+page.svelte delete mode 100644 src/routes/(app)/[username]/generate/+server.ts delete mode 100644 src/routes/(app)/[username]/invoice/+server.ts delete mode 100644 src/routes/(app)/[username]/invoice/[id]/+layout.server.ts delete mode 100644 src/routes/(app)/[username]/invoice/[id]/+layout.svelte delete mode 100644 src/routes/(app)/[username]/invoice/[id]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/invoice/[id]/+page.svelte delete mode 100644 src/routes/(app)/[username]/invoice/[id]/memo/+page.server.ts delete mode 100644 src/routes/(app)/[username]/invoice/[id]/memo/+page.svelte delete mode 100644 src/routes/(app)/[username]/invoice/[id]/paid/+page.svelte delete mode 100644 src/routes/(app)/[username]/invoice/[id]/tip/+page.server.ts delete mode 100644 src/routes/(app)/[username]/invoice/[id]/tip/+page.svelte delete mode 100644 src/routes/(app)/[username]/invoice/sent/+page.svelte delete mode 100644 src/routes/(app)/[username]/items/[id]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/items/[id]/+page.svelte delete mode 100644 src/routes/(app)/[username]/items/create/+page.server.ts delete mode 100644 src/routes/(app)/[username]/items/create/+page.svelte delete mode 100644 src/routes/(app)/[username]/map/+page.server.ts delete mode 100644 src/routes/(app)/[username]/map/+page.svelte delete mode 100644 src/routes/(app)/[username]/messages/+page.server.ts delete mode 100644 src/routes/(app)/[username]/messages/+page.svelte delete mode 100644 src/routes/(app)/[username]/messages/[recipient]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/messages/[recipient]/+page.svelte delete mode 100644 src/routes/(app)/[username]/reset/+server.ts delete mode 100644 src/routes/(app)/[username]/settings/[...tab]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/settings/[...tab]/+page.svelte delete mode 100644 src/routes/(app)/[username]/settings/[...tab]/_account.svelte delete mode 100644 src/routes/(app)/[username]/settings/[...tab]/_pos.svelte delete mode 100644 src/routes/(app)/[username]/settings/[...tab]/_security.svelte delete mode 100644 src/routes/(app)/[username]/settings/[...tab]/_shopify.svelte delete mode 100644 src/routes/(app)/[username]/verify/[code]/+page.server.ts delete mode 100644 src/routes/(app)/[username]/verify/[code]/+page.svelte create mode 100644 src/routes/(app)/account/setup/+page.svelte create mode 100644 src/routes/(app)/account/setup/step2/+page.svelte create mode 100644 src/routes/(app)/generate/+page.svelte create mode 100644 src/routes/(app)/generate/+server.ts create mode 100644 src/routes/(app)/invoice/+page.server.ts create mode 100644 src/routes/(app)/invoice/+page.svelte create mode 100644 src/routes/(app)/invoice/+server.ts create mode 100644 src/routes/(app)/invoice/[id]/+layout.server.ts create mode 100644 src/routes/(app)/invoice/[id]/+layout.svelte create mode 100644 src/routes/(app)/invoice/[id]/+page.server.ts create mode 100644 src/routes/(app)/invoice/[id]/+page.svelte create mode 100644 src/routes/(app)/invoice/[id]/memo/+page.server.ts create mode 100644 src/routes/(app)/invoice/[id]/memo/+page.svelte create mode 100644 src/routes/(app)/invoice/[id]/paid/+page.svelte create mode 100644 src/routes/(app)/invoice/[id]/tip/+page.server.ts create mode 100644 src/routes/(app)/invoice/[id]/tip/+page.svelte create mode 100644 src/routes/(app)/invoice/sent/+page.svelte create mode 100644 src/routes/(app)/items/[id]/+page.server.ts create mode 100644 src/routes/(app)/items/[id]/+page.svelte create mode 100644 src/routes/(app)/items/create/+page.server.ts create mode 100644 src/routes/(app)/items/create/+page.svelte delete mode 100644 src/routes/(app)/login/+page.server.ts delete mode 100644 src/routes/(app)/login/+page.svelte create mode 100644 src/routes/(app)/messages/+page.server.ts create mode 100644 src/routes/(app)/messages/+page.svelte create mode 100644 src/routes/(app)/messages/[recipient]/+page.server.ts create mode 100644 src/routes/(app)/messages/[recipient]/+page.svelte create mode 100644 src/routes/(app)/payments/[...page]/+page.server.ts create mode 100644 src/routes/(app)/payments/[...page]/+page.svelte create mode 100644 src/routes/(app)/payments/[...page]/+server.ts delete mode 100644 src/routes/(app)/register/+page.server.ts delete mode 100644 src/routes/(app)/register/+page.svelte create mode 100644 src/routes/(app)/settings/[...tab]/+page.server.ts create mode 100644 src/routes/(app)/settings/[...tab]/+page.svelte create mode 100644 src/routes/(app)/settings/[...tab]/_account.svelte create mode 100644 src/routes/(app)/settings/[...tab]/_pos.svelte create mode 100644 src/routes/(app)/settings/[...tab]/_security.svelte create mode 100644 src/routes/(app)/settings/[...tab]/_shopify.svelte delete mode 100644 src/routes/(app)/support/+page.svelte delete mode 100644 src/routes/(app)/support/+server.ts create mode 100644 src/routes/(app)/verify/[code]/+page.server.ts create mode 100644 src/routes/(app)/verify/[code]/+page.svelte create mode 100644 src/routes/(static)/login/+page.server.ts create mode 100644 src/routes/(static)/login/+page.svelte create mode 100644 src/routes/(static)/register/+page.server.ts create mode 100644 src/routes/(static)/register/+page.svelte create mode 100644 src/routes/(static)/support/+page.svelte create mode 100644 src/routes/(static)/support/+server.ts create mode 100644 src/routes/+error.svelte diff --git a/src/components/Account.svelte b/src/components/Account.svelte index a9b3d6ba..eb1b0bac 100644 --- a/src/components/Account.svelte +++ b/src/components/Account.svelte @@ -5,10 +5,10 @@ export let user, rate, account; let { seed, balance, id } = account; - $: type = seed ? "Savings":"Cash"; + $: type = seed ? "Savings" : "Cash"; - +
- + +
-
+
- + - -
-
-
-
diff --git a/src/routes/(app)/+layout.server.ts b/src/routes/(app)/+layout.server.ts index 655a9425..a0e30f31 100644 --- a/src/routes/(app)/+layout.server.ts +++ b/src/routes/(app)/+layout.server.ts @@ -1,8 +1,9 @@ -import { redirect } from "@sveltejs/kit"; - import { get, auth, protectedRoutes } from "$lib/utils"; +import { error, redirect } from "@sveltejs/kit"; +import { get, auth, protectedRoutes } from "$lib/utils"; export async function load({ cookies, request, url, params }) { let { pathname } = url; + let { username } = params; let token = cookies.get("token"); let rate, rates = { USD: 1 }; @@ -14,6 +15,18 @@ export async function load({ cookies, request, url, params }) { } catch (e) {} } + let subject; + if (username) { + try { + subject = await get(`/users/${username}`); + } catch (e) { + error(500, "Unable to retrieve user account data"); + } + } + + if (!subject) subject = user; + if (!user) user = subject; + if (user?.needsMigration) { redirect(307, `/migrate`); } @@ -26,10 +39,7 @@ export async function load({ cookies, request, url, params }) { redirect(307, `/${user.username}`); } - if ( - protectedRoutes.find((p) => pathname.match(p)) && - (!user || user.username !== params.username) - ) { + if ( protectedRoutes.find((p) => pathname.match(p)) && (!user)) { redirect(307, "/login"); } @@ -44,5 +54,5 @@ export async function load({ cookies, request, url, params }) { console.log(e); } - return { user, token, rate, rates }; + return { user, token, rate, rates, subject }; } diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 8d4e2940..0ff4816d 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -14,6 +14,7 @@ import { page } from "$app/stores"; import { browser } from "$app/environment"; import LoadingSplash from "$comp/LoadingSplash.svelte"; + import AppHeader from "$comp/AppHeader.svelte"; import Invoice from "$comp/Invoice.svelte"; import Password from "$comp/Password.svelte"; import Request from "$comp/Request.svelte"; @@ -35,6 +36,7 @@ }); let { generate, rate, user, subject, token, rates } = data; + console.log("SUB", subject) $: update(data); let update = (data) => { @@ -115,6 +117,7 @@
+ {#if !$loading} {/if} diff --git a/src/routes/(app)/[username]/(profile)/+layout.svelte b/src/routes/(app)/[username]/(profile)/+layout.svelte index 2caf9b30..111fdeb6 100644 --- a/src/routes/(app)/[username]/(profile)/+layout.svelte +++ b/src/routes/(app)/[username]/(profile)/+layout.svelte @@ -219,7 +219,7 @@ {#if user && user.username !== subject.username && subject.pubkey} - - {/each} - - - -
- {#if pages.length > 1} - {#each pages as _, i} - -
- {i + 1} -
-
- {/each} - {/if} -
- -
- {#each payments as p} - -
-
-
- {f(Math.abs(p.amount) * (p.rate / sats), p.currency)} - {#if p.tip} - - +{Math.round((p.tip / Math.abs(p.amount)) * 100)}% - - {/if} -
- -
- {sat(Math.abs(p.amount) + (p.tip || 0))} -
-
- -
- {#if p.type === types.pot} - -
-
- Pot -
- -
Pot
-
-
- {:else if p.with} -
-
- -
-
- {p.with.username} -
-
- {:else} -
- {#if [types.ecash, types.lightning].includes(p.type)} -
⚡️
- {:else if p.type === types.bitcoin} -
- Bitcoin -
- {:else if p.type === types.liquid} -
- Liquid -
- {/if} - -
- {p.amount > 0 - ? p.confirmed - ? "Received" - : "Pending" - : "Sent"} -
-
- {/if} -
- -
-
- {format(new Date(p.created), "h:mm aaa")} -
-
- {format(new Date(p.created), "MMM d, yy")} -
-
-
- - {:else} -

{$t("payments.empty")}

- {/each} -
- -
- {#each Object.keys(incoming) as c} - - - - - - {#if tipsIn || tipsOut}{$t("payments.tips")}{/if} - - {$t("payments.total")} - - {@const totalIn = incoming[c]?.fiat || 0} - {@const tipsIn = incoming[c]?.fiatTips || 0} - {@const subtotalIn = totalIn - tipsIn} - - {@const totalOut = -outgoing[c]?.fiat || 0} - {@const tipsOut = outgoing[c]?.fiatTips || 0} - {@const subtotalOut = totalOut - tipsOut} - - {$t("payments.income")} - - {tipsIn ? f(tipsIn, c) : "-"} - {totalIn ? f(totalIn, c) : "-"} - - {$t("payments.expenditure")} - - {tipsOut ? f(tipsOut, c) : "-"} - {totalOut ? f(totalOut, c) : "-"} - {/each} -
- - - - - - diff --git a/src/routes/(app)/[username]/[...account]/payments/[...page]/+server.ts b/src/routes/(app)/[username]/[...account]/payments/[...page]/+server.ts deleted file mode 100644 index a81faaf3..00000000 --- a/src/routes/(app)/[username]/[...account]/payments/[...page]/+server.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { get, auth } from "$lib/utils"; -import { json } from "@sveltejs/kit"; - -export async function GET({ cookies, params }) { - let parts = params.page.split("/"); - - let start, end; - if (parts.length === 1) [start] = parts; - if (parts.length === 2) [start, end] = parts; - - if (!start) start = Date.now() / 1000 - 24 * 60 * 60; - - let url = `/payments?start=${start * 1000}`; - if (end) url += `&end=${end * 1000}`; - - let { payments } = await get(url, auth(cookies)); - return json({ payments }); -} diff --git a/src/routes/(app)/[username]/[...account]/receive/[...param]/+page.server.ts b/src/routes/(app)/[username]/[...account]/receive/[...param]/+page.server.ts deleted file mode 100644 index d9614a1c..00000000 --- a/src/routes/(app)/[username]/[...account]/receive/[...param]/+page.server.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { error, redirect } from "@sveltejs/kit"; -import { auth, post } from "$lib/utils"; -import type { Invoice } from "$lib/types"; - -export let load = async ({ cookies, params, parent }) => { - let { account } = params; - let { subject, user, rates } = await parent(); - - let invoice: Invoice = { - account, - type: account ? "bitcoin" : "lightning", - rate: rates[user?.currency || subject?.currency], - }; - - if (!user) user = subject; - - try { - invoice = await post("/invoice", { invoice, account, user }, auth(cookies)); - } catch (e) { - console.log(e); - error(500, "Failed to generate invoice"); - } - - let { id } = invoice; - - if (invoice.memoPrompt && !invoice.memo) { - redirect(307, `/${user.username}/invoice/${id}/memo`); - } else redirect(307, `/${user.username}/invoice/${id}`); -}; diff --git a/src/routes/(app)/[username]/[...account]/receive/[...param]/+page.svelte b/src/routes/(app)/[username]/[...account]/receive/[...param]/+page.svelte deleted file mode 100644 index f9267105..00000000 --- a/src/routes/(app)/[username]/[...account]/receive/[...param]/+page.svelte +++ /dev/null @@ -1,116 +0,0 @@ - - - - - -
-

- {$t("payments.send")} -

- -
- {#if form?.error} -
-
- {$t("error.unrecognizedInput")} -
-
- {/if} - -
- -
- -
- -

- Coinos can automatically mark orders as Paid if you provide an API token. - -

-

- Create a new app in Apps > App Development -

- -

- Edit the Admin API scopes to enable write_orders permission then install the app into your store and copy the Admin API access - token here. -

-
- - diff --git a/src/routes/(app)/[username]/verify/[code]/+page.server.ts b/src/routes/(app)/[username]/verify/[code]/+page.server.ts deleted file mode 100644 index fec1a85c..00000000 --- a/src/routes/(app)/[username]/verify/[code]/+page.server.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { get } from "$lib/utils"; -import { redirect } from "@sveltejs/kit"; - -export let load = async ({ params: { code } }) => { - let user; - try { - user = await get(`/verify/${code}`); - } catch (e) { - console.log(e); - return { error: "Verification failed" }; - } - - redirect(307, `/${user.username}/settings/account?verified=true`); -}; diff --git a/src/routes/(app)/[username]/verify/[code]/+page.svelte b/src/routes/(app)/[username]/verify/[code]/+page.svelte deleted file mode 100644 index 1e099dae..00000000 --- a/src/routes/(app)/[username]/verify/[code]/+page.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -
- {#if error} -

- Email verification failed -

- {:else if user.verified} -
- -
- -

- Email verified successfully! -

- {/if} -
- - -
- - -
- {$t("payments.tapAnywhere")} -
diff --git a/src/routes/(app)/account/setup/+page.svelte b/src/routes/(app)/account/setup/+page.svelte new file mode 100644 index 00000000..5a15316a --- /dev/null +++ b/src/routes/(app)/account/setup/+page.svelte @@ -0,0 +1,64 @@ + + +
+

Account setup

+

Step 1

+ +
+

+ The keys to your savings account are derived from a seed phrase. When + you're ready, write it down and keep it safe. +

+ +

+ Whoever knows these words in the correct order can withdraw funds from the account. We can't + recover them if you lose them. +

+ + {#if reveal} +
+ {$mnemonic} +
+ + + {:else} +
+ +
+ {/if} +
+
diff --git a/src/routes/(app)/account/setup/step2/+page.svelte b/src/routes/(app)/account/setup/step2/+page.svelte new file mode 100644 index 00000000..8169ce06 --- /dev/null +++ b/src/routes/(app)/account/setup/step2/+page.svelte @@ -0,0 +1,52 @@ + + +
+
+

Account setup

+

Step 2

+
+ + +

+ Add an additional password to your seed phrase. It should be different + than your login password. We can't reset it if you lose it. +

+ + + + + +
diff --git a/src/routes/(app)/admin/+page.svelte b/src/routes/(app)/admin/+page.svelte index c61a2e45..214bf5b3 100644 --- a/src/routes/(app)/admin/+page.svelte +++ b/src/routes/(app)/admin/+page.svelte @@ -1,7 +1,7 @@ diff --git a/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte b/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte index 679fbe76..89de4b58 100644 --- a/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte +++ b/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte @@ -1,5 +1,4 @@ + +{#if loaded && user?.haspin && $pin?.length !== 6} + +{/if} + +
+

+ Generating new account keys +

+
+ +
+
diff --git a/src/routes/(app)/generate/+server.ts b/src/routes/(app)/generate/+server.ts new file mode 100644 index 00000000..5a442982 --- /dev/null +++ b/src/routes/(app)/generate/+server.ts @@ -0,0 +1,12 @@ +import { auth, post } from "$lib/utils"; +import { error, json } from "@sveltejs/kit"; + +export async function POST({ cookies, request }) { + try { + let body = await request.json(); + return json(await post(`/user`, body, auth(cookies))); + } catch (e: any) { + console.log(e); + error(500, e.message); + } +} diff --git a/src/routes/(app)/invoice/+page.server.ts b/src/routes/(app)/invoice/+page.server.ts new file mode 100644 index 00000000..83127457 --- /dev/null +++ b/src/routes/(app)/invoice/+page.server.ts @@ -0,0 +1,29 @@ +import { auth, post } from "$lib/utils"; +import { error, redirect } from "@sveltejs/kit"; +import type { Invoice } from "$lib/types"; + +export let load = async ({ cookies, params, parent }) => { + let { account } = params; + let { subject, user, rates } = await parent(); + + let invoice: Invoice = { + account, + type: account ? "bitcoin" : "lightning", + rate: rates[user?.currency || subject?.currency], + }; + + if (!user) user = subject; + + try { + invoice = await post("/invoice", { invoice, account, user }, auth(cookies)); + } catch (e) { + console.log(e); + error(500, "Failed to generate invoice"); + } + + let { id } = invoice; + + if (invoice.memoPrompt && !invoice.memo) { + redirect(307, `/invoice/${id}/memo`); + } else redirect(307, `/invoice/${id}`); +}; diff --git a/src/routes/(app)/invoice/+page.svelte b/src/routes/(app)/invoice/+page.svelte new file mode 100644 index 00000000..e69de29b diff --git a/src/routes/(app)/invoice/+server.ts b/src/routes/(app)/invoice/+server.ts new file mode 100644 index 00000000..5e3d0300 --- /dev/null +++ b/src/routes/(app)/invoice/+server.ts @@ -0,0 +1,7 @@ +import { auth, post } from "$lib/utils"; +import { json } from "@sveltejs/kit"; + +export let POST = async ({ cookies: c, request: r }) => { + let j = await r.json(); + return json(await post("/invoice", j, auth(c))); +}; diff --git a/src/routes/(app)/invoice/[id]/+layout.server.ts b/src/routes/(app)/invoice/[id]/+layout.server.ts new file mode 100644 index 00000000..e7144b15 --- /dev/null +++ b/src/routes/(app)/invoice/[id]/+layout.server.ts @@ -0,0 +1,36 @@ +import Qr from "qrcode-base64"; +import { get } from "$lib/utils"; +import { redirect } from "@sveltejs/kit"; + +export async function load({ depends, params, url, parent }) { + depends("app:invoice"); + + let { subject, user } = await parent(); + let { id } = params; + let invoice = await get(`/invoice/${id}`); + let options = !!url.searchParams.get("options"); + + if ( + user && + invoice.uid !== user.id && + !(url.pathname.includes("tip") || url.pathname.includes("memo")) && + !options + ) { + redirect(307, `/send/invoice/${id}`); + } + + let { amount, pending, received } = invoice; + amount = parseInt(amount); + + let paid = + (!amount && (pending || received)) || + (amount > 0 && (pending >= amount || received >= amount)); + if (paid && !url.pathname.endsWith("paid")) { + redirect( 307, `/invoice/${id}/paid` + (options ? "?options=true" : "") + ); + } + + let src = Qr.drawImg(invoice.text || "", { size: 340 }); + + return { id, invoice, subject, src }; +} diff --git a/src/routes/(app)/invoice/[id]/+layout.svelte b/src/routes/(app)/invoice/[id]/+layout.svelte new file mode 100644 index 00000000..4fa864ce --- /dev/null +++ b/src/routes/(app)/invoice/[id]/+layout.svelte @@ -0,0 +1 @@ + diff --git a/src/routes/(app)/invoice/[id]/+page.server.ts b/src/routes/(app)/invoice/[id]/+page.server.ts new file mode 100644 index 00000000..a57efa64 --- /dev/null +++ b/src/routes/(app)/invoice/[id]/+page.server.ts @@ -0,0 +1,5 @@ +import invoice from "$lib/invoice"; + +export const actions = { + default: invoice, +}; diff --git a/src/routes/(app)/invoice/[id]/+page.svelte b/src/routes/(app)/invoice/[id]/+page.svelte new file mode 100644 index 00000000..c4810889 --- /dev/null +++ b/src/routes/(app)/invoice/[id]/+page.svelte @@ -0,0 +1,351 @@ + + +
+ {#if $showQr} +
+ + {txt} + +
+ {:else} +
+ {txt} +
+ {/if} + + {#each invoice.items as i} +
+
{i.quantity}
+
+ {i.name} +
+
+ {f(i.price * i.quantity, currency)} +
+
+ {sat(btc(i.price * i.quantity, rate))} +
+
+ {/each} + + {#if amount > 0} +
+
+ {f(amountFiat, currency)} + + {#if tip} + + +{f(tip * (rate / sats), currency)} + + {/if} +
+
+ ⚡️{`${s(amount)}`} + + {#if tip} + + +⚡️{s(tip)} + + {/if} +
+
+ {/if} + +
+ + + {#if user?.id === invoice?.user?.id} + + {:else} + + + + {/if} + +
+ +
+
+ + {#if !account} +
+ + + + + +
+ {/if} + + {#if type === types.liquid} +
+
+ {$t("payments.onlyLbtc")} + L-BTC, + {$t("payments.dontDeposit")} +
+
+ {/if} + + {#if user?.id === invoice?.user?.id} + + + + {/if} +
+ +{#if settingAmount} +
+
+
+ +
+ + +
+ + +
+ {$t("payments.amountPrompt")} + +
+
+
+{/if} + + diff --git a/src/routes/(app)/invoice/[id]/memo/+page.server.ts b/src/routes/(app)/invoice/[id]/memo/+page.server.ts new file mode 100644 index 00000000..24dec1af --- /dev/null +++ b/src/routes/(app)/invoice/[id]/memo/+page.server.ts @@ -0,0 +1,13 @@ +import invoice from "$lib/invoice"; +import { redirect } from "@sveltejs/kit"; + +export async function load({ parent, params }) { + let { invoice } = await parent(); + if (!invoice.amount) { + redirect(307, `/invoice/${invoice.id}`); + } +} + +export const actions = { + default: invoice, +}; diff --git a/src/routes/(app)/invoice/[id]/memo/+page.svelte b/src/routes/(app)/invoice/[id]/memo/+page.svelte new file mode 100644 index 00000000..4d23ff19 --- /dev/null +++ b/src/routes/(app)/invoice/[id]/memo/+page.svelte @@ -0,0 +1,95 @@ + + +
+ + + + + + + + + + +

{$t("invoice.addMemo")}

+
+ +
{invoice.memoPrompt}
+
+ + +
diff --git a/src/routes/(app)/invoice/[id]/paid/+page.svelte b/src/routes/(app)/invoice/[id]/paid/+page.svelte new file mode 100644 index 00000000..df05f12b --- /dev/null +++ b/src/routes/(app)/invoice/[id]/paid/+page.svelte @@ -0,0 +1,85 @@ + + +
+ {#if received} +
+ +
+ +

+ {$t("invoice.paymentSuccessful")} +

+ +

+ {f(fiat(received - tip, rate), currency)} + {#if tip} + + + {f(fiat(tip, rate), currency)} + + {/if} +

+

+ ⚡️{s(received - tip)} + + {#if tip} + + + ⚡️{s(tip)} + + {/if} +

+ {/if} + + {#if pending} +
+ +
+ +

Payment detected

+

+ {f(fiat(pending - tip, rate), currency)} + {#if tip} + + {f(fiat(tip, rate), currency)} + {/if} +

+ +

+ ⚡️{s(pending - tip)} + {#if tip} + + + ⚡️{s(tip)} + + {/if} +

+ {/if} +
+ + +
+ + +
+ {$t("payments.tapAnywhere")} +
diff --git a/src/routes/(app)/invoice/[id]/tip/+page.server.ts b/src/routes/(app)/invoice/[id]/tip/+page.server.ts new file mode 100644 index 00000000..8417de91 --- /dev/null +++ b/src/routes/(app)/invoice/[id]/tip/+page.server.ts @@ -0,0 +1,12 @@ +import invoice from "$lib/invoice"; +import { redirect } from "@sveltejs/kit"; + +export async function load({ parent, params }) { + let { invoice } = await parent(); + if (!invoice.amount) + redirect(307, `/invoice/${invoice.id}`); +} + +export const actions = { + default: invoice, +}; diff --git a/src/routes/(app)/invoice/[id]/tip/+page.svelte b/src/routes/(app)/invoice/[id]/tip/+page.svelte new file mode 100644 index 00000000..35b24bf1 --- /dev/null +++ b/src/routes/(app)/invoice/[id]/tip/+page.svelte @@ -0,0 +1,209 @@ + + +
+
+ + + + + + + + + + {#if invoice.memoPrompt} + + {/if} + +

{$t("invoice.addTipq")}

+ {#if !showCustomAmount} +
{Math.round(tipPercent)}%
+ + + +
+
+ + {f(amountFiat, currency)} + +{f(tipAmount, currency)} + +
+ +
+ {sat(amount)} + +{sat(tip)} +
+
+ + {#if tip} +
+ + +
+ {:else} + {#each tipAmounts as amount} + + {/each} + {/if} + +
+ +
+ {/if} + + +
+ + {/if} +
+ + diff --git a/src/routes/(app)/invoice/sent/+page.svelte b/src/routes/(app)/invoice/sent/+page.svelte new file mode 100644 index 00000000..b95bc85e --- /dev/null +++ b/src/routes/(app)/invoice/sent/+page.svelte @@ -0,0 +1,11 @@ + + +Invoice sent to +
+ +

{$request.requester.username} is ready to pay

+
diff --git a/src/routes/(app)/items/[id]/+page.server.ts b/src/routes/(app)/items/[id]/+page.server.ts new file mode 100644 index 00000000..67cebd93 --- /dev/null +++ b/src/routes/(app)/items/[id]/+page.server.ts @@ -0,0 +1,21 @@ +import { fd, auth, get, post } from "$lib/utils"; +import { fail, redirect } from "@sveltejs/kit"; + +export let load = async ({ params: { id } }) => { + let item = await get(`/items/${id}`); + return { item }; +}; + +export const actions = { + default: async ({ cookies, request, url }) => { + let form = await fd(request); + try { + await post(`/items`, form, auth(cookies)); + } catch (e: any) { + return fail(400, { message: e.message }); + } + + let success = `/${url.pathname.split("/")[1]}`; + redirect(307, success); + }, +}; diff --git a/src/routes/(app)/items/[id]/+page.svelte b/src/routes/(app)/items/[id]/+page.svelte new file mode 100644 index 00000000..65720350 --- /dev/null +++ b/src/routes/(app)/items/[id]/+page.svelte @@ -0,0 +1,18 @@ + + +
+

+ {$t("items.edit")} +

+ +
diff --git a/src/routes/(app)/items/create/+page.server.ts b/src/routes/(app)/items/create/+page.server.ts new file mode 100644 index 00000000..2e006a3e --- /dev/null +++ b/src/routes/(app)/items/create/+page.server.ts @@ -0,0 +1,16 @@ +import { fail, redirect } from "@sveltejs/kit"; +import { fd, auth, post } from "$lib/utils"; + +export const actions = { + default: async ({ cookies, request, url }) => { + let form = await fd(request); + try { + await post("/items", form, auth(cookies)); + } catch (e: any) { + return fail(400, { message: e.message }); + } + + let success = `/${url.pathname.split("/")[1]}`; + redirect(307, success); + }, +}; diff --git a/src/routes/(app)/items/create/+page.svelte b/src/routes/(app)/items/create/+page.svelte new file mode 100644 index 00000000..b82889c9 --- /dev/null +++ b/src/routes/(app)/items/create/+page.svelte @@ -0,0 +1,19 @@ + + +
+

+ {$t("items.add")} +

+ +
diff --git a/src/routes/(app)/ln/[lnurl]/+page.server.ts b/src/routes/(app)/ln/[lnurl]/+page.server.ts index d1b1b86e..c078ae8e 100644 --- a/src/routes/(app)/ln/[lnurl]/+page.server.ts +++ b/src/routes/(app)/ln/[lnurl]/+page.server.ts @@ -70,6 +70,6 @@ export const actions = { let c = callback.includes("?") ? "&" : "?"; await fetch(`${callback}${c}k1=${k1}&pr=${pr}`).then((r) => r.json()); - redirect(307, `/${username}/payments`); + redirect(307, `/payments`); }, }; diff --git a/src/routes/(app)/ln/withdrawal/sent/+page.svelte b/src/routes/(app)/ln/withdrawal/sent/+page.svelte index c1a2bdb2..90814960 100644 --- a/src/routes/(app)/ln/withdrawal/sent/+page.svelte +++ b/src/routes/(app)/ln/withdrawal/sent/+page.svelte @@ -19,7 +19,7 @@

Request Sent!

- +
diff --git a/src/routes/(app)/login/+page.server.ts b/src/routes/(app)/login/+page.server.ts deleted file mode 100644 index fd7fec8c..00000000 --- a/src/routes/(app)/login/+page.server.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { fail, redirect } from "@sveltejs/kit"; -import { login, fd } from "$lib/utils"; - -export const load = async ({ parent }) => { - let { user } = await parent(); - if (user?.pubkey) redirect(307, `/${user.username}`); -}; - -export const actions = { - default: async ({ cookies, request }) => { - let form = await fd(request); - let { username, password, token, loginRedirect } = form; - let user = { username, password, token }; - - if (loginRedirect === "undefined") loginRedirect = undefined; - - try { - await login( - user, - cookies, - request.headers.get("cf-connecting-ip") - ); - } catch (e: any) { - return fail(400, { error: "Login failed", message: e.message, ...form }); - } - - redirect(307, loginRedirect || `/${user.username}`); - }, -}; diff --git a/src/routes/(app)/login/+page.svelte b/src/routes/(app)/login/+page.svelte deleted file mode 100644 index 61ea23b7..00000000 --- a/src/routes/(app)/login/+page.svelte +++ /dev/null @@ -1,188 +0,0 @@ - - -{#if need2fa} - -{/if} - -
-
- - - -
- -
-
-

{$t("login.signIn")}

- - {#if form?.error} -
- {form.error} -
- {/if} - -
- - - -
- - -
- -
- - {#if revealPassword} - - {:else} - - {/if} - -
- - - - -
- -

- {$t("login.noAccount")} - - {$t("login.register")} - -

-
-
-
diff --git a/src/routes/(app)/messages/+page.server.ts b/src/routes/(app)/messages/+page.server.ts new file mode 100644 index 00000000..94659621 --- /dev/null +++ b/src/routes/(app)/messages/+page.server.ts @@ -0,0 +1,42 @@ +import { get } from "$lib/utils"; +import { redirect } from "@sveltejs/kit"; + +interface Message { + created_at: number; +} + +interface Note { + created_at: number; + seen: number; +} + +export async function load({ params, parent, }) { + let { user } = await parent(); + if (user.username !== params.username) redirect(307, `/${params.username}`); + let { since = 0 } = params; + + let messages = [], + notes = []; + + if (user?.pubkey) { + let { pubkey } = user; + try { + messages = await get(`/${pubkey}/${since}/messages`); + messages = messages.sort((a: Message, b: Message) => b.created_at - a.created_at); + } catch (e) { + console.log(`failed to fetch nostr messages`, e); + } + + try { + notes = await get(`/${pubkey}/notes`); + } catch (e) { + console.log(`failed to fetch nostr notes for ${pubkey}`, e); + } + + notes.map((e: Note) => { + e.seen = e.created_at; + }); + } + + return { messages, notes }; +} diff --git a/src/routes/(app)/messages/+page.svelte b/src/routes/(app)/messages/+page.svelte new file mode 100644 index 00000000..547a1f21 --- /dev/null +++ b/src/routes/(app)/messages/+page.svelte @@ -0,0 +1,92 @@ + + +
+

+ {$t("user.messages")} +

+ {#if latest.length && user?.id === subject.id} +
+ {#each latest as { content, pubkey, author, recipient }} + {@const user = author.id === user.id ? recipient : author} + +
+
+ +
+
+
{user.username}
+
+ {content} +
+
+
+
+ {/each} +
+ {:else} +
{$t("user.noMessages")}
+ {/if} +
diff --git a/src/routes/(app)/messages/[recipient]/+page.server.ts b/src/routes/(app)/messages/[recipient]/+page.server.ts new file mode 100644 index 00000000..6be9f6ec --- /dev/null +++ b/src/routes/(app)/messages/[recipient]/+page.server.ts @@ -0,0 +1,24 @@ +import { get } from "$lib/utils"; +import type { Message } from "$lib/types"; + +export async function load({ params, parent }) { + let { user } = await parent(); + let { since = 0 } = params; + + let messages: Message[] = []; + let recipient = await get(`/users/${params.recipient}`); + + try { + messages = await get(`/${user.pubkey}/${since}/messages`); + + messages = messages + .filter( + (m: Message) => m.recipient?.id === recipient.id || m.author?.id === recipient.id + ) + .sort((a, b) => a.created_at - b.created_at); + } catch (e) { + console.log(`failed to fetch nostr messages`, e); + } + + return { messages, recipient, user }; +} diff --git a/src/routes/(app)/messages/[recipient]/+page.svelte b/src/routes/(app)/messages/[recipient]/+page.svelte new file mode 100644 index 00000000..98638389 --- /dev/null +++ b/src/routes/(app)/messages/[recipient]/+page.svelte @@ -0,0 +1,191 @@ + + +
+ + +
+ {#each messages as { id, author, message, created_at, pubkey }} + {@const ours = pubkey === user.pubkey} + {@const theirs = !ours} + + {#if message} +
+
+ {message} +
+
+ +
+
+
+ {format(new Date(created_at * 1000), "MMM d")}, + {format(new Date(created_at * 1000), "h:mm aa")} +
+ {/if} + {/each} +
+ +
+ + + +
+ + +
+ + diff --git a/src/routes/(app)/pay/[username]/[...amount]/+page.server.ts b/src/routes/(app)/pay/[username]/[...amount]/+page.server.ts index e9a0ec9e..7ccc23b0 100644 --- a/src/routes/(app)/pay/[username]/[...amount]/+page.server.ts +++ b/src/routes/(app)/pay/[username]/[...amount]/+page.server.ts @@ -29,7 +29,7 @@ export async function load({ cookies, params, parent }) { auth(cookies) ); - redirect(307, `/${username}/invoice/${id}`); + redirect(307, `/invoice/${id}`); } return { amount, rate, subject }; diff --git a/src/routes/(app)/pay/[username]/[...amount]/+page.svelte b/src/routes/(app)/pay/[username]/[...amount]/+page.svelte index 1652952a..f45218ea 100644 --- a/src/routes/(app)/pay/[username]/[...amount]/+page.svelte +++ b/src/routes/(app)/pay/[username]/[...amount]/+page.svelte @@ -3,7 +3,6 @@ import { goto } from "$app/navigation"; import { pin } from "$lib/store"; import { enhance } from "$app/forms"; - import AppHeader from "$comp/AppHeader.svelte"; import Avatar from "$comp/Avatar.svelte"; import Icon from "$comp/Icon.svelte"; import Numpad from "$comp/Numpad.svelte"; @@ -33,7 +32,7 @@ rate = fiat ? (sats * amountFiat) / amount : r; let id; - ({ id, hash } = await post(`/${subject.username}/invoice`, { + ({ id, hash } = await post(`/invoice`, { invoice: { amount, rate: rates[subject.currency], @@ -56,8 +55,6 @@ }; - - {#if form?.message}
{form.message} diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte index ea07be14..9a278049 100644 --- a/src/routes/(app)/payment/[id]/+page.svelte +++ b/src/routes/(app)/payment/[id]/+page.svelte @@ -96,7 +96,7 @@ }); - + diff --git a/src/routes/(app)/payments/[...page]/+page.server.ts b/src/routes/(app)/payments/[...page]/+page.server.ts new file mode 100644 index 00000000..c2cd5683 --- /dev/null +++ b/src/routes/(app)/payments/[...page]/+page.server.ts @@ -0,0 +1,28 @@ +import { get, auth } from "$lib/utils"; + +let limit = 25; + +export async function load({ cookies, depends, params }) { + depends("app:payments"); + + let parts = params.page.split("/"); + + let start, end, page; + if (parts.length === 1) [page] = parts; + if (parts.length === 2) [start, page] = parts; + if (parts.length === 3) [start, end, page] = parts; + if (!parseInt(page)) page = 1; + + let offset = (page - 1) * limit; + if (!start) start = Date.now() / 1000 - 24 * 60 * 60; + + let url = `/payments?account=${params.account}&start=${ + start * 1000 + }&limit=${limit}&offset=${offset}`; + if (end) url += `&end=${end * 1000}`; + + let { count, payments, incoming, outgoing } = await get(url, auth(cookies)); + let pages = new Array(Math.ceil(count / limit)); + + return { payments, page, pages, start, end, incoming, outgoing }; +} diff --git a/src/routes/(app)/payments/[...page]/+page.svelte b/src/routes/(app)/payments/[...page]/+page.svelte new file mode 100644 index 00000000..b7ea7b6e --- /dev/null +++ b/src/routes/(app)/payments/[...page]/+page.svelte @@ -0,0 +1,315 @@ + + +
+

+ {$t("payments.header")} +

+ +
+ + +
+ {#if pages.length > 1} + {#each pages as _, i} + +
+ {i + 1} +
+
+ {/each} + {/if} +
+ +
+ {#each payments as p} + +
+
+
+ {f(Math.abs(p.amount) * (p.rate / sats), p.currency)} + {#if p.tip} + + +{Math.round((p.tip / Math.abs(p.amount)) * 100)}% + + {/if} +
+ +
+ {sat(Math.abs(p.amount) + (p.tip || 0))} +
+
+ +
+ {#if p.type === types.pot} + +
+
+ Pot +
+ +
Pot
+
+
+ {:else if p.with} +
+
+ +
+
+ {p.with.username} +
+
+ {:else} +
+ {#if [types.ecash, types.lightning].includes(p.type)} +
⚡️
+ {:else if p.type === types.bitcoin} +
+ Bitcoin +
+ {:else if p.type === types.liquid} +
+ Liquid +
+ {/if} + +
+ {p.amount > 0 + ? p.confirmed + ? "Received" + : "Pending" + : "Sent"} +
+
+ {/if} +
+ +
+
+ {format(new Date(p.created), "h:mm aaa")} +
+
+ {format(new Date(p.created), "MMM d, yy")} +
+
+
+ + {:else} +

{$t("payments.empty")}

+ {/each} +
+ +
+ {#each Object.keys(incoming) as c} + + + + + + {#if tipsIn || tipsOut}{$t("payments.tips")}{/if} + + {$t("payments.total")} + + {@const totalIn = incoming[c]?.fiat || 0} + {@const tipsIn = incoming[c]?.fiatTips || 0} + {@const subtotalIn = totalIn - tipsIn} + + {@const totalOut = -outgoing[c]?.fiat || 0} + {@const tipsOut = outgoing[c]?.fiatTips || 0} + {@const subtotalOut = totalOut - tipsOut} + + {$t("payments.income")} + + {tipsIn ? f(tipsIn, c) : "-"} + {totalIn ? f(totalIn, c) : "-"} + + {$t("payments.expenditure")} + + {tipsOut ? f(tipsOut, c) : "-"} + {totalOut ? f(totalOut, c) : "-"} + {/each} +
+ + +
+
+ + diff --git a/src/routes/(app)/payments/[...page]/+server.ts b/src/routes/(app)/payments/[...page]/+server.ts new file mode 100644 index 00000000..a81faaf3 --- /dev/null +++ b/src/routes/(app)/payments/[...page]/+server.ts @@ -0,0 +1,18 @@ +import { get, auth } from "$lib/utils"; +import { json } from "@sveltejs/kit"; + +export async function GET({ cookies, params }) { + let parts = params.page.split("/"); + + let start, end; + if (parts.length === 1) [start] = parts; + if (parts.length === 2) [start, end] = parts; + + if (!start) start = Date.now() / 1000 - 24 * 60 * 60; + + let url = `/payments?start=${start * 1000}`; + if (end) url += `&end=${end * 1000}`; + + let { payments } = await get(url, auth(cookies)); + return json({ payments }); +} diff --git a/src/routes/(app)/receive/[...token]/+page.svelte b/src/routes/(app)/receive/[...token]/+page.svelte index 2fd4b879..7ff93fa9 100644 --- a/src/routes/(app)/receive/[...token]/+page.svelte +++ b/src/routes/(app)/receive/[...token]/+page.svelte @@ -5,7 +5,6 @@ import { tick } from "svelte"; import { browser } from "$app/environment"; import { t } from "$lib/translations"; - import AppHeader from "$comp/AppHeader.svelte"; import Avatar from "$comp/Avatar.svelte"; import Icon from "$comp/Icon.svelte"; import Spinner from "$comp/Spinner.svelte"; @@ -30,7 +29,6 @@ -

{$t("payments.voucher")} diff --git a/src/routes/(app)/register/+page.server.ts b/src/routes/(app)/register/+page.server.ts deleted file mode 100644 index 731530c4..00000000 --- a/src/routes/(app)/register/+page.server.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { fail, redirect } from "@sveltejs/kit"; -import { fd, post, login } from "$lib/utils"; - -export const load = async ({ parent }) => { - let { user } = await parent(); - if (user) redirect(307, `/${user.username}`); - - let index = Math.floor(Math.random() * 64) + 1; - - return { index }; -}; - -export const actions = { - default: async ({ cookies, request }) => { - let ip = request.headers.get("cf-connecting-ip"); - - let form = await fd(request); - let { profile, username, password, cipher, salt, pubkey, loginRedirect } = - form; - let user = { profile, username, password, cipher, salt, pubkey }; - let error; - - if (loginRedirect === "undefined") loginRedirect = undefined; - - try { - await post("/register", { user }, { "cf-connecting-ip": ip }); - } catch (e: any) { - error = e.message; - } - - try { - await login(user, cookies, ip); - error = null; - } catch (e: any) { - error ||= e.message; - } - - if (error) return fail(400, { error }); - redirect(307, loginRedirect || `/${user.username}`); - }, -}; diff --git a/src/routes/(app)/register/+page.svelte b/src/routes/(app)/register/+page.svelte deleted file mode 100644 index 0a761228..00000000 --- a/src/routes/(app)/register/+page.svelte +++ /dev/null @@ -1,314 +0,0 @@ - - -{#if need2fa} - -{/if} - -
-
- - - -
- -
-
- handleFile(e, "profile")} - /> - -
- - - - - -
- - {#if form?.error} -
- {form.error} -
- {/if} - -
- - - -
- - - -
- -
- - {#if revealPassword} - - {:else} - - {/if} - -
- -

- {$t("login.passwordRecommendation")} -

- - -
- -

- {$t("login.haveAccount")} - - {$t("login.signIn")} - -

-
-
-
diff --git a/src/routes/(app)/send/[...text]/+page.svelte b/src/routes/(app)/send/[...text]/+page.svelte index 780f70c1..d1b6cc23 100644 --- a/src/routes/(app)/send/[...text]/+page.svelte +++ b/src/routes/(app)/send/[...text]/+page.svelte @@ -5,7 +5,6 @@ import { tick } from "svelte"; import { browser } from "$app/environment"; import { t } from "$lib/translations"; - import AppHeader from "$comp/AppHeader.svelte"; import Avatar from "$comp/Avatar.svelte"; import Icon from "$comp/Icon.svelte"; import Spinner from "$comp/Spinner.svelte"; @@ -31,7 +30,6 @@ -

{$t("payments.send")} diff --git a/src/routes/(app)/send/invoice/[id]/+page.server.ts b/src/routes/(app)/send/invoice/[id]/+page.server.ts index ed0198cf..fa7d28dd 100644 --- a/src/routes/(app)/send/invoice/[id]/+page.server.ts +++ b/src/routes/(app)/send/invoice/[id]/+page.server.ts @@ -7,15 +7,15 @@ export async function load({ params: { id }, parent }) { let invoice = await get(`/invoice/${id}`); if (invoice.prompt && invoice.tip === null) - redirect(307, `/${invoice.user.username}/invoice/${id}/tip`); + redirect(307, `/invoice/${id}/tip`); if (invoice.memoPrompt && invoice.memo === null) - redirect(307, `/${invoice.user.username}/invoice/${id}/memo`); + redirect(307, `/invoice/${id}/memo`); if (invoice.user.username === user?.username) error(500, { message: "Cannot send to self" }); - if (!user) redirect(307, `/${invoice.user.username}/invoice/${id}`); + if (!user) redirect(307, `/invoice/${id}`); return { invoice, rates, user }; } diff --git a/src/routes/(app)/send/invoice/[id]/+page.svelte b/src/routes/(app)/send/invoice/[id]/+page.svelte index 81a2c521..75e4e75a 100644 --- a/src/routes/(app)/send/invoice/[id]/+page.svelte +++ b/src/routes/(app)/send/invoice/[id]/+page.svelte @@ -52,7 +52,7 @@ let toggle = () => (submitting = !submitting); let external = async () => { - let { id } = await post(`/${recipient.username}/invoice`, { + let { id } = await post(`/invoice`, { invoice: { ...invoice, type: "lightning", @@ -62,7 +62,7 @@ user: { username: recipient.username }, }); - goto(`/${recipient.username}/invoice/${id}?options=true`, { + goto(`/invoice/${id}?options=true`, { invalidateAll: true, }); }; diff --git a/src/routes/(app)/sent/+page.svelte b/src/routes/(app)/sent/+page.svelte index 136bd395..12e13c41 100644 --- a/src/routes/(app)/sent/+page.svelte +++ b/src/routes/(app)/sent/+page.svelte @@ -43,7 +43,7 @@

- +
diff --git a/src/routes/(app)/settings/[...tab]/+page.server.ts b/src/routes/(app)/settings/[...tab]/+page.server.ts new file mode 100644 index 00000000..42639b38 --- /dev/null +++ b/src/routes/(app)/settings/[...tab]/+page.server.ts @@ -0,0 +1,34 @@ +import { fail, redirect } from "@sveltejs/kit"; +import { fd, auth, get, post } from "$lib/utils"; + +export function load({ cookies, params, url }) { + if (url.pathname.endsWith("settings")) + redirect(307, url.pathname + "/account"); + params.cookies = cookies.getAll(); + return { cookies: cookies.getAll(), tab: params.tab }; +} + +export const actions = { + default: async ({ cookies, request }) => { + let form = await fd(request); + + if (form.tab === "pos") { + form.notify = form.notify === "on"; + form.nip5 = form.nip5 === "on"; + form.prompt = form.prompt === "on"; + form.autowithdraw = form.autowithdraw === "on"; + } + + let user = { ...(await get("/me", auth(cookies))), ...form }; + + try { + ({ user } = await post(`/user`, user, auth(cookies))); + } catch (e: any) { + return fail(400, { message: e.message }); + } + + if (user.language) cookies.set("lang", user.language, { path: "/" }); + + return { user, success: true }; + }, +}; diff --git a/src/routes/(app)/settings/[...tab]/+page.svelte b/src/routes/(app)/settings/[...tab]/+page.svelte new file mode 100644 index 00000000..c495a5cc --- /dev/null +++ b/src/routes/(app)/settings/[...tab]/+page.svelte @@ -0,0 +1,257 @@ + + +{#if user.haspin && $pin?.length !== 6} + +{/if} + +
+ + + +
+
+

+ {$t("user.settings.header")} +

+ +
+ {#each tabs.filter((t) => t.name !== "shopify") as { name, key }} + + + + {/each} +
+
+ + +
+ +
+ +
+
+ + diff --git a/src/routes/(app)/settings/[...tab]/_account.svelte b/src/routes/(app)/settings/[...tab]/_account.svelte new file mode 100644 index 00000000..8e3323c7 --- /dev/null +++ b/src/routes/(app)/settings/[...tab]/_account.svelte @@ -0,0 +1,190 @@ + + +
+ +
+ +
+
+ +
+ + +
+ +
+ +

+ {$t("user.settings.emailDescription")} +

+ +
+ + {#if user.verified} + + {:else if user.email} + + {/if} +
+
+ +
+ {$t("user.settings.profileImage")} + +
+ {#if $avatar || user.profile} +
+ {user.username} +
+ {:else} +
+ +
+ {/if} +
+ + + handleFile(e, "profile")} + /> +
+
+ + {#if tooLarge["avatar"]} +
Max file size 10MB
+ {/if} +
+ +
+
+ {$t("user.settings.bannerImage")} +
+ + {#if $banner || user.banner} + Banner + {:else} +
+ {/if} + + + handleFile(e, "banner")} + /> + + {#if tooLarge["banner"]} +
Max file size 10MB
+ {/if} +
+ +
+ + +
+ +
+ +

+ Coinos can automatically mark orders as Paid if you provide an API token. + +

+

+ Create a new app in Apps > App Development +

+ +

+ Edit the Admin API scopes to enable write_orders permission then install the app into your store and copy the Admin API access + token here. +

+
+ + diff --git a/src/routes/(app)/support/+page.svelte b/src/routes/(app)/support/+page.svelte deleted file mode 100644 index ad31ad1a..00000000 --- a/src/routes/(app)/support/+page.svelte +++ /dev/null @@ -1,139 +0,0 @@ - - - - -{#if user} - -{/if} - -
- {#if sent} -

Thank you!

-
- Someone will be in touch shortly. -
- - - {:else} -

- {$t("user.support.header")} -

- -

- Fill out this form or email us directly at support@coinos.io and we'll do our best to get back to you in a timely manner. -

- -
-
- - -
- -
- - -
- -
- -