forked from verdnatura/hedera-web
Merge pull request 'Vistas sección pedidos' (!77) from wbuezas/hedera-web-mindshore:feature/Pedidos into 4922-vueMigration
Reviewed-on: verdnatura/hedera-web#77 Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
This commit is contained in:
commit
5053a908f7
|
@ -24,7 +24,7 @@ module.exports = configure(function (ctx) {
|
||||||
// app boot file (/src/boot)
|
// app boot file (/src/boot)
|
||||||
// --> boot files are part of "main.js"
|
// --> boot files are part of "main.js"
|
||||||
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
|
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
|
||||||
boot: ['i18n', 'axios', 'error-handler', 'app'],
|
boot: ['i18n', 'axios', 'vnDate', 'error-handler', 'app'],
|
||||||
|
|
||||||
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
|
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
|
||||||
css: ['app.scss', 'width.scss', 'responsive.scss'],
|
css: ['app.scss', 'width.scss', 'responsive.scss'],
|
||||||
|
@ -67,7 +67,7 @@ module.exports = configure(function (ctx) {
|
||||||
// https://v2.quasar.dev/quasar-cli-webpack/handling-webpack
|
// https://v2.quasar.dev/quasar-cli-webpack/handling-webpack
|
||||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||||
|
|
||||||
chainWebpack(chain) {
|
chainWebpack (chain) {
|
||||||
chain
|
chain
|
||||||
.plugin('eslint-webpack-plugin')
|
.plugin('eslint-webpack-plugin')
|
||||||
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
||||||
|
@ -143,7 +143,7 @@ module.exports = configure(function (ctx) {
|
||||||
maxAge: 1000 * 60 * 60 * 24 * 30,
|
maxAge: 1000 * 60 * 60 * 24 * 30,
|
||||||
// Tell browser when a file from the server should expire from cache (in ms)
|
// Tell browser when a file from the server should expire from cache (in ms)
|
||||||
|
|
||||||
chainWebpackWebserver(chain) {
|
chainWebpackWebserver (chain) {
|
||||||
chain
|
chain
|
||||||
.plugin('eslint-webpack-plugin')
|
.plugin('eslint-webpack-plugin')
|
||||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||||
|
@ -163,7 +163,7 @@ module.exports = configure(function (ctx) {
|
||||||
// for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts])
|
// for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts])
|
||||||
// if using workbox in InjectManifest mode
|
// if using workbox in InjectManifest mode
|
||||||
|
|
||||||
chainWebpackCustomSW(chain) {
|
chainWebpackCustomSW (chain) {
|
||||||
chain
|
chain
|
||||||
.plugin('eslint-webpack-plugin')
|
.plugin('eslint-webpack-plugin')
|
||||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||||
|
@ -240,13 +240,13 @@ module.exports = configure(function (ctx) {
|
||||||
|
|
||||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||||
|
|
||||||
chainWebpackMain(chain) {
|
chainWebpackMain (chain) {
|
||||||
chain
|
chain
|
||||||
.plugin('eslint-webpack-plugin')
|
.plugin('eslint-webpack-plugin')
|
||||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||||
},
|
},
|
||||||
|
|
||||||
chainWebpackPreload(chain) {
|
chainWebpackPreload (chain) {
|
||||||
chain
|
chain
|
||||||
.plugin('eslint-webpack-plugin')
|
.plugin('eslint-webpack-plugin')
|
||||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||||
|
|
16
src/App.vue
16
src/App.vue
|
@ -1,11 +1,11 @@
|
||||||
|
<script setup>
|
||||||
|
import { useAppStore } from 'stores/app';
|
||||||
|
import { onBeforeMount } from 'vue';
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
onBeforeMount(() => appStore.init());
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<router-view />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'App'
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { boot } from 'quasar/wrappers'
|
import { boot } from 'quasar/wrappers';
|
||||||
import { appStore } from 'stores/app'
|
import { useAppStore } from 'stores/app';
|
||||||
import { userStore } from 'stores/user'
|
import { userStore } from 'stores/user';
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
export default boot(({ app }) => {
|
||||||
const props = app.config.globalProperties
|
const props = app.config.globalProperties;
|
||||||
props.$app = appStore()
|
props.$app = useAppStore();
|
||||||
props.$user = userStore()
|
props.$user = userStore();
|
||||||
props.$actions = document.createElement('div')
|
props.$actions = document.createElement('div');
|
||||||
})
|
});
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { boot } from 'quasar/wrappers';
|
||||||
|
|
||||||
|
export default boot(() => {
|
||||||
|
Date.vnUTC = () => {
|
||||||
|
const env = process.env.NODE_ENV;
|
||||||
|
if (!env || env === 'development') {
|
||||||
|
return new Date(Date.UTC(2001, 0, 1, 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Date();
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.vnNew = () => {
|
||||||
|
return new Date(Date.vnUTC());
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.vnNow = () => {
|
||||||
|
return new Date(Date.vnUTC()).getTime();
|
||||||
|
};
|
||||||
|
});
|
|
@ -184,7 +184,6 @@ defineExpose({
|
||||||
v-if="!loading"
|
v-if="!loading"
|
||||||
ref="addressFormRef"
|
ref="addressFormRef"
|
||||||
class="column full-width q-gutter-y-xs"
|
class="column full-width q-gutter-y-xs"
|
||||||
@submit="submit()"
|
|
||||||
>
|
>
|
||||||
<span class="text-h6 text-bold">
|
<span class="text-h6 text-bold">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -197,7 +196,7 @@ defineExpose({
|
||||||
:class="{ 'q-mt-md': showBottomActions }"
|
:class="{ 'q-mt-md': showBottomActions }"
|
||||||
>
|
>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="defaultActions"
|
v-if="defaultActions && showBottomActions"
|
||||||
:label="t('cancel')"
|
:label="t('cancel')"
|
||||||
:icon="showBottomActions ? undefined : 'check'"
|
:icon="showBottomActions ? undefined : 'check'"
|
||||||
rounded
|
rounded
|
||||||
|
@ -208,12 +207,12 @@ defineExpose({
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="defaultActions"
|
v-if="defaultActions"
|
||||||
:label="t('save')"
|
:label="t('save')"
|
||||||
type="submit"
|
|
||||||
:icon="showBottomActions ? undefined : 'check'"
|
:icon="showBottomActions ? undefined : 'check'"
|
||||||
rounded
|
rounded
|
||||||
no-caps
|
no-caps
|
||||||
flat
|
flat
|
||||||
:disabled="!showBottomActions && !updatedColumns.length"
|
:disabled="!showBottomActions && !updatedColumns.length"
|
||||||
|
@click="submit()"
|
||||||
/>
|
/>
|
||||||
<slot name="actions" />
|
<slot name="actions" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -9,7 +9,7 @@ const emit = defineEmits([
|
||||||
'remove'
|
'remove'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const $props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [String, Number],
|
type: [String, Number],
|
||||||
default: null
|
default: null
|
||||||
|
@ -33,7 +33,7 @@ const requiredFieldRule = val => !!val || t('globals.fieldRequired');
|
||||||
const vnInputRef = ref(null);
|
const vnInputRef = ref(null);
|
||||||
const value = computed({
|
const value = computed({
|
||||||
get() {
|
get() {
|
||||||
return $props.modelValue;
|
return props.modelValue;
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
emit('update:modelValue', value);
|
emit('update:modelValue', value);
|
||||||
|
@ -41,7 +41,7 @@ const value = computed({
|
||||||
});
|
});
|
||||||
const hover = ref(false);
|
const hover = ref(false);
|
||||||
const styleAttrs = computed(() => {
|
const styleAttrs = computed(() => {
|
||||||
return $props.isOutlined
|
return props.isOutlined
|
||||||
? { dense: true, outlined: true, rounded: true }
|
? { dense: true, outlined: true, rounded: true }
|
||||||
: {};
|
: {};
|
||||||
});
|
});
|
||||||
|
@ -88,9 +88,7 @@ const inputRules = [
|
||||||
<template #append>
|
<template #append>
|
||||||
<slot v-if="$slots.append && !$attrs.disabled" name="append" />
|
<slot v-if="$slots.append && !$attrs.disabled" name="append" />
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="
|
v-if="hover && value && !$attrs.disabled && props.clearable"
|
||||||
hover && value && !$attrs.disabled && $props.clearable
|
|
||||||
"
|
|
||||||
name="close"
|
name="close"
|
||||||
size="xs"
|
size="xs"
|
||||||
@click="
|
@click="
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
clickable: { type: Boolean, default: true },
|
||||||
|
rounded: { type: Boolean, default: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['click']);
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
if (props.clickable) {
|
||||||
|
emit('click');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QItem
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-ripple="clickable"
|
||||||
|
:clickable="clickable"
|
||||||
|
class="full-width row items-center justify-between card no-border-radius bg-white"
|
||||||
|
:class="{ 'cursor-pointer': clickable, 'no-radius': !rounded }"
|
||||||
|
@click="handleClick()"
|
||||||
|
>
|
||||||
|
<QItemSection class="no-padding">
|
||||||
|
<div class="row no-wrap">
|
||||||
|
<slot name="prepend" />
|
||||||
|
<div class="column full-width">
|
||||||
|
<slot name="content" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection class="no-padding" side>
|
||||||
|
<slot name="actions" />
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
border-bottom: 1px solid $gray-light;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,152 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { currency, formatDateTitle } from 'src/lib/filters.js';
|
||||||
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
ticket: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const lineDiscountSubtotal = line => {
|
||||||
|
return line.quantity * line.price;
|
||||||
|
};
|
||||||
|
|
||||||
|
const lineSubtotal = line =>
|
||||||
|
lineDiscountSubtotal(line) * ((100 - line.discount) / 100);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QCard class="vn-w-sm" style="padding: 32px">
|
||||||
|
<QCardSection class="no-padding q-mb-md">
|
||||||
|
<div class="text-h6">#{{ ticket.id }}</div>
|
||||||
|
</QCardSection>
|
||||||
|
<QCardSection class="no-padding q-mb-md q-gutter-y-xs">
|
||||||
|
<div class="text-subtitle1 text-bold">
|
||||||
|
{{ t('shippingInformation') }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('preparation') }}
|
||||||
|
{{ formatDateTitle(ticket.shipped) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('delivery') }}
|
||||||
|
{{ formatDateTitle(ticket.landed) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
|
||||||
|
{{ ticket.agency }}
|
||||||
|
</div>
|
||||||
|
</QCardSection>
|
||||||
|
<QCardSection class="no-padding q-mb-md q-gutter-y-xs">
|
||||||
|
<div class="text-subtitle1 text-bold">
|
||||||
|
{{ t('deliveryAddress') }}
|
||||||
|
</div>
|
||||||
|
<div>{{ ticket.nickname }}</div>
|
||||||
|
<div>{{ ticket.street }}</div>
|
||||||
|
<div>
|
||||||
|
{{ ticket.postalCode }} {{ ticket.city }} ({{
|
||||||
|
ticket.province
|
||||||
|
}})
|
||||||
|
</div>
|
||||||
|
</QCardSection>
|
||||||
|
<QCardSection
|
||||||
|
class="no-padding q-mb-md text-subtitle1 text-bold column"
|
||||||
|
>
|
||||||
|
<span class="text-right">
|
||||||
|
{{ t('total') }} {{ currency(ticket.taxBase) }}
|
||||||
|
</span>
|
||||||
|
<span class="text-right">
|
||||||
|
{{ t('totalTax') }} {{ currency(ticket.total) }}
|
||||||
|
</span>
|
||||||
|
</QCardSection>
|
||||||
|
<QSeparator inset />
|
||||||
|
<QList v-for="row in rows" :key="row.itemFk">
|
||||||
|
<QItem>
|
||||||
|
<QItemSection avatar>
|
||||||
|
<VnImg
|
||||||
|
storage="catalog"
|
||||||
|
size="200x200"
|
||||||
|
:id="row.image"
|
||||||
|
rounded
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel lines="1">
|
||||||
|
{{ row.concept }}
|
||||||
|
</QItemLabel>
|
||||||
|
<QItemLabel lines="1" caption>
|
||||||
|
{{ row.value5 }} {{ row.value6 }} {{ row.value7 }}
|
||||||
|
</QItemLabel>
|
||||||
|
<QItemLabel lines="1">
|
||||||
|
{{ row.quantity }} x {{ currency(row.price) }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection side class="total">
|
||||||
|
<QItemLabel>
|
||||||
|
<span class="discount" v-if="row.discount">
|
||||||
|
{{ currency(lineDiscountSubtotal(row)) }} -
|
||||||
|
{{ currency(row.discount) }} =
|
||||||
|
</span>
|
||||||
|
{{ currency(lineSubtotal(row)) }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</QList>
|
||||||
|
</QCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
shippingInformation: Shipping Information
|
||||||
|
preparation: Preparation
|
||||||
|
delivery: Delivery
|
||||||
|
agency: Agency
|
||||||
|
warehouse: Store
|
||||||
|
deliveryAddress: Delivery address
|
||||||
|
total: Total
|
||||||
|
totalTax: Total + IVA
|
||||||
|
es-ES:
|
||||||
|
shippingInformation: Datos de envío
|
||||||
|
preparation: Preparación
|
||||||
|
delivery: Entrega
|
||||||
|
agency: Agencia
|
||||||
|
warehouse: Almacén
|
||||||
|
deliveryAddress: Dirección de entrega
|
||||||
|
total: Total
|
||||||
|
totalTax: Total + IVA
|
||||||
|
ca-ES:
|
||||||
|
shippingInformation: Dades d'enviament
|
||||||
|
preparation: Preparació
|
||||||
|
delivery: Lliurament
|
||||||
|
agency: Agència
|
||||||
|
warehouse: Magatzem
|
||||||
|
deliveryAddress: Adreça de lliurament
|
||||||
|
total: Total
|
||||||
|
totalTax: Total + IVA
|
||||||
|
fr-FR:
|
||||||
|
shippingInformation: Informations sur la livraison
|
||||||
|
preparation: Préparation
|
||||||
|
delivery: Livraison
|
||||||
|
warehouse: Entrepôt
|
||||||
|
deliveryAddress: Adresse de livraison
|
||||||
|
total: Total
|
||||||
|
totalTax: Total + IVA
|
||||||
|
pt-PT:
|
||||||
|
shippingInformation: Dados de envio
|
||||||
|
preparation: Preparação
|
||||||
|
delivery: Entrega
|
||||||
|
agency: Agência
|
||||||
|
warehouse: Armazém
|
||||||
|
deliveryAddress: Endereço de entrega
|
||||||
|
total: Total
|
||||||
|
totalTax: Total + IVA
|
||||||
|
</i18n>
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { appStore } from 'stores/app';
|
import { useAppStore } from 'stores/app';
|
||||||
|
|
||||||
const $props = defineProps({
|
const props = defineProps({
|
||||||
baseURL: {
|
baseURL: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
|
@ -23,23 +23,27 @@ const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
rounded: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const app = appStore();
|
const app = useAppStore();
|
||||||
const show = ref(false);
|
const show = ref(false);
|
||||||
const url = computed(() => {
|
const url = computed(() => {
|
||||||
return `${$props.baseURL ?? app.imageUrl}/${$props.storage}/${$props.size}/${$props.id}`;
|
return `${props.baseURL ?? app.imageUrl}/${props.storage}/${props.size}/${props.id}`;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<QImg
|
<QImg
|
||||||
:class="{ zoomIn: $props.zoomSize }"
|
:class="{ zoomIn: props.zoomSize, rounded: props.rounded }"
|
||||||
:src="url"
|
:src="url"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
@click="show = !show"
|
@click="show = !show"
|
||||||
spinner-color="primary"
|
spinner-color="primary"
|
||||||
/>
|
/>
|
||||||
<QDialog v-model="show" v-if="$props.zoomSize">
|
<QDialog v-model="show" v-if="props.zoomSize">
|
||||||
<QImg
|
<QImg
|
||||||
:src="url"
|
:src="url"
|
||||||
size="full"
|
size="full"
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
noDataLabel: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
hideBottom: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
rowsPerPageOptions: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [0]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QTable
|
||||||
|
v-bind="$attrs"
|
||||||
|
:no-data-label="props.noDataLabel || t('noInvoicesFound')"
|
||||||
|
:hide-bottom="props.hideBottom"
|
||||||
|
:rows-per-page-options="props.rowsPerPageOptions"
|
||||||
|
table-header-class="vntable-header-default"
|
||||||
|
>
|
||||||
|
<template v-for="(_, slotName) in $slots" v-slot:[slotName]="slotProps">
|
||||||
|
<slot :name="slotName" v-bind="slotProps" />
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.vntable-header-default {
|
||||||
|
background-color: $accent !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { userStore as useUserStore } from 'stores/user';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
|
||||||
|
export function usePrintService() {
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const token = userStore.token;
|
||||||
|
|
||||||
|
function sendEmail(path, params) {
|
||||||
|
return axios.post(path, params).then(() =>
|
||||||
|
quasar.notify({
|
||||||
|
message: 'Notification sent',
|
||||||
|
type: 'positive',
|
||||||
|
icon: 'check'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openReport(path, params) {
|
||||||
|
params = Object.assign(
|
||||||
|
{
|
||||||
|
access_token: token
|
||||||
|
},
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
|
const query = new URLSearchParams(params).toString();
|
||||||
|
|
||||||
|
window.open(`api/${path}?${query}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sendEmail,
|
||||||
|
openReport
|
||||||
|
};
|
||||||
|
}
|
|
@ -36,3 +36,9 @@ a.link {
|
||||||
.q-page-sticky.fixed-bottom-right {
|
.q-page-sticky.fixed-bottom-right {
|
||||||
margin: 18px;
|
margin: 18px;
|
||||||
}
|
}
|
||||||
|
.no-border-radius {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
.no-padding {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
$primary: #1a1a1a;
|
$primary: #1a1a1a;
|
||||||
$secondary: #26a69a;
|
$secondary: #26a69a;
|
||||||
$accent: #8cc63f;
|
$accent: #8cc63f;
|
||||||
|
$gray-light: #ddd;
|
||||||
$dark: #1d1d1d;
|
$dark: #1d1d1d;
|
||||||
$dark-page: #121212;
|
$dark-page: #121212;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
export default {
|
||||||
|
date: {
|
||||||
|
days: [
|
||||||
|
'Diumenge',
|
||||||
|
'Dilluns',
|
||||||
|
'Dimarts',
|
||||||
|
'Dimecres',
|
||||||
|
'Dijous',
|
||||||
|
'Divendres',
|
||||||
|
'Dissabte'
|
||||||
|
],
|
||||||
|
daysShort: ['Dg', 'Dl', 'Dt', 'Dc', 'Dj', 'Dv', 'Ds'],
|
||||||
|
months: [
|
||||||
|
'Gener',
|
||||||
|
'Febrer',
|
||||||
|
'Març',
|
||||||
|
'Abril',
|
||||||
|
'Maig',
|
||||||
|
'Juny',
|
||||||
|
'Juliol',
|
||||||
|
'Agost',
|
||||||
|
'Setembre',
|
||||||
|
'Octubre',
|
||||||
|
'Novembre',
|
||||||
|
'Desembre'
|
||||||
|
],
|
||||||
|
monthsShort: [
|
||||||
|
'Gen',
|
||||||
|
'Feb',
|
||||||
|
'Mar',
|
||||||
|
'Abr',
|
||||||
|
'Mai',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Ago',
|
||||||
|
'Set',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Des'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
of: 'de',
|
||||||
|
// Menu
|
||||||
|
home: 'Inici',
|
||||||
|
catalog: 'Catàleg',
|
||||||
|
pendingOrders: 'Comandes pendents',
|
||||||
|
confirmedOrders: 'Comandes confirmades',
|
||||||
|
invoices: 'Factures',
|
||||||
|
agencyPackages: 'Paquets per agència',
|
||||||
|
accountConfig: 'Configuració',
|
||||||
|
addressesList: 'Adreces',
|
||||||
|
addressDetails: 'Configuració',
|
||||||
|
checkout: 'Configurar encàrrec',
|
||||||
|
//
|
||||||
|
orderLoadedIntoBasket: 'Comanda carregada a la cistella!'
|
||||||
|
};
|
|
@ -37,7 +37,7 @@ export default {
|
||||||
'November',
|
'November',
|
||||||
'December'
|
'December'
|
||||||
],
|
],
|
||||||
shortMonths: [
|
monthsShort: [
|
||||||
'Jan',
|
'Jan',
|
||||||
'Feb',
|
'Feb',
|
||||||
'Mar',
|
'Mar',
|
||||||
|
@ -56,6 +56,17 @@ export default {
|
||||||
// menu
|
// menu
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
catalog: 'Catalog',
|
catalog: 'Catalog',
|
||||||
|
pendingOrders: 'Pending orders',
|
||||||
|
confirmedOrders: 'Confirmed orders',
|
||||||
|
invoices: 'Invoices',
|
||||||
|
agencyPackages: 'Bundles by agency',
|
||||||
|
accountConfig: 'Configuration',
|
||||||
|
addressesList: 'Addresses',
|
||||||
|
addressDetails: 'Configuration',
|
||||||
|
checkout: 'Configure order',
|
||||||
|
//
|
||||||
|
orderLoadedIntoBasket: 'Order loaded into basket!',
|
||||||
|
|
||||||
orders: 'Orders',
|
orders: 'Orders',
|
||||||
order: 'Pending order',
|
order: 'Pending order',
|
||||||
ticket: 'Order',
|
ticket: 'Order',
|
||||||
|
@ -76,5 +87,6 @@ export default {
|
||||||
addressEdit: 'Edit address',
|
addressEdit: 'Edit address',
|
||||||
dataSaved: 'Data saved',
|
dataSaved: 'Data saved',
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
cancel: 'Cancel'
|
cancel: 'Cancel',
|
||||||
|
of: 'of'
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,7 +46,7 @@ export default {
|
||||||
'Noviembre',
|
'Noviembre',
|
||||||
'Diciembre'
|
'Diciembre'
|
||||||
],
|
],
|
||||||
shortMonths: [
|
monthsShort: [
|
||||||
'Ene',
|
'Ene',
|
||||||
'Feb',
|
'Feb',
|
||||||
'Mar',
|
'Mar',
|
||||||
|
@ -65,6 +65,17 @@ export default {
|
||||||
// Menu
|
// Menu
|
||||||
home: 'Inicio',
|
home: 'Inicio',
|
||||||
catalog: 'Catálogo',
|
catalog: 'Catálogo',
|
||||||
|
pendingOrders: 'Pedidos pendientes',
|
||||||
|
confirmedOrders: 'Pedidos confirmados',
|
||||||
|
invoices: 'Facturas',
|
||||||
|
agencyPackages: 'Bultos por agencia',
|
||||||
|
accountConfig: 'Configuración',
|
||||||
|
addressesList: 'Direcciones',
|
||||||
|
addressDetails: 'Configuración',
|
||||||
|
checkout: 'Configurar pedido',
|
||||||
|
//
|
||||||
|
orderLoadedIntoBasket: '¡Pedido cargado en la cesta!',
|
||||||
|
|
||||||
orders: 'Pedidos',
|
orders: 'Pedidos',
|
||||||
order: 'Pedido pendiente',
|
order: 'Pedido pendiente',
|
||||||
ticket: 'Pedido',
|
ticket: 'Pedido',
|
||||||
|
@ -94,5 +105,6 @@ export default {
|
||||||
addressEdit: 'Editar dirección',
|
addressEdit: 'Editar dirección',
|
||||||
dataSaved: 'Datos guardados',
|
dataSaved: 'Datos guardados',
|
||||||
save: 'Guardar',
|
save: 'Guardar',
|
||||||
cancel: 'Cancelar'
|
cancel: 'Cancelar',
|
||||||
|
of: 'de'
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
export default {
|
||||||
|
date: {
|
||||||
|
days: [
|
||||||
|
'Dimanche',
|
||||||
|
'Lundi',
|
||||||
|
'Mardi',
|
||||||
|
'Mercredi',
|
||||||
|
'Jeudi',
|
||||||
|
'Vendredi',
|
||||||
|
'Samedi'
|
||||||
|
],
|
||||||
|
daysShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
|
||||||
|
months: [
|
||||||
|
'Janvier',
|
||||||
|
'Février',
|
||||||
|
'Mars',
|
||||||
|
'Avril',
|
||||||
|
'Mai',
|
||||||
|
'Juin',
|
||||||
|
'Juillet',
|
||||||
|
'Août',
|
||||||
|
'Septembre',
|
||||||
|
'Octobre',
|
||||||
|
'Novembre',
|
||||||
|
'Décembre'
|
||||||
|
],
|
||||||
|
monthsShort: [
|
||||||
|
'Jan',
|
||||||
|
'Fév',
|
||||||
|
'Mar',
|
||||||
|
'Avr',
|
||||||
|
'Mai',
|
||||||
|
'Juin',
|
||||||
|
'Juil',
|
||||||
|
'Aoû',
|
||||||
|
'Sep',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Déc'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
of: 'de',
|
||||||
|
// Menu
|
||||||
|
home: 'Accueil',
|
||||||
|
catalog: 'Catalogue',
|
||||||
|
pendingOrders: 'Commandes en attente',
|
||||||
|
confirmedOrders: 'Commandes confirmées',
|
||||||
|
invoices: 'Factures',
|
||||||
|
agencyPackages: 'Liste par agence',
|
||||||
|
accountConfig: 'Configuration',
|
||||||
|
addressesList: 'Adresses',
|
||||||
|
addressDetails: 'Configuration',
|
||||||
|
checkout: "Définissez l'ordre",
|
||||||
|
//
|
||||||
|
orderLoadedIntoBasket: 'Commande chargée dans le panier!'
|
||||||
|
};
|
|
@ -1,7 +1,13 @@
|
||||||
import enUS from './en-US'
|
import enUS from './en-US';
|
||||||
import esES from './es-ES'
|
import esES from './es-ES';
|
||||||
|
import frFR from './fr-FR';
|
||||||
|
import ptPT from './pt-PT';
|
||||||
|
import caES from './ca-ES';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'en-US': enUS,
|
'en-US': enUS,
|
||||||
'es-ES': esES
|
'es-ES': esES,
|
||||||
}
|
'fr-FR': frFR,
|
||||||
|
'pt-PT': ptPT,
|
||||||
|
'ca-ES': caES
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
export default {
|
||||||
|
date: {
|
||||||
|
days: [
|
||||||
|
'Domingo',
|
||||||
|
'Segunda-feira',
|
||||||
|
'Terça-feira',
|
||||||
|
'Quarta-feira',
|
||||||
|
'Quinta-feira',
|
||||||
|
'Sexta-feira',
|
||||||
|
'Sábado'
|
||||||
|
],
|
||||||
|
daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
|
||||||
|
months: [
|
||||||
|
'Janeiro',
|
||||||
|
'Fevereiro',
|
||||||
|
'Março',
|
||||||
|
'Abril',
|
||||||
|
'Maio',
|
||||||
|
'Junho',
|
||||||
|
'Julho',
|
||||||
|
'Agosto',
|
||||||
|
'Setembro',
|
||||||
|
'Outubro',
|
||||||
|
'Novembro',
|
||||||
|
'Dezembro'
|
||||||
|
],
|
||||||
|
monthsShort: [
|
||||||
|
'Jan',
|
||||||
|
'Fev',
|
||||||
|
'Mar',
|
||||||
|
'Abr',
|
||||||
|
'Mai',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Ago',
|
||||||
|
'Set',
|
||||||
|
'Out',
|
||||||
|
'Nov',
|
||||||
|
'Dez'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
of: 'de',
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
home: 'Principio',
|
||||||
|
catalog: 'Catálogo',
|
||||||
|
pendingOrders: 'Pedidos pendentes',
|
||||||
|
confirmedOrders: 'Pedidos confirmados',
|
||||||
|
invoices: 'Facturas',
|
||||||
|
agencyPackages: 'Bultos por agencia',
|
||||||
|
accountConfig: 'Configuração',
|
||||||
|
addressesList: 'Moradas',
|
||||||
|
addressDetails: 'Configuração',
|
||||||
|
checkout: 'Configurar encomenda',
|
||||||
|
//
|
||||||
|
orderLoadedIntoBasket: 'Pedido carregado na cesta!'
|
||||||
|
};
|
|
@ -1,73 +1,114 @@
|
||||||
import { date as qdate, format } from 'quasar'
|
import { i18n } from 'src/boot/i18n';
|
||||||
const { pad } = format
|
import { date as qdate, format } from 'quasar';
|
||||||
|
const { pad } = format;
|
||||||
|
|
||||||
export function currency (val) {
|
export function currency(val) {
|
||||||
return typeof val === 'number' ? val.toFixed(2) + '€' : val
|
return typeof val === 'number' ? val.toFixed(2) + '€' : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function date (val, format) {
|
export function date(val, format) {
|
||||||
if (val == null) return val
|
if (val == null) return val;
|
||||||
if (!(val instanceof Date)) {
|
if (!(val instanceof Date)) {
|
||||||
val = new Date(val)
|
val = new Date(val);
|
||||||
}
|
}
|
||||||
return qdate.formatDate(val, format, window.i18n.tm('date'))
|
return qdate.formatDate(val, format, i18n.global.tm('date'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function relDate (val) {
|
export const formatDate = (timeStamp, format = 'YYYY-MM-DD') => {
|
||||||
if (val == null) return val
|
if (!timeStamp) return '';
|
||||||
|
const { messages, locale } = i18n.global;
|
||||||
|
|
||||||
|
return qdate.formatDate(timeStamp, format, {
|
||||||
|
days: messages.value[locale.value].date.days,
|
||||||
|
months: messages.value[locale.value].date.months,
|
||||||
|
daysShort: messages.value[locale.value].date.daysShort,
|
||||||
|
monthsShort: messages.value[locale.value].date.monthsShort
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Date} timeStamp - La marca de tiempo que se va a formatear. Si no se proporciona, la función devolverá una cadena vacía.
|
||||||
|
* @param {Object} options - Un objeto que contiene las opciones de formato.
|
||||||
|
* @param {boolean} options.showTime - Indica si se debe mostrar la hora en el formato de la fecha.
|
||||||
|
* @param {boolean} options.showSeconds - Indica si se deben mostrar los segundos en el formato de la hora. Solo se aplica si showTime es true.
|
||||||
|
* @param {boolean} options.shortDay - Indica si se debe usar una versión corta del día (por ejemplo, "Mon" en lugar de "Monday").
|
||||||
|
* @returns {string} La fecha formateada como un título.
|
||||||
|
*/
|
||||||
|
export const formatDateTitle = (
|
||||||
|
timeStamp,
|
||||||
|
options = { showTime: false, showSeconds: false, shortDay: false }
|
||||||
|
) => {
|
||||||
|
if (!timeStamp) return '';
|
||||||
|
const { t } = i18n.global;
|
||||||
|
|
||||||
|
const timeFormat = options.showTime
|
||||||
|
? options.showSeconds
|
||||||
|
? ` [${t('at')}] hh:mm:ss`
|
||||||
|
: ` [${t('at')}] hh:mm`
|
||||||
|
: '';
|
||||||
|
const day = options.shortDay ? 'dd' : 'dddd';
|
||||||
|
|
||||||
|
const formatString = `${day}, D [${t('of')}] MMMM [${t('of')}] YYYY${timeFormat}`;
|
||||||
|
|
||||||
|
const formattedString = formatDate(timeStamp, formatString);
|
||||||
|
return formattedString;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function relDate(val) {
|
||||||
|
if (val == null) return val;
|
||||||
if (!(val instanceof Date)) {
|
if (!(val instanceof Date)) {
|
||||||
val = new Date(val)
|
val = new Date(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dif = qdate.getDateDiff(new Date(), val, 'days')
|
const dif = qdate.getDateDiff(new Date(), val, 'days');
|
||||||
let day
|
let day;
|
||||||
|
|
||||||
switch (dif) {
|
switch (dif) {
|
||||||
case 0:
|
case 0:
|
||||||
day = 'today'
|
day = 'today';
|
||||||
break
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
day = 'yesterday'
|
day = 'yesterday';
|
||||||
break
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
day = 'tomorrow'
|
day = 'tomorrow';
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (day) {
|
if (day) {
|
||||||
day = window.i18n.t(day)
|
day = i18n.global.t(day);
|
||||||
} else {
|
} else {
|
||||||
if (dif > 0 && dif <= 7) {
|
if (dif > 0 && dif <= 7) {
|
||||||
day = qdate.formatDate(val, 'ddd', window.i18n.tm('date'))
|
day = qdate.formatDate(val, 'ddd', i18n.global.tm('date'));
|
||||||
} else {
|
} else {
|
||||||
day = qdate.formatDate(val, 'ddd, MMMM Do', window.i18n.tm('date'))
|
day = qdate.formatDate(val, 'ddd, MMMM Do', i18n.global.tm('date'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return day
|
return day;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function relTime (val) {
|
export function relTime(val) {
|
||||||
if (val == null) return val
|
if (val == null) return val;
|
||||||
if (!(val instanceof Date)) {
|
if (!(val instanceof Date)) {
|
||||||
val = new Date(val)
|
val = new Date(val);
|
||||||
}
|
}
|
||||||
return relDate(val) + ' ' + qdate.formatDate(val, 'H:mm:ss')
|
return relDate(val) + ' ' + qdate.formatDate(val, 'H:mm:ss');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function elapsedTime (val) {
|
export function elapsedTime(val) {
|
||||||
if (val == null) return val
|
if (val == null) return val;
|
||||||
if (!(val instanceof Date)) {
|
if (!(val instanceof Date)) {
|
||||||
val = new Date(val)
|
val = new Date(val);
|
||||||
}
|
}
|
||||||
const now = new Date().getTime()
|
const now = new Date().getTime();
|
||||||
val = Math.floor((now - val.getTime()) / 1000)
|
val = Math.floor((now - val.getTime()) / 1000);
|
||||||
|
|
||||||
const hours = Math.floor(val / 3600)
|
const hours = Math.floor(val / 3600);
|
||||||
val -= hours * 3600
|
val -= hours * 3600;
|
||||||
const minutes = Math.floor(val / 60)
|
const minutes = Math.floor(val / 60);
|
||||||
val -= minutes * 60
|
val -= minutes * 60;
|
||||||
const seconds = val
|
const seconds = val;
|
||||||
|
|
||||||
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)}`
|
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ onMounted(() => fetchLanguagesSql());
|
||||||
icon="location_on"
|
icon="location_on"
|
||||||
rounded
|
rounded
|
||||||
no-caps
|
no-caps
|
||||||
:to="{ name: 'AddressesList' }"
|
:to="{ name: 'addressesList' }"
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('changePassword')"
|
:label="t('changePassword')"
|
||||||
|
|
|
@ -32,7 +32,7 @@ watch(
|
||||||
async val => await getProvinces(val)
|
async val => await getProvinces(val)
|
||||||
);
|
);
|
||||||
|
|
||||||
const goBack = () => router.push({ name: 'AddressesList' });
|
const goBack = () => router.push({ name: 'addressesList' });
|
||||||
|
|
||||||
const getCountries = async () => {
|
const getCountries = async () => {
|
||||||
countriesOptions.value = await jApi.query(
|
countriesOptions.value = await jApi.query(
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { ref, onMounted, inject } from 'vue';
|
import { ref, onMounted, inject } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import CardList from 'src/components/ui/CardList.vue';
|
||||||
|
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
||||||
|
|
||||||
|
@ -17,7 +19,7 @@ const defaultAddress = ref(null);
|
||||||
const clientId = ref(null);
|
const clientId = ref(null);
|
||||||
|
|
||||||
const goToAddressDetails = (id = 0) =>
|
const goToAddressDetails = (id = 0) =>
|
||||||
router.push({ name: 'AddressDetails', params: { id } });
|
router.push({ name: 'addressDetails', params: { id } });
|
||||||
|
|
||||||
const getDefaultAddress = async () => {
|
const getDefaultAddress = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -93,42 +95,33 @@ onMounted(async () => {
|
||||||
no-caps
|
no-caps
|
||||||
/>
|
/>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<QPage class="column items-center">
|
<QPage class="vn-w-sm">
|
||||||
<QList
|
<QList class="rounded-borders shadow-1 shadow-transition" separator>
|
||||||
class="full-width rounded-borders shadow-1 shadow-transition"
|
<CardList
|
||||||
style="max-width: 544px"
|
|
||||||
separator
|
|
||||||
>
|
|
||||||
<QItem
|
|
||||||
v-for="(address, index) in addresses"
|
v-for="(address, index) in addresses"
|
||||||
:key="index"
|
:key="index"
|
||||||
clickable
|
:rounded="false"
|
||||||
v-ripple
|
|
||||||
tag="label"
|
tag="label"
|
||||||
class="full-width row items-center justify-between address-item"
|
|
||||||
style="padding: 20px"
|
|
||||||
>
|
>
|
||||||
<QItemSection>
|
<template #prepend>
|
||||||
<div class="row">
|
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="defaultAddress"
|
v-model="defaultAddress"
|
||||||
:val="address.id"
|
:val="address.id"
|
||||||
class="q-mr-sm"
|
class="q-mr-sm"
|
||||||
@update:model-value="changeDefaultAddress"
|
@update:model-value="changeDefaultAddress"
|
||||||
/>
|
/>
|
||||||
<div>
|
</template>
|
||||||
<QItemLabel class="text-bold q-mb-sm">
|
<template #content>
|
||||||
|
<span class="text-bold q-mb-sm">
|
||||||
{{ address.nickname }}
|
{{ address.nickname }}
|
||||||
</QItemLabel>
|
</span>
|
||||||
<QItemLabel>{{ address.street }}</QItemLabel>
|
<span>{{ address.street }}</span>
|
||||||
<QItemLabel>
|
<span>
|
||||||
{{ address.postalCode }},
|
{{ address.postalCode }},
|
||||||
{{ address.city }}
|
{{ address.city }}
|
||||||
</QItemLabel>
|
</span>
|
||||||
</div>
|
</template>
|
||||||
</div>
|
<template #actions>
|
||||||
</QItemSection>
|
|
||||||
<QItemSection class="actions-wrapper" side>
|
|
||||||
<QBtn
|
<QBtn
|
||||||
icon="delete"
|
icon="delete"
|
||||||
flat
|
flat
|
||||||
|
@ -147,25 +140,12 @@ onMounted(async () => {
|
||||||
rounded
|
rounded
|
||||||
@click.stop="goToAddressDetails(address.id)"
|
@click.stop="goToAddressDetails(address.id)"
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</template>
|
||||||
</QItem>
|
</CardList>
|
||||||
</QList>
|
</QList>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.address-item {
|
|
||||||
.actions-wrapper {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
.actions-wrapper {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<i18n lang="yaml">
|
<i18n lang="yaml">
|
||||||
en-US:
|
en-US:
|
||||||
addAddress: Add address
|
addAddress: Add address
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
import { ref, inject, onMounted, computed } from 'vue';
|
import { ref, inject, onMounted, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import VnTable from 'src/components/ui/VnTable.vue';
|
||||||
|
|
||||||
const jApi = inject('jApi');
|
const jApi = inject('jApi');
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -53,32 +55,15 @@ onMounted(() => getPackages());
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QPage class="flex justify-center q-pa-md">
|
<QPage class="flex justify-center q-pa-md">
|
||||||
<QTable
|
<VnTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="packages"
|
:rows="packages"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
class="q-mt-lg"
|
style="height: max-content; max-width: 100%"
|
||||||
style="max-width: 100%; height: max-content"
|
/>
|
||||||
table-header-class="packages-table-header"
|
|
||||||
hide-bottom
|
|
||||||
>
|
|
||||||
<template #body-cell-id="{ row }">
|
|
||||||
<QTd auto-width @click.stop>
|
|
||||||
<QBtn flat color="blue">{{ row.id }}</QBtn>
|
|
||||||
<ItemDescriptorProxy :id="row.id" />
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.packages-table-header {
|
|
||||||
background-color: $accent !important;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<i18n lang="yaml">
|
<i18n lang="yaml">
|
||||||
en-US:
|
en-US:
|
||||||
agency: Agency
|
agency: Agency
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<template>Basket view</template>
|
|
@ -343,19 +343,23 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { date, currency } from 'src/lib/filters.js';
|
import { date, currency, formatDate } from 'src/lib/filters.js';
|
||||||
import { date as qdate } from 'quasar';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { useAppStore } from 'stores/app';
|
||||||
|
|
||||||
const CancelToken = axios.CancelToken;
|
const CancelToken = axios.CancelToken;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HederaCatalog',
|
name: 'HederaCatalog',
|
||||||
|
setup() {
|
||||||
|
const appStore = useAppStore();
|
||||||
|
return { appStore };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
uid: 0,
|
uid: 0,
|
||||||
search: '',
|
search: '',
|
||||||
orderDate: qdate.formatDate(new Date(), 'YYYY/MM/DD'),
|
orderDate: formatDate(new Date(), 'YYYY/MM/DD'),
|
||||||
category: null,
|
category: null,
|
||||||
categories: [],
|
categories: [],
|
||||||
type: null,
|
type: null,
|
||||||
|
@ -446,7 +450,7 @@ export default {
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
|
|
||||||
const res = await this.$jApi.execQuery(
|
const res = await this.$jApi.execQuery(
|
||||||
`CALL myBasket_getAvailable;
|
`CALL myOrder_getAvailable(${this.appStore.basketOrderId});
|
||||||
SELECT DISTINCT t.id, l.name
|
SELECT DISTINCT t.id, l.name
|
||||||
FROM vn.item i
|
FROM vn.item i
|
||||||
JOIN vn.itemType t ON t.id = i.typeFk
|
JOIN vn.itemType t ON t.id = i.typeFk
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<template>Checkout</template>
|
|
@ -1,183 +0,0 @@
|
||||||
<template>
|
|
||||||
<Teleport :to="$actions">
|
|
||||||
<QSelect
|
|
||||||
v-model="year"
|
|
||||||
:options="years"
|
|
||||||
color="white"
|
|
||||||
dark
|
|
||||||
standout
|
|
||||||
dense
|
|
||||||
rounded
|
|
||||||
/>
|
|
||||||
</Teleport>
|
|
||||||
<div class="vn-w-sm">
|
|
||||||
<div
|
|
||||||
v-if="!invoices?.length"
|
|
||||||
class="text-subtitle1 text-center text-grey-7 q-pa-md"
|
|
||||||
>
|
|
||||||
{{ $t('noInvoicesFound') }}
|
|
||||||
</div>
|
|
||||||
<QCard v-if="invoices?.length">
|
|
||||||
<QTable
|
|
||||||
:columns="columns"
|
|
||||||
:pagination="pagination"
|
|
||||||
:rows="invoices"
|
|
||||||
row-key="id"
|
|
||||||
hide-header
|
|
||||||
hide-bottom
|
|
||||||
>
|
|
||||||
<template v-slot:body="props">
|
|
||||||
<QTr :props="props">
|
|
||||||
<QTd key="ref" :props="props">
|
|
||||||
{{ props.row.ref }}
|
|
||||||
</QTd>
|
|
||||||
<QTd key="issued" :props="props">
|
|
||||||
{{ date(props.row.issued, 'ddd, MMMM Do') }}
|
|
||||||
</QTd>
|
|
||||||
<QTd key="amount" :props="props">
|
|
||||||
{{ currency(props.row.amount) }}
|
|
||||||
</QTd>
|
|
||||||
<QTd key="hasPdf" :props="props">
|
|
||||||
<QBtn
|
|
||||||
v-if="props.row.hasPdf"
|
|
||||||
icon="download"
|
|
||||||
:title="$t('downloadInvoicePdf')"
|
|
||||||
:href="invoiceUrl(props.row.id)"
|
|
||||||
target="_blank"
|
|
||||||
flat
|
|
||||||
round
|
|
||||||
/>
|
|
||||||
<QIcon
|
|
||||||
v-else
|
|
||||||
name="warning"
|
|
||||||
:title="$t('notDownloadable')"
|
|
||||||
color="warning"
|
|
||||||
size="24px"
|
|
||||||
/>
|
|
||||||
</QTd>
|
|
||||||
</QTr>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</QCard>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { date, currency } from 'src/lib/filters.js';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'OrdersPendingIndex',
|
|
||||||
data() {
|
|
||||||
const curYear = new Date().getFullYear();
|
|
||||||
const years = [];
|
|
||||||
|
|
||||||
for (let year = curYear - 5; year <= curYear; year++) {
|
|
||||||
years.push(year);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
columns: [
|
|
||||||
{ name: 'ref', label: 'serial', field: 'ref', align: 'left' },
|
|
||||||
{
|
|
||||||
name: 'issued',
|
|
||||||
label: 'issued',
|
|
||||||
field: 'issued',
|
|
||||||
align: 'left'
|
|
||||||
},
|
|
||||||
{ name: 'amount', label: 'amount', field: 'amount' },
|
|
||||||
{
|
|
||||||
name: 'hasPdf',
|
|
||||||
label: 'download',
|
|
||||||
field: 'hasPdf',
|
|
||||||
align: 'center'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
pagination: {
|
|
||||||
rowsPerPage: 0
|
|
||||||
},
|
|
||||||
year: curYear,
|
|
||||||
years,
|
|
||||||
invoices: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
async mounted() {
|
|
||||||
await this.loadData();
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
async year() {
|
|
||||||
await this.loadData();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
date,
|
|
||||||
currency,
|
|
||||||
|
|
||||||
async loadData() {
|
|
||||||
const params = {
|
|
||||||
from: new Date(this.year, 0),
|
|
||||||
to: new Date(this.year, 11, 31, 23, 59, 59)
|
|
||||||
};
|
|
||||||
this._invoices = await this.$jApi.query(
|
|
||||||
`SELECT id, ref, issued, amount, hasPdf
|
|
||||||
FROM myInvoice
|
|
||||||
WHERE issued BETWEEN #from AND #to
|
|
||||||
ORDER BY issued DESC
|
|
||||||
LIMIT 500`,
|
|
||||||
params
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
invoiceUrl(id) {
|
|
||||||
return (
|
|
||||||
'?' +
|
|
||||||
new URLSearchParams({
|
|
||||||
srv: 'rest:dms/invoice',
|
|
||||||
invoice: id,
|
|
||||||
access_token: this.$user.token
|
|
||||||
}).toString()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<i18n lang="yaml">
|
|
||||||
en-US:
|
|
||||||
noInvoicesFound: No invoices found
|
|
||||||
serial: Serial
|
|
||||||
issued: Date
|
|
||||||
amount: Import
|
|
||||||
downloadInvoicePdf: Download invoice PDF
|
|
||||||
notDownloadable: Not available for download, request the invoice to your salesperson
|
|
||||||
es-ES:
|
|
||||||
noInvoicesFound: No se han encontrado facturas
|
|
||||||
serial: Serie
|
|
||||||
issued: Fecha
|
|
||||||
amount: Importe
|
|
||||||
downloadInvoicePdf: Descargar factura en PDF
|
|
||||||
notDownloadable: No disponible para descarga, solicita la factura a tu comercial
|
|
||||||
ca-ES:
|
|
||||||
noInvoicesFound: No s'han trobat factures
|
|
||||||
serial: Sèrie
|
|
||||||
issued: Data
|
|
||||||
amount: Import
|
|
||||||
downloadInvoicePdf: Descarregar PDF
|
|
||||||
notDownloadable: No disponible per cescarrega, sol·licita la factura al teu comercial
|
|
||||||
fr-FR:
|
|
||||||
noInvoicesFound: Aucune facture trouvée
|
|
||||||
serial: Série
|
|
||||||
issued: Date
|
|
||||||
amount: Montant
|
|
||||||
downloadInvoicePdf: Télécharger le PDF
|
|
||||||
notDownloadable: Non disponible en téléchargement, demander la facture à votre commercial
|
|
||||||
pt-PT:
|
|
||||||
noInvoicesFound: Nenhuma fatura encontrada
|
|
||||||
serial: Serie
|
|
||||||
issued: Data
|
|
||||||
amount: Importe
|
|
||||||
downloadInvoicePdf: Baixar PDF
|
|
||||||
notDownloadable: Não disponível para download, solicite a fatura ao seu comercial
|
|
||||||
</i18n>
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, inject, computed } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import VnTable from 'src/components/ui/VnTable.vue';
|
||||||
|
|
||||||
|
import { currency, formatDate } from 'src/lib/filters.js';
|
||||||
|
import { usePrintService } from 'src/composables/usePrintService';
|
||||||
|
// import { date as qdate } from 'quasar';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const jApi = inject('jApi');
|
||||||
|
const { openReport } = usePrintService();
|
||||||
|
|
||||||
|
const currentYear = ref(Date.vnNew().getFullYear());
|
||||||
|
const years = ref([]);
|
||||||
|
const invoices = ref([]);
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{ name: 'ref', label: t('invoice'), field: 'ref', align: 'left' },
|
||||||
|
{
|
||||||
|
name: 'issued',
|
||||||
|
label: t('issued'),
|
||||||
|
field: 'issued',
|
||||||
|
align: 'left',
|
||||||
|
format: val => formatDate(val, 'D MMM YYYY')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'amount',
|
||||||
|
label: t('amount'),
|
||||||
|
field: 'amount',
|
||||||
|
format: val => currency(val)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hasPdf',
|
||||||
|
field: 'hasPdf',
|
||||||
|
align: 'center'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fetchInvoices = async () => {
|
||||||
|
const params = {
|
||||||
|
from: new Date(currentYear.value, 0),
|
||||||
|
to: new Date(currentYear.value, 11, 31, 23, 59, 59)
|
||||||
|
};
|
||||||
|
invoices.value = await jApi.query(
|
||||||
|
`SELECT id, ref, issued, amount, hasPdf
|
||||||
|
FROM myInvoice
|
||||||
|
WHERE issued BETWEEN #from AND #to
|
||||||
|
ORDER BY issued DESC
|
||||||
|
LIMIT 100`,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await fetchInvoices();
|
||||||
|
for (let year = currentYear.value - 5; year <= currentYear.value; year++) {
|
||||||
|
years.value.push(year);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Teleport :to="$actions">
|
||||||
|
<QSelect
|
||||||
|
v-model="currentYear"
|
||||||
|
:options="years"
|
||||||
|
color="white"
|
||||||
|
dark
|
||||||
|
standout
|
||||||
|
dense
|
||||||
|
rounded
|
||||||
|
@update:model-value="fetchInvoices()"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<div class="vn-w-sm">
|
||||||
|
<VnTable
|
||||||
|
:columns="columns"
|
||||||
|
:rows="invoices"
|
||||||
|
:hide-header="!invoices.length"
|
||||||
|
>
|
||||||
|
<template #body-cell-hasPdf="{ row }">
|
||||||
|
<QTd
|
||||||
|
auto-width
|
||||||
|
@click.stop
|
||||||
|
class="flex full-width justify-center items-center"
|
||||||
|
>
|
||||||
|
<QBtn
|
||||||
|
v-if="row.hasPdf"
|
||||||
|
icon="download"
|
||||||
|
target="_blank"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
@click="openReport(`InvoiceOuts/${row.id}/download`)"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('downloadInvoicePdf') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
<QIcon
|
||||||
|
v-else
|
||||||
|
name="warning"
|
||||||
|
:title="t('notDownloadable')"
|
||||||
|
color="warning"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('requestTheInvoiceToComercial') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
noInvoicesFound: No invoices found
|
||||||
|
invoice: Invoice
|
||||||
|
issued: Date
|
||||||
|
amount: Import
|
||||||
|
downloadInvoicePdf: Download invoice PDF
|
||||||
|
notDownloadable: Not available for download, request the invoice to your salesperson
|
||||||
|
requestTheInvoiceToComercial: Request the invoice to your salesperson
|
||||||
|
es-ES:
|
||||||
|
noInvoicesFound: No se han encontrado facturas
|
||||||
|
invoice: Factura
|
||||||
|
issued: Fecha
|
||||||
|
amount: Importe
|
||||||
|
downloadInvoicePdf: Descargar factura en PDF
|
||||||
|
notDownloadable: No disponible para descarga, solicita la factura a tu comercial
|
||||||
|
requestTheInvoiceToComercial: Solicita la factura a tu comercial
|
||||||
|
ca-ES:
|
||||||
|
noInvoicesFound: No s'han trobat factures
|
||||||
|
invoice: Factura
|
||||||
|
issued: Data
|
||||||
|
amount: Import
|
||||||
|
downloadInvoicePdf: Descarregar PDF
|
||||||
|
notDownloadable: No disponible per cescarrega, sol·licita la factura al teu comercial
|
||||||
|
requestTheInvoiceToComercial: Sol·licita la factura al teu comercial
|
||||||
|
fr-FR:
|
||||||
|
noInvoicesFound: Aucune facture trouvée
|
||||||
|
invoice: Facture
|
||||||
|
issued: Date
|
||||||
|
amount: Montant
|
||||||
|
downloadInvoicePdf: Télécharger le PDF
|
||||||
|
notDownloadable: Non disponible en téléchargement, demander la facture à votre commercial
|
||||||
|
requestTheInvoiceToComercial: Demander la facture à votre commercial
|
||||||
|
pt-PT:
|
||||||
|
noInvoicesFound: Nenhuma fatura encontrada
|
||||||
|
invoice: Fatura
|
||||||
|
issued: Data
|
||||||
|
amount: Importe
|
||||||
|
downloadInvoicePdf: Baixar PDF
|
||||||
|
notDownloadable: Não disponível para download, solicite a fatura ao seu comercial
|
||||||
|
requestTheInvoiceToComercial: Solicite a fatura ao seu comercial
|
||||||
|
</i18n>
|
|
@ -1,70 +1,135 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, inject } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import CardList from 'src/components/ui/CardList.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||||
|
|
||||||
|
import { currency, formatDateTitle } from 'src/lib/filters.js';
|
||||||
|
import { tpvStore } from 'stores/tpv';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
const jApi = inject('jApi');
|
||||||
|
|
||||||
|
const showAmountToPayDialog = ref(null);
|
||||||
|
const amountToPay = ref(null);
|
||||||
|
const orders = ref(null);
|
||||||
|
const debt = ref(0);
|
||||||
|
const tpv = tpvStore();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await tpv.check(route);
|
||||||
|
|
||||||
|
orders.value = await jApi.query('CALL myTicket_list(NULL, NULL)');
|
||||||
|
debt.value = await jApi.getValue('SELECT -myClient_getDebt(NULL)');
|
||||||
|
});
|
||||||
|
|
||||||
|
const onPayClick = async () => {
|
||||||
|
showAmountToPayDialog.value = true;
|
||||||
|
|
||||||
|
if (debt.value <= 0) {
|
||||||
|
amountToPay.value = -debt.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onConfirmPay = async () => {
|
||||||
|
if (amountToPay.value) {
|
||||||
|
const amount = amountToPay.value.toString().replace('.', ',');
|
||||||
|
amountToPay.value = parseFloat(amount);
|
||||||
|
await tpv.pay(amountToPay.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Teleport :to="$actions">
|
<Teleport :to="$actions">
|
||||||
<div class="balance">
|
<div class="balance">
|
||||||
<span class="label">{{ $t('balance') }}</span>
|
<span class="label">{{ t('balance') }}</span>
|
||||||
<span class="amount" :class="{ negative: debt < 0 }">
|
<span class="amount" :class="{ negative: debt < 0 }">
|
||||||
{{ currency(debt || 0) }}
|
{{ currency(debt || 0) }}
|
||||||
</span>
|
</span>
|
||||||
<QIcon
|
<QIcon name="info" class="info" size="sm">
|
||||||
name="info"
|
<QTooltip max-width="450px">
|
||||||
:title="$t('paymentInfo')"
|
{{ t('paymentInfo') }}
|
||||||
class="info"
|
</QTooltip>
|
||||||
size="24px"
|
</QIcon>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<QBtn
|
<QBtn
|
||||||
icon="payments"
|
icon="payments"
|
||||||
:label="$t('makePayment')"
|
:label="t('makePayment')"
|
||||||
@click="onPayClick()"
|
@click="onPayClick()"
|
||||||
rounded
|
rounded
|
||||||
no-caps
|
no-caps
|
||||||
/>
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('makePayment') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
<QBtn
|
<QBtn
|
||||||
to="/ecomerce/basket"
|
:to="{ name: 'basket' }"
|
||||||
icon="shopping_cart"
|
icon="shopping_cart"
|
||||||
:label="$t('shoppingCart')"
|
:label="t('shoppingCart')"
|
||||||
rounded
|
rounded
|
||||||
no-caps
|
no-caps
|
||||||
/>
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('shoppingCart') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<div class="vn-w-sm">
|
<QPage class="vn-w-sm">
|
||||||
<div
|
<div
|
||||||
v-if="!orders?.length"
|
v-if="!orders?.length"
|
||||||
class="text-subtitle1 text-center text-grey-7 q-pa-md"
|
class="text-subtitle1 text-center text-grey-7 q-pa-md"
|
||||||
>
|
>
|
||||||
{{ $t('noOrdersFound') }}
|
{{ t('noOrdersFound') }}
|
||||||
</div>
|
</div>
|
||||||
<QCard v-if="orders?.length">
|
<QList v-if="orders?.length">
|
||||||
<QList bordered separator padding>
|
<CardList
|
||||||
<QItem
|
|
||||||
v-for="order in orders"
|
v-for="order in orders"
|
||||||
:key="order.id"
|
:key="order.id"
|
||||||
:to="`ticket/${order.id}`"
|
:to="`ticket/${order.id}`"
|
||||||
clickable
|
tag="label"
|
||||||
v-ripple
|
|
||||||
>
|
>
|
||||||
<QItemSection>
|
<template #content>
|
||||||
<QItemLabel>
|
<QItemLabel
|
||||||
{{ date(order.landed, 'ddd, MMMM Do') }}
|
class="full-width text-bold q-mb-sm flex row justify-between"
|
||||||
|
>
|
||||||
|
<span>{{ formatDateTitle(order.landed) }}</span>
|
||||||
|
<span>{{ currency(order.total) }}</span>
|
||||||
</QItemLabel>
|
</QItemLabel>
|
||||||
<QItemLabel caption>#{{ order.id }}</QItemLabel>
|
<QItemLabel>#{{ order.id }}</QItemLabel>
|
||||||
<QItemLabel caption>{{ order.nickname }}</QItemLabel>
|
<QItemLabel>{{ order.nickname }}</QItemLabel>
|
||||||
<QItemLabel caption>{{ order.agency }}</QItemLabel>
|
<QItemLabel>{{ order.agency }}</QItemLabel>
|
||||||
</QItemSection>
|
</template>
|
||||||
<QItemSection side top> {{ order.total }}€ </QItemSection>
|
</CardList>
|
||||||
</QItem>
|
|
||||||
</QList>
|
</QList>
|
||||||
</QCard>
|
|
||||||
<QPageSticky>
|
<QPageSticky>
|
||||||
<QBtn
|
<QBtn
|
||||||
fab
|
fab
|
||||||
icon="add_shopping_cart"
|
icon="add_shopping_cart"
|
||||||
color="accent"
|
color="accent"
|
||||||
to="/ecomerce/catalog"
|
:to="{ name: 'catalog' }"
|
||||||
:title="$t('startOrder')"
|
:title="t('startOrder')"
|
||||||
/>
|
/>
|
||||||
</QPageSticky>
|
</QPageSticky>
|
||||||
</div>
|
<VnConfirm
|
||||||
|
v-model="showAmountToPayDialog"
|
||||||
|
:message="t('amountToPay')"
|
||||||
|
:promise="onConfirmPay"
|
||||||
|
>
|
||||||
|
<template #customHTML>
|
||||||
|
<VnInput
|
||||||
|
v-model="amountToPay"
|
||||||
|
:clearable="false"
|
||||||
|
class="full-width"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</VnConfirm>
|
||||||
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -92,50 +157,6 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { date, currency } from 'src/lib/filters.js';
|
|
||||||
import { tpvStore } from 'stores/tpv';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'OrdersPendingIndex',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
orders: null,
|
|
||||||
debt: 0,
|
|
||||||
tpv: tpvStore()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
async mounted() {
|
|
||||||
await this.tpv.check(this.$route);
|
|
||||||
|
|
||||||
this.orders = await this.$jApi.query('CALL myTicket_list(NULL, NULL)');
|
|
||||||
this.debt = await this.$jApi.getValue('SELECT -myClient_getDebt(NULL)');
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
date,
|
|
||||||
currency,
|
|
||||||
|
|
||||||
async onPayClick() {
|
|
||||||
let amount = -this.debt;
|
|
||||||
amount = amount <= 0 ? null : amount;
|
|
||||||
|
|
||||||
let defaultAmountStr = '';
|
|
||||||
if (amount !== null) {
|
|
||||||
defaultAmountStr = amount;
|
|
||||||
}
|
|
||||||
amount = prompt(this.$t('amountToPay'), defaultAmountStr);
|
|
||||||
|
|
||||||
if (amount != null) {
|
|
||||||
amount = parseFloat(amount.replace(',', '.'));
|
|
||||||
await this.tpv.pay(amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<i18n lang="yaml">
|
<i18n lang="yaml">
|
||||||
en-US:
|
en-US:
|
||||||
startOrder: Start order
|
startOrder: Start order
|
||||||
|
@ -148,6 +169,7 @@ en-US:
|
||||||
disregards future orders. For get your order shipped, this amount must be
|
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
|
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.
|
payment button, delete the suggested amount and enter the amount you want.
|
||||||
|
amountToPay: 'Amount to pay (€):'
|
||||||
es-ES:
|
es-ES:
|
||||||
startOrder: Empezar pedido
|
startOrder: Empezar pedido
|
||||||
noOrdersFound: No se encontrado pedidos
|
noOrdersFound: No se encontrado pedidos
|
||||||
|
@ -160,6 +182,7 @@ es-ES:
|
||||||
esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
|
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
|
cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
|
||||||
cantidad que desees.
|
cantidad que desees.
|
||||||
|
amountToPay: 'Cantidad a pagar (€):'
|
||||||
ca-ES:
|
ca-ES:
|
||||||
startOrder: Començar encàrrec
|
startOrder: Començar encàrrec
|
||||||
noOrdersFound: No s'han trobat comandes
|
noOrdersFound: No s'han trobat comandes
|
||||||
|
@ -172,6 +195,7 @@ ca-ES:
|
||||||
enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
|
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
|
lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
|
||||||
e introdueix la quantitat que vulguis.
|
e introdueix la quantitat que vulguis.
|
||||||
|
amountToPay: 'Quantitat a pagar (€):'
|
||||||
fr-FR:
|
fr-FR:
|
||||||
startOrder: Acheter
|
startOrder: Acheter
|
||||||
noOrdersFound: Aucune commande trouvée
|
noOrdersFound: Aucune commande trouvée
|
||||||
|
@ -184,6 +208,7 @@ fr-FR:
|
||||||
commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
|
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
|
voulez faire un versement, le montant suggéré effacé et entrez le montant que
|
||||||
vous souhaitez.
|
vous souhaitez.
|
||||||
|
amountToPay: 'Montant à payer (€):'
|
||||||
pt-PT:
|
pt-PT:
|
||||||
startOrder: Iniciar encomenda
|
startOrder: Iniciar encomenda
|
||||||
noOrdersFound: Nenhum pedido encontrado
|
noOrdersFound: Nenhum pedido encontrado
|
||||||
|
@ -196,4 +221,5 @@ pt-PT:
|
||||||
quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
|
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
|
conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
|
||||||
a quantidade que deseje.
|
a quantidade que deseje.
|
||||||
|
amountToPay: 'Valor a pagar (€):'
|
||||||
</i18n>
|
</i18n>
|
|
@ -0,0 +1,135 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, inject, onMounted } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import CardList from 'src/components/ui/CardList.vue';
|
||||||
|
import { currency, formatDateTitle } from 'src/lib/filters.js';
|
||||||
|
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
import { useAppStore } from 'src/stores/app.js';
|
||||||
|
|
||||||
|
const jApi = inject('jApi');
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
const store = useAppStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const orders = ref([]);
|
||||||
|
|
||||||
|
const getOrders = async () => {
|
||||||
|
try {
|
||||||
|
orders.value = await jApi.query(
|
||||||
|
`SELECT o.id, o.sent, o.deliveryMethodFk, o.taxableBase,
|
||||||
|
a.nickname, am.description agency
|
||||||
|
FROM myOrder o
|
||||||
|
JOIN myAddress a ON a.id = o.addressFk
|
||||||
|
JOIN vn.agencyMode am ON am.id = o.agencyModeFk
|
||||||
|
WHERE NOT o.isConfirmed
|
||||||
|
ORDER BY o.sent DESC`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting orders:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeOrder = async (id, index) => {
|
||||||
|
try {
|
||||||
|
await jApi.execQuery(
|
||||||
|
`START TRANSACTION;
|
||||||
|
DELETE FROM hedera.myOrder WHERE ((id = #id));
|
||||||
|
COMMIT`,
|
||||||
|
{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
);
|
||||||
|
orders.value.splice(index, 1);
|
||||||
|
notify(t('dataSaved'), 'positive');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error removing order:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadOrder = orderId => {
|
||||||
|
store.loadIntoBasket(orderId);
|
||||||
|
router.push({ name: 'catalog' });
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
getOrders();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Teleport :to="$actions">
|
||||||
|
<QBtn
|
||||||
|
:to="{ name: 'checkout' }"
|
||||||
|
icon="add_shopping_cart"
|
||||||
|
:label="t('newOrder')"
|
||||||
|
rounded
|
||||||
|
no-caps
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('newOrder') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
</Teleport>
|
||||||
|
<QPage class="vn-w-sm">
|
||||||
|
<CardList
|
||||||
|
v-for="(order, index) in orders"
|
||||||
|
:key="index"
|
||||||
|
:to="{ name: 'basket', params: { id: order.id } }"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<QItemLabel class="text-bold q-mb-sm">{{
|
||||||
|
formatDateTitle(order.sent)
|
||||||
|
}}</QItemLabel>
|
||||||
|
<QItemLabel> #{{ order.id }} </QItemLabel>
|
||||||
|
<QItemLabel>{{ order.nickname }}</QItemLabel>
|
||||||
|
<QItemLabel>{{ order.agency }}</QItemLabel>
|
||||||
|
<QItemLabel>{{ currency(order.taxableBase) }}</QItemLabel>
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<QBtn
|
||||||
|
icon="delete"
|
||||||
|
flat
|
||||||
|
rounded
|
||||||
|
@click.stop.prevent="
|
||||||
|
openConfirmationModal(
|
||||||
|
null,
|
||||||
|
t('areYouSureDeleteOrder'),
|
||||||
|
() => removeOrder(order.id, index)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
icon="shopping_bag"
|
||||||
|
flat
|
||||||
|
rounded
|
||||||
|
@click.stop.prevent="loadOrder(order.id)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</CardList>
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
newOrder: New order
|
||||||
|
areYouSureDeleteOrder: Are you sure you want to delete the order?
|
||||||
|
es-ES:
|
||||||
|
newOrder: Nuevo pedido
|
||||||
|
areYouSureDeleteOrder: ¿Seguro que quieres borrar el pedido?
|
||||||
|
ca-ES:
|
||||||
|
newOrder: Nova comanda
|
||||||
|
areYouSureDeleteOrder: Segur que vols esborrar la comanda?
|
||||||
|
fr-FR:
|
||||||
|
newOrder: Nouvelle commande
|
||||||
|
areYouSureDeleteOrder: Êtes-vous sûr de vouloir supprimer la commande?
|
||||||
|
pt-PT:
|
||||||
|
newOrder: Novo pedido
|
||||||
|
areYouSureDeleteOrder: Tem certeza de que deseja excluir o pedido?
|
||||||
|
</i18n>
|
|
@ -1,145 +0,0 @@
|
||||||
<template>
|
|
||||||
<Teleport :to="$actions">
|
|
||||||
<QBtn
|
|
||||||
icon="print"
|
|
||||||
:label="$t('printDeliveryNote')"
|
|
||||||
@click="onPrintClick()"
|
|
||||||
rounded
|
|
||||||
no-caps
|
|
||||||
/>
|
|
||||||
</Teleport>
|
|
||||||
<div>
|
|
||||||
<QCard class="vn-w-sm">
|
|
||||||
<QCardSection>
|
|
||||||
<div class="text-h6">#{{ ticket.id }}</div>
|
|
||||||
</QCardSection>
|
|
||||||
<QCardSection>
|
|
||||||
<div class="text-h6">{{ $t('shippingInformation') }}</div>
|
|
||||||
<div>
|
|
||||||
{{ $t('preparation') }}
|
|
||||||
{{ date(ticket.shipped, 'ddd, MMMM Do') }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ $t('delivery') }}
|
|
||||||
{{ date(ticket.shipped, 'ddd, MMMM Do') }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ $t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
|
|
||||||
{{ ticket.agency }}
|
|
||||||
</div>
|
|
||||||
</QCardSection>
|
|
||||||
<QCardSection>
|
|
||||||
<div class="text-h6">{{ $t('deliveryAddress') }}</div>
|
|
||||||
<div>{{ ticket.nickname }}</div>
|
|
||||||
<div>{{ ticket.street }}</div>
|
|
||||||
<div>
|
|
||||||
{{ ticket.postalCode }} {{ ticket.city }} ({{
|
|
||||||
ticket.province
|
|
||||||
}})
|
|
||||||
</div>
|
|
||||||
</QCardSection>
|
|
||||||
<QSeparator inset />
|
|
||||||
<QList v-for="row in rows" :key="row.itemFk">
|
|
||||||
<QItem>
|
|
||||||
<QItemSection avatar>
|
|
||||||
<QAvatar size="68px">
|
|
||||||
<img
|
|
||||||
:src="`${$app.imageUrl}/catalog/200x200/${row.image}`"
|
|
||||||
/>
|
|
||||||
</QAvatar>
|
|
||||||
</QItemSection>
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel lines="1">
|
|
||||||
{{ row.concept }}
|
|
||||||
</QItemLabel>
|
|
||||||
<QItemLabel lines="1" caption>
|
|
||||||
{{ row.value5 }} {{ row.value6 }} {{ row.value7 }}
|
|
||||||
</QItemLabel>
|
|
||||||
<QItemLabel lines="1">
|
|
||||||
{{ row.quantity }} x {{ currency(row.price) }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
<QItemSection side class="total">
|
|
||||||
<QItemLabel>
|
|
||||||
<span class="discount" v-if="row.discount">
|
|
||||||
{{ currency(discountSubtotal(row)) }} -
|
|
||||||
{{ currency(row.discount) }} =
|
|
||||||
</span>
|
|
||||||
{{ currency(subtotal(row)) }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</QList>
|
|
||||||
</QCard>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.total {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { date, currency } from 'src/lib/filters.js';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'OrdersConfirmedView',
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
ticket: {},
|
|
||||||
rows: null,
|
|
||||||
services: null,
|
|
||||||
packages: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
async mounted() {
|
|
||||||
const params = {
|
|
||||||
ticket: parseInt(this.$route.params.id)
|
|
||||||
};
|
|
||||||
this.ticket = await this.$jApi.getObject(
|
|
||||||
'CALL myTicket_get(#ticket)',
|
|
||||||
params
|
|
||||||
);
|
|
||||||
this.rows = await this.$jApi.query(
|
|
||||||
'CALL myTicket_getRows(#ticket)',
|
|
||||||
params
|
|
||||||
);
|
|
||||||
this.services = await this.$jApi.query(
|
|
||||||
'CALL myTicket_getServices(#ticket)',
|
|
||||||
params
|
|
||||||
);
|
|
||||||
this.packages = await this.$jApi.query(
|
|
||||||
'CALL myTicket_getPackages(#ticket)',
|
|
||||||
params
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
date,
|
|
||||||
currency,
|
|
||||||
|
|
||||||
discountSubtotal(line) {
|
|
||||||
return line.quantity * line.price;
|
|
||||||
},
|
|
||||||
|
|
||||||
subtotal(line) {
|
|
||||||
const discount = line.discount;
|
|
||||||
return this.discountSubtotal(line) * ((100 - discount) / 100);
|
|
||||||
},
|
|
||||||
|
|
||||||
onPrintClick() {
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
access_token: this.$user.token,
|
|
||||||
recipientId: this.$user.id,
|
|
||||||
type: 'deliveryNote'
|
|
||||||
});
|
|
||||||
window.open(
|
|
||||||
`/api/Tickets/${this.ticket.id}/delivery-note-pdf?${params.toString()}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, inject, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import TicketDetails from 'src/components/ui/TicketDetails.vue';
|
||||||
|
|
||||||
|
import { userStore as useUserStore } from 'stores/user';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const jApi = inject('jApi');
|
||||||
|
const route = useRoute();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const ticket = ref({});
|
||||||
|
const rows = ref([]);
|
||||||
|
const services = ref(null);
|
||||||
|
const packages = ref(null);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const params = {
|
||||||
|
ticket: parseInt(route.params.id)
|
||||||
|
};
|
||||||
|
ticket.value = await jApi.getObject('CALL myTicket_get(#ticket)', params);
|
||||||
|
rows.value = await jApi.query('CALL myTicket_getRows(#ticket)', params);
|
||||||
|
services.value = await jApi.query(
|
||||||
|
'CALL myTicket_getServices(#ticket)',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
packages.value = await jApi.query(
|
||||||
|
'CALL myTicket_getPackages(#ticket)',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onPrintClick = () => {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
access_token: userStore.token,
|
||||||
|
recipientId: userStore.id,
|
||||||
|
type: 'deliveryNote'
|
||||||
|
});
|
||||||
|
window.open(
|
||||||
|
`/api/Tickets/${ticket.value.id}/delivery-note-pdf?${params.toString()}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Teleport :to="$actions">
|
||||||
|
<QBtn
|
||||||
|
icon="print"
|
||||||
|
:label="t('printDeliveryNote')"
|
||||||
|
@click="onPrintClick()"
|
||||||
|
rounded
|
||||||
|
no-caps
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<QPage>
|
||||||
|
<TicketDetails :rows="rows" :ticket="ticket" />
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
printDeliveryNote: Print delivery note
|
||||||
|
es-ES:
|
||||||
|
printDeliveryNote: Imprimir albarán
|
||||||
|
ca-ES:
|
||||||
|
printDeliveryNote: Imprimir albarà
|
||||||
|
fr-FR:
|
||||||
|
printDeliveryNote: Imprimer bulletin de livraison
|
||||||
|
pt-PT:
|
||||||
|
printDeliveryNote: Imprimir nota de entrega
|
||||||
|
</i18n>
|
|
@ -1,12 +1,13 @@
|
||||||
import { route } from 'quasar/wrappers'
|
import { route } from 'quasar/wrappers';
|
||||||
import { appStore } from 'stores/app'
|
import { useAppStore } from 'stores/app';
|
||||||
import {
|
import {
|
||||||
createRouter,
|
createRouter,
|
||||||
createMemoryHistory,
|
createMemoryHistory,
|
||||||
createWebHistory,
|
createWebHistory,
|
||||||
createWebHashHistory
|
createWebHashHistory
|
||||||
} from 'vue-router'
|
} from 'vue-router';
|
||||||
import routes from './routes'
|
import routes from './routes';
|
||||||
|
import { i18n } from 'src/boot/i18n';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If not building with SSR mode, you can
|
* If not building with SSR mode, you can
|
||||||
|
@ -22,7 +23,7 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
? createMemoryHistory
|
? createMemoryHistory
|
||||||
: process.env.VUE_ROUTER_MODE === 'history'
|
: process.env.VUE_ROUTER_MODE === 'history'
|
||||||
? createWebHistory
|
? createWebHistory
|
||||||
: createWebHashHistory
|
: createWebHashHistory;
|
||||||
|
|
||||||
const Router = createRouter({
|
const Router = createRouter({
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||||
|
@ -34,18 +35,18 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
history: createHistory(
|
history: createHistory(
|
||||||
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
|
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
|
||||||
)
|
)
|
||||||
})
|
});
|
||||||
|
|
||||||
Router.afterEach((to, from) => {
|
Router.afterEach((to, from) => {
|
||||||
if (from.name === to.name) return
|
if (from.name === to.name) return;
|
||||||
const app = appStore()
|
const app = useAppStore();
|
||||||
app.$patch({
|
app.$patch({
|
||||||
title: window.i18n.t(to.name || 'home'),
|
title: i18n.global.t(to.name || 'home'),
|
||||||
subtitle: null,
|
subtitle: null,
|
||||||
useRightDrawer: false,
|
useRightDrawer: false,
|
||||||
rightDrawerOpen: true
|
rightDrawerOpen: true
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
return Router
|
return Router;
|
||||||
})
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ const routes = [
|
||||||
component: () => import('layouts/LoginLayout.vue'),
|
component: () => import('layouts/LoginLayout.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Login',
|
name: 'login',
|
||||||
path: '/login/:email?',
|
path: '/login/:email?',
|
||||||
component: () => import('pages/Login/LoginView.vue')
|
component: () => import('pages/Login/LoginView.vue')
|
||||||
},
|
},
|
||||||
|
@ -35,19 +35,24 @@ const routes = [
|
||||||
component: () => import('src/pages/Cms/HomeView.vue')
|
component: () => import('src/pages/Cms/HomeView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'orders',
|
name: 'confirmedOrders',
|
||||||
path: '/ecomerce/orders',
|
path: '/ecomerce/orders',
|
||||||
component: () => import('pages/Ecomerce/Orders.vue')
|
component: () => import('pages/Ecomerce/OrdersView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ticket',
|
name: 'ticket',
|
||||||
path: '/ecomerce/ticket/:id',
|
path: '/ecomerce/ticket/:id',
|
||||||
component: () => import('pages/Ecomerce/Ticket.vue')
|
component: () => import('pages/Ecomerce/TicketView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'invoices',
|
name: 'invoices',
|
||||||
path: '/ecomerce/invoices',
|
path: '/ecomerce/invoices',
|
||||||
component: () => import('pages/Ecomerce/Invoices.vue')
|
component: () => import('pages/Ecomerce/InvoicesView.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pendingOrders',
|
||||||
|
path: '/ecomerce/pending',
|
||||||
|
component: () => import('pages/Ecomerce/PendingOrders.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'catalog',
|
name: 'catalog',
|
||||||
|
@ -55,22 +60,32 @@ const routes = [
|
||||||
component: () => import('pages/Ecomerce/Catalog.vue')
|
component: () => import('pages/Ecomerce/Catalog.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'packages',
|
name: 'basket',
|
||||||
|
path: '/ecomerce/basket/:id?',
|
||||||
|
component: () => import('pages/Ecomerce/BasketView.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'checkout',
|
||||||
|
path: '/ecomerce/checkout',
|
||||||
|
component: () => import('pages/Ecomerce/CheckoutView.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'agencyPackages',
|
||||||
path: '/agencies/packages',
|
path: '/agencies/packages',
|
||||||
component: () => import('src/pages/Agencies/PackagesView.vue')
|
component: () => import('src/pages/Agencies/PackagesView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Account',
|
name: 'accountConfig',
|
||||||
path: '/account/conf',
|
path: '/account/conf',
|
||||||
component: () => import('pages/Account/AccountConfig.vue')
|
component: () => import('pages/Account/AccountConfig.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AddressesList',
|
name: 'addressesList',
|
||||||
path: '/account/address-list',
|
path: '/account/address-list',
|
||||||
component: () => import('pages/Account/AddressList.vue')
|
component: () => import('pages/Account/AddressList.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AddressDetails',
|
name: 'addressDetails',
|
||||||
path: '/account/address/:id?',
|
path: '/account/address/:id?',
|
||||||
component: () => import('pages/Account/AddressDetails.vue')
|
component: () => import('pages/Account/AddressDetails.vue')
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,52 @@
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia';
|
||||||
import { jApi } from 'boot/axios'
|
import { jApi } from 'boot/axios';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
export const appStore = defineStore('hedera', {
|
const { notify } = useNotify();
|
||||||
|
|
||||||
|
export const useAppStore = defineStore('hedera', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
title: null,
|
title: null,
|
||||||
subtitle: null,
|
subtitle: null,
|
||||||
imageUrl: '',
|
imageUrl: '',
|
||||||
useRightDrawer: false,
|
useRightDrawer: false,
|
||||||
rightDrawerOpen: false
|
rightDrawerOpen: false,
|
||||||
|
basketOrderId: null,
|
||||||
|
isHeaderMounted: false
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async loadConfig () {
|
async init() {
|
||||||
const imageUrl = await jApi.getValue('SELECT url FROM imageConfig')
|
this.getBasketOrderId();
|
||||||
this.$patch({ imageUrl })
|
},
|
||||||
|
|
||||||
|
getBasketOrderId() {
|
||||||
|
this.basketOrderId = localStorage.getItem('hederaBasket');
|
||||||
|
},
|
||||||
|
|
||||||
|
async loadConfig() {
|
||||||
|
const imageUrl = await jApi.getValue('SELECT url FROM imageConfig');
|
||||||
|
this.$patch({ imageUrl });
|
||||||
|
},
|
||||||
|
|
||||||
|
async checkOrder(orderId) {
|
||||||
|
try {
|
||||||
|
const resultSet = await jApi.execQuery(
|
||||||
|
'CALL myOrder_checkConfig(#id)',
|
||||||
|
{ id: orderId }
|
||||||
|
);
|
||||||
|
resultSet.fetchValue();
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error checking order', err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadIntoBasket(orderId) {
|
||||||
|
if (this.basketOrderId !== orderId) {
|
||||||
|
localStorage.setItem('hederaBasket', orderId);
|
||||||
|
this.basketOrderId = orderId;
|
||||||
|
notify('orderLoadedIntoBasket', 'positive');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { store } from 'quasar/wrappers'
|
import { store } from 'quasar/wrappers';
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If not building with SSR mode, you can
|
* If not building with SSR mode, you can
|
||||||
|
@ -11,10 +11,10 @@ import { createPinia } from 'pinia'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default store((/* { ssrContext } */) => {
|
export default store((/* { ssrContext } */) => {
|
||||||
const pinia = createPinia()
|
const pinia = createPinia();
|
||||||
|
|
||||||
// You can add Pinia plugins here
|
// You can add Pinia plugins here
|
||||||
// pinia.use(SomePiniaPlugin)
|
// pinia.use(SomePiniaPlugin)
|
||||||
|
|
||||||
return pinia
|
return pinia;
|
||||||
})
|
});
|
||||||
|
|
Loading…
Reference in New Issue