Merge pull request '#7750 - first-beta-review' (!95) from wbuezas/hedera-web-mindshore:first-beta-review into beta
gitea/hedera-web/pipeline/head This commit looks good Details

Reviewed-on: #95
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
This commit is contained in:
Javier Segarra 2024-12-09 23:18:06 +00:00
commit 0f1bde3b77
27 changed files with 280 additions and 209 deletions

View File

@ -6,31 +6,30 @@ Hedera is the main web page for Verdnatura.
Required dependencies.
* PHP >= 7.0
* Node.js >= 18.0
- PHP >= 7.0
- Node.js >= 18.0
Launch application for development.
```
$ quasar dev
```
Launch Salix backend.
```
npm run salix
```
Launch legacy PHP backend.
```
npm run back
pnpm run back
```
Run server side method from command line.
```
php hedera-web.php -m method_path
```
## Built with
* [Webpack](https://webpack.js.org/)
* [MooTools](https://mootools.net/)
* [TinyMCE](https://www.tinymce.com/)
- [Webpack](https://webpack.js.org/)
- [MooTools](https://mootools.net/)
- [TinyMCE](https://www.tinymce.com/)

View File

@ -3,6 +3,7 @@ import { Connection } from '../js/db/connection';
import { useUserStore } from 'stores/user';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
import { useAppStore } from 'src/stores/app';
const { notify } = useNotify();
// Be careful when using SSR for cross-request state pollution
@ -37,9 +38,11 @@ const onResponseError = error => {
export default boot(({ app }) => {
const userStore = useUserStore();
const appStore = useAppStore();
function addToken(config) {
if (userStore.token) {
config.headers.Authorization = userStore.token;
config.headers['Accept-Language'] = appStore.siteLang;
}
return config;
}

View File

@ -129,6 +129,8 @@ async function filterHandler(val, update) {
if (!$props.defaultFilter) return update();
const newOptions = filter(val, myOptionsOriginal.value);
setTimeout(() => {
update(
() => {
myOptions.value = newOptions;
@ -140,6 +142,7 @@ async function filterHandler(val, update) {
}
}
);
}, 300);
}
</script>
@ -178,6 +181,13 @@ async function filterHandler(val, update) {
>
<slot :name="slotName" v-bind="slotData ?? {}" :key="slotName" />
</template>
<template #no-option>
<QItem>
<QItemSection class="text-grey">
{{ t('emptyList') }}
</QItemSection>
</QItem>
</template>
</QSelect>
</template>

View File

@ -100,26 +100,21 @@ const onSubmit = async () => {
en-US:
name: Name
file: File
send: Send
imageAdded: Image added successfully
es-ES:
name: Nombre
file: Archivo
send: Enviar
imageAdded: Imagen añadida correctamente
ca-ES:
name: Nom
file: Arxiu
send: Enviar
imageAdded: Imatge afegida correctament
fr-FR:
name: Nom
file: Fichier
send: Envoyer
imageAdded: Image ajoutée correctement
pt-PT:
name: Nome
file: Arquivo
send: Enviar
imageAdded: Imagen adicionada corretamente
</i18n>

View File

@ -67,6 +67,10 @@ const url = computed(() => {
return `${props.baseURL ?? app.imageUrl}/${props.storage}/${props.size}/${props.id}`;
});
const zoomUrl = computed(() => {
return `${props.baseURL ?? app.imageUrl}/${props.storage}/${props.zoomSize}/${props.id}`;
});
const rounded = computed(() => {
const roundedMap = {
none: '',
@ -114,7 +118,7 @@ const rounded = computed(() => {
<QDialog v-if="props.zoomSize" v-model="showZoom">
<QImg
:src="url"
:src="zoomUrl"
size="full"
class="img_zoom"
v-bind="$attrs"

View File

@ -6,10 +6,6 @@ defineProps({
type: String,
default: 'emptyList'
},
emptyIcon: {
type: String,
default: 'block'
},
rows: {
type: Array,
default: () => []
@ -29,7 +25,6 @@ const { t } = useI18n();
v-if="!rows?.length"
class="flex items-center q-pa-md justify-center items-center"
>
<QIcon :name="emptyIcon" size="sm" class="q-mr-sm" />
{{ t(emptyMessage) }}
</span>
<QSpinner v-if="loading" color="primary" size="3em" :thickness="2" />

View File

@ -40,6 +40,11 @@ const search = async () => {
query: searchTerm.value ? { search: searchTerm.value } : {}
});
if (!searchTerm.value) {
emit('onSearchError');
return;
}
if (props.sqlQuery) {
data = await jApi.query(props.sqlQuery, {
[props.searchField]: searchTerm.value

View File

@ -134,6 +134,7 @@ export default {
minQuantity: 'Quantitat mínima',
introduceSearchTerm: 'Introdueix un terme de cerca',
noOrdersFound: `No s'han trobat comandes`,
send: 'Enviar',
// Image related translations
'Cant lock cache': 'No es pot bloquejar la memòria cau',
'Bad file format': 'Format de fitxer no reconegut',

View File

@ -168,6 +168,7 @@ export default {
minQuantity: 'Minimum quantity',
introduceSearchTerm: 'Enter a search term',
noOrdersFound: 'No orders found',
send: 'Send',
// Image related translations
'Cant lock cache': 'The cache could not be blocked',
'Bad file format': 'Unrecognized file format',

View File

@ -167,6 +167,7 @@ export default {
minQuantity: 'Cantidad mínima',
introduceSearchTerm: 'Introduce un término de búsqueda',
noOrdersFound: 'No se encontrado pedidos',
send: 'Enviar',
// Image related translations
'Cant lock cache': 'La caché no pudo ser bloqueada',
'Bad file format': 'Formato de archivo no reconocido',

View File

@ -135,6 +135,7 @@ export default {
minQuantity: 'Quantité minimum',
introduceSearchTerm: 'Entrez un terme de recherche',
noOrdersFound: 'Aucune commande trouvée',
send: 'Envoyer',
// Image related translations
'Cant lock cache': "Le cache n'a pas pu être verrouillé",
'Bad file format': 'Format de fichier non reconnu',

View File

@ -133,6 +133,7 @@ export default {
minQuantity: 'Quantidade mínima',
introduceSearchTerm: 'Digite um termo de pesquisa',
noOrdersFound: 'Nenhum pedido encontrado',
send: 'Enviar',
// Image related translations
'Cant lock cache': 'O cache não pôde ser bloqueado',
'Bad file format': 'Formato de arquivo inválido',

View File

@ -3,13 +3,11 @@
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 }">
<QPageContainer class="column q-pa-md row items-center justify-center">
<transition>
<component :is="Component" />
<router-view />
</transition>
</router-view>
</div>
</QPageContainer>
</QLayout>
</template>

View File

@ -47,7 +47,7 @@ const logoutSupplantedUser = async () => {
</script>
<template>
<QLayout view="hhh Lpr fFf">
<QLayout view="hhh LpR fFf">
<QHeader>
<QToolbar>
<QBtn
@ -216,6 +216,10 @@ const logoutSupplantedUser = async () => {
padding: 16px;
}
div .q-drawer-container {
padding: 0 !important;
}
@include mobile {
#actions {
.q-btn {

View File

@ -109,12 +109,12 @@ const fetchData = async () => {
</QBtn>
<QBtn
icon="shopping_bag"
:label="t('catalog')"
:label="t('titles.Catalog')"
:to="{ name: 'catalog' }"
rounded
no-caps
>
<QTooltip>{{ t('catalog') }}</QTooltip>
<QTooltip>{{ t('titles.Catalog') }}</QTooltip>
</QBtn>
<QBtn
icon="shopping_cart_checkout"

View File

@ -25,8 +25,9 @@ const { t } = useI18n();
storage="catalog"
size="200x200"
:id="item.image"
height="210px"
height="190px"
rounded="bottom"
zoom-size="1600x900"
/>
<div
class="column"
@ -45,7 +46,7 @@ const { t } = useI18n();
</span>
<span> #{{ item.id }}</span>
</div>
<div class="tags q-pt-xs text-caption">
<div class="tags text-caption">
<div
v-for="(tag, index) in item.previewTags"
:key="index"
@ -75,7 +76,7 @@ const { t } = useI18n();
<div class="row justify-between items-cente q-gutter-x-xs">
<QBadge
:label="`x${item.grouping}`"
color="grey"
color="grey-4"
class="col-2 justify-end text-body2"
>
<QTooltip>
@ -85,8 +86,7 @@ const { t } = useI18n();
<QBadge
outline
:label="item.available"
color="accent"
text-color="black"
color="grey-6"
class="col justify-end text-body2"
>
<QTooltip>
@ -97,7 +97,6 @@ const { t } = useI18n();
outline
:label="currency(item.price)"
color="accent"
text-color="black"
class="col justify-end text-body2"
>
<QTooltip>
@ -117,6 +116,7 @@ const { t } = useI18n();
height="105px"
rounded-borders="full"
class="q-mr-md"
zoom-size="1600x900"
/>
</template>
<template #content>
@ -153,7 +153,8 @@ const { t } = useI18n();
<div class="row justify-end items-center q-gutter-x-xs q-mt-sm">
<QBadge
:label="`x${item.grouping}`"
color="grey"
color="grey-4"
text-color="black"
class="col-2 justify-end text-body2"
>
<QTooltip>
@ -163,8 +164,7 @@ const { t } = useI18n();
<QBadge
outline
:label="item.available"
color="accent"
text-color="black"
color="grey-6"
class="col-3 justify-end text-body2"
>
<QTooltip>
@ -175,7 +175,6 @@ const { t } = useI18n();
outline
:label="currency(item.price)"
color="accent"
text-color="black"
class="col-3 justify-end text-body2"
>
<QTooltip>

View File

@ -1,7 +1,14 @@
<template>
<Teleport v-if="isHeaderMounted" to="#actions">
<div class="row">
<VnSearchBar :search-term="search" @on-search-error="items = []" />
<VnSearchBar
@on-search-error="
() => {
items = [];
search = '';
}
"
/>
<QBtn
:icon="viewTypeButtonContent.icon"
:label="viewTypeButtonContent.label"
@ -36,7 +43,7 @@
/>
</div>
</Teleport>
<div style="padding-bottom: 5em">
<div>
<QDrawer v-model="rightDrawerOpen" side="right" :width="250" persistent>
<div class="q-pa-md">
<div class="basket-info q-gutter-y-sm">
@ -55,6 +62,9 @@
no-caps
@click="redirectToCheckout()"
data-testid="orderModifyButton"
color="light-green-7"
unelevated
text-color="white"
>
{{ t('modify') }}
</QBtn>
@ -132,6 +142,12 @@
:disable="!category"
:label="t('category')"
/>
<div
v-if="isSomeFilterSelected"
class="q-mt-md text-grey-7"
>
{{ t('orderBy') }}
</div>
<VnSelect
v-if="isSomeFilterSelected"
v-model="selectedOrderBy"
@ -139,7 +155,7 @@
option-value="value"
option-label="label"
:is-clearable="false"
:label="t('orderBy')"
:label="t('sort')"
/>
</div>
<span
@ -153,7 +169,7 @@
<div
:class="
viewMode === 'grid'
? 'q-pa-md row justify-center q-gutter-md'
? ' row justify-center q-gutter-md'
: 'column items-center'
"
>
@ -167,7 +183,6 @@
v-else-if="!items || !items.length || !isSomeFilterSelected"
class="text-subtitle1 text-grey-7 q-pa-md"
>
<QIcon name="refresh" size="sm" class="q-mr-sm"></QIcon>
<span>{{ t('pleaseSetFilter') }}</span>
</div>
<CatalogCard
@ -180,13 +195,13 @@
/>
</div>
<QDialog v-model="showItemDialog" @hide="resetAmounts()">
<QCard style="width: 25em" class="column">
<QCard v-if="selectedItem" style="width: 25em" class="column">
<div class="q-pa-md relative-position">
<div class="q-mb-md" style="display: flex">
<VnImg
storage="catalog"
size="200x200"
:id="'asd'"
:id="selectedItem.image"
width="112px"
height="112px"
rounded="bottom"
@ -282,6 +297,7 @@
</QBtn>
</div>
</QCard>
<QSpinner v-else color="primary" size="3em" :thickness="5" />
</QDialog>
</div>
</template>
@ -744,7 +760,8 @@ const getSubcategories = async () => {
DROP TEMPORARY TABLE tmp.itemAvailable;`,
{ orderId: basketOrderId.value }
);
itemSubcategories.value = res.results[1].data;
const filtered = res.results[1].data.filter(item => item.category);
itemSubcategories.value = filtered.map(i => i.category);
} catch (error) {
console.error('Error getting subcategories:', error);
}
@ -753,11 +770,13 @@ const getSubcategories = async () => {
const showItem = async item => {
if (checkGuest()) return;
const itemLots = await calcItem(item.id);
const tags = await getItemTags(item.id);
showItemDialog.value = true;
const [itemLots, tags] = await Promise.all([
calcItem(item.id),
getItemTags(item.id)
]);
item.lots = itemLots;
item.tags = tags;
showItemDialog.value = true;
selectedItem.value = item;
};
@ -848,6 +867,7 @@ const onAddLotClick = async lot => {
};
const resetAmounts = () => {
selectedItem.value = null;
addedItemsAmountAcc.value = {};
amount.value = 0;
};
@ -1031,6 +1051,8 @@ en-US:
filterBy: Filter by
chooseCategory: Choose a category
youMustBeLoggedIn: You must be a registered user
sort: Order
amountNotAvailable: Amount not available
es-ES:
category: Categoría
deleteFilter: Quitar filtro
@ -1054,6 +1076,8 @@ es-ES:
filterBy: Filtrar por
chooseCategory: Elige una categoría
youMustBeLoggedIn: Debes estar registrado como usuario
sort: Ordenar
amountNotAvailable: Cantidad no disponible
ca-ES:
category: Categoría
deleteFilter: Eliminar filtro
@ -1075,6 +1099,8 @@ ca-ES:
filterBy: Filtrar per
chooseCategory: Tria una categoria
youMustBeLoggedIn: Has d'estar registrat com a usuari
sort: Ordenar
amountNotAvailable: Quantitat no disponible
fr-FR:
category: Catégorie
deleteFilter: Supprimer le filtre
@ -1096,6 +1122,8 @@ fr-FR:
filterBy: Filtrer par
chooseCategory: Choisissez une catégorie
youMustBeLoggedIn: Vous devez être un utilisateur enregistré
sort: Trier
amountNotAvailable: Quantité non disponible
pt-PT:
category: Categoria
deleteFilter: Apagar filtro
@ -1117,4 +1145,6 @@ pt-PT:
filterBy: Filtrar por
chooseCategory: Escolha uma categoria
youMustBeLoggedIn: Deves estar registrado como usuario
sort: Ordenar
amountNotAvailable: Quantidade não disponível
</i18n>

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, onMounted, inject, computed } from 'vue';
import { ref, onMounted, inject, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
@ -28,6 +28,7 @@ const agencies = ref([]);
const warehouses = ref([]);
const currentStep = ref('method');
const id = route.params.id;
const defaultValues = ref(null);
const orderForm = ref({
method: 'AGENCY',
date: formatDate(Date.vnNew(), 'YYYY/MM/DD'),
@ -179,6 +180,15 @@ const getAgencies = async () => {
}
);
agencies.value = results[1].data;
if (agencies.value && agencies.value.length && defaultValues.value) {
const found = agencies.value.find(
agency => agency.id === defaultValues.value.defaultAgencyFk
);
if (found)
orderForm.value.agency = defaultValues.value.defaultAgencyFk;
}
} catch (error) {
console.error('Error getting agencies:', error);
}
@ -284,6 +294,13 @@ const submit = async () => {
}
};
const getDefaultValues = async () => {
return await jApi.query(
`SELECT deliveryMethod, agencyModeFk, addressFk, defaultAgencyFk
FROM myBasketDefaults`
);
};
onMounted(async () => {
today.value = Date.vnNew();
today.value.setHours(0, 0, 0, 0);
@ -305,10 +322,21 @@ onMounted(async () => {
orderForm.value.agency = order.agencyModeFk;
orderForm.value.address = order.addressFk;
}
} else {
const [_defaultValues] = await getDefaultValues();
if (_defaultValues) defaultValues.value = _defaultValues;
}
getAddresses();
});
watch(
() => orderForm.value.method,
() => {
orderForm.value.address = '';
orderForm.value.agency = '';
}
);
</script>
<template>
@ -468,7 +496,7 @@ onMounted(async () => {
</QTooltip>
</QBtn>
<QBtn
v-if="showNavigationButtons"
v-if="showNavigationButtons || currentStep === 'confirm'"
@click="onNextStep(stepIndex)"
:color="currentStep === 'confirm' ? 'accent ' : 'primary'"
:icon="
@ -477,6 +505,7 @@ onMounted(async () => {
dense
class="right-navigation-button"
data-testid="checkoutStepperRightButton"
:loading="loading"
>
<QTooltip>
{{ t(`${step.nextButtonLabel || 'next'}`) }}
@ -491,7 +520,7 @@ onMounted(async () => {
@import 'src/css/responsive';
.step-title {
min-width: 100%;
max-width: 90%;
margin-bottom: 16px;
text-align: center;
font-weight: bold;
@ -523,7 +552,7 @@ onMounted(async () => {
.left-navigation-button {
position: absolute;
left: 5px;
top: 50%;
top: 25px;
@include mobile {
top: 35%;
}
@ -532,7 +561,7 @@ onMounted(async () => {
.right-navigation-button {
position: absolute;
right: 5px;
top: 50%;
top: 25px;
@include mobile {
top: 35%;
}

View File

@ -288,9 +288,8 @@ onMounted(async () => {
>
<div
v-if="!transferAccounts.length"
class="row items-center justify-center q-pa-md bg-red"
class="row items-center justify-center q-pa-md"
>
<QIcon class="q-mr-md" name="block" size="sm" />
<span>{{ t('emptyList') }}</span>
</div>
<QList>

View File

@ -172,7 +172,6 @@ const deleteRow = id => {
class="row items-center justify-center q-pa-md"
style="margin-top: 32px"
>
<QIcon class="q-mr-md" name="block" size="sm" />
<span>{{ t('emptyList') }}</span>
</div>
</QCard>

View File

@ -136,8 +136,11 @@ const loginAsGuest = async () => {
outline
/>
</div>
<p class="password-forgotten text-center q-mt-lg">
<router-link to="/remember-password" class="link">
<p
class="password-forgotten text-center q-mt-lg"
data-testid="recoverPasswordViewLink"
>
<router-link :to="{ name: 'recoverPassword' }" class="link">
{{ $t('haveForgottenPassword') }}
</router-link>
</p>

View File

@ -0,0 +1,99 @@
<script setup>
import { ref } from 'vue';
import { api } from 'boot/axios';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import useNotify from 'src/composables/useNotify.js';
import VnInput from 'src/components/common/VnInput.vue';
const user = ref('');
const router = useRouter();
const { t } = useI18n();
const { notify } = useNotify();
const onSend = async () => {
const params = {
user: user.value,
app: 'hedera'
};
await api.post('VnUsers/recoverPassword', params);
notify(t('weHaveSentEmailToRecover'), 'positive');
router.push('/login');
};
</script>
<template>
<QPage 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">
<VnInput
v-model="user"
:label="t('user')"
autofocus
data-testid="recoverPasswordUserInput"
/>
<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
data-testid="recoverPasswordSubmitButton"
/>
<div class="text-center q-mt-md">
<router-link to="/login" class="link">
{{ t('back') }}
</router-link>
</div>
</div>
</QForm>
</div>
</QPage>
</template>
<style lang="scss" scoped>
.q-btn {
height: 50px;
}
</style>
<i18n lang="yaml">
en-US:
inputEmail: Input email
rememberPassword: Rememeber password
weSendEmail: We will sent you an email to recover your password
weHaveSentEmailToRecover: We've sent you an email where you can recover your password
es-ES:
inputEmail: Introduce el correo electrónico
rememberPassword: Recordar contraseña
weSendEmail: Te enviaremos un correo para restablecer tu contraseña
weHaveSentEmailToRecover: Te hemos enviado un correo donde podrás recuperar tu contraseña
ca-ES:
inputEmail: Introdueix el correu electrònic
rememberPassword: Recordar contrasenya
weSendEmail: T'enviarem un correu per restablir la teva contrasenya
weHaveSentEmailToRecover: T'hem enviat un correu on podràs recuperar la teva contrasenya
fr-FR:
inputEmail: Entrez l'email
rememberPassword: Se souvenir du mot de passe
weSendEmail: Nous vous enverrons un e-mail pour récupérer votre mot de passe
weHaveSentEmailToRecover: Nous vous avons envoyé un e-mail vous pouvez récupérer votre mot de passe
pr-BR:
inputEmail: Digite o e-mail
rememberPassword: Lembrar senha
weSendEmail: Enviaremos um e-mail para recuperar sua senha
weHaveSentEmailToRecover: Enviamos um e-mail onde você pode recuperar sua senha
</i18n>

View File

@ -1,114 +0,0 @@
<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>
<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>
</div>
</template>
<style lang="scss" scoped>
#image {
height: 190px;
}
.q-btn {
height: 50px;
}
a {
color: inherit;
font-size: 0.8rem;
}
</style>
<script>
export default {
name: 'VnRememberPasword',
data() {
return {
email: ''
};
},
methods: {
async onSend() {
const params = {
email: this.email
};
await this.$axios.post('Users/reset', params);
this.$q.notify({
message: this.$t('weHaveSentEmailToRecover'),
type: 'positive'
});
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
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
</i18n>

View File

@ -39,10 +39,11 @@ export default route(function (/* { store, ssrContext } */) {
Router.beforeEach((to, from, next) => {
const userStore = useUserStore();
const allowedRoutes = ['login', 'recoverPassword'];
if (
!userStore.storage.getItem('token') &&
to.name !== 'login' &&
!allowedRoutes.includes(to.name) &&
!userStore.isGuest
) {
return next({ name: 'login' });

View File

@ -5,17 +5,17 @@ const routes = [
children: [
{
name: 'login',
path: '/login/:email?',
path: '',
component: () => import('pages/Login/LoginView.vue')
},
{
name: 'rememberPassword',
path: '/remember-password',
component: () => import('pages/Login/RememberPassword.vue')
name: 'recoverPassword',
path: 'recover',
component: () => import('pages/Login/RecoverPassword.vue')
},
{
name: 'resetPassword',
path: '/reset-password',
path: 'reset',
component: () => import('pages/Login/ResetPassword.vue')
}
]

View File

@ -20,12 +20,7 @@ export const useAppStore = defineStore('hedera', {
menuEssentialLinks: [],
hiddenMenuLinks: new Set(['Reports']),
basketOrderId: null,
localeDates: {
days: [],
months: [],
daysShort: [],
monthsShort: []
},
siteLang: null,
localeOptions: [
{ label: t('langs.en'), lang: 'en-US', value: 'en' },
@ -66,20 +61,9 @@ export const useAppStore = defineStore('hedera', {
this.$patch({ imageUrl });
},
getLocaleDates() {
const { messages, locale } = i18n.global;
this.localeDates = {
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
};
},
async init() {
this.updateSiteLocale(localStorage.getItem('siteLang') || 'es-ES');
this.getBasketOrderId();
this.getLocaleDates();
},
getBasketOrderId() {
@ -187,6 +171,12 @@ export const useAppStore = defineStore('hedera', {
isDesktop() {
const $q = useQuasar();
return $q?.screen?.width > 1024;
},
localeDates() {
const { messages, locale } = i18n.global;
const { days, months, daysShort, monthsShort } =
messages.value[locale.value].date;
return { days, months, daysShort, monthsShort };
}
}
});

View File

@ -0,0 +1,18 @@
describe('Login Tests', () => {
beforeEach(() => {
cy.visit('/#/login');
});
it('should ssend recover email', () => {
cy.dataCy('recoverPasswordViewLink').should('exist');
cy.dataCy('recoverPasswordViewLink').click();
cy.dataCy('recoverPasswordUserInput').find('input').should('exist');
cy.dataCy('recoverPasswordUserInput').find('input').type('developer');
cy.dataCy('recoverPasswordSubmitButton').should('exist');
cy.dataCy('recoverPasswordSubmitButton').click();
cy.checkNotify(
'positive',
'Te hemos enviado un correo donde podrás recuperar tu contraseña'
);
});
});