feat: stuff
This commit is contained in:
parent
b41e499591
commit
761a3137a6
9 changed files with 221 additions and 21 deletions
|
|
@ -33,7 +33,7 @@
|
||||||
<q-tooltip>{{ publicKey }}</q-tooltip>
|
<q-tooltip>{{ publicKey }}</q-tooltip>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section side>
|
<q-item-section side>
|
||||||
<q-btn class="gt-xs" size="12px" flat dense round icon="delete" @click="removeMerchant(publicKey)" />
|
<q-btn size="12px" flat dense round icon="delete" @click="removeMerchant(publicKey)" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
alt="Product Image" loading="lazy" spinner-color="white" fit="contain" height="300px"></q-img>
|
alt="Product Image" loading="lazy" spinner-color="white" fit="contain" height="300px"></q-img>
|
||||||
|
|
||||||
<q-card-section class="q-pb-xs q-pt-md">
|
<q-card-section class="q-pb-xs q-pt-md">
|
||||||
<q-btn v-if="isStall" round :disabled="product.quantity < 1" color="primary" icon="shopping_cart" size="lg" style="
|
<q-btn v-if="isStall" round :disabled="product.quantity < 1" color="primary" rounded icon="shopping_cart" size="lg" style="
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-mt-md"
|
class="q-mt-md"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
rounded
|
||||||
icon="shopping_cart"
|
icon="shopping_cart"
|
||||||
label="Add to cart"
|
label="Add to cart"
|
||||||
@click="$emit('add-to-cart', product)"
|
@click="$emit('add-to-cart', product)"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
<div>
|
||||||
|
<q-card v-if="cart" bordered class="q-mb-md">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-avatar>
|
||||||
|
<img v-if="cart.merchant?.profile?.picture" :src="cart.merchant?.profile?.picture">
|
||||||
|
<img v-else src="/nostrmarket/static/images/blank-avatar.webp">
|
||||||
|
</q-avatar>
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
<strong>
|
||||||
|
<span v-text="cart.products[0]?.stallName"></span>
|
||||||
|
</strong>
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
By <span v-text="cart.merchant?.profile?.name || cart.merchant?.publicKey"></span>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<q-card-section horizontal>
|
||||||
|
<q-card-section class="col-7">
|
||||||
|
<div class="row q-mt-md">
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
<strong>Subtotal:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
<strong>{{formatCurrency(cartTotal,
|
||||||
|
cart.products[0]?.currency)}}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row q-mt-md">
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
<strong>Shipping:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
<strong>00.00</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<q-separator class="q-mt-sm" />
|
||||||
|
<div class="row q-mt-md">
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
<strong>Total:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-4">
|
||||||
|
<strong>00.00</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
<strong>Subtotal:</strong>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label> <strong>{{formatCurrency(cartTotal,
|
||||||
|
cart.products[0]?.currency)}}</strong></q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label> xx</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
<strong>Shipping:</strong>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label> 0.00</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label> xx</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-separator />
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
<strong>Total:</strong>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label> </q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item> -->
|
||||||
|
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-separator vertical />
|
||||||
|
|
||||||
|
<q-card-section>
|
||||||
|
<strong>Payment Method</strong>
|
||||||
|
<q-option-group v-model="paymentMethod" :options="paymentOptions" color="green" disable />
|
||||||
|
</q-card-section>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<q-card-actions align="right">
|
||||||
|
|
||||||
|
<q-btn @click="requestInvoice(cart)" flat color="primary">
|
||||||
|
Request Invoice
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
async function shoppingCartCheckout(path) {
|
||||||
|
const template = await loadTemplateAsync(path)
|
||||||
|
|
||||||
|
Vue.component('shopping-cart-checkout', {
|
||||||
|
name: 'shopping-cart-checkout',
|
||||||
|
template,
|
||||||
|
|
||||||
|
props: ['cart'],
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
paymentMethod: 'ln',
|
||||||
|
paymentOptions: [
|
||||||
|
{
|
||||||
|
label: 'Lightning Network',
|
||||||
|
value: 'ln'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'BTC Onchain',
|
||||||
|
value: 'btc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cashu',
|
||||||
|
value: 'cashu'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
cartTotal() {
|
||||||
|
if (!this.cart.products?.length) return 0
|
||||||
|
return this.cart.products.reduce((t, p) => p.price + t, 0)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatCurrency: function (value, unit) {
|
||||||
|
return formatCurrency(value, unit)
|
||||||
|
},
|
||||||
|
requestInvoice: function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
console.log('### shoppingCartCheckout', this.cart)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
<div>
|
<div>
|
||||||
|
<q-card v-if="!carts?.length" bordered class="q-mb-md">
|
||||||
|
<q-card-section>
|
||||||
|
<strong>No products in cart!</strong>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
<div v-for="cart in carts">
|
<div v-for="cart in carts">
|
||||||
|
|
||||||
<q-card bordered class="q-mb-md">
|
<q-card bordered class="q-mb-md">
|
||||||
|
|
@ -21,7 +26,11 @@
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section side>
|
<q-item-section side>
|
||||||
|
<div>
|
||||||
|
<q-btn @click="removeCart(cart.id)" flat color="pink">
|
||||||
|
Clear Cart
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
|
|
@ -51,20 +60,19 @@
|
||||||
<q-item-label><strong>{{ formatCurrency(product.price, product.currency)}}</strong></q-item-label>
|
<q-item-label><strong>{{ formatCurrency(product.price, product.currency)}}</strong></q-item-label>
|
||||||
<q-item-label></q-item-label>
|
<q-item-label></q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<!-- " -->
|
|
||||||
<q-item-section class="q-ma-sm">
|
<q-item-section class="q-ma-sm">
|
||||||
<q-input v-model.number="product.orderedQuantity" @change="quantityChanged(product)" type="number" rounded outlined min="1"
|
<q-input v-model.number="product.orderedQuantity" @change="quantityChanged(product)" type="number"
|
||||||
:max="product.quantity"></q-input>
|
rounded outlined min="1" :max="product.quantity"></q-input>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label><strong>{{ formatCurrency(product.price * product.orderedQuantity, product.currency)}}
|
<q-item-label><strong>{{ formatCurrency(product.price * product.orderedQuantity, product.currency)}}
|
||||||
</strong></q-item-label>
|
</strong></q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section side>
|
<q-item-section side>
|
||||||
<div>
|
<div>
|
||||||
<q-btn flat dense round icon="delete"
|
<q-btn flat dense round icon="delete" @click="removeProduct(product.stall_id, product.id)" />
|
||||||
@click="removeProduct(product.stall_id, product.id)" />
|
|
||||||
</div>
|
</div>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
||||||
|
|
@ -75,9 +83,11 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-separator />
|
<q-separator />
|
||||||
|
|
||||||
|
|
||||||
<q-card-actions align="right">
|
<q-card-actions align="right">
|
||||||
|
|
||||||
Total: <strong class="q-ma-md"> {{cartTotalFormatted(cart)}} </strong>
|
Total: <strong class="q-ma-md"> {{cartTotalFormatted(cart)}} </strong>
|
||||||
<q-btn flat color="primary">
|
<q-btn @click="proceedToCheckout(cart)" flat color="primary">
|
||||||
Proceed to Checkout
|
Proceed to Checkout
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,14 @@ async function shoppingCartList(path) {
|
||||||
removeProduct: function (stallId, productId) {
|
removeProduct: function (stallId, productId) {
|
||||||
this.$emit('remove-from-cart', { stallId, productId })
|
this.$emit('remove-from-cart', { stallId, productId })
|
||||||
},
|
},
|
||||||
|
removeCart: function (stallId) {
|
||||||
|
this.$emit('remove-cart', stallId)
|
||||||
|
},
|
||||||
quantityChanged: function (product) {
|
quantityChanged: function (product) {
|
||||||
this.$emit('add-to-cart', product)
|
this.$emit('add-to-cart', product)
|
||||||
|
},
|
||||||
|
proceedToCheckout: function(cart){
|
||||||
|
this.$emit('checkout-cart', cart)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() { }
|
created() { }
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const market = async () => {
|
||||||
productDetail('static/components/product-detail/product-detail.html'),
|
productDetail('static/components/product-detail/product-detail.html'),
|
||||||
shoppingCart('static/components/shopping-cart/shopping-cart.html'),
|
shoppingCart('static/components/shopping-cart/shopping-cart.html'),
|
||||||
shoppingCartList('static/components/shopping-cart-list/shopping-cart-list.html'),
|
shoppingCartList('static/components/shopping-cart-list/shopping-cart-list.html'),
|
||||||
|
shoppingCartCheckout('static/components/shopping-cart-checkout/shopping-cart-checkout.html'),
|
||||||
chatDialog('static/components/chat-dialog/chat-dialog.html'),
|
chatDialog('static/components/chat-dialog/chat-dialog.html'),
|
||||||
marketConfig('static/components/market-config/market-config.html')
|
marketConfig('static/components/market-config/market-config.html')
|
||||||
])
|
])
|
||||||
|
|
@ -52,6 +53,7 @@ const market = async () => {
|
||||||
|
|
||||||
merchants: [],
|
merchants: [],
|
||||||
shoppingCarts: [],
|
shoppingCarts: [],
|
||||||
|
shoppingCartCheckout: null,
|
||||||
|
|
||||||
activePage: 'market',
|
activePage: 'market',
|
||||||
|
|
||||||
|
|
@ -592,7 +594,6 @@ const market = async () => {
|
||||||
product.orderedQuantity = Math.min(product.quantity, item.orderedQuantity || (product.orderedQuantity + 1))
|
product.orderedQuantity = Math.min(product.quantity, item.orderedQuantity || (product.orderedQuantity + 1))
|
||||||
|
|
||||||
this.$q.localStorage.set('nostrmarket.shoppingCarts', this.shoppingCarts)
|
this.$q.localStorage.set('nostrmarket.shoppingCarts', this.shoppingCarts)
|
||||||
console.log('### this.shoppingCarts', this.shoppingCarts)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
removeProductFromCart(item) {
|
removeProductFromCart(item) {
|
||||||
|
|
@ -604,6 +605,15 @@ const market = async () => {
|
||||||
}
|
}
|
||||||
this.$q.localStorage.set('nostrmarket.shoppingCarts', this.shoppingCarts)
|
this.$q.localStorage.set('nostrmarket.shoppingCarts', this.shoppingCarts)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
removeCart(stallId) {
|
||||||
|
this.shoppingCarts = this.shoppingCarts.filter(s => s.id !== stallId)
|
||||||
|
this.$q.localStorage.set('nostrmarket.shoppingCarts', this.shoppingCarts)
|
||||||
|
},
|
||||||
|
|
||||||
|
checkoutCart(cart) {
|
||||||
|
this.shoppingCartCheckout = cart
|
||||||
|
this.setActivePage('shopping-cart-checkout')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,11 +181,11 @@
|
||||||
<q-btn v-else @click="accountDialog.show = true" color="gray" icon="person_add" flat
|
<q-btn v-else @click="accountDialog.show = true" color="gray" icon="person_add" flat
|
||||||
size="lg"><q-tooltip>User
|
size="lg"><q-tooltip>User
|
||||||
Config</q-tooltip></q-btn>
|
Config</q-tooltip></q-btn>
|
||||||
<q-btn color="gray" icon="shopping_cart" dense round flat size="lg"
|
<q-btn color="gray" icon="shopping_cart" dense round flat size="lg"
|
||||||
@click="setActivePage('shopping-cart-list')">
|
@click="setActivePage('shopping-cart-list')">
|
||||||
<q-tooltip>Shopping Cart</q-tooltip>
|
<q-tooltip>Shopping Cart</q-tooltip>
|
||||||
|
|
||||||
<q-badge v-if="allCartsItemCount" color="secondary" floating>
|
<q-badge v-if="allCartsItemCount" color="secondary" floating>
|
||||||
<span v-text="allCartsItemCount"></span>
|
<span v-text="allCartsItemCount"></span>
|
||||||
</q-badge>
|
</q-badge>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
@ -211,7 +211,10 @@
|
||||||
<market-config v-if="activePage === 'market-config'" :merchants="merchants" @add-merchant="addMerchant"
|
<market-config v-if="activePage === 'market-config'" :merchants="merchants" @add-merchant="addMerchant"
|
||||||
@remove-merchant="removeMerchant"></market-config>
|
@remove-merchant="removeMerchant"></market-config>
|
||||||
<shopping-cart-list v-else-if="activePage === 'shopping-cart-list'" :carts="shoppingCarts"
|
<shopping-cart-list v-else-if="activePage === 'shopping-cart-list'" :carts="shoppingCarts"
|
||||||
@add-to-cart="addProductToCart" @remove-from-cart="removeProductFromCart"></shopping-cart-list>
|
@add-to-cart="addProductToCart" @remove-from-cart="removeProductFromCart" @remove-cart="removeCart"
|
||||||
|
@checkout-cart="checkoutCart"></shopping-cart-list>
|
||||||
|
<shopping-cart-checkout v-else-if="activePage === 'shopping-cart-checkout'"
|
||||||
|
:cart="shoppingCartCheckout"></shopping-cart-checkout>
|
||||||
<customer-stall v-else-if="!isLoading && activeStall" :stall="stalls.find(stall => stall.id == activeStall)"
|
<customer-stall v-else-if="!isLoading && activeStall" :stall="stalls.find(stall => stall.id == activeStall)"
|
||||||
:products="filterProducts" :stall-products="products.filter(p => p.stall_id == activeStall)"
|
:products="filterProducts" :stall-products="products.filter(p => p.stall_id == activeStall)"
|
||||||
:product-detail="activeProduct" :relays="relays" :account="account" :pool="pool" :styles="config?.opts ?? {}"
|
:product-detail="activeProduct" :relays="relays" :account="account" :pool="pool" :styles="config?.opts ?? {}"
|
||||||
|
|
@ -225,7 +228,7 @@
|
||||||
|
|
||||||
<!-- ACCOUNT DIALOG -->
|
<!-- ACCOUNT DIALOG -->
|
||||||
<q-dialog v-model="accountDialog.show" position="top">
|
<q-dialog v-model="accountDialog.show" position="top">
|
||||||
<q-card >
|
<q-card>
|
||||||
<q-card-section class="row">
|
<q-card-section class="row">
|
||||||
<div class="text-h6">Account Setup</div>
|
<div class="text-h6">Account Setup</div>
|
||||||
<q-space></q-space>
|
<q-space></q-space>
|
||||||
|
|
@ -236,16 +239,13 @@
|
||||||
|
|
||||||
<q-card-section class="q-pt-none">
|
<q-card-section class="q-pt-none">
|
||||||
<q-input dense label="Nsec/Hex" v-model="accountDialog.data.key" autofocus @keyup.enter="createAccount"
|
<q-input dense label="Nsec/Hex" v-model="accountDialog.data.key" autofocus @keyup.enter="createAccount"
|
||||||
:error="accountDialog.data.key && !isValidAccountKey"
|
:error="accountDialog.data.key && !isValidAccountKey" hint="Enter you private key"></q-input>
|
||||||
hint="Enter you private key"></q-input>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-card-actions align="right" class="text-primary">
|
<q-card-actions align="right" class="text-primary">
|
||||||
<q-btn v-if="isValidAccountKey" label="Login" color="primary" @click="() => createAccount()"></q-btn>
|
<q-btn v-if="isValidAccountKey" label="Login" color="primary" @click="() => createAccount()"></q-btn>
|
||||||
<q-btn v-else flat label="Generate" @click="generateKeyPair"></q-btn>
|
<q-btn v-else flat label="Generate" @click="generateKeyPair"></q-btn>
|
||||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
||||||
>Close</q-btn
|
|
||||||
>
|
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
@ -292,6 +292,8 @@
|
||||||
<script src="{{ url_for('nostrmarket_static', path='components/product-detail/product-detail.js') }}"></script>
|
<script src="{{ url_for('nostrmarket_static', path='components/product-detail/product-detail.js') }}"></script>
|
||||||
<script src="{{ url_for('nostrmarket_static', path='components/shopping-cart/shopping-cart.js') }}"></script>
|
<script src="{{ url_for('nostrmarket_static', path='components/shopping-cart/shopping-cart.js') }}"></script>
|
||||||
<script src="{{ url_for('nostrmarket_static', path='components/shopping-cart-list/shopping-cart-list.js') }}"></script>
|
<script src="{{ url_for('nostrmarket_static', path='components/shopping-cart-list/shopping-cart-list.js') }}"></script>
|
||||||
|
<script
|
||||||
|
src="{{ url_for('nostrmarket_static', path='components/shopping-cart-checkout/shopping-cart-checkout.js') }}"></script>
|
||||||
<script src="{{ url_for('nostrmarket_static', path='components/chat-dialog/chat-dialog.js') }}"></script>
|
<script src="{{ url_for('nostrmarket_static', path='components/chat-dialog/chat-dialog.js') }}"></script>
|
||||||
<script src="{{ url_for('nostrmarket_static', path='components/market-config/market-config.js') }}"></script>
|
<script src="{{ url_for('nostrmarket_static', path='components/market-config/market-config.js') }}"></script>
|
||||||
<script src="{{ url_for('nostrmarket_static', path='js/market.js') }}"></script>
|
<script src="{{ url_for('nostrmarket_static', path='js/market.js') }}"></script>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue