make partials for readability

This commit is contained in:
Tiago Vasconcelos 2022-12-20 16:44:33 +00:00
parent dd09eac2a5
commit f1f68658d2
4 changed files with 872 additions and 959 deletions

View file

@ -0,0 +1,57 @@
<q-card>
<q-card-section>
<h6 class="text-subtitle1 q-my-none">Messages</h6>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
</q-card-section>
<q-card-section>
<q-select
v-model="customerKey"
:options="Object.keys(messages).map(k => ({label: `${k.slice(0, 25)}...`, value: k}))"
label="Customers"
@input="chatRoom(customerKey)"
emit-value
></q-select>
</q-card-section>
<q-card-section>
<div class="chat-container" ref="chatCard">
<div class="chat-box">
<!-- <p v-if="Object.keys(messages).length === 0">No messages yet</p> -->
<div class="chat-messages">
<q-chat-message
:key="index"
v-for="(message, index) in orderMessages"
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
:text="[message.msg]"
:sent="message.pubkey == keys.pubkey ? true : false"
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
/>
</div>
</div>
<q-card-section>
<q-form @submit="sendMessage" class="full-width chat-input">
<q-input
ref="newMessage"
v-model="newMessage"
placeholder="Message"
class="full-width"
dense
outlined
>
<template>
<q-btn
round
dense
flat
type="submit"
icon="send"
color="primary"
/>
</template>
</q-input>
</q-form>
</q-card-section>
</div>
</q-card-section>
</q-card>

View file

