forked from verdnatura/hedera-web
#4922 Catalog & fixes
This commit is contained in:
parent
0234e14c6b
commit
6458d8db5e
|
@ -59,5 +59,27 @@ export default {
|
||||||
'Nov',
|
'Nov',
|
||||||
'Dec'
|
'Dec'
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// menu
|
||||||
|
home: 'Home',
|
||||||
|
catalog: 'Catalog',
|
||||||
|
orders: 'Orders',
|
||||||
|
order: 'Pending order',
|
||||||
|
ticket: 'Order',
|
||||||
|
conditions: 'Conditions',
|
||||||
|
about: 'About us',
|
||||||
|
admin: 'Administration',
|
||||||
|
panel: 'Control panel',
|
||||||
|
users: 'Users',
|
||||||
|
connections: 'Connections',
|
||||||
|
visits: 'Visits',
|
||||||
|
news: 'News',
|
||||||
|
newEdit: 'Edit new',
|
||||||
|
images: 'Images',
|
||||||
|
items: 'Items',
|
||||||
|
config: 'Configuration',
|
||||||
|
user: 'User',
|
||||||
|
addresses: 'Addresses',
|
||||||
|
addressEdit: 'Edit address'
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,5 +59,27 @@ export default {
|
||||||
'Nov',
|
'Nov',
|
||||||
'Dic'
|
'Dic'
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
home: 'Inicio',
|
||||||
|
catalog: 'Catálogo',
|
||||||
|
orders: 'Pedidos',
|
||||||
|
order: 'Pedido pendiente',
|
||||||
|
ticket: 'Pedido',
|
||||||
|
conditions: 'Condiciones',
|
||||||
|
about: 'Sobre nosotros',
|
||||||
|
admin: 'Administración',
|
||||||
|
panel: 'Panel de control',
|
||||||
|
users: 'Usuarios',
|
||||||
|
connections: 'Conexiones',
|
||||||
|
visits: 'Visitas',
|
||||||
|
news: 'Noticias',
|
||||||
|
newEdit: 'Editar noticia',
|
||||||
|
images: 'Imágenes',
|
||||||
|
items: 'Artículos',
|
||||||
|
config: 'Configuración',
|
||||||
|
user: 'Usuario',
|
||||||
|
addresses: 'Direcciones',
|
||||||
|
addressEdit: 'Editar dirección'
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,11 @@ export class ResultSet {
|
||||||
const result = this.fetch()
|
const result = this.fetch()
|
||||||
|
|
||||||
if (result !== null) {
|
if (result !== null) {
|
||||||
if (result.data instanceof Array) { return new Result(result) } else { return true }
|
if (result.data instanceof Array) {
|
||||||
|
return new Result(result)
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
@ -73,7 +77,9 @@ export class ResultSet {
|
||||||
const result = this.fetch()
|
const result = this.fetch()
|
||||||
|
|
||||||
if (result !== null &&
|
if (result !== null &&
|
||||||
result.data instanceof Array) { return result.data }
|
result.data instanceof Array) {
|
||||||
|
return result.data
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -104,7 +110,9 @@ export class ResultSet {
|
||||||
result.data.length > 0) {
|
result.data.length > 0) {
|
||||||
const object = result.data[0]
|
const object = result.data[0]
|
||||||
const row = new Array(result.columns.length)
|
const row = new Array(result.columns.length)
|
||||||
for (let i = 0; i < row.length; i++) { row[i] = object[result.columns[i].name] }
|
for (let i = 0; i < row.length; i++) {
|
||||||
|
row[i] = object[result.columns[i].name]
|
||||||
|
}
|
||||||
return row
|
return row
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,8 +179,6 @@ export class JsonConnection extends VnObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error.exception === 'SessionExpired') { this.clearToken() }
|
|
||||||
|
|
||||||
this.emit('error', error)
|
this.emit('error', error)
|
||||||
reject(error)
|
reject(error)
|
||||||
} else { resolve(data) }
|
} else { resolve(data) }
|
||||||
|
|
|
@ -10,10 +10,24 @@
|
||||||
aria-label="Menu"
|
aria-label="Menu"
|
||||||
@click="toggleLeftDrawer"/>
|
@click="toggleLeftDrawer"/>
|
||||||
<q-toolbar-title>
|
<q-toolbar-title>
|
||||||
Home
|
{{$app.title}}
|
||||||
|
<div
|
||||||
|
v-if="$app.subtitle"
|
||||||
|
class="subtitle text-caption">
|
||||||
|
{{$app.subtitle}}
|
||||||
|
</div>
|
||||||
</q-toolbar-title>
|
</q-toolbar-title>
|
||||||
<div id="actions" ref="actions">
|
<div id="actions" ref="actions">
|
||||||
</div>
|
</div>
|
||||||
|
<q-btn
|
||||||
|
v-if="$app.useRightDrawer"
|
||||||
|
@click="$app.rightDrawerOpen = !$app.rightDrawerOpen"
|
||||||
|
aria-label="Menu"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
round>
|
||||||
|
<q-icon name="menu"/>
|
||||||
|
</q-btn>
|
||||||
</q-toolbar>
|
</q-toolbar>
|
||||||
</q-header>
|
</q-header>
|
||||||
<q-drawer
|
<q-drawer
|
||||||
|
@ -133,6 +147,10 @@
|
||||||
.q-page-container > * {
|
.q-page-container > * {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
#actions > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
@include mobile {
|
@include mobile {
|
||||||
#actions > div {
|
#actions > div {
|
||||||
.q-btn {
|
.q-btn {
|
||||||
|
|
|
@ -71,4 +71,10 @@ export default {
|
||||||
startOrder: Start order
|
startOrder: Start order
|
||||||
es-ES:
|
es-ES:
|
||||||
startOrder: Empezar pedido
|
startOrder: Empezar pedido
|
||||||
|
ca-ES:
|
||||||
|
startOrder: Començar comanda
|
||||||
|
fr-FR:
|
||||||
|
startOrder: Lancer commande
|
||||||
|
pt-PT:
|
||||||
|
startOrder: Comece uma encomenda
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -0,0 +1,668 @@
|
||||||
|
<template>
|
||||||
|
<Teleport :to="$actions">
|
||||||
|
<q-input
|
||||||
|
:placeholder="$t('search')"
|
||||||
|
v-model="search"
|
||||||
|
debounce="500"
|
||||||
|
class="search q-mr-sm"
|
||||||
|
rounded
|
||||||
|
dark
|
||||||
|
dense
|
||||||
|
standout>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon
|
||||||
|
v-if="search === ''"
|
||||||
|
name="search"
|
||||||
|
/>
|
||||||
|
<q-icon
|
||||||
|
v-else
|
||||||
|
name="clear"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="search = ''"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
<q-btn
|
||||||
|
:icon="$t(viewMode == 'list' ? 'view_list' : 'grid_on')"
|
||||||
|
:label="$t(viewMode == 'list' ? 'listView' : 'gridView')"
|
||||||
|
@click="onViewModeClick()"
|
||||||
|
rounded
|
||||||
|
no-caps/>
|
||||||
|
</Teleport>
|
||||||
|
<div style="padding-bottom: 5em;">
|
||||||
|
<q-drawer
|
||||||
|
v-model="$app.rightDrawerOpen"
|
||||||
|
side="right"
|
||||||
|
:width="250">
|
||||||
|
<div class="q-pa-md">
|
||||||
|
<div class="basket-info">
|
||||||
|
<p>{{date(new Date())}}</p>
|
||||||
|
<p>
|
||||||
|
{{$t('warehouse')}}
|
||||||
|
{{'Algemesi'}}
|
||||||
|
</p>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
rounded
|
||||||
|
no-caps>
|
||||||
|
{{$t('modify')}}
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
<div class="q-mt-md">
|
||||||
|
<div class="q-mb-xs text-grey-7">
|
||||||
|
{{$t('category')}}
|
||||||
|
<q-icon
|
||||||
|
v-if="category"
|
||||||
|
style="font-size: 1.3em;"
|
||||||
|
name="cancel"
|
||||||
|
class="cursor-pointer"
|
||||||
|
:title="$t('deleteFilter')"
|
||||||
|
@click="$router.push({params: {category: null}})"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="categories">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
class="category q-pa-sm"
|
||||||
|
v-for="cat in categories"
|
||||||
|
:class="{active: category == cat.id}"
|
||||||
|
:key="cat.id"
|
||||||
|
:title="cat.name"
|
||||||
|
:to="{params: {category: cat.id, type: null}}">
|
||||||
|
<img :src="`statics/category/${cat.code}.svg`">
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="q-mt-md"
|
||||||
|
v-if="category || search">
|
||||||
|
<div class="q-mb-xs text-grey-7">
|
||||||
|
{{$t('filterBy')}}
|
||||||
|
</div>
|
||||||
|
<q-select
|
||||||
|
v-model="type"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
:options="types"
|
||||||
|
:disable="!category"
|
||||||
|
clearable
|
||||||
|
:label="$t('family')"
|
||||||
|
@filter="filterType"
|
||||||
|
@input="$router.push({params: {type: type && type.id}})"
|
||||||
|
/>
|
||||||
|
<q-select
|
||||||
|
v-model="order"
|
||||||
|
input-debounce="0"
|
||||||
|
:options="orderOptions"
|
||||||
|
:label="$t('orderBy')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="q-pa-md"
|
||||||
|
v-if="typeId || search">
|
||||||
|
<div class="q-mb-md"
|
||||||
|
v-for="tag in tags"
|
||||||
|
:key="tag.uid">
|
||||||
|
<div class="q-mb-xs text-caption text-grey-7">
|
||||||
|
{{tag.name}}
|
||||||
|
<q-icon
|
||||||
|
v-if="tag.hasFilter"
|
||||||
|
style="font-size: 1.3em;"
|
||||||
|
name="cancel"
|
||||||
|
:title="$t('deleteFilter')"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="onResetTagFilterClick(tag)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="!tag.useRange">
|
||||||
|
<div
|
||||||
|
v-for="value in tag.values.slice(0, tag.showCount)"
|
||||||
|
:key="value">
|
||||||
|
<q-checkbox
|
||||||
|
v-model="tag.filter"
|
||||||
|
:dense="true"
|
||||||
|
:val="value"
|
||||||
|
:label="value"
|
||||||
|
@input="onCheck(tag)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="tag.values.length > tag.showCount">
|
||||||
|
<span
|
||||||
|
class="cursor-pointer text-blue"
|
||||||
|
@click="tag.showCount = Infinity">
|
||||||
|
<q-icon name="keyboard_arrow_down" />
|
||||||
|
{{$t('viewMore')}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="tag.showCount == Infinity">
|
||||||
|
<span
|
||||||
|
class="cursor-pointer text-blue"
|
||||||
|
@click="tag.showCount = tag.initialCount">
|
||||||
|
<q-icon name="keyboard_arrow_up" />
|
||||||
|
{{$t('viewLess')}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="q-mx-md">
|
||||||
|
<q-range
|
||||||
|
class="q-mt-lg"
|
||||||
|
v-if="tag.useRange"
|
||||||
|
v-model="tag.filter"
|
||||||
|
:min="tag.min"
|
||||||
|
:max="tag.max"
|
||||||
|
:step="tag.step"
|
||||||
|
:color="tag.hasFilter ? 'primary' : 'grey-6'"
|
||||||
|
@input="onRangeChange(tag, true)"
|
||||||
|
@change="onRangeChange(tag)"
|
||||||
|
label-always
|
||||||
|
markers
|
||||||
|
snap
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-drawer>
|
||||||
|
<q-infinite-scroll
|
||||||
|
@load="onLoad"
|
||||||
|
scroll-taget="html"
|
||||||
|
:offset="800"
|
||||||
|
:disable="disableScroll">
|
||||||
|
<div class="q-pa-md row justify-center q-gutter-md">
|
||||||
|
<q-spinner
|
||||||
|
v-if="isLoading"
|
||||||
|
color="primary"
|
||||||
|
size="50px">
|
||||||
|
</q-spinner>
|
||||||
|
<div
|
||||||
|
v-if="items && !items.length"
|
||||||
|
class="text-subtitle1 text-grey-7 q-pa-md">
|
||||||
|
{{$t('noItemsFound')}}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="!items && !isLoading"
|
||||||
|
class="text-subtitle1 text-grey-7 q-pa-md">
|
||||||
|
{{$t('pleaseSetFilter')}}
|
||||||
|
</div>
|
||||||
|
<q-card
|
||||||
|
class="my-card"
|
||||||
|
v-for="item in items"
|
||||||
|
:key="item.id">
|
||||||
|
<img :src="`${$imageBase}/catalog/200x200/${item.image}`" />
|
||||||
|
<q-card-section>
|
||||||
|
<div class="name text-subtitle1">
|
||||||
|
{{item.longName}}
|
||||||
|
</div>
|
||||||
|
<div class="sub-name text-uppercase text-subtitle1 text-grey-7 ellipsize q-pt-xs">
|
||||||
|
{{item.subName}}
|
||||||
|
</div>
|
||||||
|
<div class="tags q-pt-xs">
|
||||||
|
<div v-for="tag in item.tags" :key="tag.tagFk">
|
||||||
|
<span class="text-grey-7">{{tag.tag.name}}</span> {{tag.value}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions class="actions justify-between">
|
||||||
|
<div class="q-pl-sm">
|
||||||
|
<span class="available bg-green text-white">{{item.available}}</span>
|
||||||
|
{{$t('from')}}
|
||||||
|
<span class="price">{{currency(item.buy?.price3)}}</span>
|
||||||
|
</div>
|
||||||
|
<q-btn
|
||||||
|
icon="add_shopping_cart"
|
||||||
|
:title="$t('buy')"
|
||||||
|
@click="showItem(item)"
|
||||||
|
flat>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<template v-slot:loading>
|
||||||
|
<div class="row justify-center q-my-md">
|
||||||
|
<q-spinner color="primary" name="dots" size="40px" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-infinite-scroll>
|
||||||
|
<q-dialog v-model="showItemDialog">
|
||||||
|
<q-card style="width: 25em;">
|
||||||
|
<q-img
|
||||||
|
:src="`${$imageBase}/catalog/200x200/${item.image}`"
|
||||||
|
:ratio="5/3">
|
||||||
|
<div class="absolute-bottom text-center q-pa-xs">
|
||||||
|
<div class="text-subtitle1">
|
||||||
|
{{item.longName}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-img>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-uppercase text-subtitle1 text-grey-7 ellipsize">
|
||||||
|
{{item.subName}}
|
||||||
|
</div>
|
||||||
|
<div class="text-grey-7">
|
||||||
|
#{{item.id}}
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<div v-for="tag in item.tags" :key="tag.tagFk">
|
||||||
|
<span class="text-grey-7">{{tag.tag.name}}</span> {{tag.value}}
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn
|
||||||
|
@click="showItemDialog = false"
|
||||||
|
flat>
|
||||||
|
{{$t('cancel')}}
|
||||||
|
</q-btn>
|
||||||
|
<q-btn
|
||||||
|
@click="showItemDialog = false"
|
||||||
|
flat>
|
||||||
|
{{$t('accept')}}
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
<q-page-sticky>
|
||||||
|
<q-btn
|
||||||
|
fab
|
||||||
|
to="/ecomerce/basket"
|
||||||
|
icon="shopping_cart"
|
||||||
|
color="accent"
|
||||||
|
:title="$t('shoppingCart')"/>
|
||||||
|
</q-page-sticky>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search {
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
.basket-info {
|
||||||
|
background-color: #8cc63f;
|
||||||
|
color: white;
|
||||||
|
padding: 17px 28px;
|
||||||
|
border-radius: 7px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
& > p {
|
||||||
|
margin: 0;
|
||||||
|
padding: .4em 0;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.categories {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 220px;
|
||||||
|
|
||||||
|
.category {
|
||||||
|
width: 55px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: rgba(0, 0, 0, .08);
|
||||||
|
}
|
||||||
|
& > img {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tags {
|
||||||
|
max-height: 4.6em;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.available {
|
||||||
|
padding: .15em;
|
||||||
|
border-radius: .2em;
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
.price {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
.my-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 17.5em;
|
||||||
|
height: 32.5em;
|
||||||
|
overflow: hidden;
|
||||||
|
.name, .sub-name {
|
||||||
|
line-height: 1.3em;
|
||||||
|
}
|
||||||
|
.ellipsize {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
height: 40px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { date, currency } from 'src/lib/filters.js'
|
||||||
|
import { date as qdate } from 'quasar'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const CancelToken = axios.CancelToken
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HederaCatalog',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
uid: 0,
|
||||||
|
search: '',
|
||||||
|
orderDate: qdate.formatDate(new Date(), 'YYYY/MM/DD'),
|
||||||
|
category: null,
|
||||||
|
categories: [],
|
||||||
|
type: null,
|
||||||
|
typeId: null,
|
||||||
|
types: [],
|
||||||
|
orgTypes: [],
|
||||||
|
item: {},
|
||||||
|
showItemDialog: false,
|
||||||
|
tags: [],
|
||||||
|
isLoading: false,
|
||||||
|
items: null,
|
||||||
|
limit: null,
|
||||||
|
pageSize: 30,
|
||||||
|
maxTags: 5,
|
||||||
|
disableScroll: true,
|
||||||
|
viewMode: 'list',
|
||||||
|
order: {
|
||||||
|
label: this.$t('relevancy'),
|
||||||
|
value: 'relevancy DESC, longName'
|
||||||
|
},
|
||||||
|
orderOptions: [
|
||||||
|
{
|
||||||
|
label: this.$t('relevancy'),
|
||||||
|
value: 'relevancy DESC, longName'
|
||||||
|
}, {
|
||||||
|
label: this.$t('name'),
|
||||||
|
value: 'longName'
|
||||||
|
}, {
|
||||||
|
label: this.$t('siceAsc'),
|
||||||
|
value: 'size ASC'
|
||||||
|
}, {
|
||||||
|
label: this.$t('sizeDesc'),
|
||||||
|
value: 'size DESC'
|
||||||
|
}, {
|
||||||
|
label: this.$t('priceAsc'),
|
||||||
|
value: 'price ASC'
|
||||||
|
}, {
|
||||||
|
label: this.$t('priceDesc'),
|
||||||
|
value: 'price DESC'
|
||||||
|
}, {
|
||||||
|
label: this.$t('available'),
|
||||||
|
value: 'available'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$app.useRightDrawer = true
|
||||||
|
},
|
||||||
|
async mounted () {
|
||||||
|
this.categories = await this.$jApi.query(
|
||||||
|
`SELECT c.id, l.name, c.color, c.code
|
||||||
|
FROM vn.itemCategory c
|
||||||
|
JOIN vn.itemCategoryL10n l ON l.id = c.id
|
||||||
|
WHERE c.display
|
||||||
|
ORDER BY display`
|
||||||
|
)
|
||||||
|
this.onRouteChange(this.$route)
|
||||||
|
},
|
||||||
|
beforeUnmount () {
|
||||||
|
this.clearTimeoutAndRequest()
|
||||||
|
},
|
||||||
|
beforeRouteUpdate (to, from, next) {
|
||||||
|
this.onRouteChange(to)
|
||||||
|
next()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
categories () {
|
||||||
|
this.refreshTitle()
|
||||||
|
},
|
||||||
|
orgTypes () {
|
||||||
|
this.refreshTitle()
|
||||||
|
},
|
||||||
|
order () {
|
||||||
|
this.loadItems()
|
||||||
|
},
|
||||||
|
date () {
|
||||||
|
this.loadItems()
|
||||||
|
},
|
||||||
|
async category (value) {
|
||||||
|
this.orgTypes = []
|
||||||
|
if (!value) return
|
||||||
|
|
||||||
|
const res = await this.$jApi.execQuery(
|
||||||
|
`CALL myBasket_getAvailable;
|
||||||
|
SELECT DISTINCT t.id, l.name
|
||||||
|
FROM vn.item i
|
||||||
|
JOIN vn.itemType t ON t.id = i.typeFk
|
||||||
|
JOIN tmp.itemAvailable a ON a.id = i.id
|
||||||
|
JOIN vn.itemTypeL10n l ON l.id = t.id
|
||||||
|
WHERE t.\`order\` >= 0
|
||||||
|
AND t.categoryFk = #category
|
||||||
|
ORDER BY t.\`order\`, l.name;
|
||||||
|
DROP TEMPORARY TABLE tmp.itemAvailable;`,
|
||||||
|
{ category: value }
|
||||||
|
)
|
||||||
|
res.fetch()
|
||||||
|
this.orgTypes = res.fetchData()
|
||||||
|
},
|
||||||
|
search (value) {
|
||||||
|
const location = { params: this.$route.params }
|
||||||
|
if (value) location.query = { search: value }
|
||||||
|
this.$router.push(location)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
date,
|
||||||
|
currency,
|
||||||
|
onViewModeClick () {
|
||||||
|
this.viewMode = this.viewMode === 'list' ? 'grid' : 'list'
|
||||||
|
},
|
||||||
|
onRouteChange (route) {
|
||||||
|
let { category, type } = route.params
|
||||||
|
|
||||||
|
category = parseInt(category) || null
|
||||||
|
type = parseInt(type) || null
|
||||||
|
|
||||||
|
this.category = category
|
||||||
|
this.typeId = category ? type : null
|
||||||
|
this.search = route.query.search || ''
|
||||||
|
this.tags = []
|
||||||
|
|
||||||
|
this.refreshTitle()
|
||||||
|
this.loadItems()
|
||||||
|
},
|
||||||
|
refreshTitle () {
|
||||||
|
let title = this.$t(this.$router.currentRoute.value.name)
|
||||||
|
let subtitle
|
||||||
|
|
||||||
|
if (this.category) {
|
||||||
|
const category = this.categories.find(i => i.id === this.category) || {}
|
||||||
|
title = category.name
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.typeId) {
|
||||||
|
this.type = this.orgTypes.find(i => i.id === this.typeId)
|
||||||
|
subtitle = title
|
||||||
|
title = this.type && this.type.name
|
||||||
|
} else {
|
||||||
|
this.type = null
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$app.$patch({ title, subtitle })
|
||||||
|
},
|
||||||
|
clearTimeoutAndRequest () {
|
||||||
|
if (this.timeout) {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
this.timeout = null
|
||||||
|
}
|
||||||
|
if (this.source) {
|
||||||
|
this.source.cancel()
|
||||||
|
this.source = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadItemsDelayed () {
|
||||||
|
this.clearTimeoutAndRequest()
|
||||||
|
this.timeout = setTimeout(() => this.loadItems(), 500)
|
||||||
|
},
|
||||||
|
loadItems () {
|
||||||
|
this.items = null
|
||||||
|
this.isLoading = true
|
||||||
|
this.limit = this.pageSize
|
||||||
|
this.disableScroll = false
|
||||||
|
this.isLoading = false
|
||||||
|
// this.loadItemsBase().finally(() => (this.isLoading = false))
|
||||||
|
},
|
||||||
|
onLoad (index, done) {
|
||||||
|
if (this.isLoading) return done()
|
||||||
|
this.limit += this.pageSize
|
||||||
|
done()
|
||||||
|
// this.loadItemsBase().finally(done)
|
||||||
|
},
|
||||||
|
loadItemsBase () {
|
||||||
|
this.clearTimeoutAndRequest()
|
||||||
|
|
||||||
|
if (!(this.category || this.typeId || this.search)) {
|
||||||
|
this.tags = []
|
||||||
|
return Promise.resolve(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagFilter = []
|
||||||
|
|
||||||
|
for (const tag of this.tags) {
|
||||||
|
if (tag.hasFilter) {
|
||||||
|
tagFilter.push({
|
||||||
|
tagFk: tag.id,
|
||||||
|
values: tag.filter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.source = CancelToken.source()
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
dated: this.orderDate,
|
||||||
|
typeFk: this.typeId,
|
||||||
|
categoryFk: this.category,
|
||||||
|
search: this.search,
|
||||||
|
order: this.order.value,
|
||||||
|
limit: this.limit,
|
||||||
|
tagFilter
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
params,
|
||||||
|
cancelToken: this.source.token
|
||||||
|
}
|
||||||
|
return this.$axios.get('Items/catalog', config)
|
||||||
|
.then(res => this.onItemsGet(res))
|
||||||
|
.catch(err => this.onItemsError(err))
|
||||||
|
.finally(() => (this.cancel = null))
|
||||||
|
},
|
||||||
|
onItemsError (err) {
|
||||||
|
if (err.__CANCEL__) return
|
||||||
|
this.disableScroll = true
|
||||||
|
throw err
|
||||||
|
},
|
||||||
|
onItemsGet (res) {
|
||||||
|
for (const tag of res.data.tags) {
|
||||||
|
tag.uid = this.uid++
|
||||||
|
|
||||||
|
if (tag.filter) {
|
||||||
|
tag.hasFilter = true
|
||||||
|
tag.useRange =
|
||||||
|
tag.filter.max ||
|
||||||
|
tag.filter.min
|
||||||
|
} else {
|
||||||
|
tag.useRange = tag.isQuantitative &&
|
||||||
|
tag.values.length > this.maxTags
|
||||||
|
this.resetTagFilter(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.values) {
|
||||||
|
tag.initialCount = this.maxTags
|
||||||
|
if (Array.isArray(tag.filter)) {
|
||||||
|
tag.initialCount = Math.max(tag.initialCount, tag.filter.length)
|
||||||
|
}
|
||||||
|
tag.showCount = tag.initialCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.items = res.data.items
|
||||||
|
this.tags = res.data.tags
|
||||||
|
this.disableScroll = this.items.length < this.limit
|
||||||
|
},
|
||||||
|
onRangeChange (tag, delay) {
|
||||||
|
tag.hasFilter = true
|
||||||
|
|
||||||
|
if (!delay) this.loadItems()
|
||||||
|
else this.loadItemsDelayed()
|
||||||
|
},
|
||||||
|
onCheck (tag) {
|
||||||
|
tag.hasFilter = tag.filter.length > 0
|
||||||
|
this.loadItems()
|
||||||
|
},
|
||||||
|
resetTagFilter (tag) {
|
||||||
|
tag.hasFilter = false
|
||||||
|
|
||||||
|
if (tag.useRange) {
|
||||||
|
tag.filter = {
|
||||||
|
min: tag.min,
|
||||||
|
max: tag.max
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tag.filter = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onResetTagFilterClick (tag) {
|
||||||
|
this.resetTagFilter(tag)
|
||||||
|
this.loadItems()
|
||||||
|
},
|
||||||
|
filterType (val, update) {
|
||||||
|
if (val === '') {
|
||||||
|
update(() => { this.types = this.orgTypes })
|
||||||
|
} else {
|
||||||
|
update(() => {
|
||||||
|
const needle = val.toLowerCase()
|
||||||
|
this.types = this.orgTypes.filter(type =>
|
||||||
|
type.name.toLowerCase().indexOf(needle) > -1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showItem (item) {
|
||||||
|
this.item = item
|
||||||
|
this.showItemDialog = true
|
||||||
|
|
||||||
|
const conf = this.$state.catalogConfig
|
||||||
|
const params = {
|
||||||
|
dated: this.orderDate,
|
||||||
|
addressFk: conf.addressFk,
|
||||||
|
agencyModeFk: conf.agencyModeFk
|
||||||
|
}
|
||||||
|
this.$axios.get(`Items/${item.id}/calcCatalog`, { params })
|
||||||
|
.then(res => (this.lots = res.data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
es-ES:
|
||||||
|
gridView: Vista de rejilla
|
||||||
|
listView: Vista de lista
|
||||||
|
shoppingCart: Cesta de la compra
|
||||||
|
warehouse: Almacén
|
||||||
|
agency: Agencia
|
||||||
|
modify: Modificar
|
||||||
|
category: Categoría
|
||||||
|
deleteFilter: Quitar filtro
|
||||||
|
filterBy: Filtrar por
|
||||||
|
family: Familia
|
||||||
|
orderBy: Ordernar por
|
||||||
|
pleaseSetFilter: Elige un filtro en el menú de la derecha
|
||||||
|
search: Buscar
|
||||||
|
</i18n>
|
|
@ -144,9 +144,58 @@ export default {
|
||||||
noOrdersFound: No orders found
|
noOrdersFound: No orders found
|
||||||
makePayment: Make payment
|
makePayment: Make payment
|
||||||
shoppingCart: Shopping cart
|
shoppingCart: Shopping cart
|
||||||
|
balance: 'Balance:'
|
||||||
|
paymentInfo: >-
|
||||||
|
The amount shown is your slope (negative) or favorable balance today, it
|
||||||
|
disregards future orders. For get your order shipped, this amount must be
|
||||||
|
equal to or greater than 0. If you want to make a down payment, click the
|
||||||
|
payment button, delete the suggested amount and enter the amount you want.
|
||||||
es-ES:
|
es-ES:
|
||||||
startOrder: Empezar pedido
|
startOrder: Empezar pedido
|
||||||
noOrdersFound: No se encontrado pedidos
|
noOrdersFound: No se encontrado pedidos
|
||||||
makePayment: Realizar pago
|
makePayment: Realizar pago
|
||||||
shoppingCart: Cesta de la compra
|
shoppingCart: Cesta de la compra
|
||||||
|
balance: 'Saldo:'
|
||||||
|
paymentInfo: >-
|
||||||
|
La cantidad mostrada es tu saldo pendiente (negativa) o favorable a día de
|
||||||
|
hoy, no tiene en cuenta pedidos del futuro. Para que tu pedido sea enviado,
|
||||||
|
esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
|
||||||
|
cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
|
||||||
|
cantidad que desees.
|
||||||
|
ca-ES:
|
||||||
|
startOrder: Començar encàrrec
|
||||||
|
noOrdersFound: No s'han trobat comandes
|
||||||
|
makePayment: Realitzar pagament
|
||||||
|
shoppingCart: Cistella de la compra
|
||||||
|
balance: 'Saldo:'
|
||||||
|
paymentInfo: >-
|
||||||
|
La quantitat mostrada és el teu saldo pendent (negatiu) o favorable a dia
|
||||||
|
d'avui, no té en compte comandes del futur. Perquè la teva comanda sigui
|
||||||
|
enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
|
||||||
|
lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
|
||||||
|
e introdueix la quantitat que vulguis.
|
||||||
|
fr-FR:
|
||||||
|
startOrder: Acheter
|
||||||
|
noOrdersFound: Aucune commande trouvée
|
||||||
|
makePayment: Effectuer un paiement
|
||||||
|
shoppingCart: Panier
|
||||||
|
balance: 'Balance:'
|
||||||
|
paymentInfo: >-
|
||||||
|
Le montant indiqué est votre pente (négative) ou balance favorable
|
||||||
|
aujourd'hui, ne tient pas compte pour les commandes futures. Obtenir votre
|
||||||
|
commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
|
||||||
|
voulez faire un versement, le montant suggéré effacé et entrez le montant que
|
||||||
|
vous souhaitez.
|
||||||
|
pt-PT:
|
||||||
|
startOrder: Iniciar encomenda
|
||||||
|
noOrdersFound: Nenhum pedido encontrado
|
||||||
|
makePayment: Realizar pagamento
|
||||||
|
shoppingCart: Cesta da compra
|
||||||
|
balance: 'Saldo:'
|
||||||
|
paymentInfo: >-
|
||||||
|
A quantidade mostrada é seu saldo pendente (negativo) ou favorável a dia de
|
||||||
|
hoje, não se vincula a pedidos futuros. Para que seu pedido seja enviado, esta
|
||||||
|
quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
|
||||||
|
conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
|
||||||
|
a quantidade que deseje.
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { route } from 'quasar/wrappers'
|
import { route } from 'quasar/wrappers'
|
||||||
|
import { appStore } from 'stores/app'
|
||||||
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
|
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
|
||||||
import routes from './routes'
|
import routes from './routes'
|
||||||
|
|
||||||
|
@ -26,5 +27,16 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE)
|
history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Router.afterEach((to, from) => {
|
||||||
|
if (from.name === to.name) return
|
||||||
|
const app = appStore()
|
||||||
|
app.$patch({
|
||||||
|
title: window.i18n.t(to.name || 'home'),
|
||||||
|
subtitle: null,
|
||||||
|
useRightDrawer: false,
|
||||||
|
rightDrawerOpen: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
return Router
|
return Router
|
||||||
})
|
})
|
||||||
|
|
|
@ -42,6 +42,10 @@ const routes = [
|
||||||
name: 'invoices',
|
name: 'invoices',
|
||||||
path: '/ecomerce/invoices',
|
path: '/ecomerce/invoices',
|
||||||
component: () => import('pages/Ecomerce/Invoices.vue')
|
component: () => import('pages/Ecomerce/Invoices.vue')
|
||||||
|
}, {
|
||||||
|
name: 'catalog',
|
||||||
|
path: '/ecomerce/catalog/:category?/:type?',
|
||||||
|
component: () => import('pages/Ecomerce/Catalog.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,11 @@ import { jApi } from 'boot/axios'
|
||||||
|
|
||||||
export const appStore = defineStore('hedera', {
|
export const appStore = defineStore('hedera', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
imageUrl: ''
|
title: null,
|
||||||
|
subtitle: null,
|
||||||
|
imageUrl: '',
|
||||||
|
useRightDrawer: false,
|
||||||
|
rightDrawerOpen: false
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { api, jApi } from 'boot/axios'
|
||||||
export const userStore = defineStore('user', {
|
export const userStore = defineStore('user', {
|
||||||
state: () => {
|
state: () => {
|
||||||
const token =
|
const token =
|
||||||
localStorage.getItem('vnToken') ||
|
sessionStorage.getItem('vnToken') ||
|
||||||
sessionStorage.getItem('vnToken')
|
localStorage.getItem('vnToken')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
|
@ -38,7 +38,9 @@ export const userStore = defineStore('user', {
|
||||||
|
|
||||||
async logout () {
|
async logout () {
|
||||||
if (this.token != null) {
|
if (this.token != null) {
|
||||||
|
try {
|
||||||
await api.post('Accounts/logout')
|
await api.post('Accounts/logout')
|
||||||
|
} catch (e) {}
|
||||||
localStorage.removeItem('vnToken')
|
localStorage.removeItem('vnToken')
|
||||||
sessionStorage.removeItem('vnToken')
|
sessionStorage.removeItem('vnToken')
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue