0
1
Fork 0

More linting and formatting

This commit is contained in:
William Buezas 2024-07-16 22:02:31 -03:00
parent e0cc4e40ba
commit bf2094163d
17 changed files with 1416 additions and 1367 deletions

View File

@ -15,22 +15,19 @@ module.exports = {
'vue/setup-compiler-macros': true,
},
extends: [
// Base ESLint recommended rules
// 'eslint:recommended',
// Uncomment any of the lines below to choose desired strictness,
// but leave only one uncommented!
// See https://eslint.vuejs.org/rules/#available-rules
'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
'standard'
],
extends: [
// Base ESLint recommended rules
// 'eslint:recommended',
// Uncomment any of the lines below to choose desired strictness,
// but leave only one uncommented!
// See https://eslint.vuejs.org/rules/#available-rules
'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
'standard',
],
plugins: ['vue', 'prettier'],
@ -71,13 +68,14 @@ module.exports = {
// allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
},
overrides: [
overrides: [
{
extends: ['plugin:vue/vue3-essential'],
files: ['src/**/*.{js,vue,scss}'], // Aplica ESLint solo a archivos .js, .vue y .scss dentro de src (Proyecto de quasar)
rules: {
semi: 'off',
indent: ['error', 4, { SwitchCase: 1 }],
semi: 'off',
indent: ['error', 4, { SwitchCase: 1 }],
'space-before-function-paren': 'off',
},
},
],

View File

@ -3,7 +3,7 @@ module.exports = {
tabWidth: 4,
useTabs: false,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: true,
arrowParens: 'avoid',
trailingComma: 'none'
};

13
.vscode/settings.json vendored
View File

@ -4,14 +4,7 @@
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.fixAll.eslint"
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"vue"
],
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": ["source.fixAll.eslint"],
"eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"]
}

View File

@ -1,11 +1,11 @@
<template>
<router-view />
<router-view />
</template>
<script>
import { defineComponent } from 'vue'
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App'
})
});
</script>

View File

@ -1,34 +1,34 @@
<template>
<QLayout
id="bg"
class="fullscreen row justify-center items-center layout-view scroll"
>
<div class="column q-pa-md row items-center justify-center">
<router-view v-slot="{ Component }">
<transition>
<component :is="Component" />
</transition>
</router-view>
</div>
</QLayout>
<QLayout
id="bg"
class="fullscreen row justify-center items-center layout-view scroll"
>
<div class="column q-pa-md row items-center justify-center">
<router-view v-slot="{ Component }">
<transition>
<component :is="Component" />
</transition>
</router-view>
</div>
</QLayout>
</template>
<style lang="scss" scoped>
#bg {
background: white;
background: white;
}
.column {
width: 270px;
overflow: hidden;
width: 270px;
overflow: hidden;
& > * {
width: 100%;
}
& > * {
width: 100%;
}
}
</style>
<script>
export default {
name: 'LoginLayout'
}
};
</script>

View File