@ -0,0 +1,384 @@
<!-- PRODUCT DIALOG -->
<q-dialog v-model="productDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendProductFormData" class="q-gutter-md">
<q-select
filled
dense
emit-value
v-model="productDialog.data.stall"
:options="stalls.map(s => ({label: s.name, value: s.id}))"
label="Stall"
>
</q-select>
<q-input
filled
dense
v-model.trim="productDialog.data.product"
label="Product"
></q-input>
<q-input
filled
dense
v-model.trim="productDialog.data.description"
label="Description"
></q-input>
<!-- <div class="row"> -->
<!-- <div class="col-5">
<q-select
filled
dense
multiple
v-model.trim="productDialog.data.categories"
:options="categories"
label="Categories"
class="q-pr-sm"
></q-select>
</div> -->
<!-- <div class="col-7"> -->
<q-select
filled
multiple
dense
emit-value
v-model.trim="productDialog.data.categories"
use-input
use-chips
multiple
hide-dropdown-icon
input-debounce="0"
new-value-mode="add-unique"
label="Categories"
placeholder="crafts,robots,etc"
hint="Hit Enter to add"
></q-select>
<!-- </div> -->
<!-- </div> -->
<q-file
class="q-pr-md"
filled
dense
capture="environment"
accept="image/jpeg, image/png"
:max-file-size="3*1024**2"
label="Small image (optional)"
clearable
@input="imageAdded"
@clear="imageCleared"
>
<template v-if="productDialog.data.image" v-slot:before>
<img style="height: 1em" :src="productDialog.data.image" />
</template>
<template v-if="productDialog.data.image" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="imageCleared"
class="cursor-pointer"
/>
</template>
</q-file>
<q-input
filled
dense
v-model.number="productDialog.data.price"
type="number"
label="Price"
></q-input>
<q-input
filled
dense
v-model.number="productDialog.data.quantity"
type="number"
label="Quantity"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="productDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Product</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="productDialog.data.price == null
|| productDialog.data.product == null
|| productDialog.data.description == null
|| productDialog.data.quantity == null"
type="submit"
>Create Product</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('productDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<!-- ZONE DIALOG -->
<q-dialog v-model="zoneDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendZoneFormData" class="q-gutter-md">
<q-select
filled
dense
multiple
:options="shippingZoneOptions"
label="Countries"
v-model.trim="zoneDialog.data.countries"
></q-select>
<q-input
filled
dense
type="number"
v-model.trim="zoneDialog.data.cost"
label="Cost (sats)"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="zoneDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Shipping Zone</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="zoneDialog.data.countries == null
|| zoneDialog.data.cost == null"
type="submit"
>Create Shipping Zone</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('zoneDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<!-- MARKETPLACE/SHOP DIALOG -->
<q-dialog v-model="marketDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendMarketplaceFormData" class="q-gutter-md">
<q-toggle
label="Activate marketplace"
color="primary"
v-model="marketDialog.data.activate"
></q-toggle>
<q-select
filled
dense
multiple
emit-value
:options="stalls.map(s => ({label: s.name, value: s.id}))"
label="Stalls"
v-model.trim="marketDialog.data.stalls"
></q-select>
<q-input
filled
dense
v-model.trim="marketDialog.data.name"
label="Name"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="marketDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Marketplace</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="marketDialog.data.activate == null
|| marketDialog.data.stalls == null"
type="submit"
>Launch Marketplace</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('marketDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<!-- STALL/STORE DIALOG -->
<q-dialog v-model="stallDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendStallFormData" class="q-gutter-md">
<q-input
filled
dense
v-model.trim="stallDialog.data.name"
label="Name"
></q-input>
<q-select
filled
dense
emit-value
v-model="stallDialog.data.wallet"
:options="g.user.walletOptions"
label="Wallet *"
>
</q-select>
<q-input
v-if="diagonalley"
v-if="keys"
filled
dense
v-model.trim="stallDialog.data.publickey"
label="Public Key"
></q-input>
<q-input
v-if="diagonalley"
v-if="keys"
filled
dense
v-model.trim="stallDialog.data.privatekey"
label="Private Key"
></q-input>
<!-- NOSTR -->
<div v-if="diagonalley" class="row">
<div class="col-5">
<q-btn unelevated @click="generateKeys" color="primary"
>Generate keys</q-btn
>
</div>
<div class="col-5">
<q-btn unelevated @click="restoreKeys" color="primary"
>Restore keys</q-btn
>
</div>
</div>
<q-select
:options="zoneOptions"
filled
dense
multiple
v-model.trim="stallDialog.data.shippingzones"
label="Shipping Zones"
></q-select>
<q-select
v-if="diagonalley"
:options="relayOptions"
filled
dense
multiple
v-model.trim="stallDialog.data.relays"
label="Relays"
></q-select>
<q-input
v-if="diagonalley"
filled
dense
v-model.trim="stallDialog.data.crelays"
label="Custom relays (seperate by comma)"
></q-input>
<q-input
v-if="diagonalley"
filled
dense
v-model.trim="stallDialog.data.nostrShops"
label="Nostr shop public keys (seperate by comma)"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="stallDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Stall</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="stallDialog.data.wallet == null
|| stallDialog.data.shippingzones == null"
type="submit"
>Create Stall</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('stallDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<q-dialog v-model="onboarding.show">
<q-card class="q-pa-lg">
<h6 class="q-my-md text-primary">How to use Shop</h6>
<q-stepper v-model="step" color="primary" vertical animated>
<q-step
:name="1"
title="Create a Shipping Zone"
icon="settings"
:done="step > 1"
>
Create Shipping Zones you're willing to ship to. You can define
different values for different zones.
<q-stepper-navigation>
<q-btn @click="step = step + 1" color="primary" label="Next" />
</q-stepper-navigation>
</q-step>
<q-step
:name="2"
title="Create a Stall"
icon="create_new_folder"
:done="step > 2"
>
Create a Stall and provide private and public keys to use for
communication. If you don't have one, LNbits will create a key pair for
you. It will be saved and can be used on other stalls.
<q-stepper-navigation>
<q-btn @click="step = step + 1" color="primary" label="Next" />
</q-stepper-navigation>
</q-step>
<q-step :name="3" title="Create Products" icon="assignment">
Create your products, add a small description and an image. Choose to
what stall, if you have more than one, it belongs to
<q-stepper-navigation>
<q-btn @click="onboarding.finish" color="primary" label="Finish" />
</q-stepper-navigation>
<div>
<q-checkbox v-model="onboarding.showAgain" label="Show this again?" />
</div>
</q-step>
</q-stepper>
</q-card>
</q-dialog>

View file

@ -0,0 +1,428 @@
<q-card>
<!-- ORDERS TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Orders</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportOrdersCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="orders"
row-key="id"
:columns="ordersTable.columns"
:pagination.sync="ordersTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
size="sm"
color="accent"
round
dense
@click="props.expand = !props.expand"
:icon="props.expand ? 'remove' : 'add'"
/>
</q-td>
<q-td auto-width>
<q-btn
size="sm"
color="green"
dense
icon="chat"
@click="chatRoom(props.row.invoiceid)"
>
<q-badge
v-if="props.row.unread"
color="red"
rounded
floating
style="padding: 6px; border-radius: 6px"
/>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="shipOrder(props.row.id)"
icon="add_shopping_cart"
color="green"
>
<q-tooltip> Product shipped? </q-tooltip>
</q-btn>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="deleteOrder(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
<q-tr v-show="props.expand" :props="props">
<q-td colspan="100%">
<template>
<div class="q-pa-md">
<q-list>
<q-item-label header>Order Details</q-item-label>
<q-item v-for="col in props.row.details" :key="col.id">
<q-item-section>
<q-item-label>Products</q-item-label>
<q-item-label caption
>{{ products.length && (_.findWhere(products, {id:
col.product_id})).product }}</q-item-label
>
<q-item-label caption
>Quantity: {{ col.quantity }}</q-item-label
>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>Shipping to</q-item-label>
<q-item-label caption
>{{ props.row.address }}</q-item-label
>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>User info</q-item-label>
<q-item-label caption v-if="props.row.username"
>{{ props.row.username }}</q-item-label
>
<q-item-label caption>{{ props.row.email }}</q-item-label>
<q-item-label caption v-if="props.row.pubkey"
>{{ props.row.pubkey }}</q-item-label
>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>Total</q-item-label>
<q-item-label>{{ props.row.total }}</q-item-label>
<!-- <q-icon name="star" color="yellow" /> -->
</q-item-section>
</q-item>
</q-list>
</div>
</template>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card>
<!-- PRODUCTS TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Products</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportProductsCSV"
>Export to CSV</q-btn
>
</div>
</div>
<q-table
dense
flat
:data="products"
row-key="id"
:columns="productsTable.columns"
:pagination.sync="productsTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
disabled
unelevated
dense
size="xs"
icon="add_shopping_cart"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="props.row.wallet"
target="_blank"
></q-btn>
<q-tooltip> Link to pass to stall relay </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td class="text-center" auto-width>
<img
v-if="props.row.image"
:src="props.row.image"
style="height: 1.5em"
/>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openProductUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteProduct(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card>
<!-- STALLS TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Market Stalls</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportStallsCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="stalls"
row-key="id"
:columns="stallTable.columns"
:pagination.sync="stallTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
unelevated
dense
size="xs"
icon="storefront"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="'/shop/stalls/' + props.row.id"
target="_blank"
></q-btn>
<q-tooltip> Stall simple UI shopping cart </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openStallUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteStall(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card v-if="markets.length">
<!-- MARKETPLACES TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Marketplaces</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportStallsCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="markets"
row-key="id"
:columns="marketTable.columns"
:pagination.sync="marketTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
unelevated
dense
size="xs"
icon="storefront"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="'/shop/market/' + props.row.id"
target="_blank"
></q-btn>
<q-tooltip> Link to pass to stall relay </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openStallUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteStall(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card>
<!-- ZONES TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Shipping Zones</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportZonesCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="zones"
row-key="id"
:columns="zonesTable.columns"
:pagination.sync="zonesTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openZoneUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteZone(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>

View file

@ -1,348 +1,7 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}
<div class="row q-col-gutter-md">
<!-- PRODUCT DIALOG -->
<q-dialog v-model="productDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendProductFormData" class="q-gutter-md">
<q-select
filled
dense
emit-value
v-model="productDialog.data.stall"
:options="stalls.map(s => ({label: s.name, value: s.id}))"
label="Stall"
>
</q-select>
<q-input
filled
dense
v-model.trim="productDialog.data.product"
label="Product"
></q-input>
<q-input
filled
dense
v-model.trim="productDialog.data.description"
label="Description"
></q-input>
<!-- <div class="row"> -->
<!-- <div class="col-5">
<q-select
filled
dense
multiple
v-model.trim="productDialog.data.categories"
:options="categories"
label="Categories"
class="q-pr-sm"
></q-select>
</div> -->
<!-- <div class="col-7"> -->
<q-select
filled
multiple
dense
emit-value
v-model.trim="productDialog.data.categories"
use-input
use-chips
multiple
hide-dropdown-icon
input-debounce="0"
new-value-mode="add-unique"
label="Categories"
placeholder="crafts,robots,etc"
hint="Hit Enter to add"
></q-select>
<!-- </div> -->
<!-- </div> -->
<q-file
class="q-pr-md"
filled
dense
capture="environment"
accept="image/jpeg, image/png"
:max-file-size="3*1024**2"
label="Small image (optional)"
clearable
@input="imageAdded"
@clear="imageCleared"
>
<template v-if="productDialog.data.image" v-slot:before>
<img style="height: 1em" :src="productDialog.data.image" />
</template>
<template v-if="productDialog.data.image" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="imageCleared"
class="cursor-pointer"
/>
</template>
</q-file>
<q-input
filled
dense
v-model.number="productDialog.data.price"
type="number"
label="Price"
></q-input>
<q-input
filled
dense
v-model.number="productDialog.data.quantity"
type="number"
label="Quantity"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="productDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Product</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="productDialog.data.price == null
|| productDialog.data.product == null
|| productDialog.data.description == null
|| productDialog.data.quantity == null"
type="submit"
>Create Product</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('productDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<!-- ZONE DIALOG -->
<q-dialog v-model="zoneDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendZoneFormData" class="q-gutter-md">
<q-select
filled
dense
multiple
:options="shippingZoneOptions"
label="Countries"
v-model.trim="zoneDialog.data.countries"
></q-select>
<q-input
filled
dense
type="number"
v-model.trim="zoneDialog.data.cost"
label="Cost (sats)"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="zoneDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Shipping Zone</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="zoneDialog.data.countries == null
|| zoneDialog.data.cost == null"
type="submit"
>Create Shipping Zone</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('zoneDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<!-- MARKETPLACE/SHOP DIALOG -->
<q-dialog v-model="marketDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendMarketplaceFormData" class="q-gutter-md">
<q-toggle
label="Activate marketplace"
color="primary"
v-model="marketDialog.data.activate"
></q-toggle>
<q-select
filled
dense
multiple
emit-value
:options="stalls.map(s => ({label: s.name, value: s.id}))"
label="Stalls"
v-model.trim="marketDialog.data.stalls"
></q-select>
<q-input
filled
dense
v-model.trim="marketDialog.data.name"
label="Name"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="marketDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Marketplace</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="marketDialog.data.activate == null
|| marketDialog.data.stalls == null"
type="submit"
>Launch Marketplace</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('marketDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
<!-- STALL/STORE DIALOG -->
<q-dialog v-model="stallDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendStallFormData" class="q-gutter-md">
<q-input
filled
dense
v-model.trim="stallDialog.data.name"
label="Name"
></q-input>
<q-select
filled
dense
emit-value
v-model="stallDialog.data.wallet"
:options="g.user.walletOptions"
label="Wallet *"
>
</q-select>
<q-input
v-if="diagonalley"
v-if="keys"
filled
dense
v-model.trim="stallDialog.data.publickey"
label="Public Key"
></q-input>
<q-input
v-if="diagonalley"
v-if="keys"
filled
dense
v-model.trim="stallDialog.data.privatekey"
label="Private Key"
></q-input>
<!-- NOSTR -->
<div v-if="diagonalley" class="row">
<div class="col-5">
<q-btn unelevated @click="generateKeys" color="primary"
>Generate keys</q-btn
>
</div>
<div class="col-5">
<q-btn unelevated @click="restoreKeys" color="primary"
>Restore keys</q-btn
>
</div>
</div>
<q-select
:options="zoneOptions"
filled
dense
multiple
v-model.trim="stallDialog.data.shippingzones"
label="Shipping Zones"
></q-select>
<q-select
v-if="diagonalley"
:options="relayOptions"
filled
dense
multiple
v-model.trim="stallDialog.data.relays"
label="Relays"
></q-select>
<q-input
v-if="diagonalley"
filled
dense
v-model.trim="stallDialog.data.crelays"
label="Custom relays (seperate by comma)"
></q-input>
<q-input
v-if="diagonalley"
filled
dense
v-model.trim="stallDialog.data.nostrShops"
label="Nostr shop public keys (seperate by comma)"
></q-input>
<div class="row q-mt-lg">
<q-btn
v-if="stallDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Stall</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="stallDialog.data.wallet == null
|| stallDialog.data.shippingzones == null"
type="submit"
>Create Stall</q-btn
>
<q-btn
v-close-popup
flat
@click="resetDialog('stallDialog')"
color="grey"
class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card>
</q-dialog>
{% include "shop/_dialogs.html" %}
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<q-card>
<q-card-section>
@ -427,444 +86,7 @@
</q-card-section>
</q-card>
<q-card>
<!-- ORDERS TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Orders</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportOrdersCSV"
>Export to CSV</q-btn
>
</div>
</div>
<q-table
dense
flat
:data="orders"
row-key="id"
:columns="ordersTable.columns"
:pagination.sync="ordersTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
size="sm"
color="accent"
round
dense
@click="props.expand = !props.expand"
:icon="props.expand ? 'remove' : 'add'"
/>
</q-td>
<q-td auto-width>
<q-btn
size="sm"
color="green"
dense
icon="chat"
@click="chatRoom(props.row.invoiceid)"
>
<q-badge
v-if="props.row.unread"
color="red"
rounded
floating
style="padding: 6px; border-radius: 6px"
/>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="shipOrder(props.row.id)"
icon="add_shopping_cart"
color="green"
>
<q-tooltip> Product shipped? </q-tooltip>
</q-btn>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="deleteOrder(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
<q-tr v-show="props.expand" :props="props">
<q-td colspan="100%">
<template>
<div class="q-pa-md">
<q-list>
<q-item-label header>Order Details</q-item-label>
<q-item v-for="col in props.row.details" :key="col.id">
<q-item-section>
<q-item-label>Products</q-item-label>
<q-item-label caption
>{{ products.length && (_.findWhere(products, {id:
col.product_id})).product }}</q-item-label
>
<q-item-label caption
>Quantity: {{ col.quantity }}</q-item-label
>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>Shipping to</q-item-label>
<q-item-label caption
>{{ props.row.address }}</q-item-label
>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>User info</q-item-label>
<q-item-label caption v-if="props.row.username"
>{{ props.row.username }}</q-item-label
>
<q-item-label caption
>{{ props.row.email }}</q-item-label
>
<q-item-label caption v-if="props.row.pubkey"
>{{ props.row.pubkey }}</q-item-label
>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label>Total</q-item-label>
<q-item-label>{{ props.row.total }}</q-item-label>
<!-- <q-icon name="star" color="yellow" /> -->
</q-item-section>
</q-item>
</q-list>
</div>
</template>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card>
<!-- PRODUCTS TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Products</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportProductsCSV"
>Export to CSV</q-btn
>
</div>
</div>
<q-table
dense
flat
:data="products"
row-key="id"
:columns="productsTable.columns"
:pagination.sync="productsTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
disabled
unelevated
dense
size="xs"
icon="add_shopping_cart"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="props.row.wallet"
target="_blank"
></q-btn>
<q-tooltip> Link to pass to stall relay </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td class="text-center" auto-width>
<img
v-if="props.row.image"
:src="props.row.image"
style="height: 1.5em"
/>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openProductUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteProduct(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card>
<!-- STALLS TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Market Stalls</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportStallsCSV"
>Export to CSV</q-btn
>
</div>
</div>
<q-table
dense
flat
:data="stalls"
row-key="id"
:columns="stallTable.columns"
:pagination.sync="stallTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
unelevated
dense
size="xs"
icon="storefront"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="'/shop/stalls/' + props.row.id"
target="_blank"
></q-btn>
<q-tooltip> Stall simple UI shopping cart </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openStallUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteStall(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card v-if="markets.length">
<!-- MARKETPLACES TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Marketplaces</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportStallsCSV"
>Export to CSV</q-btn
>
</div>
</div>
<q-table
dense
flat
:data="markets"
row-key="id"
:columns="marketTable.columns"
:pagination.sync="marketTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
unelevated
dense
size="xs"
icon="storefront"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="'/shop/market/' + props.row.id"
target="_blank"
></q-btn>
<q-tooltip> Link to pass to stall relay </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openStallUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteStall(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
<q-card>
<!-- ZONES TABLE -->
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Shipping Zones</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportZonesCSV"
>Export to CSV</q-btn
>
</div>
</div>
<q-table
dense
flat
:data="zones"
row-key="id"
:columns="zonesTable.columns"
:pagination.sync="zonesTable.pagination"
>
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="openZoneUpdateDialog(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteZone(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
{% include "shop/_tables.html" %}
<!-- KEYS -->
<q-card>
<q-card-section>
@ -926,186 +148,8 @@
</q-card-section>
</q-card>
<!-- CHAT BOX -->
<q-card>
<q-card-section>
<h6 class="text-subtitle1 q-my-none">Messages</h6>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
</q-card-section>
<q-card-section>
<q-select
v-model="customerKey"
:options="Object.keys(messages).map(k => ({label: `${k.slice(0, 25)}...`, value: k}))"
label="Customers"
@input="chatRoom(customerKey)"
emit-value
></q-select>
</q-card-section>
<q-card-section>
<div class="chat-container" ref="chatCard">
<div class="chat-box">
<!-- <p v-if="Object.keys(messages).length === 0">No messages yet</p> -->
<div class="chat-messages">
<q-chat-message
:key="index"
v-for="(message, index) in orderMessages"
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
:text="[message.msg]"
:sent="message.pubkey == keys.pubkey ? true : false"
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
/>
</div>
</div>
<q-card-section>
<q-form @submit="sendMessage" class="full-width chat-input">
<q-input
ref="newMessage"
v-model="newMessage"
placeholder="Message"
class="full-width"
dense
outlined
>
<template>
<q-btn
round
dense
flat
type="submit"
icon="send"
color="primary"
/>
</template>
</q-input>
</q-form>
</q-card-section>
</div>
</q-card-section>
</q-card>
<!-- <q-card>
<q-card-section>
<h6 class="text-subtitle1 q-my-none">Messages</h6>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
<div
ref="chatCard"
class="q-ma-md q-pb-lg"
style="height: 350px"
>
<div class="q-pb-md">
<q-select
v-model="customerKey"
style="width: 80%"
:options="Object.keys(messages)"
label="Customers"
@input="chatRoom(customerKey)"
></q-select>
<div class="chat-container q-pa-md">
<div class="chat-box">
<p v-if="Object.keys(messages).length === 0">No messages yet</p>
<div class="chat-messages">
<q-chat-message
:key="index"
v-for="(message, index) in orderMessages"
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
:text="[message.msg]"
:sent="message.pubkey == keys.pubkey ? true : false"
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
/>
</div>
</div>
<q-form @submit="sendMessage" class="full-width chat-input">
<q-input
ref="newMessage"
v-model="newMessage"
placeholder="Message"
class="full-width"
dense
outlined
>
<template>
<q-btn
round
dense
flat
type="submit"
icon="send"
color="primary"
/>
</template>
</q-input>
</q-form>
</div>
</div>
<div class="col-8 q-px-md">
<div v-for="message in customerMessages">
<q-chat-message
v-if="message[0] == 'out'"
:text="[message[1]]"
sent
></q-chat-message>
<q-chat-message v-else :text="[message[1]]"></q-chat-message>
</div>
</div>
<div class="col on-right" style="width: 90%">
<q-input>
<template v-slot:after>
<q-btn round dense flat icon="send" />
</template>
</q-input>
</div>
</div>
</q-card-section>
</q-card> -->
{% include "shop/_chat_box.html" %}
</div>
<q-dialog v-model="onboarding.show">
<q-card class="q-pa-lg">
<h6 class="q-my-md text-primary">How to use Shop</h6>
<q-stepper v-model="step" color="primary" vertical animated>
<q-step
:name="1"
title="Create a Shipping Zone"
icon="settings"
:done="step > 1"
>
Create Shipping Zones you're willing to ship to. You can define
different values for different zones.
<q-stepper-navigation>
<q-btn @click="step = step + 1" color="primary" label="Next" />
</q-stepper-navigation>
</q-step>
<q-step
:name="2"
title="Create a Stall"
icon="create_new_folder"
:done="step > 2"
>
Create a Stall and provide private and public keys to use for
communication. If you don't have one, LNbits will create a key pair
for you. It will be saved and can be used on other stalls.
<q-stepper-navigation>
<q-btn @click="step = step + 1" color="primary" label="Next" />
</q-stepper-navigation>
</q-step>
<q-step :name="3" title="Create Products" icon="assignment">
Create your products, add a small description and an image. Choose to
what stall, if you have more than one, it belongs to
<q-stepper-navigation>
<q-btn @click="onboarding.finish" color="primary" label="Finish" />
</q-stepper-navigation>
<div>
<q-checkbox
v-model="onboarding.showAgain"
label="Show this again?"
/>
</div>
</q-step>
</q-stepper>
</q-card>
</q-dialog>
</div>
{% endblock %} {% block scripts %} {{ window_vars(user) }}