aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsecondl1ght <[email protected]>2022-08-24 18:47:21 -0400
committersecondl1ght <[email protected]>2022-08-24 18:47:21 -0400
commit8f8f85983d2f4cb734ed15b33ebc140028711733 (patch)
tree1bb87287c2dbeb681be1fb83971eea945fe19926 /src
parent80d2b8db2b85829ee539814c176ebcf354939ad6 (diff)
parente54f0cf98d65e71153c4613a1e9a9b845b9f8f87 (diff)
downloadcoinos-ui-8f8f85983d2f4cb734ed15b33ebc140028711733.tar.gz
coinos-ui-8f8f85983d2f4cb734ed15b33ebc140028711733.zip
Merge branch 'master' of github.com:coinos/coinos-ui-v2
Diffstat (limited to 'src')
-rw-r--r--src/components/About.svelte11
-rw-r--r--src/components/LocaleSelector.svelte4
-rw-r--r--src/lib/translations/index.js39
-rw-r--r--src/lib/translations/lang.json2
-rw-r--r--src/lib/utils.js2
-rw-r--r--src/locales/en.json1
-rw-r--r--src/locales/fr.json122
-rw-r--r--src/locales/guided_translation.py59
-rw-r--r--src/routes/+error.svelte6
-rw-r--r--src/routes/+layout.svelte13
-rw-r--r--src/routes/[username]/receive/+page.svelte2
-rw-r--r--src/routes/invoice/+server.js24
-rw-r--r--src/routes/invoice/[id]/+page.server.js14
-rw-r--r--src/routes/invoice/[id]/+page.svelte103
14 files changed, 313 insertions, 89 deletions
diff --git a/src/components/About.svelte b/src/components/About.svelte
index 794a5107..3cd25f8c 100644
--- a/src/components/About.svelte
+++ b/src/components/About.svelte
@@ -54,9 +54,14 @@
</div>
</div>
- <ul
- class="w-full mx-auto md:w-[700px] lg:w-[500px] xl:w-auto text-secondary px-1 md:px-10 text-xl list-disc space-y-5"
- />
+ <ul class="w-full mx-auto md:w-[700px] lg:w-[500px] xl:w-auto text-secondary px-1 md:px-10 text-xl list-disc space-y-5">
+ <li>{$t('about.founder.qualifications.bitcoin')}</li>
+ <li>{$t('about.founder.qualifications.webDev')}</li>
+ <li>{$t('about.founder.qualifications.bitcoinVancouver')}</li>
+ <li>{$t('about.founder.qualifications.bitcoinCoop')}</li>
+ <li>{$t('about.founder.qualifications.beliefs')}</li>
+ <li>{$t('about.founder.qualifications.familialRelationships')}</li>
+ </ul>
</div>
<div class="mt-20">
diff --git a/src/components/LocaleSelector.svelte b/src/components/LocaleSelector.svelte
index ec5bc781..e1888e9f 100644
--- a/src/components/LocaleSelector.svelte
+++ b/src/components/LocaleSelector.svelte
@@ -1,10 +1,10 @@
<script>
- import { locale, locales } from '$lib/translations';
+ import { t, locale, locales } from '$lib/translations';
export let style;
</script>
<select name="language" bind:value={$locale} class={style}>
{#each $locales as locale}
- <option value={locale}>{locale}</option>
+ <option value={locale}>{$t(`lang.${locale}`)}</option>
{/each}
</select>
diff --git a/src/lib/translations/index.js b/src/lib/translations/index.js
index 023da884..dc03c0b6 100644
--- a/src/lib/translations/index.js
+++ b/src/lib/translations/index.js
@@ -1,9 +1,44 @@
import i18n from 'sveltekit-i18n';
-import translations from './translations';
+import lang from './lang.json';
+
+// setup loaders & translations from lang.json data
+function createLocaleLoader(localeCode) {
+ return {
+ locale: localeCode,
+ key: '',
+ loader: async () => (
+ await import(`../../locales/${localeCode}.json`)
+ ).default
+ };
+}
+
+const availableLocales = Object.keys(lang);
+const translations = {};
+for (let i = 0; i < availableLocales.length; i++) {
+ translations[availableLocales[i]] = { lang };
+}
+const loaders = availableLocales.map(createLocaleLoader);
const config = {
initLocale: 'en',
- translations
+ fallbackLocale: 'en',
+ translations: translations,
+ loaders: [
+ {
+ locale: 'en',
+ key: '',
+ loader: async () => (
+ await import("../../locales/en.json")
+ ).default
+ },
+ {
+ locale: 'fr',
+ key: '',
+ loader: async () => (
+ await import("../../locales/fr.json")
+ ).default
+ }
+ ]
};
export const { t, l, locales, locale } = new i18n(config);
diff --git a/src/lib/translations/lang.json b/src/lib/translations/lang.json
index 6cf55908..b01c522b 100644
--- a/src/lib/translations/lang.json
+++ b/src/lib/translations/lang.json
@@ -1,4 +1,4 @@
{
"en": "English",
- "fr": "French"
+ "fr": "Français"
}
diff --git a/src/lib/utils.js b/src/lib/utils.js
index a1bdf8d7..65025c3a 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -47,6 +47,8 @@ export const put = (url, body, headers) => {
method: 'PUT',
body: JSON.stringify(body),
headers
+ }).then(async (r) => {
+ if (!r.ok) throw new Error('put failed');
});
};
diff --git a/src/locales/en.json b/src/locales/en.json
index 1d3446c9..df7c8b0f 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -1,5 +1,4 @@
{
- "langname": "English",
"404": {
"404": "404",
"pageNotFound": "Page not found."
diff --git a/src/locales/fr.json b/src/locales/fr.json
index acc0eda7..1d279513 100644
--- a/src/locales/fr.json
+++ b/src/locales/fr.json
@@ -1,16 +1,128 @@
{
- "langname": "Français",
+ "404": {
+ "404": "404",
+ "pageNotFound": "Page non trouvée."
+ },
"about": {
- "header": "À Propos"
+ "header": "À Propos",
+ "p1": "<strong>CoinOS</strong> est un portefeuille, point de vente, marché d'e-commerce et plateforme d'échange de bitcoin <strong>open source</strong>. Development a commencé en Vancouver le septembre de 2012 pour donner aux marchands du coin un façon pratique d'accepter des paiements en bitcoin.",
+ "p2": "Il a eu plus de fonctions au fil des ans pour satisfaire une grande variété de cas d'utilisation avec le but de rendre commencer utiliser bitcoin rapidement, à bas prix, et en sécurité aussi façile que possible pour n'importe qui.",
+ "p3": "Tout le monde peux télécharger le code source et héberger leur propre instance de la plateforme soutenu par leur propres nœuds de bitcoin, liquid ou lightning, ou contactez-nous et nous l'installalons pour vous avec plaisir.",
+ "p4": "Transferts entre comptes de garde d'utilisateurs différents en notre serveur sont complètement gratuits, instants et sans limites.",
+ "founder": {
+ "header": "Le Fondateur",
+ "name": "Adam Soltys",
+ "position": "Officier Technique Principal",
+ "qualifications": {
+ "bitcoin": "Utilisant bitcoin depuis 2011",
+ "webDev": "20+ ans d'experience de programmation web en gouvernement et industrie",
+ "bitcoinVancouver": "Organisateur précoce de la rencontre bitcoin Vancouver",
+ "bitcoinCoop": "Fondateur de The Bitcoin Co-op et défenseur précoce de Decentral Vancouver",
+ "beliefs": "Yogi, permaculturiste, anarchiste, décentraliste",
+ "familialRelationships": "Mari, père, frère, fils"
+ }
+ },
+ "locations": {
+ "header": "Établissements",
+ "description": "Il y a des entreprises qui acceptent bitcoin utilisant le point de vente CoinOS. Si vous utilisez notre appli, s'il vous plait <a href=\"mailto:[email protected]\" class=\"underline underline-offset-4\">fais-le-nous savoir!</a>"
+ }
+ },
+ "error": {
+ "header": "Erreur",
+ "message": "S'il vous plait réessayez ou contactez l'assistance.",
+ "signIn": "Vous devez connecter pour continuer."
},
"faq": {
- "header": "FAQ"
+ "header": "FAQ",
+ "cost": {
+ "question": "Qu'est-ce que c'est le coût?",
+ "answer": "CoinOS est gratuit à utiliser. Vous seulment payez un prix 1% quand vous convertez vos fonds entre Bitcoin, Liquid et Lightning. Comparez-ça à les frais de dossir typiques 3% des cartes credit."
+ },
+ "compatibility": {
+ "question": "Est-ce que j'ai besoin du logiciel ou appareil special?",
+ "answer": "Non. CoinOS est un site Web, alors vous pouvez l'utiliser sur n'importe quelle appareil tant que vous aves un connexion d'Internet. La plupart des marchands l'utilise sur un téléphone ou une tablette."
+ },
+ "safety": {
+ "question": "Sont mes fonds saufs?",
+ "answer": "Vos fonds sont entreposés en notre serveur sécurisé, mais nous recommendons que vous les retirez à votre propre entreposage pour les sauvegarder à long terme."
+ }
+ },
+ "footer": {
+ "followUs": "Suivez-Nous",
+ "twitter": "Twitter",
+ "github": "GitHub",
+ "company": "Entreprise",
+ "telegram": "Telegram",
+ "support": "Assistance",
+ "jobs": "Jobs"
},
"howItWorks": {
- "header": "Comment Elle Fonctionne"
+ "header": "Comment Elle Fonctionne",
+ "step1": {
+ "header": "1. Crée votre compte",
+ "description": "Un nom d'utilateur et mot de passe est tout qui est besoin pour commencer."
+ },
+ "step2": {
+ "header": "2. Demande pour des paiements",
+ "description": "Comme vous faisiez normalement, mais avec bitcoin."
+ },
+ "step3": {
+ "header": "3. C'est tout!",
+ "description": "Vous pouvez convertir au monnaie local n'importe quand."
+ }
+ },
+ "landing": {
+ "header_before_icon": "Le",
+ "header_with_icon": "façon",
+ "header_after_icon": "le plus façile d'accepter bitcoin en votre magasin.",
+ "subheader": "Aggrandir votre clientèle et chiffre d'affaires par accepter bitcoin avec un point de vente façile à utiliser et dirigé. Logiciel et matériel informatique non obligatoire.",
+ "info1": {
+ "title": "Paiements instants avec Lightning",
+ "description": "Le moment que votre client envoie un paiment, c'est la. Vous ne devez pas attendre pour les décisions de banques ou vous inquieter pour des rejets de débit. Décisions instant, en secondes. Dis au revoir aux frais de dossir 3% des cartes de crédit."
+ },
+ "info2": {
+ "title": "Simple à utiliser, en garde par défaut",
+ "description1": "Juste entrer une quantité, partager le code QR et c'est tout!",
+ "description2": "Tes contes sont en garde par défaut, qui élimine le nécessité de comprendre comment bitcoin/lightning fonctionnent. Nous réalisons le plus gros du travail pour que vous pouvez vous concentrer sur votre entreprise.",
+ "description3": "Vous toujours avez l'option de <span class=\"underline undeline-offset-4\">prendre garde</span> de vos clés."
+ },
+ "info3": {
+ "title": "Personalise-le comment vous voulez",
+ "description": "Personalisez votre point de vente, ou rettenez-le au défaut - c'est votre chois."
+ }
+ },
+ "login": {
+ "username": "Nom d'utilisateur",
+ "password": "Mot de passe",
+ "passwordRecommendation": "Nous recommendons un mot de passe long et au hazard, généré par un gestionnaire de mots de passe.",
+ "forgotPassword": "Oublié ton mot de passe?",
+ "haveAccount": "Avez-vous déjà une conte?",
+ "noAccount": "N'avez-vous pas un conte?",
+ "register": "Enregistrer",
+ "signIn": "Connexion",
+ "failed": "Connexion failli"
},
"nav": {
"startInSeconds": "Commence en Secondes",
- "signIn": "Connexion"
+ "account": "Conte",
+ "signIn": "Connexion",
+ "signOut": "Déconnexion",
+ "dashboard": "Tableau de bord",
+ "settings": "Préférences",
+ "support": "Assistance"
+ },
+ "invoice": {
+ "addTip": "Ajoutez un pourboire",
+ "addTipq": "Ajouter un pourboire?",
+ "done": "Fini",
+ "paymentSuccessful": "Paiement réussi!"
+ },
+ "jobs": {
+ "header": "Emplois",
+ "subheader": "Postes disponibles actuels",
+ "pitch1": "CoinOS recherche pour des développeurs pour joindre notre équipe croissant (temps plein ou partiel, télétravail OK)",
+ "pitch2": "Avez-vous hâte de travailler sur bitcoin open source? Regardez sur nos dépôts sur",
+ "github": "GitHub",
+ "pitch3": "Si vous pensez que vous pouvez exercer une influence positive, nous voulons que vous contribuez. Envoyer votre CV à"
}
}
diff --git a/src/locales/guided_translation.py b/src/locales/guided_translation.py
index e5f94cfe..65f58db2 100644
--- a/src/locales/guided_translation.py
+++ b/src/locales/guided_translation.py
@@ -1,8 +1,10 @@
#!/usr/bin/python
-import argparse, json, logging
+import argparse, json, logging, sys
+from pathlib import Path
DEFAULT_FROM_LOCALE = 'en'
+LOCALE_DATA_FILEPATH = '../lib/translations/lang.json'
def nested_dict_keys(d, _keyname_prefix=''):
entry_list = []
@@ -14,6 +16,18 @@ def nested_dict_keys(d, _keyname_prefix=''):
entry_list += [_keyname_prefix + key]
return entry_list
+def create_locale(locale_code):
+ logging.debug("Creating locale %s...", locale_code)
+ with open(LOCALE_DATA_FILEPATH, 'r', encoding='utf-8') as lang_file:
+ lang_data = json.load(lang_file)
+
+ lang_data[locale_code] = input("What is the name of the language " + locale_code + "? ")
+
+ with open(LOCALE_DATA_FILEPATH, 'w') as lang_file:
+ json.dump(lang_data, lang_file, ensure_ascii=False, indent='\t')
+ lang_file.write('\n')
+ logging.debug("Created locale %s.", locale_code)
+
def localize_string(string_id, from_data, to_data):
logging.debug("Translating string with id %s", string_id)
id_parts = string_id.split('.')
@@ -28,6 +42,7 @@ def localize_string(string_id, from_data, to_data):
print(to_translate)
translated = input("Type the translated text then press ENTER: ")
+ print(translated)
# find/create place to put translated string
translation_location = to_data # the dictionary or list that should contain the translated string
@@ -42,22 +57,35 @@ if __name__ == "__main__":
# setup and parse commandline arguments
args_parser = argparse.ArgumentParser(description="guided translation of CoinOS")
args_parser.add_argument('from_locale', nargs='?', type=str,
- help='which locale to translate from')
+ help="which locale to translate from")
args_parser.add_argument('to_locale', nargs='?', type=str,
- help='which locale to translate to')
+ help="which locale to translate to")
+ args_parser.add_argument('-v', '--verbose', action='count', default=0,
+ help="show more information")
+ args_parser.add_argument('-V', '--version', action='store_true',
+ help="show version info and exit")
args = args_parser.parse_args()
+ if args.version:
+ print("Guided Translation Script version 0.2.0")
+ sys.exit(0)
+
from_locale = args.from_locale or input("Which locale do you want to translate from (default: %s)? "
% DEFAULT_FROM_LOCALE) or DEFAULT_FROM_LOCALE
to_locale = args.to_locale or input("Which locale do you want to translate to? ")
if not to_locale:
raise ValueError("You need to specify a language to translate to.")
- logging.basicConfig(format='%(levelname)s: %(message)s')
+ if args.verbose >= 2:
+ logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
+ elif args.verbose >= 1:
+ logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
+ else:
+ logging.basicConfig(format='%(levelname)s: %(message)s')
# load locale files
logging.debug("Reading file to convert from (%s.json)", from_locale)
- with open(from_locale + ".json", 'r') as from_file:
+ with open(from_locale + ".json", 'r', encoding='utf-8') as from_file:
from_json_text = from_file.read()
logging.debug("Converting from data from JSON to object")
from_data = json.loads(from_json_text)
@@ -67,10 +95,16 @@ if __name__ == "__main__":
logging.debug("List of strings: %s", from_id_list)
logging.debug("Reading file to convert to (%s.json)", to_locale)
- with open(to_locale + ".json", 'r') as to_file:
- to_json_text = to_file.read()
- logging.debug("Converting to data from JSON to object")
- to_data = json.loads(to_json_text)
+ to_filepath = "./" + to_locale + ".json"
+ if Path(to_filepath).exists():
+ with open(to_locale + ".json", 'r', encoding='utf-8') as to_file:
+ to_json_text = to_file.read()
+ logging.debug("Converting to data from JSON to object")
+ to_data = json.loads(to_json_text)
+ else:
+ logging.info("No file found. Creating new locale.")
+ create_locale(to_locale)
+ to_data = {}
to_id_list = nested_dict_keys(to_data)
logging.info("Successfully obtained %d strings from locale %s",
len(to_id_list), to_locale)
@@ -83,9 +117,10 @@ if __name__ == "__main__":
localize_string(string_id, from_data, to_data)
to_id_list.append(string_id)
except KeyboardInterrupt:
- print("Program interrupted. Saving strings and closing program...")
+ print("\nProgram interrupted. Saving strings...")
# save localized data
- with open(to_locale + ".json", 'w') as to_file:
- json.dump(to_data, to_file, ensure_ascii=False, indent=2)
+ with open(to_locale + ".json", 'w', encoding='utf-8') as to_file:
+ json.dump(to_data, to_file, ensure_ascii=False, indent='\t')
+ to_file.write('\n')
logging.info("Saved %d localized strings to %s.json", len(to_id_list), to_locale)
diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte
index d3b9306d..58a3144d 100644
--- a/src/routes/+error.svelte
+++ b/src/routes/+error.svelte
@@ -15,9 +15,9 @@
<Icon icon="error" style="mx-auto w-56" />
- <h1 class="font-bold text-5xl">{($t('error.header'), { default: 'Error' })}</h1>
- <p class="px-1 w-full md:w-96 break-all font-bold">{$page.error.message.toUpperCase()}</p>
- <p>{($t('error.message'), { default: 'Please try again or contact support.' })}</p>
+ <h1 class="font-bold text-5xl">{$t('error.header')}</h1>
+ <p class="px-1 w-full md:w-96 break-all font-bold">{$page.error.message}</p>
+ <p>{$t('error.message')}</p>
</div>
</div>
{/if}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 185eb140..5eab20bd 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -9,7 +9,9 @@
import { goto } from '$app/navigation';
import { LoadingSplash } from '$comp';
import { warning, protectedRoutes } from '$lib/utils';
- import { t } from '$lib/translations';
+ import { t, locale } from '$lib/translations';
+
+ const localeLocalStorageKey = 'sveltekit-i18n-locale';
$: $token = data.token;
@@ -19,13 +21,18 @@
$: $selectedRate = data.user && $rate * (data.rates[data.user.currency] / data.rates.USD);
onMount(() => {
+ let localStorageLocale = localStorage.getItem(localeLocalStorageKey);
+ if (localStorageLocale) locale.set(localStorageLocale);
+
+ locale.subscribe((lng) => {
+ if (lng) localStorage.setItem(localeLocalStorageKey, lng);
+ });
+
if (protectedRoutes.find((p) => $page.url.pathname.match(p))) {
if (!$token) {
goto('/login');
warning($t('error.signIn'));
}
- } else {
- ready = true;
}
connect();
diff --git a/src/routes/[username]/receive/+page.svelte b/src/routes/[username]/receive/+page.svelte
index 181f8ea6..c588bbe0 100644
--- a/src/routes/[username]/receive/+page.svelte
+++ b/src/routes/[username]/receive/+page.svelte
@@ -81,7 +81,7 @@
};
let submit = async () => {
- let { id } = await post('/invoice', {
+ let id = await post('/invoice', {
amount,
rate: $selectedRate,
username: $page.params.username
diff --git a/src/routes/invoice/+server.js b/src/routes/invoice/+server.js
index c77784d7..4b961be9 100644
--- a/src/routes/invoice/+server.js
+++ b/src/routes/invoice/+server.js
@@ -1,16 +1,16 @@
-import { json as json$1 } from '@sveltejs/kit';
-import { post } from '$lib/utils';
-import { user } from '$lib/store';
-
-let network = 'lightning';
+import cookie from 'cookie';
+import { get, post } from '$lib/utils';
export async function POST({ request }) {
- let { amount, rate, username, text } = await request.json();
- if (!text) ({ text } = await post('/lightning/invoice', { amount }));
- let { uuid: id } = await post('/invoice', {
- invoice: { amount, currency: user.currency, network, rate, text },
- user: { username }
- });
+ let { token } = cookie.parse(request.headers.get('cookie') || '');
+
+ let network = 'lightning';
+ let { amount, currency, rate, tip, text, username } = await request.json();
+ let headers = { authorization: `Bearer ${token}` };
+
+ ({ text } = await post('/lightning/invoice', { amount }, headers));
+ let invoice = { amount, currency, network, rate, tip, text };
+ let { uuid } = await post('/invoice', { invoice, user: { username } }, headers);
- return json$1({ id });
+ return new Response(JSON.stringify(uuid), { headers: { 'content-type': 'application/json' } });
}
diff --git a/src/routes/invoice/[id]/+page.server.js b/src/routes/invoice/[id]/+page.server.js
index 78607545..d46d039b 100644
--- a/src/routes/invoice/[id]/+page.server.js
+++ b/src/routes/invoice/[id]/+page.server.js
@@ -1,14 +1,8 @@
-import { get } from '$lib/utils';
+import cookie from 'cookie';
+import { get, post } from '$lib/utils';
export async function load({ params }) {
let { id } = params;
- let {
- amount,
- rate,
- status,
- text,
- user: { username }
- } = await get(`/invoice?uuid=${id}`);
-
- return { amount, id, rate, username, status, text };
+ return { id, invoice: await get(`/invoice?uuid=${id}`) };
}
+
diff --git a/src/routes/invoice/[id]/+page.svelte b/src/routes/invoice/[id]/+page.svelte
index 19809f9f..e8bd9edf 100644
--- a/src/routes/invoice/[id]/+page.svelte
+++ b/src/routes/invoice/[id]/+page.svelte
@@ -3,54 +3,85 @@
import { browser } from '$app/env';
import { invoices, user } from '$lib/store';
import { Icon, Image } from '$comp';
- import { goto } from '$app/navigation';
- import { onMount } from 'svelte';
+ import { goto, invalidate } from '$app/navigation';
+ import { onMount, tick } from 'svelte';
import { copy } from '$lib/utils';
import { t } from '$lib/translations';
export let data;
- $: ({ amount, id, rate, status, text, username } = data);
- $invoices[id] = { amount, id, rate, status, text, username };
+ $: refresh(data);
+ let { invoice, id } = data;
+ let {
+ amount,
+ rate,
+ status,
+ text,
+ tip,
+ user: { username, currency }
+ } = invoice;
+
+ amount -= tip;
+
+ let refresh = (data) => {
+ ({ invoice, id } = data);
+ ({
+ amount,
+ rate,
+ status,
+ text,
+ tip,
+ user: { username, currency }
+ } = invoice);
+
+ amount -= tip;
+
+ tipPercent = Math.round((tip / amount) * 100);
+ };
+
+ $invoices[id] = { amount, id, rate, status, text, tip, username };
$: amountFiat = parseFloat(((amount * rate) / 100000000).toFixed(2));
let tipPercent = 0;
let qr;
- $: tipAmount = customTipAmount
- ? customTipAmount < 0
- ? (customTipAmount = 0)
- : customTipAmount
- : (amountFiat / 100) * tipPercent;
+ $: tipAmount = (amountFiat / 100) * tipPercent;
$: tipAmountFormatted = new Intl.NumberFormat('en-US', {
style: 'currency',
- currency: $user.currency
+ currency
}).format(tipAmount);
- $: tipAmountSats = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(
- tipAmount / (rate / 100000000)
- );
+ $: tipAmountSats = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(tip);
$: totalAmountSats = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(
amount + parseFloat(tipAmountSats.replace(/,/g, ''))
);
- $: update(tipAmountSats);
- let update = async (n) => {
- let { id } = await post('/invoice', {
- amount: amount + reverseFormat(n),
+ let apply = async () => {
+ tipAmount = customTipAmount;
+ tipPercent = Math.round((tipAmount / amountFiat) * 100);
+ update();
+ };
+
+ let update = async () => {
+ await tick();
+ tip = (tipAmount * 100000000) / rate;
+ let r = await post(`/invoice`, {
+ amount: amount + tip,
rate,
+ tip,
text,
username
});
- ({ text } = await get(`/invoice/${id}`));
+
+ goto(`/invoice/${r}`);
};
$: totalAmountFormatted = new Intl.NumberFormat('en-US', {
style: 'currency',
- currency: $user.currency
+ currency
}).format(amountFiat + parseFloat(tipAmount));
const amountFormatted = new Intl.NumberFormat('en-US', {
@@ -59,13 +90,22 @@
$: invoiceAmountFiatFormatted = new Intl.NumberFormat('en-US', {
style: 'currency',
- currency: $user.currency
+ currency
}).format(amountFiat);
let customTipAmount;
const tipAmounts = ['None', '10%', '15%', '20%'];
+ let timeout;
+ const handleSlide = (e) => {
+ customTipAmount = '';
+ customInput.value = '';
+ tipPercent = e.target.value;
+ clearTimeout(timeout);
+ timeout = setTimeout(update, 100);
+ };
+
const handleTipButtonClick = (amount) => {
customTipAmount = '';
customInput.value = '';
@@ -75,6 +115,8 @@
} else {
tipPercent = amount.slice(0, 2);
}
+
+ update();
};
const handleCustomTipAmount = (e) => {
@@ -83,8 +125,8 @@
};
$: generate(text);
- let generate = async (ready) => {
- if (!ready) return;
+ let generate = async (text) => {
+ if (!(browser && text)) return;
let { default: QRCodeStyling } = await import('qr-code-styling');
const qrCode = new QRCodeStyling({
@@ -103,6 +145,7 @@
}
});
+ while (qr.firstChild) qr.removeChild(qr.lastChild);
qrCode.append(qr);
};
@@ -116,18 +159,14 @@
tipAmount = 0;
showMobileTip = false;
} else {
- goto(`/${$user.username}/receive`);
+ goto(`/${username}/receive`);
}
};
let customInput;
const handleDoneClick = () => {
- if ($user) {
- goto(`/${$user.username}/receive`);
- } else {
- goto('/');
- }
+ goto(`/${username}/receive`);
};
</script>
@@ -167,11 +206,7 @@
max="100"
value={tipPercent}
class="px-2"
- on:input={(e) => {
- customTipAmount = '';
- customInput.value = '';
- tipPercent = e.target.value;
- }}
+ on:input={handleSlide}
/>
<div>
@@ -210,7 +245,7 @@
? 'opacity-50'
: 'opacity-100'}"
disabled={showMobileTip ? !customTipAmount && !tipAmount : !customTipAmount}
- on:click={() => (showMobileTip = false)}>Done</button
+ on:click={apply}>Apply</button
>
</div>
</div>