@ -1,129 +1,131 @@
<template>
<QLayout view="lHh Lpr lFf">
<QHeader>
<QToolbar>
<QBtn
flat
dense
round
icon="menu"
aria-label="Menu"
@click="toggleLeftDrawer"
/>
<QToolbarTitle>
{{ $app.title }}
<div v-if="$app.subtitle" class="subtitle text-caption">
{{ $app.subtitle }}
</div>
</QToolbarTitle>
<div id="actions" ref="actions"></div>
<QBtn
v-if="$app.useRightDrawer"
@click="$app.rightDrawerOpen = !$app.rightDrawerOpen"
aria-label="Menu"
flat
dense
round
>
<QIcon name="menu" />
</QBtn>
</QToolbar>
</QHeader>
<QDrawer v-model="leftDrawerOpen" :width="250" show-if-above>
<QToolbar class="logo">
<img src="statics/logo-dark.svg" />
</QToolbar>
<div class="user-info">
<div>
<span id="user-name">{{ user.nickname }}</span>
<QBtn flat icon="logout" alt="_Exit" @click="logout()" />
</div>
<div id="supplant" class="supplant">
<span id="supplanted">{{ supplantedUser }}</span>
<QBtn flat icon="logout" alt="_Exit" />
</div>
</div>
<QList v-for="item in essentialLinks" :key="item.id">
<QItem v-if="!item.childs" :to="`/${item.path}`">
<QItemSection>
<QItemLabel>{{ item.description }}</QItemLabel>
</QItemSection>
</QItem>
<QExpansionItem
v-if="item.childs"
:label="item.description"
expand-separator
>
<QList>
<QItem
v-for="subitem in item.childs"
:key="subitem.id"
:to="`/${subitem.path}`"
class="q-pl-lg"
>
<QItemSection>
<QItemLabel>{{ subitem.description }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</QExpansionItem>
</QList>
</QDrawer>
<QPageContainer>
<router-view />
</QPageContainer>
</QLayout>
<QLayout view="lHh Lpr lFf">
<QHeader>
<QToolbar>
<QBtn
flat
dense
round
icon="menu"
aria-label="Menu"
@click="toggleLeftDrawer"
/>
<QToolbarTitle>
{{ $app.title }}
<div v-if="$app.subtitle" class="subtitle text-caption">
{{ $app.subtitle }}
</div>
</QToolbarTitle>
<div id="actions" ref="actions"></div>
<QBtn
v-if="$app.useRightDrawer"
@click="$app.rightDrawerOpen = !$app.rightDrawerOpen"
aria-label="Menu"
flat
dense
round
>
<QIcon name="menu" />
</QBtn>
</QToolbar>
</QHeader>
<QDrawer v-model="leftDrawerOpen" :width="250" show-if-above>
<QToolbar class="logo">
<img src="statics/logo-dark.svg" />
</QToolbar>
<div class="user-info">
<div>
<span id="user-name">{{ user.nickname }}</span>
<QBtn flat icon="logout" alt="_Exit" @click="logout()" />
</div>
<div id="supplant" class="supplant">
<span id="supplanted">{{ supplantedUser }}</span>
<QBtn flat icon="logout" alt="_Exit" />
</div>
</div>
<QList v-for="item in essentialLinks" :key="item.id">
<QItem v-if="!item.childs" :to="`/${item.path}`">
<QItemSection>
<QItemLabel>{{ item.description }}</QItemLabel>
</QItemSection>
</QItem>
<QExpansionItem
v-if="item.childs"
:label="item.description"
expand-separator
>
<QList>
<QItem
v-for="subitem in item.childs"
:key="subitem.id"
:to="`/${subitem.path}`"
class="q-pl-lg"
>
<QItemSection>
<QItemLabel>
{{ subitem.description }}
</QItemLabel>
</QItemSection>
</QItem>
</QList>
</QExpansionItem>
</QList>
</QDrawer>
<QPageContainer>
<router-view />
</QPageContainer>
</QLayout>
</template>
<style lang="scss" scoped>
.q-toolbar {
min-height: 64px;
min-height: 64px;
}
.logo {
background-color: $primary;
justify-content: center;
background-color: $primary;
justify-content: center;
& > img {
width: 160px;
}
& > img {
width: 160px;
}
}
.user-info {
margin: 25px;
margin: 25px;
& > div {
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
border: 1px solid #eaeaea;
& > span {
padding: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: bold;
}
.q-btn {
display: block;
margin: 0;
padding: 9px;
border-radius: 0;
&:hover {
background-color: #1a1a1a;
color: white;
}
}
&.supplant {
display: none;
border-top: none;
&.show {
& > div {
display: flex;
}
justify-content: space-between;
align-items: center;
overflow: hidden;
border: 1px solid #eaeaea;
& > span {
padding: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: bold;
}
.q-btn {
display: block;
margin: 0;
padding: 9px;
border-radius: 0;
&:hover {
background-color: #1a1a1a;
color: white;
}
}
&.supplant {
display: none;
border-top: none;
&.show {
display: flex;
}
}
}
}
}
</style>
@ -131,107 +133,107 @@
@import 'src/css/responsive';
.q-drawer {
.q-item {
padding-left: 38px;
}
.q-list .q-list .q-item {
padding-left: 50px;
}
.q-item {
padding-left: 38px;
}
.q-list .q-list .q-item {
padding-left: 50px;
}
}
.q-page-container > * {
padding: 16px;
padding: 16px;
}
#actions > div {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
@include mobile {
#actions > div {
.q-btn {
border-radius: 50%;
padding: 10px;
#actions > div {
.q-btn {
border-radius: 50%;
padding: 10px;
&__content {
& > .q-icon {
margin-right: 0;
&__content {
& > .q-icon {
margin-right: 0;
}
& > .block {
display: none !important;
}
}
}
& > .block {
display: none !important;
}
}
}
}
}
</style>
<script>
import { defineComponent, ref } from 'vue'
import { userStore } from 'stores/user'
import { defineComponent, ref } from 'vue';
import { userStore } from 'stores/user';
export default defineComponent({
name: 'MainLayout',
props: {},
setup () {
const leftDrawerOpen = ref(false)
setup() {
const leftDrawerOpen = ref(false);
return {
user: userStore(),
supplantedUser: ref(''),
essentialLinks: ref(null),
leftDrawerOpen,
toggleLeftDrawer () {
leftDrawerOpen.value = !leftDrawerOpen.value
toggleLeftDrawer() {
leftDrawerOpen.value = !leftDrawerOpen.value;
}
}
};
},
async mounted () {
this.$refs.actions.appendChild(this.$actions)
await this.user.loadData()
await this.$app.loadConfig()
await this.fetchData()
async mounted() {
this.$refs.actions.appendChild(this.$actions);
await this.user.loadData();
await this.$app.loadConfig();
await this.fetchData();
},
methods: {
async fetchData () {
const sections = await this.$jApi.query('SELECT * FROM myMenu')
async fetchData() {
const sections = await this.$jApi.query('SELECT * FROM myMenu');
const sectionMap = new Map()
const sectionMap = new Map();
for (const section of sections) {
sectionMap.set(section.id, section)
sectionMap.set(section.id, section);
}
const sectionTree = []
const sectionTree = [];
for (const section of sections) {
const parent = section.parentFk
const parent = section.parentFk;
if (parent) {
const parentSection = sectionMap.get(parent)
if (!parentSection) continue
let childs = parentSection.childs
const parentSection = sectionMap.get(parent);
if (!parentSection) continue;
let childs = parentSection.childs;
if (!childs) {
childs = parentSection.childs = []
childs = parentSection.childs = [];
}
childs.push(section)
childs.push(section);
} else {
sectionTree.push(section)
sectionTree.push(section);
}
}
this.essentialLinks = sectionTree
this.essentialLinks = sectionTree;
},
async logout () {
this.user.logout()
this.$router.push('/login')
async logout() {
this.user.logout();
this.$router.push('/login');
}
}
})
});
</script>
<i18n lang="yaml">
en-US:
visitor: Visitor
visitor: Visitor
es-ES:
visitor: Visitante
visitor: Visitante
</i18n>

View File

@ -1,76 +1,77 @@
<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>
<QImg :src="`${$app.imageUrl}/news/full/${myNew.image}`"> </QImg>
<QCardSection>
<div class="text-h5">{{ myNew.title }}</div>
</QCardSection>
<QCardSection class="new-body">
<div v-html="myNew.text" />
</QCardSection>
</QCard>
</div>
<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>
<QImg :src="`${$app.imageUrl}/news/full/${myNew.image}`">
</QImg>
<QCardSection>
<div class="text-h5">{{ myNew.title }}</div>
</QCardSection>
<QCardSection class="new-body">
<div v-html="myNew.text" />
</QCardSection>
</QCard>
</div>
</div>
<QPageSticky>
<QBtn
fab
icon="add_shopping_cart"
color="accent"
to="/ecomerce/catalog"
:title="$t('startOrder')"
/>
</QPageSticky>
</div>
<QPageSticky>
<QBtn
fab
icon="add_shopping_cart"
color="accent"
to="/ecomerce/catalog"
:title="$t('startOrder')"
/>
</QPageSticky>
</div>
</template>
<style lang="scss" scoped>
.new-card {
width: 100%;
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%;
}
@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';
font-family: 'Open Sans';
}
</style>
<script>
export default {
name: 'PageIndex',
data () {
data() {
return {
news: []
}
};
},
async mounted () {
async mounted() {
this.news = await this.$jApi.query(
`SELECT title, text, image, id
FROM news
ORDER BY priority, created DESC`
)
);
}
}
};
</script>
<i18n lang="yaml">
en-US:
startOrder: Start order
startOrder: Start order
es-ES:
startOrder: Empezar pedido
startOrder: Empezar pedido
ca-ES:
startOrder: Començar comanda
startOrder: Començar comanda
fr-FR:
startOrder: Lancer commande
startOrder: Lancer commande
pt-PT:
startOrder: Comece uma encomenda
startOrder: Comece uma encomenda
</i18n>

File diff suppressed because it is too large Load Diff

View File

@ -1,86 +1,96 @@
<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') }}
<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>
<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'
import { date, currency } from 'src/lib/filters.js';
export default {
name: 'OrdersPendingIndex',
data () {
const curYear = new Date().getFullYear()
const years = []
data() {
const curYear = new Date().getFullYear();
const years = [];
for (let year = curYear - 5; year <= curYear; year++) {
years.push(year)
years.push(year);
}
return {
columns: [
{ name: 'ref', label: 'serial', field: 'ref', align: 'left' },
{ name: 'issued', label: 'issued', field: 'issued', align: 'left' },
{
name: 'issued',
label: 'issued',
field: 'issued',
align: 'left'
},
{ name: 'amount', label: 'amount', field: 'amount' },
{ name: 'hasPdf', label: 'download', field: 'hasPdf', align: 'center' }
{
name: 'hasPdf',
label: 'download',
field: 'hasPdf',
align: 'center'
}
],
pagination: {
rowsPerPage: 0
@ -88,16 +98,16 @@ export default {
year: curYear,
years,
invoices: null
}
};
},
async mounted () {
await this.loadData()
async mounted() {
await this.loadData();
},
watch: {
async year () {
await this.loadData()
async year() {
await this.loadData();
}
},
@ -105,11 +115,11 @@ export default {
date,
currency,
async loadData () {
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
@ -117,57 +127,57 @@ export default {
ORDER BY issued DESC
LIMIT 500`,
params
)
);
},
invoiceUrl (id) {
invoiceUrl(id) {
return (
'?' +
new URLSearchParams({
srv: 'rest:dms/invoice',
invoice: id,
access_token: this.$user.token
}).toString()
)
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
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
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
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
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
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>

View File

@ -1,194 +1,199 @@
<template>
<Teleport :to="$actions">
<div class="balance">
<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" />
</div>
<QBtn
icon="payments"
:label="$t('makePayment')"
@click="onPayClick()"
rounded
no-caps
/>
<QBtn
to="/ecomerce/basket"
icon="shopping_cart"
:label="$t('shoppingCart')"
rounded
no-caps
/>
</Teleport>
<div class="vn-w-sm">
<div
v-if="!orders?.length"
class="text-subtitle1 text-center text-grey-7 q-pa-md"
>
{{ $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
<Teleport :to="$actions">
<div class="balance">
<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"
/>
</div>
<QBtn
icon="payments"
:label="$t('makePayment')"
@click="onPayClick()"
rounded
no-caps
/>
<QBtn
to="/ecomerce/basket"
icon="shopping_cart"
:label="$t('shoppingCart')"
rounded
no-caps
/>
</Teleport>
<div class="vn-w-sm">
<div
v-if="!orders?.length"
class="text-subtitle1 text-center text-grey-7 q-pa-md"
>
<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>
<QPageSticky>
<QBtn
fab
icon="add_shopping_cart"
color="accent"
to="/ecomerce/catalog"
:title="$t('startOrder')"
/>
</QPageSticky>
</div>
{{ $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>
<QPageSticky>
<QBtn
fab
icon="add_shopping_cart"
color="accent"
to="/ecomerce/catalog"
:title="$t('startOrder')"
/>
</QPageSticky>
</div>
</template>
<style lang="scss" scoped>
.balance {
margin-right: 8px;
white-space: nowrap;
display: inline-block;
margin-right: 8px;
white-space: nowrap;
display: inline-block;
& > * {
vertical-align: middle;
}
& > .amount {
padding: 4px;
margin: 0 4px;
&.negative {
background-color: #e55;
border-radius: 2px;
box-shadow: 0 0 5px #333;
& > * {
vertical-align: middle;
}
& > .amount {
padding: 4px;
margin: 0 4px;
&.negative {
background-color: #e55;
border-radius: 2px;
box-shadow: 0 0 5px #333;
}
}
& > .info {
cursor: pointer;
}
}
& > .info {
cursor: pointer;
}
}
</style>
<script>
import { date, currency } from 'src/lib/filters.js'
import { tpvStore } from 'stores/tpv'
import { date, currency } from 'src/lib/filters.js';
import { tpvStore } from 'stores/tpv';
export default {
name: 'OrdersPendingIndex',
data () {
data() {
return {
orders: null,
debt: 0,
tpv: tpvStore()
}
};
},
async mounted () {
await this.tpv.check(this.$route)
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)')
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
async onPayClick() {
let amount = -this.debt;
amount = amount <= 0 ? null : amount;
let defaultAmountStr = ''
let defaultAmountStr = '';
if (amount !== null) {
defaultAmountStr = amount
defaultAmountStr = amount;
}
amount = prompt(this.$t('amountToPay'), defaultAmountStr)
amount = prompt(this.$t('amountToPay'), defaultAmountStr);
if (amount != null) {
amount = parseFloat(amount.replace(',', '.'))
await this.tpv.pay(amount)
amount = parseFloat(amount.replace(',', '.'));
await this.tpv.pay(amount);
}
}
}
}
};
</script>
<i18n lang="yaml">
en-US:
startOrder: Start order
noOrdersFound: No orders found
makePayment: Make payment
shoppingCart: Shopping cart
balance: 'Balance:'
paymentInfo: >-
The amount shown is your slope (negative) or favorable balance today, it
disregards future orders. For get your order shipped, this amount must be
equal to or greater than 0. If you want to make a down payment, click the
payment button, delete the suggested amount and enter the amount you want.
startOrder: Start order
noOrdersFound: No orders found
makePayment: Make payment
shoppingCart: Shopping cart
balance: 'Balance:'
paymentInfo: >-
The amount shown is your slope (negative) or favorable balance today, it
disregards future orders. For get your order shipped, this amount must be
equal to or greater than 0. If you want to make a down payment, click the
payment button, delete the suggested amount and enter the amount you want.
es-ES:
startOrder: Empezar pedido
noOrdersFound: No se encontrado pedidos
makePayment: Realizar pago
shoppingCart: Cesta de la compra
balance: 'Saldo:'
paymentInfo: >-
La cantidad mostrada es tu saldo pendiente (negativa) o favorable a día de
hoy, no tiene en cuenta pedidos del futuro. Para que tu pedido sea enviado,
esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
cantidad que desees.
startOrder: Empezar pedido
noOrdersFound: No se encontrado pedidos
makePayment: Realizar pago
shoppingCart: Cesta de la compra
balance: 'Saldo:'
paymentInfo: >-
La cantidad mostrada es tu saldo pendiente (negativa) o favorable a día de
hoy, no tiene en cuenta pedidos del futuro. Para que tu pedido sea enviado,
esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
cantidad que desees.
ca-ES:
startOrder: Començar encàrrec
noOrdersFound: No s'han trobat comandes
makePayment: Realitzar pagament
shoppingCart: Cistella de la compra
balance: 'Saldo:'
paymentInfo: >-
La quantitat mostrada és el teu saldo pendent (negatiu) o favorable a dia
d'avui, no en compte comandes del futur. Perquè la teva comanda sigui
enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
e introdueix la quantitat que vulguis.
startOrder: Començar encàrrec
noOrdersFound: No s'han trobat comandes
makePayment: Realitzar pagament
shoppingCart: Cistella de la compra
balance: 'Saldo:'
paymentInfo: >-
La quantitat mostrada és el teu saldo pendent (negatiu) o favorable a dia
d'avui, no en compte comandes del futur. Perquè la teva comanda sigui
enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
e introdueix la quantitat que vulguis.
fr-FR:
startOrder: Acheter
noOrdersFound: Aucune commande trouvée
makePayment: Effectuer un paiement
shoppingCart: Panier
balance: 'Balance:'
paymentInfo: >-
Le montant indiqué est votre pente (négative) ou balance favorable
aujourd'hui, ne tient pas compte pour les commandes futures. Obtenir votre
commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
voulez faire un versement, le montant suggéré effacé et entrez le montant que
vous souhaitez.
startOrder: Acheter
noOrdersFound: Aucune commande trouvée
makePayment: Effectuer un paiement
shoppingCart: Panier
balance: 'Balance:'
paymentInfo: >-
Le montant indiqué est votre pente (négative) ou balance favorable
aujourd'hui, ne tient pas compte pour les commandes futures. Obtenir votre
commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
voulez faire un versement, le montant suggéré effacé et entrez le montant que
vous souhaitez.
pt-PT:
startOrder: Iniciar encomenda
noOrdersFound: Nenhum pedido encontrado
makePayment: Realizar pagamento
shoppingCart: Cesta da compra
balance: 'Saldo:'
paymentInfo: >-
A quantidade mostrada é seu saldo pendente (negativo) ou favorável a dia de
hoje, não se vincula a pedidos futuros. Para que seu pedido seja enviado, esta
quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
a quantidade que deseje.
startOrder: Iniciar encomenda
noOrdersFound: Nenhum pedido encontrado
makePayment: Realizar pagamento
shoppingCart: Cesta da compra
balance: 'Saldo:'
paymentInfo: >-
A quantidade mostrada é seu saldo pendente (negativo) ou favorável a dia de
hoje, não se vincula a pedidos futuros. Para que seu pedido seja enviado, esta
quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
a quantidade que deseje.
</i18n>

View File

@ -1,136 +1,145 @@
<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>
<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;
justify-content: flex-end;
}
</style>
<script>
import { date, currency } from 'src/lib/filters.js'
import { date, currency } from 'src/lib/filters.js';
export default {
name: 'OrdersConfirmedView',
data () {
data() {
return {
ticket: {},
rows: null,
services: null,
packages: null
}
};
},
async mounted () {
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.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
discountSubtotal(line) {
return line.quantity * line.price;
},
subtotal (line) {
const discount = line.discount
return this.discountSubtotal(line) * ((100 - discount) / 100)
subtotal(line) {
const discount = line.discount;
return this.discountSubtotal(line) * ((100 - discount) / 100);
},
onPrintClick () {
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>

View File

@ -1,29 +1,31 @@
<template>
<div
class="fullscreen bg-accent text-white text-center q-pa-md flex flex-center"
>
<div>
<div style="font-size: 30vh">404</div>
<div
class="fullscreen bg-accent text-white text-center q-pa-md flex flex-center"
>
<div>
<div style="font-size: 30vh">404</div>
<div class="text-h2" style="opacity: 0.4">Oops. Nothing here...</div>
<div class="text-h2" style="opacity: 0.4">
Oops. Nothing here...
</div>
<QBtn
class="q-mt-xl"
color="white"
text-color="accent"
unelevated
to="/"
label="Go Home"
no-caps
/>
<QBtn
class="q-mt-xl"
color="white"
text-color="accent"
unelevated
to="/"
label="Go Home"
no-caps
/>
</div>
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue'
import { defineComponent } from 'vue';
export default defineComponent({
name: 'ErrorNotFound'
})
});
</script>

View File

@ -1,17 +1,17 @@
<template>
<QPage class="flex flex-center">
<img
alt="Quasar logo"
src="~assets/quasar-logo-vertical.svg"
style="width: 200px; height: 200px"
/>
</QPage>
<QPage class="flex flex-center">
<img
alt="Quasar logo"
src="~assets/quasar-logo-vertical.svg"
style="width: 200px; height: 200px"
/>
</QPage>
</template>
<script>
import { defineComponent } from 'vue'
import { defineComponent } from 'vue';
export default defineComponent({
name: 'IndexPage'
})
});
</script>

View File

@ -1,72 +1,78 @@
<template>
<div class="main">
<div class="header">
<router-link to="/" class="block">
<img src="statics/logo.svg" alt="Verdnatura" class="block" />
</router-link>
<div class="main">
<div class="header">
<router-link to="/" class="block">
<img src="statics/logo.svg" alt="Verdnatura" class="block" />
</router-link>
</div>
<QForm @submit="onLogin" class="q-gutter-y-md">
<div class="q-gutter-y-sm">
<QInput v-model="email" :label="$t('user')" autofocus />
<QInput
v-model="password"
ref="password"
:label="$t('password')"
:type="showPwd ? 'password' : 'text'"
>
<template v-slot:append>
<QIcon
:name="showPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="showPwd = !showPwd"
/>
</template>
</QInput>
<QCheckbox
v-model="remember"
:label="$t('remindMe')"
class="remember"
dense
/>
</div>
<div class="justify-center">
<QBtn
type="submit"
:label="$t('logIn')"
class="full-width"
color="primary"
rounded
no-caps
unelevated
/>
</div>
<div class="justify-center">
<QBtn
to="/"
:label="$t('logInAsGuest')"
class="full-width"
color="primary"
rounded
no-caps
outline
/>
</div>
<p class="password-forgotten text-center q-mt-lg">
<router-link to="/remember-password" class="link">
{{ $t('haveForgottenPassword') }}
</router-link>
</p>
</QForm>
<div class="footer text-center">
<p>
{{ $t('notACustomerYet') }}
<a
href="//verdnatura.es/register/"
target="_blank"
class="link"
>
{{ $t('signUp') }}
</a>
</p>
<p class="contact">
{{ $t('loginPhone') }} · {{ $t('loginMail') }}
</p>
</div>
</div>
<QForm @submit="onLogin" class="q-gutter-y-md">
<div class="q-gutter-y-sm">
<QInput v-model="email" :label="$t('user')" autofocus />
<QInput
v-model="password"
ref="password"
:label="$t('password')"
:type="showPwd ? 'password' : 'text'"
>
<template v-slot:append>
<QIcon
:name="showPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="showPwd = !showPwd"
/>
</template>
</QInput>
<QCheckbox
v-model="remember"
:label="$t('remindMe')"
class="remember"
dense
/>
</div>
<div class="justify-center">
<QBtn
type="submit"
:label="$t('logIn')"
class="full-width"
color="primary"
rounded
no-caps
unelevated
/>
</div>
<div class="justify-center">
<QBtn
to="/"
:label="$t('logInAsGuest')"
class="full-width"
color="primary"
rounded
no-caps
outline
/>
</div>
<p class="password-forgotten text-center q-mt-lg">
<router-link to="/remember-password" class="link">
{{ $t('haveForgottenPassword') }}
</router-link>
</p>
</QForm>
<div class="footer text-center">
<p>
{{ $t('notACustomerYet') }}
<a href="//verdnatura.es/register/" target="_blank" class="link">
{{ $t('signUp') }}
</a>
</p>
<p class="contact">{{ $t('loginPhone') }} · {{ $t('loginMail') }}</p>
</div>
</div>
</template>
<style lang="scss" scoped>
@ -74,106 +80,106 @@ $login-margin-top: 50px;
$login-margin-between: 55px;
.main {
max-width: 280px;
max-width: 280px;
}
a {
color: inherit;
color: inherit;
}
.header {
margin-top: $login-margin-top;
margin-bottom: $login-margin-between;
margin-top: $login-margin-top;
margin-bottom: $login-margin-between;
img {
display: block;
margin: 0 auto;
width: 90%;
}
img {
display: block;
margin: 0 auto;
width: 90%;
}
}
.remember {
margin-top: 20px;
margin-bottom: 40px;
margin-top: 20px;
margin-bottom: 40px;
}
.q-btn {
height: 50px;
height: 50px;
}
.password-forgotten {
font-size: 0.8rem;
font-size: 0.8rem;
}
.footer {
margin-bottom: $login-margin-top;
margin-top: $login-margin-between;
text-align: center;
font-size: 0.8rem;
margin-bottom: $login-margin-top;
margin-top: $login-margin-between;
text-align: center;
font-size: 0.8rem;
.contact {
margin-top: 15px;
color: grey;
}
a {
font-weight: bold;
}
.contact {
margin-top: 15px;
color: grey;
}
a {
font-weight: bold;
}
}
</style>
<script>
import { userStore } from 'stores/user'
import { userStore } from 'stores/user';
export default {
name: 'VnLogin',
data () {
data() {
return {
user: userStore(),
email: '',
password: '',
remember: false,
showPwd: true
}
};
},
mounted () {
mounted() {
if (this.$route.query.emailConfirmed !== undefined) {
this.$q.notify({
message: this.$t('emailConfirmedSuccessfully'),
type: 'positive'
})
});
}
if (this.$route.params.email) {
this.email = this.$route.params.email
this.$refs.password.focus()
this.email = this.$route.params.email;
this.$refs.password.focus();
}
},
methods: {
async onLogin () {
await this.user.login(this.email, this.password, this.remember)
this.$router.push('/')
async onLogin() {
await this.user.login(this.email, this.password, this.remember);
this.$router.push('/');
}
}
}
};
</script>
<i18n lang="yaml">
en-US:
user: User
password: Password
remindMe: Remind me
logInAsGuest: Log in as guest
logIn: Log in
loginMail: infoverdnatura.es
loginPhone: +34 607 562 391
haveForgottenPassword: Have you forgotten your password?
notACustomerYet: Not a customer yet?
signUp: Register
user: User
password: Password
remindMe: Remind me
logInAsGuest: Log in as guest
logIn: Log in
loginMail: infoverdnatura.es
loginPhone: +34 607 562 391
haveForgottenPassword: Have you forgotten your password?
notACustomerYet: Not a customer yet?
signUp: Register
es-ES:
user: Usuario
password: Contraseña
remindMe: Recuérdame
logInAsGuest: Entrar como invitado
logIn: Iniciar sesión
loginMail: infoverdnatura.es
loginPhone: +34 963 242 100
haveForgottenPassword: ¿Has olvidado tu contraseña?
notACustomerYet: ¿Todavía no eres cliente?
signUp: Registrarme
user: Usuario
password: Contraseña
remindMe: Recuérdame
logInAsGuest: Entrar como invitado
logIn: Iniciar sesión
loginMail: infoverdnatura.es
loginPhone: +34 963 242 100
haveForgottenPassword: ¿Has olvidado tu contraseña?
notACustomerYet: ¿Todavía no eres cliente?
signUp: Registrarme
</i18n>

View File

@ -1,108 +1,108 @@
<template>
<div class="text-center">
<div>
<QIcon
name="contact_support"
class="block q-mx-auto text-accent"
style="font-size: 120px"
/>
</div>
<div>
<QForm @submit="onSend" class="q-gutter-y-md text-grey-8">
<div class="text-h5">
<div>
{{ $t('dontWorry') }}
</div>
<div>
{{ $t('fillData') }}
</div>
</div>
<QInput
v-model="email"
:label="$t('user')"
:rules="[(val) => !!val || $t('inputEmail')]"
autofocus
/>
<div class="q-mt-lg">
{{ $t('weSendEmail') }}
<div class="text-center">
<div>
<QIcon
name="contact_support"
class="block q-mx-auto text-accent"
style="font-size: 120px"
/>
</div>
<div>
<QBtn
type="submit"
:label="$t('send')"
class="full-width q-mt-md"
color="primary"
rounded
no-caps
unelevated
/>
<div class="text-center q-mt-md">
<router-link to="/login" class="link">
{{ $t('return') }}
</router-link>
</div>
<QForm @submit="onSend" class="q-gutter-y-md text-grey-8">
<div class="text-h5">
<div>
{{ $t('dontWorry') }}
</div>
<div>
{{ $t('fillData') }}
</div>
</div>
<QInput
v-model="email"
:label="$t('user')"
:rules="[val => !!val || $t('inputEmail')]"
autofocus
/>
<div class="q-mt-lg">
{{ $t('weSendEmail') }}
</div>
<div>
<QBtn
type="submit"
:label="$t('send')"
class="full-width q-mt-md"
color="primary"
rounded
no-caps
unelevated
/>
<div class="text-center q-mt-md">
<router-link to="/login" class="link">
{{ $t('return') }}
</router-link>
</div>
</div>
</QForm>
</div>
</QForm>
</div>
</div>
</template>
<style lang="scss" scoped>
#image {
height: 190px;
height: 190px;
}
.q-btn {
height: 50px;
height: 50px;
}
a {
color: inherit;
font-size: 0.8rem;
color: inherit;
font-size: 0.8rem;
}
</style>
<script>
export default {
name: 'VnRememberPasword',
data () {
data() {
return {
email: ''
}
};
},
methods: {
async onSend () {
async onSend() {
const params = {
email: this.email
}
await this.$axios.post('Users/reset', params)
};
await this.$axios.post('Users/reset', params);
this.$q.notify({
message: this.$t('weHaveSentEmailToRecover'),
type: 'positive'
})
this.$router.push('/login')
});
this.$router.push('/login');
}
}
}
};
</script>
<i18n lang="yaml">
en-US:
user: User
inputEmail: Input email
rememberPassword: Rememeber password
dontWorry: Don't worry!
fillData: Fill the data
weSendEmail: We will sent you an email to recover your password
weHaveSentEmailToRecover: We've sent you an email where you can recover your password
send: Send
return: Return
user: User
inputEmail: Input email
rememberPassword: Rememeber password
dontWorry: Don't worry!
fillData: Fill the data
weSendEmail: We will sent you an email to recover your password
weHaveSentEmailToRecover: We've sent you an email where you can recover your password
send: Send
return: Return
es-ES:
user: Usuario
inputEmail: Introduce el correo electrónico
rememberPassword: Recordar contraseña
dontWorry: ¡No te preocupes!
fillData: Rellena los datos
weSendEmail: Te enviaremos un correo para restablecer tu contraseña
weHaveSentEmailToRecover: Te hemos enviado un correo donde podrás recuperar tu contraseña
send: Enviar
return: Volver
user: Usuario
inputEmail: Introduce el correo electrónico
rememberPassword: Recordar contraseña
dontWorry: ¡No te preocupes!
fillData: Rellena los datos
weSendEmail: Te enviaremos un correo para restablecer tu contraseña
weHaveSentEmailToRecover: Te hemos enviado un correo donde podrás recuperar tu contraseña
send: Enviar
return: Volver
</i18n>

View File

@ -1,99 +1,106 @@
<template>
<div>
<QCard-section>
<QIcon
name="check"
class="block q-mx-auto text-accent"
style="font-size: 120px"
/>
</QCard-section>
<QCard-section>
<QForm @submit="onRegister" ref="form" class="q-gutter-y-md">
<div class="text-grey-8 text-h5 text-center">
{{ $t('fillData') }}
</div>
<div class="q-gutter-y-sm">
<QInput
v-model="password"
:label="$t('password')"
:type="showPwd ? 'password' : 'text'"
autofocus
hint=""
filled
>
<template v-slot:append>
<QIcon
:name="showPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="showPwd = !showPwd"
/>
</template>
</QInput>
<QInput
v-model="repeatPassword"
:label="$t('repeatPassword')"
:type="showRpPwd ? 'password' : 'text'"
:rules="[(value) => value == password || $t('repeatPasswordError')]"
hint=""
filled
>
<template v-slot:append>
<QIcon
:name="showRpPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="showRpPwd = !showRpPwd"
/>
</template>
</QInput>
</div>
<div>
<QBtn
type="submit"
:label="$t('resetPassword')"
class="full-width"
color="primary"
/>
<div class="text-center q-mt-xs">
<router-link to="/login" class="link">
{{ $t('return') }}
</router-link>
</div>
</div>
</QForm>
</QCard-section>
</div>
<div>
<QCard-section>
<QIcon
name="check"
class="block q-mx-auto text-accent"
style="font-size: 120px"
/>
</QCard-section>
<QCard-section>
<QForm @submit="onRegister" ref="form" class="q-gutter-y-md">
<div class="text-grey-8 text-h5 text-center">
{{ $t('fillData') }}
</div>
<div class="q-gutter-y-sm">
<QInput
v-model="password"
:label="$t('password')"
:type="showPwd ? 'password' : 'text'"
autofocus
hint=""
filled
>
<template v-slot:append>
<QIcon
:name="
showPwd ? 'visibility_off' : 'visibility'
"
class="cursor-pointer"
@click="showPwd = !showPwd"
/>
</template>
</QInput>
<QInput
v-model="repeatPassword"
:label="$t('repeatPassword')"
:type="showRpPwd ? 'password' : 'text'"
:rules="[
value =>
value == password || $t('repeatPasswordError')
]"
hint=""
filled
>
<template v-slot:append>
<QIcon
:name="
showRpPwd ? 'visibility_off' : 'visibility'
"
class="cursor-pointer"
@click="showRpPwd = !showRpPwd"
/>
</template>
</QInput>
</div>
<div>
<QBtn
type="submit"
:label="$t('resetPassword')"
class="full-width"
color="primary"
/>
<div class="text-center q-mt-xs">
<router-link to="/login" class="link">
{{ $t('return') }}
</router-link>
</div>
</div>
</QForm>
</QCard-section>
</div>
</template>
<script>
export default {
name: 'VnRegister',
data () {
data() {
return {
password: '',
repeatPassword: '',
showPwd: true,
showRpPwd: true
}
};
},
methods: {
async onRegister () {
async onRegister() {
const headers = {
Authorization: this.$route.query.access_token
}
};
await this.$axios.post(
'users/reset-password',
{
newPassword: this.password
},
{ headers }
)
);
this.$q.notify({
message: this.$t('passwordResetSuccessfully'),
type: 'positive'
})
this.$router.push('/login')
});
this.$router.push('/login');
}
}
}
};
</script>

View File

@ -1,10 +1,11 @@
import { defineStore } from 'pinia'
import { api, jApi } from 'boot/axios'
import { defineStore } from 'pinia';
import { api, jApi } from 'boot/axios';
export const userStore = defineStore('user', {
state: () => {
const token =
sessionStorage.getItem('vnToken') || localStorage.getItem('vnToken')
sessionStorage.getItem('vnToken') ||
localStorage.getItem('vnToken');
return {
token,
@ -12,50 +13,50 @@ export const userStore = defineStore('user', {
name: null,
nickname: null,
isGuest: false
}
};
},
getters: {
loggedIn: (state) => state.token != null
loggedIn: state => state.token != null
},
actions: {
async login (user, password, remember) {
const params = { user, password }
const res = await api.post('Accounts/login', params)
async login(user, password, remember) {
const params = { user, password };
const res = await api.post('Accounts/login', params);
if (remember) {
localStorage.setItem('vnToken', res.data.token)
localStorage.setItem('vnToken', res.data.token);
} else {
sessionStorage.setItem('vnToken', res.data.token)
sessionStorage.setItem('vnToken', res.data.token);
}
this.$patch({
token: res.data.token,
name: user
})
});
},
async logout () {
async logout() {
if (this.token != null) {
try {
await api.post('Accounts/logout')
await api.post('Accounts/logout');
} catch (e) {}
localStorage.removeItem('vnToken')
sessionStorage.removeItem('vnToken')
localStorage.removeItem('vnToken');
sessionStorage.removeItem('vnToken');
}
this.$reset()
this.$reset();
},
async loadData () {
async loadData() {
const userData = await jApi.getObject(
'SELECT id, nickname FROM account.myUser'
)
);
this.$patch({
id: userData.id,
nickname: userData.nickname
})
});
}
}
})
});