aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes/(app)/settings
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-11-07 21:16:25 -0800
committerAdam Soltys <[email protected]>2024-11-08 09:27:40 -0800
commit32fcc461cd43c8907df5e306d520bb671307eab1 (patch)
tree0253780c569998b6c1a5f43026586e94916c3fee /src/routes/(app)/settings
parentbe5aa52cea1d57c875cfb22d25c6a866b8de2239 (diff)
downloadcoinos-ui-32fcc461cd43c8907df5e306d520bb671307eab1.tar.gz
coinos-ui-32fcc461cd43c8907df5e306d520bb671307eab1.zip
svelte 5
Diffstat (limited to 'src/routes/(app)/settings')
-rw-r--r--src/routes/(app)/settings/[...tab]/+page.svelte53
-rw-r--r--src/routes/(app)/settings/[...tab]/_account.svelte50
-rw-r--r--src/routes/(app)/settings/[...tab]/_pos.svelte41
-rw-r--r--src/routes/(app)/settings/[...tab]/_security.svelte87
-rw-r--r--src/routes/(app)/settings/[...tab]/_shopify.svelte20
5 files changed, 144 insertions, 107 deletions
diff --git a/src/routes/(app)/settings/[...tab]/+page.svelte b/src/routes/(app)/settings/[...tab]/+page.svelte
index d2da3722..5b9e048d 100644
--- a/src/routes/(app)/settings/[...tab]/+page.svelte
+++ b/src/routes/(app)/settings/[...tab]/+page.svelte
@@ -1,4 +1,6 @@
<script>
+ import { run, preventDefault } from 'svelte/legacy';
+
import { browser } from "$app/environment";
import { onMount, tick } from "svelte";
import { fly } from "svelte/transition";
@@ -22,24 +24,20 @@
import { PUBLIC_COINOS_URL } from "$env/static/public";
- export let data;
- export let form;
+ let { data, form } = $props();
- let submit;
- let formElement;
+ let submit = $state();
+ let formElement = $state();
- let { user, token, rates, tab, cookies, subscriptions } = data;
+ let { user, token, rates, tab, cookies, subscriptions } = $state(data);
let prev;
- $: update(data);
let update = () => {
({ user, token, rates, tab, subscriptions } = data);
prev = { ...user };
};
- $: form?.user && ({ user } = form);
- $: form?.success && throttledSuccess();
let justUpdated;
let throttledSuccess = () => {
@@ -50,12 +48,7 @@
}
};
- $: form?.message && fail(form.message);
- $: if (form?.message?.startsWith("Pin")) {
- fail("Wrong pin, try again");
- $pin = "";
- }
let tabs = [
{ name: "account", key: "ACCOUNT", comp: Account },
@@ -64,13 +57,10 @@
{ name: "shopify", key: "SHOPIFY", comp: Shopify },
];
- $: ({ comp } = tabs.find((t) => t.name === tab));
let { address, id, username } = user;
- let submitting;
+ let submitting = $state();
- $: if (!$loading && $page.url.searchParams.get("verified"))
- success($t("user.settings.verified"));
async function handleSubmit() {
try {
@@ -191,6 +181,31 @@
submitting = false;
}
+ run(() => {
+ update(data);
+ });
+ run(() => {
+ form?.user && ({ user } = form);
+ });
+ run(() => {
+ form?.success && throttledSuccess();
+ });
+ run(() => {
+ form?.message && fail(form.message);
+ });
+ run(() => {
+ if (form?.message?.startsWith("Pin")) {
+ fail("Wrong pin, try again");
+ $pin = "";
+ }
+ });
+ let { comp } = $derived(tabs.find((t) => t.name === tab));
+ run(() => {
+ if (!$loading && $page.url.searchParams.get("verified"))
+ success($t("user.settings.verified"));
+ });
+
+ const SvelteComponent = $derived(comp);
</script>
{#if user.haspin && $pin?.length !== 6}
@@ -200,7 +215,7 @@
<form
method="POST"
class="mb-[154px] settings"
- on:submit|preventDefault={handleSubmit}
+ onsubmit={preventDefault(handleSubmit)}
bind:this={formElement}
>
<input type="hidden" name="pin" value={$pin} />
@@ -229,7 +244,7 @@
</div>
</div>
- <svelte:component this={comp} {user} {rates} {submit} {subscriptions} />
+ <SvelteComponent {user} {rates} {submit} {subscriptions} />
</div>
<div
diff --git a/src/routes/(app)/settings/[...tab]/_account.svelte b/src/routes/(app)/settings/[...tab]/_account.svelte
index 8537322e..54249265 100644
--- a/src/routes/(app)/settings/[...tab]/_account.svelte
+++ b/src/routes/(app)/settings/[...tab]/_account.svelte
@@ -4,11 +4,11 @@
import { t } from "$lib/translations";
import { page } from "$app/stores";
- export let user, rates, submit;
+ let { user = $bindable(), rates, submit } = $props();
let { id } = user;
- let avatarFile, avatarInput, bannerFile, bannerInput;
+ let avatarFile, avatarInput = $state(), bannerFile, bannerInput = $state();
let selectAvatar = () => avatarInput.click();
let selectBanner = () => bannerInput.click();
@@ -18,7 +18,7 @@
percent = Math.round((event.loaded / event.total) * 100);
};
- let tooLarge = {};
+ let tooLarge = $state({});
let handleFile = async ({ target }, type) => {
tooLarge[type] = false;
@@ -47,9 +47,9 @@
if (!user.display) user.display = user.username;
- $: url = `${$page.url.host}/${user.username}`;
- $: full = `${$page.url.protocol}//${url}`;
- $: addr = `${user.username}@${$page.url.host}`;
+ let url = $derived(`${$page.url.host}/${user.username}`);
+ let full = $derived(`${$page.url.protocol}//${url}`);
+ let addr = $derived(`${user.username}@${$page.url.host}`);
</script>
<div>
@@ -83,13 +83,13 @@
icon="ph:check-bold"
class="text-success ml-auto"
width="32"
- />
+></iconify-icon>
{:else if user.email}
<iconify-icon
icon="ph:clock-bold"
class="text-warning ml-auto"
width="32"
- />
+></iconify-icon>
{/if}
</label>
</div>
@@ -101,8 +101,8 @@
{#if $avatar || user.profile}
<div
class="relative rounded-full overflow-hidden text-center w-20 h-20 my-auto hover:opacity-80 cursor-pointer"
- on:click={selectAvatar}
- on:keydown={selectAvatar}
+ onclick={selectAvatar}
+ onkeydown={selectAvatar}
>
<img
src={$avatar?.src || `/api/public/${user.profile}.webp`}
@@ -113,11 +113,11 @@
{:else}
<div
class="rounded-full border-4 border-white p-4 bg-gradient-to-r from-primary to-gradient w-24 my-auto hover:opacity-80 cursor-pointer"
- on:click={selectAvatar}
- on:keydown={selectAvatar}
+ onclick={selectAvatar}
+ onkeydown={selectAvatar}
>
<Icon icon="logo-symbol-white" style="mx-auto" />
- <iconify-icon icon="ph:floppy-disk-bold" width="32" />
+ <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon>
</div>
{/if}
<div class="ml-2 p-2">
@@ -125,14 +125,14 @@
<button
type="button"
class="btn"
- on:click={selectAvatar}
- on:keydown={selectAvatar}>{$t("user.settings.select")}</button
+ onclick={selectAvatar}
+ onkeydown={selectAvatar}>{$t("user.settings.select")}</button
>
<input
type="file"
class="hidden"
bind:this={avatarInput}
- on:change={(e) => handleFile(e, "profile")}
+ onchange={(e) => handleFile(e, "profile")}
/>
</div>
</div>
@@ -151,30 +151,30 @@
<img
src={$banner ? $banner.src : `/api/public/${user.banner}.webp`}
class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80"
- on:click={selectBanner}
- on:keydown={selectBanner}
+ onclick={selectBanner}
+ onkeydown={selectBanner}
alt="Banner"
/>
{:else}
<div
class="bg-gradient-to-r from-primary to-gradient w-full h-48 mb-4 cursor-pointer hover:opacity-80"
- on:click={selectBanner}
- on:keydown={selectBanner}
+ onclick={selectBanner}
+ onkeydown={selectBanner}
alt="Banner"
- />
+></div>
{/if}
<button
type="button"
class="btn !w-auto"
- on:click={selectBanner}
- on:keydown={selectBanner}>{$t("user.settings.select")}</button
+ onclick={selectBanner}
+ onkeydown={selectBanner}>{$t("user.settings.select")}</button
>
<input
type="file"
class="hidden"
bind:this={bannerInput}
- on:change={(e) => handleFile(e, "banner")}
+ onchange={(e) => handleFile(e, "banner")}
/>
{#if tooLarge["banner"]}
@@ -191,5 +191,5 @@
name="address"
bind:value={user.address}
placeholder={$t("user.settings.aboutPlaceholder")}
- />
+></textarea>
</div>
diff --git a/src/routes/(app)/settings/[...tab]/_pos.svelte b/src/routes/(app)/settings/[...tab]/_pos.svelte
index f4a01c09..3f68eebc 100644
--- a/src/routes/(app)/settings/[...tab]/_pos.svelte
+++ b/src/routes/(app)/settings/[...tab]/_pos.svelte
@@ -1,4 +1,6 @@
<script>
+ import { run } from 'svelte/legacy';
+
import { onMount, tick } from "svelte";
import { browser } from "$app/environment";
import Numpad from "$comp/Numpad.svelte";
@@ -9,16 +11,20 @@
import { page } from "$app/stores";
import { PUBLIC_VAPID_PUBKEY } from "$env/static/public";
- export let user, rates, submit, subscriptions;
+ let {
+ user = $bindable(),
+ rates,
+ submit,
+ subscriptions
+ } = $props();
- let { currency } = user;
- let rate = rates[currency];
+ let { currency } = $state(user);
+ let rate = $state(rates[currency]);
let fiats = Object.keys(rates).sort((a, b) => a.localeCompare(b));
- $: user.language = $locale;
let keypress = (e) => e.key === "Enter" && (e.preventDefault() || el.click());
- let editingReserve, editingThreshold, doneReserve, doneThreshold;
+ let editingReserve = $state(), editingThreshold = $state(), doneReserve = $state(), doneThreshold;
let doneEditing = () => {
editingReserve = false;
editingThreshold = false;
@@ -38,9 +44,9 @@
if (!user.threshold) user.threshold = 1000000;
if (!user.reserve) user.reserve = 100000;
- let reserveEl, thresholdEl;
+ let reserveEl = $state(), thresholdEl = $state();
- let push, pm, subscription;
+ let push = $state(), pm, subscription;
onMount(async () => {
if (!browser) return;
@@ -60,8 +66,7 @@
}
});
- let permission;
- $: updateNotifications(push);
+ let permission = $state();
let updateNotifications = async (push) => {
if (!browser || !pm) return (push = false);
@@ -80,6 +85,12 @@
await post("/subscription", { subscription });
}
};
+ run(() => {
+ user.language = $locale;
+ });
+ run(() => {
+ updateNotifications(push);
+ });
</script>
<div>
@@ -154,17 +165,17 @@
<textarea
name="destination"
placeholder={$t("user.settings.destinationPlaceholder")}
- on:keypress={keypress}
+ onkeypress={keypress}
class="w-full p-4 border rounded-xl h-48"
bind:value={user.destination}
- />
+></textarea>
</div>
<div>
<label for="display" class="font-bold mb-1 block"
>{$t("user.settings.threshold")}</label
>
- <button type="button" class="flex w-full" on:click={editThreshold}>
+ <button type="button" class="flex w-full" onclick={editThreshold}>
<div class="p-4 border rounded-2xl rounded-r-none border-r-0 bg-base-200">
⚡️
</div>
@@ -184,7 +195,7 @@
<label for="display" class="font-bold mb-1 block"
>{$t("user.settings.reserve")}</label
>
- <button type="button" class="flex w-full" on:click={editReserve}>
+ <button type="button" class="flex w-full" onclick={editReserve}>
<div class="p-4 border rounded-2xl rounded-r-none border-r-0 bg-base-200">
⚡️
</div>
@@ -220,7 +231,7 @@
<button
bind:this={doneReserve}
type="button"
- on:click={doneEditing}
+ onclick={doneEditing}
class="btn">Ok</button
>
</div>
@@ -247,7 +258,7 @@
<button
bind:this={doneReserve}
type="button"
- on:click={doneEditing}
+ onclick={doneEditing}
class="btn">Ok</button
>
</div>
diff --git a/src/routes/(app)/settings/[...tab]/_security.svelte b/src/routes/(app)/settings/[...tab]/_security.svelte
index d67bda37..8bb8a3fa 100644
--- a/src/routes/(app)/settings/[...tab]/_security.svelte
+++ b/src/routes/(app)/settings/[...tab]/_security.svelte
@@ -1,4 +1,6 @@
<script>
+ import { run } from 'svelte/legacy';
+
import { getMnemonic, getNsec } from "$lib/nostr";
import { tick } from "svelte";
import { t } from "$lib/translations";
@@ -10,26 +12,26 @@
import { invalidate } from "$app/navigation";
import { page } from "$app/stores";
- export let user, rates, submit;
+ let { user = $bindable(), rates, submit } = $props();
- let confirming2fa,
- disabling2fa,
- importing,
+ let confirming2fa = $state(),
+ disabling2fa = $state(),
+ importing = $state(),
locked,
mnemonic,
- newNsec,
- nsec,
+ newNsec = $state(),
+ nsec = $state(),
old,
- otp,
- password,
- pin,
- revealPassword,
+ otp = $state(),
+ password = $state(),
+ pin = $state(),
+ revealPassword = $state(),
revealSeed,
- revealNsec,
- token = "",
- setting2fa,
- settingPin,
- verify;
+ revealNsec = $state(),
+ token = $state(""),
+ setting2fa = $state(),
+ settingPin = $state(),
+ verify = $state();
let toggleImporting = () => {
revealNsec = false;
@@ -56,8 +58,6 @@
}
};
- $: verifying = pin?.length > 5;
- $: verify && checkPin(pin);
let checkPin = async () => {
old = $current;
@@ -88,7 +88,7 @@
return true;
};
- let disablingPin = false;
+ let disablingPin = $state(false);
let togglePin = async () => {
if (user.haspin) {
@@ -129,7 +129,6 @@
disabling2fa = false;
};
- $: enable2fa(token);
let enable2fa = async (twoFa) => {
try {
if (setting2fa && token.length === 6) {
@@ -143,7 +142,6 @@
}
};
- $: disable2fa(token);
let disable2fa = async () => {
try {
if (disabling2fa && token.length === 6) {
@@ -157,6 +155,19 @@
fail("Failed to disable 2FA, try again");
}
};
+ let verifying;
+ run(() => {
+ verifying = pin?.length > 5;
+ });
+ run(() => {
+ verify && checkPin(pin);
+ });
+ run(() => {
+ enable2fa(token);
+ });
+ run(() => {
+ disable2fa(token);
+ });
</script>
<input type="hidden" name="newpin" value={disablingPin ? "delete" : pin} />
@@ -173,14 +184,14 @@
{/if}
<button
type="button"
- on:click={togglePassword}
- on:keydown={togglePassword}
+ onclick={togglePassword}
+ onkeydown={togglePassword}
class="absolute right-5 top-11"
>
<iconify-icon
icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"}
width="32"
- />
+></iconify-icon>
</button>
</div>
@@ -203,12 +214,12 @@
notify={false}
/>
{:else}
- <button type="button" class="btn" on:click={togglePin}
+ <button type="button" class="btn" onclick={togglePin}
>
<iconify-icon
icon={user.haspin ? "ph:lock-key-open-bold" : "ph:lock-key-bold"}
width="32"
- />
+></iconify-icon>
{user.haspin
? $t("user.settings.disablePIN")
: $t("user.settings.enablePIN")}</button
@@ -232,18 +243,18 @@
<b>{otp.secret}</b>
</div>
- <button type="button" class="btn" on:click={startConfirming2fa}>
- <iconify-icon icon="ph:numpad-bold" width="32" />
+ <button type="button" class="btn" onclick={startConfirming2fa}>
+ <iconify-icon icon="ph:numpad-bold" width="32"></iconify-icon>
<div class="my-auto">Confirm</div>
</button>
{:else if user.twofa}
- <button type="button" class="btn" on:click={startDisabling2fa}>
- <iconify-icon icon="ph:device-mobile-bold" width="32" />
+ <button type="button" class="btn" onclick={startDisabling2fa}>
+ <iconify-icon icon="ph:device-mobile-bold" width="32"></iconify-icon>
<div class="my-auto">{$t("user.settings.twofaDisable")}</div>
</button>
{:else}
- <button type="button" class="btn" on:click={startEnabling2fa}>
- <iconify-icon icon="ph:device-mobile-bold" width="32" />
+ <button type="button" class="btn" onclick={startEnabling2fa}>
+ <iconify-icon icon="ph:device-mobile-bold" width="32"></iconify-icon>
<div class="my-auto">{$t("user.settings.twofaSetup")}</div>
</button>
{/if}
@@ -269,12 +280,12 @@
</p>
<div class="flex gap-2">
- <button type="button" class="btn !w-auto flex-grow" on:click={toggleNsec}>
+ <button type="button" class="btn !w-auto flex-grow" onclick={toggleNsec}>
{#if revealNsec}
- <iconify-icon icon="ph:eye-slash-bold" width="32" />
+ <iconify-icon icon="ph:eye-slash-bold" width="32"></iconify-icon>
{$t("user.settings.hideNsec")}
{:else}
- <iconify-icon icon="ph:warning-bold" width="32" />
+ <iconify-icon icon="ph:warning-bold" width="32"></iconify-icon>
{$t("user.settings.revealNsec")}
{/if}
</button>
@@ -282,9 +293,9 @@
<button
type="button"
class="btn !w-auto flex-grow"
- on:click={toggleImporting}
+ onclick={toggleImporting}
>
- <iconify-icon icon="ph:floppy-disk-bold" width="32" />
+ <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon>
{$t("user.settings.import")}
</button>
</div>
@@ -298,8 +309,8 @@
{nsec}
</div>
- <button type="button" class="btn" on:click={() => copy(nsec)}>
- <iconify-icon icon="ph:copy-bold" width="32" />
+ <button type="button" class="btn" onclick={() => copy(nsec)}>
+ <iconify-icon icon="ph:copy-bold" width="32"></iconify-icon>
Copy
</button>
{/if}
diff --git a/src/routes/(app)/settings/[...tab]/_shopify.svelte b/src/routes/(app)/settings/[...tab]/_shopify.svelte
index 48fe7718..cc746c49 100644
--- a/src/routes/(app)/settings/[...tab]/_shopify.svelte
+++ b/src/routes/(app)/settings/[...tab]/_shopify.svelte
@@ -3,22 +3,22 @@
import Icon from "$comp/Icon.svelte";
import { page } from "$app/stores";
- export let user;
- $: paymentsUrl =
- user.shopifyStore &&
+ let { user = $bindable() } = $props();
+ let paymentsUrl =
+ $derived(user.shopifyStore &&
"https://admin.shopify.com/store/" +
user.shopifyStore +
- "/settings/payments";
- $: checkoutUrl =
- user.shopifyStore &&
+ "/settings/payments");
+ let checkoutUrl =
+ $derived(user.shopifyStore &&
"https://admin.shopify.com/store/" +
user.shopifyStore +
- "/settings/checkout";
- $: appsUrl =
- user.shopifyStore &&
+ "/settings/checkout");
+ let appsUrl =
+ $derived(user.shopifyStore &&
"https://admin.shopify.com/store/" +
user.shopifyStore +
- "/settings/apps/development";
+ "/settings/apps/development");
let script = `<script src="${$page.url.protocol}//${$page.url.host}/${user.username}/shopify.js"><\/script>`;
</script>