forked from verdnatura/hedera-web
#4922 Catalog & fixes
This commit is contained in:
parent
0234e14c6b
commit
6458d8db5e
|
@ -59,5 +59,27 @@ export default {
|
|||
'Nov',
|
||||
'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',
|
||||
'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()
|
||||
|
||||
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
|
||||
|
@ -73,7 +77,9 @@ export class ResultSet {
|
|||
const result = this.fetch()
|
||||
|
||||
if (result !== null &&
|
||||
result.data instanceof Array) { return result.data }
|
||||
result.data instanceof Array) {
|
||||
return result.data
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
@ -104,7 +110,9 @@ export class ResultSet {
|
|||
result.data.length > 0) {
|
||||
const object = result.data[0]
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -179,8 +179,6 @@ export class JsonConnection extends VnObject {
|
|||
}
|
||||
|
||||
if (error) {
|
||||
if (error.exception === 'SessionExpired') { this.clearToken() }
|
||||
|
||||
this.emit('error', error)
|
||||
reject(error)
|
||||
} else { resolve(data) }
|
||||
|
|
|
@ -10,10 +10,24 @@
|
|||
aria-label="Menu"
|
||||
@click="toggleLeftDrawer"/>
|
||||
<q-toolbar-title>
|
||||
Home
|
||||
{{$app.title}}
|
||||
<div
|
||||
v-if="$app.subtitle"
|
||||
class="subtitle text-caption">
|
||||
{{$app.subtitle}}
|
||||
</div>
|
||||
</q-toolbar-title>
|
||||
<div id="actions" ref="actions">
|
||||
</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-header>
|
||||
<q-drawer
|
||||
|
@ -133,6 +147,10 @@
|
|||
.q-page-container > * {
|
||||
padding: 16px;
|
||||
}
|
||||
#actions > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@include mobile {
|
||||
#actions > div {
|
||||
.q-btn {
|
||||
|
|
|
@ -71,4 +71,10 @@ export default {
|
|||
startOrder: Start order
|
||||
es-ES:
|
||||
startOrder: Empezar pedido
|
||||
ca-ES:
|
||||
startOrder: Començar comanda
|
||||
fr-FR:
|
||||
startOrder: Lancer commande
|
||||
pt-PT:
|
||||
startOrder: Comece uma encomenda
|
||||
</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
|
||||
makePayment: Make payment
|
||||
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:
|
||||
startOrder: Empezar pedido
|
||||
noOrdersFound: No se encontrado pedidos
|
||||
makePayment: Realizar pago
|
||||
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>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { route } from 'quasar/wrappers'
|
||||
import { appStore } from 'stores/app'
|
||||
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
|
||||
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)
|
||||
})
|
||||
|
||||
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
|
||||
})
|
||||
|
|
|
@ -42,6 +42,10 @@ const routes = [
|
|||
name: 'invoices',
|
||||
path: '/ecomerce/invoices',
|
||||
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', {
|
||||
state: () => ({
|
||||
imageUrl: ''
|
||||
title: null,
|
||||
subtitle: null,
|
||||
imageUrl: '',
|
||||
useRightDrawer: false,
|
||||
rightDrawerOpen: false
|
||||
}),
|
||||
|
||||
actions: {
|
||||
|
|
|
@ -4,8 +4,8 @@ import { api, jApi } from 'boot/axios'
|
|||
export const userStore = defineStore('user', {
|
||||
state: () => {
|
||||
const token =
|
||||
localStorage.getItem('vnToken') ||
|
||||
sessionStorage.getItem('vnToken')
|
||||
sessionStorage.getItem('vnToken') ||
|
||||
localStorage.getItem('vnToken')
|
||||
|
||||
return {
|
||||
token,
|
||||
|
@ -38,7 +38,9 @@ export const userStore = defineStore('user', {
|
|||
|
||||
async logout () {
|
||||
if (this.token != null) {
|
||||
try {
|
||||
await api.post('Accounts/logout')
|
||||
} catch (e) {}
|
||||
localStorage.removeItem('vnToken')
|
||||
sessionStorage.removeItem('vnToken')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue