From 7ae14aa32f143c85bac18b897e030c584d081e8d Mon Sep 17 00:00:00 2001 From: Tiago Vasconcelos Date: Sat, 4 Mar 2023 19:49:58 +0000 Subject: [PATCH] general fixes, prop passing and shopping cart (doesn't send dm) --- .../customer-stall/customer-stall.html | 106 ++++++++++- .../customer-stall/customer-stall.js | 167 +++++++++++++++++- .../components/product-card/product-card.html | 16 ++ .../components/product-card/product-card.js | 2 +- .../product-detail/product-detail.html | 12 +- .../product-detail/product-detail.js | 15 +- .../shopping-cart/shopping-cart.html | 52 +++++- .../components/shopping-cart/shopping-cart.js | 2 +- static/js/market.js | 17 +- templates/nostrmarket/market.html | 1 + templates/nostrmarket/stall.html | 61 ------- 11 files changed, 355 insertions(+), 96 deletions(-) delete mode 100644 templates/nostrmarket/stall.html diff --git a/static/components/customer-stall/customer-stall.html b/static/components/customer-stall/customer-stall.html index 9bc302c..aedec55 100644 --- a/static/components/customer-stall/customer-stall.html +++ b/static/components/customer-stall/customer-stall.html @@ -10,13 +10,20 @@ - +
@@ -28,7 +35,102 @@ v-for="(item, idx) in products" :key="idx" > - +
+ + + + + + + + + +
+
+ Generate key pair +
+
+ Get from Extension +
+
+ + +

Select the shipping zone:

+
+ +
+
+ Total: {{ stall.currency != 'sat' ? getAmountFormated(finalCost) : + finalCost + 'sats' }} + ({{ getValueInSats(finalCost) }} sats) +
+
+ Checkout + Cancel +
+
+
+
+ diff --git a/static/components/customer-stall/customer-stall.js b/static/components/customer-stall/customer-stall.js index 1d9b395..858ed9d 100644 --- a/static/components/customer-stall/customer-stall.js +++ b/static/components/customer-stall/customer-stall.js @@ -10,23 +10,184 @@ async function customerStall(path) { 'products', 'exchange-rates', 'product-detail', - 'change-page' + 'change-page', + 'relays' ], data: function () { - return {} + return { + cart: { + total: 0, + size: 0, + products: new Map() + }, + cartMenu: [], + hasNip07: false, + checkoutDialog: { + show: false, + data: { + pubkey: null + } + }, + qrCodeDialog: { + data: { + payment_request: null + }, + show: false + } + } }, computed: { product() { if (this.productDetail) { return this.products.find(p => p.id == this.productDetail) } + }, + finalCost() { + if (!this.checkoutDialog.data.shippingzone) return this.cart.total + + let zoneCost = this.stall.shipping.find( + z => z.id == this.checkoutDialog.data.shippingzone + ) + return +this.cart.total + zoneCost.cost } }, methods: { changePageS(page, opts) { this.$emit('change-page', page, opts) + }, + getValueInSats(amount, unit = 'USD') { + if (!this.exchangeRates) return 0 + return Math.ceil( + (amount / this.exchangeRates[`BTC${unit}`][unit]) * 1e8 + ) + }, + getAmountFormated(amount, unit = 'USD') { + return LNbits.utils.formatCurrency(amount, unit) + }, + addToCart(item) { + console.log('add to cart', item) + let prod = this.cart.products + if (prod.has(item.id)) { + let qty = prod.get(item.id).quantity + prod.set(item.id, { + ...prod.get(item.id), + quantity: qty + 1 + }) + } else { + prod.set(item.id, { + name: item.name, + quantity: 1, + price: item.price, + image: item?.images[0] || null + }) + } + this.$q.notify({ + type: 'positive', + message: `${item.name} added to cart`, + icon: 'thumb_up' + }) + this.cart.products = prod + this.updateCart(+item.price) + }, + removeFromCart(item) { + this.cart.products.delete(item.id) + this.updateCart(+item.price, true) + }, + updateCart(price, del = false) { + console.log(this.cart, this.cartMenu) + if (del) { + this.cart.total -= price + this.cart.size-- + } else { + this.cart.total += price + this.cart.size++ + } + this.cartMenu = Array.from(this.cart.products, item => { + return {id: item[0], ...item[1]} + }) + console.log(this.cart, this.cartMenu) + }, + resetCart() { + this.cart = { + total: 0, + size: 0, + products: new Map() + } + }, + async getPubkey() { + try { + this.checkoutDialog.data.pubkey = await window.nostr.getPublicKey() + this.checkoutDialog.data.privkey = null + } catch (err) { + console.error( + `Failed to get a public key from a Nostr extension: ${err}` + ) + } + }, + generateKeyPair() { + let sk = NostrTools.generatePrivateKey() + let pk = NostrTools.getPublicKey(sk) + this.checkoutDialog.data.pubkey = pk + this.checkoutDialog.data.privkey = sk + }, + placeOrder() { + LNbits.utils + .confirmDialog( + `Send the order to the merchant? You should receive a message with the payment details.` + ) + .onOk(async () => { + let orderData = this.checkoutDialog.data + let content = { + name: orderData?.username, + description: null, + address: orderData.address, + message: null, + contact: { + nostr: orderData.pubkey, + phone: null, + email: orderData?.email + }, + items: Array.from(this.cart.products, p => { + return {product_id: p[0], quantity: p[1].quantity} + }) + } + let event = { + kind: 4, + created_at: Math.floor(Date.now() / 1000), + tags: [], + content: await window.nostr.nip04.encrypt( + orderData.pubkey, + content + ), + pubkey: orderData.pubkey + } + event.id = NostrTools.getEventHash(event) + if (orderData.privkey) { + event.sig = NostrTools.signEvent(event, orderData.privkey) + } else if (this.hasNip07) { + await window.nostr.signEvent(event) + } + await this.sendOrder(event) + }) + }, + async sendOrder(order) { + const pool = new NostrTools.SimplePool() + let relays = Array.from(this.relays) + let pubs = await pool.publish(relays, order) + pubs.on('ok', relay => { + console.log(`${relay.url} has accepted our event`) + }) + pubs.on('failed', reason => { + console.log(`failed to publish to ${reason}`) + }) } }, - created() {} + created() { + setTimeout(() => { + if (window.nostr) { + this.hasNip07 = true + } + }, 1000) + } }) } diff --git a/static/components/product-card/product-card.html b/static/components/product-card/product-card.html index 93d4d96..5a92ba3 100644 --- a/static/components/product-card/product-card.html +++ b/static/components/product-card/product-card.html @@ -9,6 +9,22 @@ > + Add to cart
{{ product.name }}
diff --git a/static/components/product-card/product-card.js b/static/components/product-card/product-card.js index 9e8490b..5e049df 100644 --- a/static/components/product-card/product-card.js +++ b/static/components/product-card/product-card.js @@ -4,7 +4,7 @@ async function productCard(path) { name: 'product-card', template, - props: ['product', 'change-page'], + props: ['product', 'change-page', 'add-to-cart', 'is-stall'], data: function () { return {} }, diff --git a/static/components/product-detail/product-detail.html b/static/components/product-detail/product-detail.html index 92fa1c0..be31eda 100644 --- a/static/components/product-detail/product-detail.html +++ b/static/components/product-detail/product-detail.html @@ -17,6 +17,11 @@ style="/*background-size: contain; background-repeat: no-repeat*/" > +
@@ -47,7 +52,7 @@ {{ product.amount > 0 ? 'In stock.' : 'Out of stock.' }}{{ product.quantity > 0 ? 'In stock.' : 'Out of stock.' }}
@@ -56,12 +61,13 @@ color="primary" icon="shopping_cart" label="Add to cart" + @click="$emit('add-to-cart', product)" />
diff --git a/static/components/product-detail/product-detail.js b/static/components/product-detail/product-detail.js index 7b60f6b..d55b653 100644 --- a/static/components/product-detail/product-detail.js +++ b/static/components/product-detail/product-detail.js @@ -4,23 +4,14 @@ async function productDetail(path) { name: 'product-detail', template, - props: ['product'], + props: ['product', 'add-to-cart'], data: function () { return { slide: 1 } }, - computed: { - win_width() { - return this.$q.screen.width - 59 - }, - win_height() { - return this.$q.screen.height - 0 - } - }, + computed: {}, methods: {}, - created() { - console.log('ping') - } + created() {} }) } diff --git a/static/components/shopping-cart/shopping-cart.html b/static/components/shopping-cart/shopping-cart.html index 8650cc6..2864cf3 100644 --- a/static/components/shopping-cart/shopping-cart.html +++ b/static/components/shopping-cart/shopping-cart.html @@ -1 +1,51 @@ - + + + {{ cart.size }} + + + + + + {{p.quantity}} x + + + + + + + + + {{ p.name }} + + + + + {{p.currency != 'sat' ? p.formatedPrice : p.price + 'sats'}} + + + + + + +
+ +
diff --git a/static/components/shopping-cart/shopping-cart.js b/static/components/shopping-cart/shopping-cart.js index e0ad053..8f6902d 100644 --- a/static/components/shopping-cart/shopping-cart.js +++ b/static/components/shopping-cart/shopping-cart.js @@ -5,7 +5,7 @@ async function shoppingCart(path) { name: 'shopping-cart', template, - props: [], + props: ['cart', 'cart-menu', 'remove-from-cart', 'reset-cart'], data: function () { return {} }, diff --git a/static/js/market.js b/static/js/market.js index 6a0d723..95bf5a6 100644 --- a/static/js/market.js +++ b/static/js/market.js @@ -1,20 +1,13 @@ const market = async () => { Vue.component(VueQrcode.name, VueQrcode) - const nostr = window.NostrTools + const NostrTools = window.NostrTools const defaultRelays = [ 'wss://relay.damus.io', 'wss://relay.snort.social', - 'wss://nos.lol', 'wss://nostr.wine', - 'wss://relay.nostr.bg', 'wss://nostr-pub.wellorder.net', - 'wss://nostr-pub.semisol.dev', - 'wss://eden.nostr.land', - 'wss://nostr.mom', - 'wss://nostr.fmt.wiz.biz', - 'wss://nostr.zebedee.cloud', - 'wss://nostr.rocks' + 'wss://nostr.zebedee.cloud' ] const eventToObj = event => { event.content = JSON.parse(event.content) @@ -128,7 +121,7 @@ const market = async () => { }, methods: { naddr() { - let naddr = nostr.nip19.naddrEncode({ + let naddr = NostrTools.nip19.naddrEncode({ identifier: '1234', pubkey: 'c1415f950a1e3431de2bc5ee35144639e2f514cf158279abff9ed77d50118796', @@ -139,7 +132,7 @@ const market = async () => { }, async initNostr() { this.$q.loading.show() - const pool = new nostr.SimplePool() + const pool = new NostrTools.SimplePool() let relays = Array.from(this.relays) let products = new Map() let stalls = new Map() @@ -243,7 +236,7 @@ const market = async () => { let regExp = /^#([0-9a-f]{3}){1,2}$/i if (pubkey.startsWith('n')) { try { - let {type, data} = nostr.nip19.decode(pubkey) + let {type, data} = NostrTools.nip19.decode(pubkey) if (type === 'npub') pubkey = data else if (type === 'nprofile') { pubkey = data.pubkey diff --git a/templates/nostrmarket/market.html b/templates/nostrmarket/market.html index c885e10..5f01c41 100644 --- a/templates/nostrmarket/market.html +++ b/templates/nostrmarket/market.html @@ -145,6 +145,7 @@ :products="filterProducts" :exchange-rates="exchangeRates" :product-detail="activeProduct" + :relays="relays" @change-page="navigateTo" > -{% endblock %} {% block scripts %} - - -{% endblock %}