0
1
Fork 0

Merge pull request 'Home view adjustments' (!70) from wbuezas/hedera-web-mindshore:feature/HomeViewAdjustments into 4922-vueMigration

Reviewed-on: verdnatura/hedera-web#70
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
This commit is contained in:
Javier Segarra 2024-07-19 12:17:13 +00:00
commit d589b89a62
7 changed files with 425 additions and 271 deletions

View File

@ -7,12 +7,12 @@ module.exports = {
parserOptions: { parserOptions: {
parser: '@babel/eslint-parser', parser: '@babel/eslint-parser',
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports sourceType: 'module' // Allows for the use of imports
}, },
env: { env: {
browser: true, browser: true,
'vue/setup-compiler-macros': true, 'vue/setup-compiler-macros': true
}, },
extends: [ extends: [
@ -26,7 +26,7 @@ module.exports = {
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
'standard', 'standard'
], ],
plugins: ['vue', 'prettier'], plugins: ['vue', 'prettier'],
@ -41,7 +41,7 @@ module.exports = {
__QUASAR_SSR_PWA__: 'readonly', __QUASAR_SSR_PWA__: 'readonly',
process: 'readonly', process: 'readonly',
Capacitor: 'readonly', Capacitor: 'readonly',
chrome: 'readonly', chrome: 'readonly'
}, },
// add your custom rules here // add your custom rules here
@ -66,7 +66,7 @@ module.exports = {
'prefer-promise-reject-errors': 'off', 'prefer-promise-reject-errors': 'off',
semi: 'off', semi: 'off',
// allow debugger during development only // allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}, },
overrides: [ overrides: [
{ {
@ -75,8 +75,8 @@ module.exports = {
rules: { rules: {
semi: 'off', semi: 'off',
indent: ['error', 4, { SwitchCase: 1 }], indent: ['error', 4, { SwitchCase: 1 }],
'space-before-function-paren': 'off', 'space-before-function-paren': 'off'
}, }
}, }
], ]
}; };

View File

@ -5,17 +5,26 @@ Hedera is the main web page for Verdnatura.
## Getting Started ## Getting Started
Required dependencies. Required dependencies.
* PHP >= 7.0
* Node.js >= 8.0 - PHP >= 7.0
- Node.js >= 8.0
Launch application for development. Launch application for development.
``` ```
$ npm run dev $ npm run dev
``` ```
Launch project backend.
```
$ php -S 127.0.0.1:3002 -t . index.php
Run server side method from command line. Run server side method from command line.
``` ```
$ php hedera-web.php -m method_path $ php hedera-web.php -m method_path
``` ```
## Built with ## Built with
@ -23,3 +32,4 @@ $ php hedera-web.php -m method_path
* [Webpack](https://webpack.js.org/) * [Webpack](https://webpack.js.org/)
* [MooTools](https://mootools.net/) * [MooTools](https://mootools.net/)
* [TinyMCE](https://www.tinymce.com/) * [TinyMCE](https://www.tinymce.com/)
```

View File

@ -8,10 +8,10 @@
// Configuration for your app // Configuration for your app
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js // https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js
const ESLintPlugin = require('eslint-webpack-plugin') const ESLintPlugin = require('eslint-webpack-plugin');
const path = require('path') const path = require('path');
const { configure } = require('quasar/wrappers') const { configure } = require('quasar/wrappers');
module.exports = configure(function (ctx) { module.exports = configure(function (ctx) {
return { return {
@ -24,19 +24,10 @@ 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: [ boot: ['i18n', 'axios', 'error-handler', 'app'],
'i18n',
'axios',
'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: [ css: ['app.scss', 'width.scss', 'responsive.scss'],
'app.scss',
'width.scss',
'responsive.scss'
],
// https://github.com/quasarframework/quasar/tree/dev/extras // https://github.com/quasarframework/quasar/tree/dev/extras
extras: [ extras: [
@ -77,8 +68,9 @@ 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
chainWebpack(chain) { chainWebpack(chain) {
chain.plugin('eslint-webpack-plugin') chain
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]) .plugin('eslint-webpack-plugin')
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
chain.module chain.module
.rule('i18n-resource') .rule('i18n-resource')
@ -87,15 +79,14 @@ module.exports = configure(function (ctx) {
.end() .end()
.type('javascript/auto') .type('javascript/auto')
.use('i18n-resource') .use('i18n-resource')
.loader('@intlify/vue-i18n-loader') .loader('@intlify/vue-i18n-loader');
chain.module chain.module
.rule('i18n') .rule('i18n')
.resourceQuery(/blockType=i18n/) .resourceQuery(/blockType=i18n/)
.type('javascript/auto') .type('javascript/auto')
.use('i18n') .use('i18n')
.loader('@intlify/vue-i18n-loader') .loader('@intlify/vue-i18n-loader');
} }
}, },
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-devServer // Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-devServer
@ -112,7 +103,7 @@ module.exports = configure(function (ctx) {
'/api': 'http://localhost:3000', '/api': 'http://localhost:3000',
'/': { '/': {
target: 'http://localhost:3001', target: 'http://localhost:3001',
bypass: (req) => req.path !== '/' ? req.path : null bypass: req => (req.path !== '/' ? req.path : null)
} }
} }
}, },
@ -132,9 +123,7 @@ module.exports = configure(function (ctx) {
// directives: [], // directives: [],
// Quasar plugins // Quasar plugins
plugins: [ plugins: ['Notify']
'Notify'
]
}, },
// animations: 'all', // --- includes all animations // animations: 'all', // --- includes all animations
@ -155,8 +144,9 @@ module.exports = configure(function (ctx) {
// 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.plugin('eslint-webpack-plugin') chain
.use(ESLintPlugin, [{ extensions: ['js'] }]) .plugin('eslint-webpack-plugin')
.use(ESLintPlugin, [{ extensions: ['js'] }]);
}, },
middlewares: [ middlewares: [
@ -174,14 +164,15 @@ module.exports = configure(function (ctx) {
// if using workbox in InjectManifest mode // if using workbox in InjectManifest mode
chainWebpackCustomSW(chain) { chainWebpackCustomSW(chain) {
chain.plugin('eslint-webpack-plugin') chain
.use(ESLintPlugin, [{ extensions: ['js'] }]) .plugin('eslint-webpack-plugin')
.use(ESLintPlugin, [{ extensions: ['js'] }]);
}, },
manifest: { manifest: {
name: 'Hedera', name: 'Hedera',
short_name: 'Hedera', short_name: 'Hedera',
description: 'Verdnatura\'s webshop', description: "Verdnatura's webshop",
display: 'standalone', display: 'standalone',
orientation: 'portrait', orientation: 'portrait',
background_color: '#ffffff', background_color: '#ffffff',
@ -232,13 +223,11 @@ module.exports = configure(function (ctx) {
packager: { packager: {
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
// OS X / Mac App Store // OS X / Mac App Store
// appBundleId: '', // appBundleId: '',
// appCategoryType: '', // appCategoryType: '',
// osxSign: '', // osxSign: '',
// protocol: 'myapp://path', // protocol: 'myapp://path',
// Windows only // Windows only
// win32metadata: { ... } // win32metadata: { ... }
}, },
@ -252,15 +241,16 @@ 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.plugin('eslint-webpack-plugin') chain
.use(ESLintPlugin, [{ extensions: ['js'] }]) .plugin('eslint-webpack-plugin')
.use(ESLintPlugin, [{ extensions: ['js'] }]);
}, },
chainWebpackPreload(chain) { chainWebpackPreload(chain) {
chain.plugin('eslint-webpack-plugin') chain
.use(ESLintPlugin, [{ extensions: ['js'] }]) .plugin('eslint-webpack-plugin')
} .use(ESLintPlugin, [{ extensions: ['js'] }]);
} }
} }
}) };
});

View File

@ -1,7 +1,7 @@
import { boot } from 'quasar/wrappers' import { boot } from 'quasar/wrappers';
import { Connection } from '../js/db/connection' import { Connection } from '../js/db/connection';
import { userStore } from 'stores/user' import { userStore } from 'stores/user';
import axios from 'axios' import axios from 'axios';
// Be careful when using SSR for cross-request state pollution // Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here; // due to creating a Singleton instance here;
@ -11,32 +11,33 @@ import axios from 'axios'
// for each client) // for each client)
const api = axios.create({ const api = axios.create({
baseURL: `//${location.hostname}:${location.port}/api/` baseURL: `//${location.hostname}:${location.port}/api/`
}) });
const jApi = new Connection() const jApi = new Connection();
export default boot(({ app }) => { export default boot(({ app }) => {
const user = userStore() const user = userStore();
function addToken(config) { function addToken(config) {
if (user.token) { if (user.token) {
config.headers.Authorization = user.token config.headers.Authorization = user.token;
} }
return config return config;
} }
api.interceptors.request.use(addToken) api.interceptors.request.use(addToken);
jApi.use(addToken) jApi.use(addToken);
// for use inside Vue files (Options API) through this.$axios and this.$api // for use inside Vue files (Options API) through this.$axios and this.$api
app.config.globalProperties.$axios = axios app.config.globalProperties.$axios = axios;
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
// so you won't necessarily have to import axios in each vue file // so you won't necessarily have to import axios in each vue file
app.config.globalProperties.$api = api app.config.globalProperties.$api = api;
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
// so you can easily perform requests against your app's API // so you can easily perform requests against your app's API
app.config.globalProperties.$jApi = jApi app.config.globalProperties.$jApi = jApi;
}) app.provide('jApi', jApi);
});
export { api, jApi } export { api, jApi };

View File

@ -0,0 +1,66 @@
<script setup>
import { ref, computed } from 'vue';
import { appStore } from 'stores/app';
const $props = defineProps({
baseURL: {
type: String,
default: null
},
storage: {
type: [String, Number],
default: 'Images'
},
size: {
type: String,
default: 'full'
},
zoomSize: {
type: String,
required: false,
default: 'lg'
},
id: {
type: Number,
required: true
}
});
const app = appStore();
const show = ref(false);
const url = computed(() => {
return `${$props.baseURL ?? app.imageUrl}/${$props.storage}/${$props.size}/${$props.id}`;
});
</script>
<template>
<QImg
:class="{ zoomIn: $props.zoomSize }"
:src="url"
v-bind="$attrs"
@click="show = !show"
spinner-color="primary"
/>
<QDialog v-model="show" v-if="$props.zoomSize">
<QImg
:src="url"
size="full"
class="img_zoom"
v-bind="$attrs"
spinner-color="primary"
/>
</QDialog>
</template>
<style lang="scss" scoped>
.q-img {
&.zoomIn {
cursor: zoom-in;
}
min-width: 50px;
}
.rounded {
border-radius: 50%;
}
.img_zoom {
border-radius: 0%;
}
</style>

View File

@ -0,0 +1,87 @@
<script setup>
import { ref, onMounted, inject } from 'vue';
import VnImg from 'src/components/ui/VnImg.vue';
const jApi = inject('jApi');
const news = ref([]);
const showPreview = ref(false);
const selectedImageSrc = ref('');
const fetchData = async () => {
news.value = await jApi.query(
`SELECT title, text, image, id
FROM news
ORDER BY priority, created DESC`
);
};
onMounted(async () => await fetchData());
</script>
<template>
<div style="padding: 0">
<div class="q-pa-sm row items-start">
<div class="new-card q-pa-sm" v-for="myNew in news" :key="myNew.id">
<QCard>
<VnImg :id="myNew.image" storage="news" />
<QCardSection>
<div class="text-h5">{{ myNew.title }}</div>
</QCardSection>
<QCardSection class="new-body">
<div v-html="myNew.text" class="card-text" />
</QCardSection>
</QCard>
</div>
</div>
<QPageSticky>
<QBtn
fab
icon="add_shopping_cart"
color="accent"
to="/ecomerce/catalog"
:title="$t('startOrder')"
/>
</QPageSticky>
</div>
<QDialog v-model="showPreview" @hide="selectedImageSrc = ''">
<QImg :src="selectedImageSrc" />
</QDialog>
</template>
<style lang="scss" scoped>
.new-card {
width: 100%;
@media screen and (min-width: 800px) and (max-width: 1400px) {
width: 50%;
}
@media screen and (min-width: 1401px) and (max-width: 1920px) {
width: 33.33%;
}
@media screen and (min-width: 19021) {
width: 25%;
}
}
.new-body {
font-family: 'Open Sans';
}
.card-text {
:deep(a) {
color: $accent;
}
}
</style>
<i18n lang="yaml">
en-US:
startOrder: Start order
es-ES:
startOrder: Empezar pedido
ca-ES:
startOrder: Començar comanda
fr-FR:
startOrder: Lancer commande
pt-PT:
startOrder: Comece uma encomenda
</i18n>

View File

@ -27,12 +27,12 @@ const routes = [
{ {
name: '', name: '',
path: '', path: '',
component: () => import('src/pages/Cms/Home.vue') component: () => import('src/pages/Cms/HomeView.vue')
}, },
{ {
name: 'home', name: 'home',
path: '/cms/home', path: '/cms/home',
component: () => import('src/pages/Cms/Home.vue') component: () => import('src/pages/Cms/HomeView.vue')
}, },
{ {
name: 'orders', name: 'orders',
@ -63,6 +63,6 @@ const routes = [
path: '/:catchAll(.*)*', path: '/:catchAll(.*)*',
component: () => import('pages/ErrorNotFound.vue') component: () => import('pages/ErrorNotFound.vue')
} }
] ];
export default routes export default routes;