Merge branch 'beta' into feature/Account-view-refactor
gitea/hedera-web/pipeline/pr-beta This commit looks good
Details
gitea/hedera-web/pipeline/pr-beta This commit looks good
Details
This commit is contained in:
commit
c8620a53e4
|
@ -0,0 +1,66 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, inject } from 'vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
autoLoad: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
sortBy: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['onFetch']);
|
||||||
|
const api = inject('api');
|
||||||
|
|
||||||
|
defineExpose({ fetch });
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if ($props.autoLoad) {
|
||||||
|
await fetch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetch(fetchFilter = {}) {
|
||||||
|
try {
|
||||||
|
const filter = { ...fetchFilter, ...$props.filter }; // eslint-disable-line vue/no-dupe-keys
|
||||||
|
if ($props.where && !fetchFilter.where) filter.where = $props.where;
|
||||||
|
if ($props.sortBy) filter.order = $props.sortBy;
|
||||||
|
if ($props.limit) filter.limit = $props.limit;
|
||||||
|
|
||||||
|
const { data } = await api.get($props.url, {
|
||||||
|
params: { filter: JSON.stringify(filter), ...$props.params }
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('onFetch', data);
|
||||||
|
return data;
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<template></template>
|
||||||
|
</template>
|
|
@ -5,32 +5,26 @@ import { useRouter, useRoute } from 'vue-router';
|
||||||
|
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnForm from 'src/components/common/VnForm.vue';
|
import FormModel from 'src/components/common/FormModel.vue';
|
||||||
|
|
||||||
|
import { useUserStore } from 'stores/user';
|
||||||
import { useAppStore } from 'stores/app';
|
import { useAppStore } from 'stores/app';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const jApi = inject('jApi');
|
const api = inject('api');
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const { isHeaderMounted } = storeToRefs(appStore);
|
const { isHeaderMounted } = storeToRefs(appStore);
|
||||||
|
|
||||||
const vnFormRef = ref(null);
|
const vnFormRef = ref(null);
|
||||||
const countriesOptions = ref([]);
|
const countriesOptions = ref([]);
|
||||||
const provincesOptions = ref([]);
|
const provincesOptions = ref([]);
|
||||||
const pks = { id: route.params.id };
|
|
||||||
const isEditMode = route.params.id !== '0';
|
const isEditMode = route.params.id !== '0';
|
||||||
const fetchAddressDataSql = {
|
const editAddressData = ref(null);
|
||||||
query: `
|
const showForm = ref(false);
|
||||||
SELECT a.id, a.street, a.nickname, a.city, a.postalCode, a.provinceFk, p.countryFk
|
|
||||||
FROM myAddress a
|
|
||||||
LEFT JOIN vn.province p ON p.id = a.provinceFk
|
|
||||||
WHERE a.id = #address
|
|
||||||
`,
|
|
||||||
params: { address: route.params.id }
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => vnFormRef?.value?.formData?.countryFk,
|
() => vnFormRef?.value?.formData?.countryFk,
|
||||||
|
@ -40,23 +34,49 @@ watch(
|
||||||
const goBack = () => router.push({ name: 'addressesList' });
|
const goBack = () => router.push({ name: 'addressesList' });
|
||||||
|
|
||||||
const getCountries = async () => {
|
const getCountries = async () => {
|
||||||
countriesOptions.value = await jApi.query(
|
const filter = { fields: ['id', 'name'], order: 'name' };
|
||||||
`SELECT id, name FROM vn.country
|
const { data } = await api.get('Countries', {
|
||||||
ORDER BY name`
|
params: { filter: JSON.stringify(filter) }
|
||||||
);
|
});
|
||||||
|
countriesOptions.value = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProvinces = async countryFk => {
|
const getProvinces = async countryFk => {
|
||||||
if (!countryFk) return;
|
if (!countryFk) return;
|
||||||
provincesOptions.value = await jApi.query(
|
|
||||||
`SELECT id, name FROM vn.province
|
const filter = {
|
||||||
WHERE countryFk = #id
|
where: { countryFk },
|
||||||
ORDER BY name`,
|
fields: ['id', 'name'],
|
||||||
{ id: countryFk }
|
order: 'name'
|
||||||
);
|
};
|
||||||
|
const { data } = await api.get('Provinces', {
|
||||||
|
params: { filter: JSON.stringify(filter) }
|
||||||
|
});
|
||||||
|
provincesOptions.value = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => getCountries());
|
const getAddressDetails = async () => {
|
||||||
|
const { data } = await api.get(`Addresses/${route.params.id}`);
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
const { nickname, street, city, postalCode, province, provinceFk } = data;
|
||||||
|
editAddressData.value = {
|
||||||
|
nickname,
|
||||||
|
street,
|
||||||
|
city,
|
||||||
|
postalCode,
|
||||||
|
countryFk: province?.countryFk,
|
||||||
|
provinceFk
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (isEditMode) {
|
||||||
|
await getAddressDetails();
|
||||||
|
}
|
||||||
|
getCountries();
|
||||||
|
showForm.value = true;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -74,42 +94,49 @@ onMounted(() => getCountries());
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<VnForm
|
<FormModel
|
||||||
|
v-if="showForm"
|
||||||
ref="vnFormRef"
|
ref="vnFormRef"
|
||||||
:fetch-form-data-sql="fetchAddressDataSql"
|
:url-create="
|
||||||
:columns-to-ignore-update="['countryFk']"
|
!isEditMode
|
||||||
:create-model-default="{
|
? `Clients/${userStore?.user?.id}/createAddress`
|
||||||
field: 'clientFk',
|
: ''
|
||||||
value: 'account.myUser_getId()'
|
"
|
||||||
}"
|
:url-update="
|
||||||
:pks="pks"
|
isEditMode
|
||||||
:is-edit-mode="isEditMode"
|
? `Clients/${userStore?.user?.id}/updateAddress/${route?.params?.id}`
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
:form-initial-data="editAddressData"
|
||||||
:title="t(isEditMode ? 'editAddress' : 'addAddress')"
|
:title="t(isEditMode ? 'editAddress' : 'addAddress')"
|
||||||
table="myAddress"
|
|
||||||
schema="hedera"
|
|
||||||
@on-data-saved="goBack()"
|
@on-data-saved="goBack()"
|
||||||
|
:show-bottom-actions="false"
|
||||||
>
|
>
|
||||||
<template #form="{ data }">
|
<template #form="{ data }">
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="data.nickname"
|
v-model="data.nickname"
|
||||||
:label="t('name')"
|
:label="t('name')"
|
||||||
data-cy="addressFormNickname"
|
data-cy="addressFormNickname"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="data.street"
|
v-model="data.street"
|
||||||
:label="t('address')"
|
:label="t('address')"
|
||||||
data-cy="addressFormStreet"
|
data-cy="addressFormStreet"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="data.city"
|
v-model="data.city"
|
||||||
:label="t('city')"
|
:label="t('city')"
|
||||||
data-cy="addressFormCity"
|
data-cy="addressFormCity"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="data.postalCode"
|
v-model="data.postalCode"
|
||||||
type="number"
|
type="number"
|
||||||
:label="t('postalCode')"
|
:label="t('postalCode')"
|
||||||
data-cy="addressFormPostcode"
|
data-cy="addressFormPostcode"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.countryFk"
|
v-model="data.countryFk"
|
||||||
|
@ -117,15 +144,17 @@ onMounted(() => getCountries());
|
||||||
:options="countriesOptions"
|
:options="countriesOptions"
|
||||||
@update:model-value="data.provinceFk = null"
|
@update:model-value="data.provinceFk = null"
|
||||||
data-cy="addressFormCountry"
|
data-cy="addressFormCountry"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.provinceFk"
|
v-model="data.provinceFk"
|
||||||
:label="t('province')"
|
:label="t('province')"
|
||||||
:options="provincesOptions"
|
:options="provincesOptions"
|
||||||
data-cy="addressFormProvince"
|
data-cy="addressFormProvince"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnForm>
|
</FormModel>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -5,19 +5,24 @@ import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import CardList from 'src/components/ui/CardList.vue';
|
import CardList from 'src/components/ui/CardList.vue';
|
||||||
import VnList from 'src/components/ui/VnList.vue';
|
import VnList from 'src/components/ui/VnList.vue';
|
||||||
|
import FetchData from 'src/components/common/FetchData.vue';
|
||||||
|
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
||||||
import { useAppStore } from 'stores/app';
|
import { useAppStore } from 'stores/app';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useUserStore } from 'stores/user';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const jApi = inject('jApi');
|
const jApi = inject('jApi');
|
||||||
|
const api = inject('api');
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const { isHeaderMounted } = storeToRefs(appStore);
|
const { isHeaderMounted } = storeToRefs(appStore);
|
||||||
|
const fetchAddressesRef = ref(null);
|
||||||
|
|
||||||
const addresses = ref([]);
|
const addresses = ref([]);
|
||||||
const defaultAddress = ref(null);
|
const defaultAddress = ref(null);
|
||||||
|
@ -38,19 +43,6 @@ const getDefaultAddress = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getActiveAddresses = async () => {
|
|
||||||
try {
|
|
||||||
addresses.value = await jApi.query(
|
|
||||||
`SELECT a.id, a.nickname, p.name province, a.postalCode, a.city, a.street, a.isActive
|
|
||||||
FROM myAddress a
|
|
||||||
LEFT JOIN vn.province p ON p.id = a.provinceFk
|
|
||||||
WHERE a.isActive`
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error getting active addresses:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeDefaultAddress = async () => {
|
const changeDefaultAddress = async () => {
|
||||||
if (!clientId.value) return;
|
if (!clientId.value) return;
|
||||||
await jApi.execQuery(
|
await jApi.execQuery(
|
||||||
|
@ -65,32 +57,46 @@ const changeDefaultAddress = async () => {
|
||||||
notify(t('defaultAddressModified'), 'positive');
|
notify(t('defaultAddressModified'), 'positive');
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeAddress = async id => {
|
async function removeAddress(address) {
|
||||||
try {
|
try {
|
||||||
await jApi.execQuery(
|
await api.patch(
|
||||||
`START TRANSACTION;
|
`/Clients/${userStore?.user?.id}/updateAddress/${address.id}`,
|
||||||
UPDATE hedera.myAddress SET isActive = FALSE
|
|
||||||
WHERE ((id = #id));
|
|
||||||
SELECT isActive FROM hedera.myAddress WHERE ((id = #id));
|
|
||||||
COMMIT`,
|
|
||||||
{
|
{
|
||||||
id
|
...address,
|
||||||
|
isActive: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
getActiveAddresses();
|
fetchAddressesRef.value.fetch();
|
||||||
notify(t('dataSaved'), 'positive');
|
notify(t('dataSaved'), 'positive');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error removing address:', error);
|
console.error('Error removing address:', error);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
getDefaultAddress();
|
getDefaultAddress();
|
||||||
getActiveAddresses();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<FetchData
|
||||||
|
v-if="userStore?.user?.id"
|
||||||
|
ref="fetchAddressesRef"
|
||||||
|
url="Addresses"
|
||||||
|
:filter="{
|
||||||
|
where: { clientFk: userStore.user.id, isActive: true },
|
||||||
|
fields: [
|
||||||
|
'id',
|
||||||
|
'nickname',
|
||||||
|
'postalCode',
|
||||||
|
'city',
|
||||||
|
'street',
|
||||||
|
'isActive'
|
||||||
|
]
|
||||||
|
}"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="data => (addresses = data)"
|
||||||
|
/>
|
||||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('addAddress')"
|
:label="t('addAddress')"
|
||||||
|
@ -145,7 +151,7 @@ onMounted(async () => {
|
||||||
openConfirmationModal(
|
openConfirmationModal(
|
||||||
null,
|
null,
|
||||||
t('confirmDeleteAddress'),
|
t('confirmDeleteAddress'),
|
||||||
() => removeAddress(address.id)
|
() => removeAddress(address)
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, inject } from 'vue';
|
import { ref, onMounted, inject } from 'vue';
|
||||||
const jApi = inject('jApi');
|
const jApi = inject('jApi');
|
||||||
|
const api = inject('api');
|
||||||
const news = ref([]);
|
const news = ref([]);
|
||||||
const showPreview = ref(false);
|
const showPreview = ref(false);
|
||||||
const selectedImageSrc = ref('');
|
const selectedImageSrc = ref('');
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
news.value = await jApi.query(
|
const newsResponse = await api.get('News');
|
||||||
`SELECT title, text, image, id
|
|
||||||
FROM news
|
news.value = newsResponse.data;
|
||||||
ORDER BY priority, created DESC`
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showImagePreview = src => {
|
const showImagePreview = src => {
|
||||||
|
|
|
@ -32,7 +32,10 @@ export const useAppStore = defineStore('hedera', {
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async getMenuLinks() {
|
async getMenuLinks() {
|
||||||
const sections = await jApi.query('SELECT * FROM myMenu');
|
const { data: sections } = await api.get('MyMenus');
|
||||||
|
|
||||||
|
if (!sections) return;
|
||||||
|
|
||||||
const sectionMap = new Map();
|
const sectionMap = new Map();
|
||||||
for (const section of sections) {
|
for (const section of sections) {
|
||||||
sectionMap.set(section.id, section);
|
sectionMap.set(section.id, section);
|
||||||
|
|
|
@ -248,11 +248,10 @@ export const useUserStore = defineStore('user', () => {
|
||||||
|
|
||||||
const fetchUser = async (userType = 'user') => {
|
const fetchUser = async (userType = 'user') => {
|
||||||
try {
|
try {
|
||||||
const userData = await jApi.getObject(
|
const userData = await api.get('VnUsers/getCurrentUserData');
|
||||||
'SELECT id, nickname, name, lang FROM account.myUser'
|
|
||||||
);
|
if (userType === 'user') mainUser.value = userData.data;
|
||||||
if (userType === 'user') mainUser.value = userData;
|
else supplantedUser.value = userData.data;
|
||||||
else supplantedUser.value = userData;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching user: ', error);
|
console.error('Error fetching user: ', error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,15 +46,28 @@ describe('PendingOrders', () => {
|
||||||
.should('contain', data.postcode);
|
.should('contain', data.postcode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
it('should fail if we enter a wrong postcode', () => {
|
||||||
|
cy.dataCy('newAddressBtn').should('exist');
|
||||||
|
cy.dataCy('newAddressBtn').click();
|
||||||
|
cy.dataCy('formModelDefaultSaveButton').should('exist');
|
||||||
|
cy.dataCy('formModelDefaultSaveButton').should('be.disabled');
|
||||||
|
const addressFormData = getRandomAddressFormData();
|
||||||
|
fillFormWithData(addressFormData);
|
||||||
|
cy.dataCy('formModelDefaultSaveButton').should('not.be.disabled');
|
||||||
|
cy.dataCy('formModelDefaultSaveButton').click();
|
||||||
|
cy.checkNotify('negative');
|
||||||
|
});
|
||||||
|
|
||||||
it('should create a new address', () => {
|
it('should create a new address', () => {
|
||||||
cy.dataCy('newAddressBtn').should('exist');
|
cy.dataCy('newAddressBtn').should('exist');
|
||||||
cy.dataCy('newAddressBtn').click();
|
cy.dataCy('newAddressBtn').click();
|
||||||
cy.dataCy('formDefaultSaveButton').should('exist');
|
cy.dataCy('formModelDefaultSaveButton').should('exist');
|
||||||
cy.dataCy('formDefaultSaveButton').should('be.disabled');
|
cy.dataCy('formModelDefaultSaveButton').should('be.disabled');
|
||||||
const addressFormData = getRandomAddressFormData();
|
const addressFormData = getRandomAddressFormData();
|
||||||
|
addressFormData.postcode = '46460'; // Usamos un postcode válido
|
||||||
fillFormWithData(addressFormData);
|
fillFormWithData(addressFormData);
|
||||||
cy.dataCy('formDefaultSaveButton').should('not.be.disabled');
|
cy.dataCy('formModelDefaultSaveButton').should('not.be.disabled');
|
||||||
cy.dataCy('formDefaultSaveButton').click();
|
cy.dataCy('formModelDefaultSaveButton').click();
|
||||||
cy.checkNotify('positive', 'Datos guardados');
|
cy.checkNotify('positive', 'Datos guardados');
|
||||||
verifyAddressCardData(addressFormData);
|
verifyAddressCardData(addressFormData);
|
||||||
});
|
});
|
||||||
|
@ -71,9 +84,10 @@ describe('PendingOrders', () => {
|
||||||
});
|
});
|
||||||
// Fill form with new data
|
// Fill form with new data
|
||||||
const addressFormData = getRandomAddressFormData();
|
const addressFormData = getRandomAddressFormData();
|
||||||
|
addressFormData.postcode = '46460'; // Usamos un postcode válido
|
||||||
fillFormWithData(addressFormData);
|
fillFormWithData(addressFormData);
|
||||||
cy.dataCy('formDefaultSaveButton').should('not.be.disabled');
|
cy.dataCy('formModelDefaultSaveButton').should('not.be.disabled');
|
||||||
cy.dataCy('formDefaultSaveButton').click();
|
cy.dataCy('formModelDefaultSaveButton').click();
|
||||||
cy.checkNotify('positive', 'Datos guardados');
|
cy.checkNotify('positive', 'Datos guardados');
|
||||||
verifyAddressCardData(addressFormData);
|
verifyAddressCardData(addressFormData);
|
||||||
});
|
});
|
||||||
|
|
|
@ -90,5 +90,6 @@ Cypress.Commands.add('setConfirmDialog', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('checkNotify', (status, content) => {
|
Cypress.Commands.add('checkNotify', (status, content) => {
|
||||||
cy.dataCy(`${status}Notify`).should('contain', content);
|
if (content) cy.dataCy(`${status}Notify`).should('contain', content);
|
||||||
|
else cy.dataCy(`${status}Notify`).should('exist');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue