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
448
quasar.config.js
448
quasar.config.js
|
@ -14,243 +14,243 @@ const path = require('path');
|
|||
const { configure } = require('quasar/wrappers');
|
||||
|
||||
module.exports = configure(function (ctx) {
|
||||
return {
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/supporting-ts
|
||||
supportTS: false,
|
||||
return {
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/supporting-ts
|
||||
supportTS: false,
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/prefetch-feature
|
||||
// preFetch: true,
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/prefetch-feature
|
||||
// preFetch: true,
|
||||
|
||||
// app boot file (/src/boot)
|
||||
// --> boot files are part of "main.js"
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
|
||||
boot: ['i18n', 'axios', 'error-handler', 'app'],
|
||||
// app boot file (/src/boot)
|
||||
// --> boot files are part of "main.js"
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
|
||||
boot: ['i18n', 'axios', 'vnDate', 'error-handler', 'app'],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
|
||||
css: ['app.scss', 'width.scss', 'responsive.scss'],
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
|
||||
css: ['app.scss', 'width.scss', 'responsive.scss'],
|
||||
|
||||
// https://github.com/quasarframework/quasar/tree/dev/extras
|
||||
extras: [
|
||||
// 'ionicons-v4',
|
||||
// 'mdi-v5',
|
||||
// 'fontawesome-v6',
|
||||
// 'eva-icons',
|
||||
// 'themify',
|
||||
// 'line-awesome',
|
||||
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
|
||||
// https://github.com/quasarframework/quasar/tree/dev/extras
|
||||
extras: [
|
||||
// 'ionicons-v4',
|
||||
// 'mdi-v5',
|
||||
// 'fontawesome-v6',
|
||||
// 'eva-icons',
|
||||
// 'themify',
|
||||
// 'line-awesome',
|
||||
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
|
||||
|
||||
'roboto-font', // optional, you are not bound to it
|
||||
'material-icons' // optional, you are not bound to it
|
||||
],
|
||||
'roboto-font', // optional, you are not bound to it
|
||||
'material-icons' // optional, you are not bound to it
|
||||
],
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-build
|
||||
build: {
|
||||
vueRouterMode: 'hash', // available values: 'hash', 'history'
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-build
|
||||
build: {
|
||||
vueRouterMode: 'hash', // available values: 'hash', 'history'
|
||||
|
||||
// transpile: false,
|
||||
// publicPath: '/',
|
||||
// transpile: false,
|
||||
// publicPath: '/',
|
||||
|
||||
// Add dependencies for transpiling with Babel (Array of string/regex)
|
||||
// (from node_modules, which are by default not transpiled).
|
||||
// Applies only if "transpile" is set to true.
|
||||
// transpileDependencies: [],
|
||||
// Add dependencies for transpiling with Babel (Array of string/regex)
|
||||
// (from node_modules, which are by default not transpiled).
|
||||
// Applies only if "transpile" is set to true.
|
||||
// transpileDependencies: [],
|
||||
|
||||
// rtl: true, // https://quasar.dev/options/rtl-support
|
||||
// preloadChunks: true,
|
||||
// showProgress: false,
|
||||
// gzip: true,
|
||||
// analyze: true,
|
||||
// rtl: true, // https://quasar.dev/options/rtl-support
|
||||
// preloadChunks: true,
|
||||
// showProgress: false,
|
||||
// gzip: true,
|
||||
// analyze: true,
|
||||
|
||||
// Options below are automatically set depending on the env, set them if you want to override
|
||||
// extractCSS: false,
|
||||
// Options below are automatically set depending on the env, set them if you want to override
|
||||
// extractCSS: false,
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/handling-webpack
|
||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/handling-webpack
|
||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||
|
||||
chainWebpack(chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
||||
chainWebpack (chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
||||
|
||||
chain.module
|
||||
.rule('i18n-resource')
|
||||
.test(/\.(json5?|ya?ml)$/)
|
||||
.include.add(path.resolve(__dirname, './src/i18n'))
|
||||
.end()
|
||||
.type('javascript/auto')
|
||||
.use('i18n-resource')
|
||||
.loader('@intlify/vue-i18n-loader');
|
||||
chain.module
|
||||
.rule('i18n')
|
||||
.resourceQuery(/blockType=i18n/)
|
||||
.type('javascript/auto')
|
||||
.use('i18n')
|
||||
.loader('@intlify/vue-i18n-loader');
|
||||
}
|
||||
},
|
||||
chain.module
|
||||
.rule('i18n-resource')
|
||||
.test(/\.(json5?|ya?ml)$/)
|
||||
.include.add(path.resolve(__dirname, './src/i18n'))
|
||||
.end()
|
||||
.type('javascript/auto')
|
||||
.use('i18n-resource')
|
||||
.loader('@intlify/vue-i18n-loader');
|
||||
chain.module
|
||||
.rule('i18n')
|
||||
.resourceQuery(/blockType=i18n/)
|
||||
.type('javascript/auto')
|
||||
.use('i18n')
|
||||
.loader('@intlify/vue-i18n-loader');
|
||||
}
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-devServer
|
||||
devServer: {
|
||||
server: {
|
||||
type: 'http'
|
||||
},
|
||||
port: 8080,
|
||||
open: false,
|
||||
// static: __dirname,
|
||||
headers: { 'Access-Control-Allow-Origin': '*' },
|
||||
// stats: { chunks: false },
|
||||
proxy: {
|
||||
'/api': 'http://localhost:3000',
|
||||
'/': {
|
||||
target: 'http://localhost:3002',
|
||||
bypass: req => (req.path !== '/' ? req.path : null)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-framework
|
||||
framework: {
|
||||
config: {},
|
||||
autoImportComponentCase: 'pascal',
|
||||
// iconSet: 'material-icons', // Quasar icon set
|
||||
// lang: 'en-US', // Quasar language pack
|
||||
|
||||
// For special cases outside of where the auto-import strategy can have an impact
|
||||
// (like functional components as one of the examples),
|
||||
// you can manually specify Quasar components/directives to be available everywhere:
|
||||
//
|
||||
// components: [],
|
||||
// directives: [],
|
||||
|
||||
// Quasar plugins
|
||||
plugins: ['Notify', 'Dialog']
|
||||
},
|
||||
|
||||
// animations: 'all', // --- includes all animations
|
||||
// https://quasar.dev/options/animations
|
||||
animations: [],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/developing-ssr/configuring-ssr
|
||||
ssr: {
|
||||
pwa: false,
|
||||
|
||||
// manualStoreHydration: true,
|
||||
// manualPostHydrationTrigger: true,
|
||||
|
||||
prodPort: 3000, // The default port that the production server should use
|
||||
// (gets superseded if process.env.PORT is specified at runtime)
|
||||
|
||||
maxAge: 1000 * 60 * 60 * 24 * 30,
|
||||
// Tell browser when a file from the server should expire from cache (in ms)
|
||||
|
||||
chainWebpackWebserver(chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
},
|
||||
|
||||
middlewares: [
|
||||
ctx.prod ? 'compression' : '',
|
||||
'render' // keep this as last one
|
||||
]
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/developing-pwa/configuring-pwa
|
||||
pwa: {
|
||||
workboxPluginMode: 'GenerateSW', // 'GenerateSW' or 'InjectManifest'
|
||||
workboxOptions: {}, // only for GenerateSW
|
||||
|
||||
// for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts])
|
||||
// if using workbox in InjectManifest mode
|
||||
|
||||
chainWebpackCustomSW(chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
},
|
||||
|
||||
manifest: {
|
||||
name: 'Hedera',
|
||||
short_name: 'Hedera',
|
||||
description: "Verdnatura's webshop",
|
||||
display: 'standalone',
|
||||
orientation: 'portrait',
|
||||
background_color: '#ffffff',
|
||||
theme_color: '#027be3',
|
||||
icons: [
|
||||
{
|
||||
src: 'icons/icon-128x128.png',
|
||||
sizes: '128x128',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-192x192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-256x256.png',
|
||||
sizes: '256x256',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-384x384.png',
|
||||
sizes: '384x384',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-cordova-apps/configuring-cordova
|
||||
cordova: {
|
||||
// noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-capacitor-apps/configuring-capacitor
|
||||
capacitor: {
|
||||
hideSplashscreen: true
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-electron-apps/configuring-electron
|
||||
electron: {
|
||||
bundler: 'packager', // 'packager' or 'builder'
|
||||
|
||||
packager: {
|
||||
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
|
||||
// OS X / Mac App Store
|
||||
// appBundleId: '',
|
||||
// appCategoryType: '',
|
||||
// osxSign: '',
|
||||
// protocol: 'myapp://path',
|
||||
// Windows only
|
||||
// win32metadata: { ... }
|
||||
},
|
||||
|
||||
builder: {
|
||||
// https://www.electron.build/configuration/configuration
|
||||
|
||||
appId: 'hedera-web'
|
||||
},
|
||||
|
||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||
|
||||
chainWebpackMain(chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
},
|
||||
|
||||
chainWebpackPreload(chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
}
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-devServer
|
||||
devServer: {
|
||||
server: {
|
||||
type: 'http'
|
||||
},
|
||||
port: 8080,
|
||||
open: false,
|
||||
// static: __dirname,
|
||||
headers: { 'Access-Control-Allow-Origin': '*' },
|
||||
// stats: { chunks: false },
|
||||
proxy: {
|
||||
'/api': 'http://localhost:3000',
|
||||
'/': {
|
||||
target: 'http://localhost:3002',
|
||||
bypass: req => (req.path !== '/' ? req.path : null)
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-framework
|
||||
framework: {
|
||||
config: {},
|
||||
autoImportComponentCase: 'pascal',
|
||||
// iconSet: 'material-icons', // Quasar icon set
|
||||
// lang: 'en-US', // Quasar language pack
|
||||
|
||||
// For special cases outside of where the auto-import strategy can have an impact
|
||||
// (like functional components as one of the examples),
|
||||
// you can manually specify Quasar components/directives to be available everywhere:
|
||||
//
|
||||
// components: [],
|
||||
// directives: [],
|
||||
|
||||
// Quasar plugins
|
||||
plugins: ['Notify', 'Dialog']
|
||||
},
|
||||
|
||||
// animations: 'all', // --- includes all animations
|
||||
// https://quasar.dev/options/animations
|
||||
animations: [],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/developing-ssr/configuring-ssr
|
||||
ssr: {
|
||||
pwa: false,
|
||||
|
||||
// manualStoreHydration: true,
|
||||
// manualPostHydrationTrigger: true,
|
||||
|
||||
prodPort: 3000, // The default port that the production server should use
|
||||
// (gets superseded if process.env.PORT is specified at runtime)
|
||||
|
||||
maxAge: 1000 * 60 * 60 * 24 * 30,
|
||||
// Tell browser when a file from the server should expire from cache (in ms)
|
||||
|
||||
chainWebpackWebserver (chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
},
|
||||
|
||||
middlewares: [
|
||||
ctx.prod ? 'compression' : '',
|
||||
'render' // keep this as last one
|
||||
]
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-webpack/developing-pwa/configuring-pwa
|
||||
pwa: {
|
||||
workboxPluginMode: 'GenerateSW', // 'GenerateSW' or 'InjectManifest'
|
||||
workboxOptions: {}, // only for GenerateSW
|
||||
|
||||
// for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts])
|
||||
// if using workbox in InjectManifest mode
|
||||
|
||||
chainWebpackCustomSW (chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
},
|
||||
|
||||
manifest: {
|
||||
name: 'Hedera',
|
||||
short_name: 'Hedera',
|
||||
description: "Verdnatura's webshop",
|
||||
display: 'standalone',
|
||||
orientation: 'portrait',
|
||||
background_color: '#ffffff',
|
||||
theme_color: '#027be3',
|
||||
icons: [
|
||||
{
|
||||
src: 'icons/icon-128x128.png',
|
||||
sizes: '128x128',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-192x192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-256x256.png',
|
||||
sizes: '256x256',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-384x384.png',
|
||||
sizes: '384x384',
|
||||
type: 'image/png'
|
||||
},
|
||||
{
|
||||
src: 'icons/icon-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-cordova-apps/configuring-cordova
|
||||
cordova: {
|
||||
// noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-capacitor-apps/configuring-capacitor
|
||||
capacitor: {
|
||||
hideSplashscreen: true
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-electron-apps/configuring-electron
|
||||
electron: {
|
||||
bundler: 'packager', // 'packager' or 'builder'
|
||||
|
||||
packager: {
|
||||
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
|
||||
// OS X / Mac App Store
|
||||
// appBundleId: '',
|
||||
// appCategoryType: '',
|
||||
// osxSign: '',
|
||||
// protocol: 'myapp://path',
|
||||
// Windows only
|
||||
// win32metadata: { ... }
|
||||
},
|
||||
|
||||
builder: {
|
||||
// https://www.electron.build/configuration/configuration
|
||||
|
||||
appId: 'hedera-web'
|
||||
},
|
||||
|
||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||
|
||||
chainWebpackMain (chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js'] }]);
|
||||
},
|
||||
|
||||
chainWebpackPreload (chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.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>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App'
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { boot } from 'quasar/wrappers'
|
||||
import { appStore } from 'stores/app'
|
||||
import { userStore } from 'stores/user'
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { userStore } from 'stores/user';
|
||||
|
||||
export default boot(({ app }) => {
|
||||
const props = app.config.globalProperties
|
||||
props.$app = appStore()
|
||||
props.$user = userStore()
|
||||
props.$actions = document.createElement('div')
|
||||
})
|
||||
const props = app.config.globalProperties;
|
||||
props.$app = useAppStore();
|
||||
props.$user = userStore();
|
||||
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"
|
||||
ref="addressFormRef"
|
||||
class="column full-width q-gutter-y-xs"
|
||||
@submit="submit()"
|
||||
>
|
||||
<span class="text-h6 text-bold">
|
||||
{{ title }}
|
||||
|
@ -197,7 +196,7 @@ defineExpose({
|
|||
:class="{ 'q-mt-md': showBottomActions }"
|
||||
>
|
||||
<QBtn
|
||||
v-if="defaultActions"
|
||||
v-if="defaultActions && showBottomActions"
|
||||
:label="t('cancel')"
|
||||
:icon="showBottomActions ? undefined : 'check'"
|
||||
rounded
|
||||
|
@ -208,12 +207,12 @@ defineExpose({
|
|||
<QBtn
|
||||
v-if="defaultActions"
|
||||
:label="t('save')"
|
||||
type="submit"
|
||||
:icon="showBottomActions ? undefined : 'check'"
|
||||
rounded
|
||||
no-caps
|
||||
flat
|
||||
:disabled="!showBottomActions && !updatedColumns.length"
|
||||
@click="submit()"
|
||||
/>
|
||||
<slot name="actions" />
|
||||
</component>
|
||||
|
|
|
@ -9,7 +9,7 @@ const emit = defineEmits([
|
|||
'remove'
|
||||
]);
|
||||
|
||||
const $props = defineProps({
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
|
@ -33,7 +33,7 @@ const requiredFieldRule = val => !!val || t('globals.fieldRequired');
|
|||
const vnInputRef = ref(null);
|
||||
const value = computed({
|
||||
get() {
|
||||
return $props.modelValue;
|
||||
return props.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
emit('update:modelValue', value);
|
||||
|
@ -41,7 +41,7 @@ const value = computed({
|
|||
});
|
||||
const hover = ref(false);
|
||||
const styleAttrs = computed(() => {
|
||||
return $props.isOutlined
|
||||
return props.isOutlined
|
||||
? { dense: true, outlined: true, rounded: true }
|
||||
: {};
|
||||
});
|
||||
|
@ -88,9 +88,7 @@ const inputRules = [
|
|||
<template #append>
|
||||
<slot v-if="$slots.append && !$attrs.disabled" name="append" />
|
||||
<QIcon
|
||||
v-if="
|
||||
hover && value && !$attrs.disabled && $props.clearable
|
||||
"
|
||||
v-if="hover && value && !$attrs.disabled && props.clearable"
|
||||
name="close"
|
||||
size="xs"
|
||||
@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>
|
||||
import { ref, computed } from 'vue';
|
||||
import { appStore } from 'stores/app';
|
||||
import { useAppStore } from 'stores/app';
|
||||
|
||||
const $props = defineProps({
|
||||
const props = defineProps({
|
||||
baseURL: {
|
||||
type: String,
|
||||
default: null
|
||||
|
@ -23,23 +23,27 @@ const $props = defineProps({
|
|||
id: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
rounded: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
const app = appStore();
|
||||
const app = useAppStore();
|
||||
const show = ref(false);
|
||||
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>
|
||||
<template>
|
||||
<QImg
|
||||
:class="{ zoomIn: $props.zoomSize }"
|
||||
:class="{ zoomIn: props.zoomSize, rounded: props.rounded }"
|
||||
:src="url"
|
||||
v-bind="$attrs"
|
||||
@click="show = !show"
|
||||
spinner-color="primary"
|
||||
/>
|
||||
<QDialog v-model="show" v-if="$props.zoomSize">
|
||||
<QDialog v-model="show" v-if="props.zoomSize">
|
||||
<QImg
|
||||
:src="url"
|
||||
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
|
||||
};
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
// app global css in SCSS form
|
||||
|
||||
@font-face {
|
||||
font-family: Poppins;
|
||||
src: url(./poppins.ttf) format('truetype');
|
||||
font-family: Poppins;
|
||||
src: url(./poppins.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
|
@ -36,3 +36,9 @@ a.link {
|
|||
.q-page-sticky.fixed-bottom-right {
|
||||
margin: 18px;
|
||||
}
|
||||
.no-border-radius {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.no-padding {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
$primary: #1a1a1a;
|
||||
$secondary: #26a69a;
|
||||
$accent: #8cc63f;
|
||||
|
||||
$gray-light: #ddd;
|
||||
$dark: #1d1d1d;
|
||||
$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',
|
||||
'December'
|
||||
],
|
||||
shortMonths: [
|
||||
monthsShort: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
|
@ -56,6 +56,17 @@ export default {
|
|||
// menu
|
||||
home: 'Home',
|
||||
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',
|
||||
order: 'Pending order',
|
||||
ticket: 'Order',
|
||||
|
@ -76,5 +87,6 @@ export default {
|
|||
addressEdit: 'Edit address',
|
||||
dataSaved: 'Data saved',
|
||||
save: 'Save',
|
||||
cancel: 'Cancel'
|
||||
cancel: 'Cancel',
|
||||
of: 'of'
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ export default {
|
|||
'Noviembre',
|
||||
'Diciembre'
|
||||
],
|
||||
shortMonths: [
|
||||
monthsShort: [
|
||||
'Ene',
|
||||
'Feb',
|
||||
'Mar',
|
||||
|
@ -65,6 +65,17 @@ export default {
|
|||
// Menu
|
||||
home: 'Inicio',
|
||||
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',
|
||||
order: 'Pedido pendiente',
|
||||
ticket: 'Pedido',
|
||||
|
@ -94,5 +105,6 @@ export default {
|
|||
addressEdit: 'Editar dirección',
|
||||
dataSaved: 'Datos guardados',
|
||||
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 esES from './es-ES'
|
||||
import enUS from './en-US';
|
||||
import esES from './es-ES';
|
||||
import frFR from './fr-FR';
|
||||
import ptPT from './pt-PT';
|
||||
import caES from './ca-ES';
|
||||
|
||||
export default {
|
||||
'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'
|
||||
const { pad } = format
|
||||
import { i18n } from 'src/boot/i18n';
|
||||
import { date as qdate, format } from 'quasar';
|
||||
const { pad } = format;
|
||||
|
||||
export function currency (val) {
|
||||
return typeof val === 'number' ? val.toFixed(2) + '€' : val
|
||||
export function currency(val) {
|
||||
return typeof val === 'number' ? val.toFixed(2) + '€' : val;
|
||||
}
|
||||
|
||||
export function date (val, format) {
|
||||
if (val == null) return val
|
||||
export function date(val, format) {
|
||||
if (val == null) return val;
|
||||
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) {
|
||||
if (val == null) return val
|
||||
export const formatDate = (timeStamp, format = 'YYYY-MM-DD') => {
|
||||
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)) {
|
||||
val = new Date(val)
|
||||
val = new Date(val);
|
||||
}
|
||||
|
||||
const dif = qdate.getDateDiff(new Date(), val, 'days')
|
||||
let day
|
||||
const dif = qdate.getDateDiff(new Date(), val, 'days');
|
||||
let day;
|
||||
|
||||
switch (dif) {
|
||||
case 0:
|
||||
day = 'today'
|
||||
break
|
||||
day = 'today';
|
||||
break;
|
||||
case 1:
|
||||
day = 'yesterday'
|
||||
break
|
||||
day = 'yesterday';
|
||||
break;
|
||||
case -1:
|
||||
day = 'tomorrow'
|
||||
break
|
||||
day = 'tomorrow';
|
||||
break;
|
||||
}
|
||||
|
||||
if (day) {
|
||||
day = window.i18n.t(day)
|
||||
day = i18n.global.t(day);
|
||||
} else {
|
||||
if (dif > 0 && dif <= 7) {
|
||||
day = qdate.formatDate(val, 'ddd', window.i18n.tm('date'))
|
||||
day = qdate.formatDate(val, 'ddd', i18n.global.tm('date'));
|
||||
} 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) {
|
||||
if (val == null) return val
|
||||
export function relTime(val) {
|
||||
if (val == null) return val;
|
||||
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) {
|
||||
if (val == null) return val
|
||||
export function elapsedTime(val) {
|
||||
if (val == null) return val;
|
||||
if (!(val instanceof Date)) {
|
||||
val = new Date(val)
|
||||
val = new Date(val);
|
||||
}
|
||||
const now = new Date().getTime()
|
||||
val = Math.floor((now - val.getTime()) / 1000)
|
||||
const now = new Date().getTime();
|
||||
val = Math.floor((now - val.getTime()) / 1000);
|
||||
|
||||
const hours = Math.floor(val / 3600)
|
||||
val -= hours * 3600
|
||||
const minutes = Math.floor(val / 60)
|
||||
val -= minutes * 60
|
||||
const seconds = val
|
||||
const hours = Math.floor(val / 3600);
|
||||
val -= hours * 3600;
|
||||
const minutes = Math.floor(val / 60);
|
||||
val -= minutes * 60;
|
||||
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"
|
||||
rounded
|
||||
no-caps
|
||||
:to="{ name: 'AddressesList' }"
|
||||
:to="{ name: 'addressesList' }"
|
||||
/>
|
||||
<QBtn
|
||||
:label="t('changePassword')"
|
||||
|
|
|
@ -32,7 +32,7 @@ watch(
|
|||
async val => await getProvinces(val)
|
||||
);
|
||||
|
||||
const goBack = () => router.push({ name: 'AddressesList' });
|
||||
const goBack = () => router.push({ name: 'addressesList' });
|
||||
|
||||
const getCountries = async () => {
|
||||
countriesOptions.value = await jApi.query(
|
||||
|
|
|
@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n';
|
|||
import { ref, onMounted, inject } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import CardList from 'src/components/ui/CardList.vue';
|
||||
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
||||
|
||||
|
@ -17,7 +19,7 @@ const defaultAddress = ref(null);
|
|||
const clientId = ref(null);
|
||||
|
||||
const goToAddressDetails = (id = 0) =>
|
||||
router.push({ name: 'AddressDetails', params: { id } });
|
||||
router.push({ name: 'addressDetails', params: { id } });
|
||||
|
||||
const getDefaultAddress = async () => {
|
||||
try {
|
||||
|
@ -93,42 +95,33 @@ onMounted(async () => {
|
|||
no-caps
|
||||
/>
|
||||
</Teleport>
|
||||
<QPage class="column items-center">
|
||||
<QList
|
||||
class="full-width rounded-borders shadow-1 shadow-transition"
|
||||
style="max-width: 544px"
|
||||
separator
|
||||
>
|
||||
<QItem
|
||||
<QPage class="vn-w-sm">
|
||||
<QList class="rounded-borders shadow-1 shadow-transition" separator>
|
||||
<CardList
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
clickable
|
||||
v-ripple
|
||||
:rounded="false"
|
||||
tag="label"
|
||||
class="full-width row items-center justify-between address-item"
|
||||
style="padding: 20px"
|
||||
>
|
||||
<QItemSection>
|
||||
<div class="row">
|
||||
<QRadio
|
||||
v-model="defaultAddress"
|
||||
:val="address.id"
|
||||
class="q-mr-sm"
|
||||
@update:model-value="changeDefaultAddress"
|
||||
/>
|
||||
<div>
|
||||
<QItemLabel class="text-bold q-mb-sm">
|
||||
{{ address.nickname }}
|
||||
</QItemLabel>
|
||||
<QItemLabel>{{ address.street }}</QItemLabel>
|
||||
<QItemLabel>
|
||||
{{ address.postalCode }},
|
||||
{{ address.city }}
|
||||
</QItemLabel>
|
||||
</div>
|
||||
</div>
|
||||
</QItemSection>
|
||||
<QItemSection class="actions-wrapper" side>
|
||||
<template #prepend>
|
||||
<QRadio
|
||||
v-model="defaultAddress"
|
||||
:val="address.id"
|
||||
class="q-mr-sm"
|
||||
@update:model-value="changeDefaultAddress"
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
<span class="text-bold q-mb-sm">
|
||||
{{ address.nickname }}
|
||||
</span>
|
||||
<span>{{ address.street }}</span>
|
||||
<span>
|
||||
{{ address.postalCode }},
|
||||
{{ address.city }}
|
||||
</span>
|
||||
</template>
|
||||
<template #actions>
|
||||
<QBtn
|
||||
icon="delete"
|
||||
flat
|
||||
|
@ -147,25 +140,12 @@ onMounted(async () => {
|
|||
rounded
|
||||
@click.stop="goToAddressDetails(address.id)"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</CardList>
|
||||
</QList>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.address-item {
|
||||
.actions-wrapper {
|
||||
visibility: hidden;
|
||||
}
|
||||
&:hover {
|
||||
.actions-wrapper {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
addAddress: Add address
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import { ref, inject, onMounted, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import VnTable from 'src/components/ui/VnTable.vue';
|
||||
|
||||
const jApi = inject('jApi');
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -53,32 +55,15 @@ onMounted(() => getPackages());
|
|||
|
||||
<template>
|
||||
<QPage class="flex justify-center q-pa-md">
|
||||
<QTable
|
||||
<VnTable
|
||||
:columns="columns"
|
||||
:rows="packages"
|
||||
:loading="loading"
|
||||
class="q-mt-lg"
|
||||
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>
|
||||
style="height: max-content; max-width: 100%"
|
||||
/>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.packages-table-header {
|
||||
background-color: $accent !important;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
agency: Agency
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<template>Basket view</template>
|
|
@ -343,19 +343,23 @@
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import { date, currency } from 'src/lib/filters.js';
|
||||
import { date as qdate } from 'quasar';
|
||||
import { date, currency, formatDate } from 'src/lib/filters.js';
|
||||
import axios from 'axios';
|
||||
import { useAppStore } from 'stores/app';
|
||||
|
||||
const CancelToken = axios.CancelToken;
|
||||
|
||||
export default {
|
||||
name: 'HederaCatalog',
|
||||
setup() {
|
||||
const appStore = useAppStore();
|
||||
return { appStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uid: 0,
|
||||
search: '',
|
||||
orderDate: qdate.formatDate(new Date(), 'YYYY/MM/DD'),
|
||||
orderDate: formatDate(new Date(), 'YYYY/MM/DD'),
|
||||
category: null,
|
||||
categories: [],
|
||||
type: null,
|
||||
|
@ -446,7 +450,7 @@ export default {
|
|||
if (!value) return;
|
||||
|
||||
const res = await this.$jApi.execQuery(
|
||||
`CALL myBasket_getAvailable;
|
||||
`CALL myOrder_getAvailable(${this.appStore.basketOrderId});
|
||||
SELECT DISTINCT t.id, l.name
|
||||
FROM vn.item i
|
||||
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>
|
||||
<Teleport :to="$actions">
|
||||
<div class="balance">
|
||||
<span class="label">{{ $t('balance') }}</span>
|
||||
<span class="label">{{ t('balance') }}</span>
|
||||
<span class="amount" :class="{ negative: debt < 0 }">
|
||||
{{ currency(debt || 0) }}
|
||||
</span>
|
||||
<QIcon
|
||||
name="info"
|
||||
:title="$t('paymentInfo')"
|
||||
class="info"
|
||||
size="24px"
|
||||
/>
|
||||
<QIcon name="info" class="info" size="sm">
|
||||
<QTooltip max-width="450px">
|
||||
{{ t('paymentInfo') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
<QBtn
|
||||
icon="payments"
|
||||
:label="$t('makePayment')"
|
||||
:label="t('makePayment')"
|
||||
@click="onPayClick()"
|
||||
rounded
|
||||
no-caps
|
||||
/>
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('makePayment') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
to="/ecomerce/basket"
|
||||
:to="{ name: 'basket' }"
|
||||
icon="shopping_cart"
|
||||
:label="$t('shoppingCart')"
|
||||
:label="t('shoppingCart')"
|
||||
rounded
|
||||
no-caps
|
||||
/>
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('shoppingCart') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</Teleport>
|
||||
<div class="vn-w-sm">
|
||||
<QPage class="vn-w-sm">
|
||||
<div
|
||||
v-if="!orders?.length"
|
||||
class="text-subtitle1 text-center text-grey-7 q-pa-md"
|
||||
>
|
||||
{{ $t('noOrdersFound') }}
|
||||
{{ t('noOrdersFound') }}
|
||||
</div>
|
||||
<QCard v-if="orders?.length">
|
||||
<QList bordered separator padding>
|
||||
<QItem
|
||||
v-for="order in orders"
|
||||
:key="order.id"
|
||||
:to="`ticket/${order.id}`"
|
||||
clickable
|
||||
v-ripple
|
||||
>
|
||||
<QItemSection>
|
||||
<QItemLabel>
|
||||
{{ date(order.landed, 'ddd, MMMM Do') }}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>#{{ order.id }}</QItemLabel>
|
||||
<QItemLabel caption>{{ order.nickname }}</QItemLabel>
|
||||
<QItemLabel caption>{{ order.agency }}</QItemLabel>
|
||||
</QItemSection>
|
||||
<QItemSection side top> {{ order.total }}€ </QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QCard>
|
||||
<QList v-if="orders?.length">
|
||||
<CardList
|
||||
v-for="order in orders"
|
||||
:key="order.id"
|
||||
:to="`ticket/${order.id}`"
|
||||
tag="label"
|
||||
>
|
||||
<template #content>
|
||||
<QItemLabel
|
||||
class="full-width text-bold q-mb-sm flex row justify-between"
|
||||
>
|
||||
<span>{{ formatDateTitle(order.landed) }}</span>
|
||||
<span>{{ currency(order.total) }}</span>
|
||||
</QItemLabel>
|
||||
<QItemLabel>#{{ order.id }}</QItemLabel>
|
||||
<QItemLabel>{{ order.nickname }}</QItemLabel>
|
||||
<QItemLabel>{{ order.agency }}</QItemLabel>
|
||||
</template>
|
||||
</CardList>
|
||||
</QList>
|
||||
<QPageSticky>
|
||||
<QBtn
|
||||
fab
|
||||
icon="add_shopping_cart"
|
||||
color="accent"
|
||||
to="/ecomerce/catalog"
|
||||
:title="$t('startOrder')"
|
||||
:to="{ name: 'catalog' }"
|
||||
:title="t('startOrder')"
|
||||
/>
|
||||
</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>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -92,50 +157,6 @@
|
|||
}
|
||||
</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">
|
||||
en-US:
|
||||
startOrder: Start order
|
||||
|
@ -148,6 +169,7 @@ en-US:
|
|||
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.
|
||||
amountToPay: 'Amount to pay (€):'
|
||||
es-ES:
|
||||
startOrder: Empezar pedido
|
||||
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
|
||||
cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
|
||||
cantidad que desees.
|
||||
amountToPay: 'Cantidad a pagar (€):'
|
||||
ca-ES:
|
||||
startOrder: Començar encàrrec
|
||||
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
|
||||
lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
|
||||
e introdueix la quantitat que vulguis.
|
||||
amountToPay: 'Quantitat a pagar (€):'
|
||||
fr-FR:
|
||||
startOrder: Acheter
|
||||
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
|
||||
voulez faire un versement, le montant suggéré effacé et entrez le montant que
|
||||
vous souhaitez.
|
||||
amountToPay: 'Montant à payer (€):'
|
||||
pt-PT:
|
||||
startOrder: Iniciar encomenda
|
||||
noOrdersFound: Nenhum pedido encontrado
|
||||
|
@ -196,4 +221,5 @@ pt-PT:
|
|||
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.
|
||||
amountToPay: 'Valor a pagar (€):'
|
||||
</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 { appStore } from 'stores/app'
|
||||
import { route } from 'quasar/wrappers';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import {
|
||||
createRouter,
|
||||
createMemoryHistory,
|
||||
createWebHistory,
|
||||
createWebHashHistory
|
||||
} from 'vue-router'
|
||||
import routes from './routes'
|
||||
} from 'vue-router';
|
||||
import routes from './routes';
|
||||
import { i18n } from 'src/boot/i18n';
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
|
@ -22,7 +23,7 @@ export default route(function (/* { store, ssrContext } */) {
|
|||
? createMemoryHistory
|
||||
: process.env.VUE_ROUTER_MODE === 'history'
|
||||
? createWebHistory
|
||||
: createWebHashHistory
|
||||
: createWebHashHistory;
|
||||
|
||||
const Router = createRouter({
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
|
@ -34,18 +35,18 @@ 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()
|
||||
if (from.name === to.name) return;
|
||||
const app = useAppStore();
|
||||
app.$patch({
|
||||
title: window.i18n.t(to.name || 'home'),
|
||||
title: i18n.global.t(to.name || 'home'),
|
||||
subtitle: null,
|
||||
useRightDrawer: false,
|
||||
rightDrawerOpen: true
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
return Router
|
||||
})
|
||||
return Router;
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ const routes = [
|
|||
component: () => import('layouts/LoginLayout.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'Login',
|
||||
name: 'login',
|
||||
path: '/login/:email?',
|
||||
component: () => import('pages/Login/LoginView.vue')
|
||||
},
|
||||
|
@ -35,19 +35,24 @@ const routes = [
|
|||
component: () => import('src/pages/Cms/HomeView.vue')
|
||||
},
|
||||
{
|
||||
name: 'orders',
|
||||
name: 'confirmedOrders',
|
||||
path: '/ecomerce/orders',
|
||||
component: () => import('pages/Ecomerce/Orders.vue')
|
||||
component: () => import('pages/Ecomerce/OrdersView.vue')
|
||||
},
|
||||
{
|
||||
name: 'ticket',
|
||||
path: '/ecomerce/ticket/:id',
|
||||
component: () => import('pages/Ecomerce/Ticket.vue')
|
||||
component: () => import('pages/Ecomerce/TicketView.vue')
|
||||
},
|
||||
{
|
||||
name: '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',
|
||||
|
@ -55,22 +60,32 @@ const routes = [
|
|||
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',
|
||||
component: () => import('src/pages/Agencies/PackagesView.vue')
|
||||
},
|
||||
{
|
||||
name: 'Account',
|
||||
name: 'accountConfig',
|
||||
path: '/account/conf',
|
||||
component: () => import('pages/Account/AccountConfig.vue')
|
||||
},
|
||||
{
|
||||
name: 'AddressesList',
|
||||
name: 'addressesList',
|
||||
path: '/account/address-list',
|
||||
component: () => import('pages/Account/AddressList.vue')
|
||||
},
|
||||
{
|
||||
name: 'AddressDetails',
|
||||
name: 'addressDetails',
|
||||
path: '/account/address/:id?',
|
||||
component: () => import('pages/Account/AddressDetails.vue')
|
||||
}
|
||||
|
|
|
@ -1,19 +1,52 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { jApi } from 'boot/axios'
|
||||
import { defineStore } from 'pinia';
|
||||
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: () => ({
|
||||
title: null,
|
||||
subtitle: null,
|
||||
imageUrl: '',
|
||||
useRightDrawer: false,
|
||||
rightDrawerOpen: false
|
||||
rightDrawerOpen: false,
|
||||
basketOrderId: null,
|
||||
isHeaderMounted: false
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async loadConfig () {
|
||||
const imageUrl = await jApi.getValue('SELECT url FROM imageConfig')
|
||||
this.$patch({ imageUrl })
|
||||
async init() {
|
||||
this.getBasketOrderId();
|
||||
},
|
||||
|
||||
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 { createPinia } from 'pinia'
|
||||
import { store } from 'quasar/wrappers';
|
||||
import { createPinia } from 'pinia';
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
|
@ -11,10 +11,10 @@ import { createPinia } from 'pinia'
|
|||
*/
|
||||
|
||||
export default store((/* { ssrContext } */) => {
|
||||
const pinia = createPinia()
|
||||
const pinia = createPinia();
|
||||
|
||||
// You can add Pinia plugins here
|
||||
// pinia.use(SomePiniaPlugin)
|
||||
|
||||
return pinia
|
||||
})
|
||||
return pinia;
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue