feat: stuff

This commit is contained in:
Vlad Stan 2023-07-07 14:24:00 +03:00
parent b41e499591
commit 761a3137a6
9 changed files with 221 additions and 21 deletions

View file

@ -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>

View file

@ -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;

View file

@ -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)"

View file

@ -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>

View file

@ -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)
}
})
}

View file

@ -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>

View file

@ -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() { }

View file

@ -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')
} }
} }

View file

@ -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>