forked from verdnatura/salix-front
refactor: refs #6896 end migration orders
This commit is contained in:
parent
19bdd4fc36
commit
98159de257
|
@ -3,14 +3,15 @@ import { computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import VnInput from 'components/common/VnInput.vue';
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
|
import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
|
||||||
|
import { useValidator } from 'src/composables/useValidator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
dataKey: {
|
dataKey: {
|
||||||
|
@ -21,32 +22,34 @@ const props = defineProps({
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
tagValue: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const categoryList = ref(null);
|
const categoryList = ref(null);
|
||||||
const selectedCategoryFk = ref(null);
|
const selectedCategoryFk = ref(null);
|
||||||
const typeList = ref(null);
|
const typeList = ref(null);
|
||||||
const selectedTypeFk = ref(null);
|
const selectedTypeFk = ref(null);
|
||||||
|
const validationsStore = useValidator();
|
||||||
|
const selectedOrder = ref(null);
|
||||||
|
const selectedOrderField = ref(null);
|
||||||
|
const moreFields = ref([]);
|
||||||
|
const moreFieldsOrder = ref([]);
|
||||||
|
const createValue = (val, done) => {
|
||||||
|
if (val.length > 2) {
|
||||||
|
// if (!tagOptions.value.includes(val)) {
|
||||||
|
// done(tagOptions.value, 'add-unique');
|
||||||
|
// }
|
||||||
|
tagValues.value.push({ value: val });
|
||||||
|
}
|
||||||
|
};
|
||||||
const resetCategory = () => {
|
const resetCategory = () => {
|
||||||
selectedCategoryFk.value = null;
|
selectedCategoryFk.value = null;
|
||||||
typeList.value = null;
|
typeList.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedOrder = ref(null);
|
|
||||||
const orderList = [
|
|
||||||
{ way: 'ASC', name: 'Ascendant' },
|
|
||||||
{ way: 'DESC', name: 'Descendant' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const selectedOrderField = ref(null);
|
|
||||||
const OrderFields = [
|
|
||||||
{ field: 'relevancy DESC, name', name: 'Relevancy', priority: 999 },
|
|
||||||
{ field: 'showOrder, price', name: 'Color and price', priority: 999 },
|
|
||||||
{ field: 'name', name: 'Name', priority: 999 },
|
|
||||||
{ field: 'price', name: 'Price', priority: 999 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const clearFilter = (key) => {
|
const clearFilter = (key) => {
|
||||||
if (key === 'categoryFk') {
|
if (key === 'categoryFk') {
|
||||||
resetCategory();
|
resetCategory();
|
||||||
|
@ -72,21 +75,6 @@ const loadTypes = async (categoryFk) => {
|
||||||
typeList.value = data;
|
typeList.value = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onFilterInit = async ({ params }) => {
|
|
||||||
if (params.typeFk) {
|
|
||||||
selectedTypeFk.value = params.typeFk;
|
|
||||||
}
|
|
||||||
if (params.categoryFk) {
|
|
||||||
await loadTypes(params.categoryFk);
|
|
||||||
selectedCategoryFk.value = params.categoryFk;
|
|
||||||
}
|
|
||||||
if (params.orderBy) {
|
|
||||||
orderByParam.value = JSON.parse(params.orderBy);
|
|
||||||
selectedOrder.value = orderByParam.value?.way;
|
|
||||||
selectedOrderField.value = orderByParam.value?.field;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectedCategory = computed(() =>
|
const selectedCategory = computed(() =>
|
||||||
(categoryList.value || []).find(
|
(categoryList.value || []).find(
|
||||||
(category) => category?.id === selectedCategoryFk.value
|
(category) => category?.id === selectedCategoryFk.value
|
||||||
|
@ -109,12 +97,25 @@ function exprBuilder(param, value) {
|
||||||
|
|
||||||
const selectedTag = ref(null);
|
const selectedTag = ref(null);
|
||||||
const tagValues = ref([{}]);
|
const tagValues = ref([{}]);
|
||||||
const tagOptions = ref(null);
|
const tagOptions = ref([]);
|
||||||
const isButtonDisabled = computed(
|
|
||||||
() => !selectedTag.value || tagValues.value.some((item) => !item.value)
|
|
||||||
);
|
|
||||||
|
|
||||||
const applyTagFilter = (params, search) => {
|
const applyTagFilter = (params, search) => {
|
||||||
|
// console.log('params: ', params);
|
||||||
|
// if (!selectedTag.value) {
|
||||||
|
// console.log('values: ', selectedTag?.value?.name);
|
||||||
|
|
||||||
|
// params.tagGroups.push(
|
||||||
|
// JSON.stringify({
|
||||||
|
// values: selectedTag?.value?.name,
|
||||||
|
// // tagSelection: {
|
||||||
|
// // ...selectedTag.value,
|
||||||
|
// // orgShowField: selectedTag?.value?.name,
|
||||||
|
// // },
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// search();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
if (!tagValues.value?.length) {
|
if (!tagValues.value?.length) {
|
||||||
params.tagGroups = null;
|
params.tagGroups = null;
|
||||||
search();
|
search();
|
||||||
|
@ -125,12 +126,12 @@ const applyTagFilter = (params, search) => {
|
||||||
}
|
}
|
||||||
params.tagGroups.push(
|
params.tagGroups.push(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
values: tagValues.value,
|
values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
|
||||||
tagSelection: {
|
tagSelection: {
|
||||||
...selectedTag.value,
|
...selectedTag.value,
|
||||||
orgShowField: selectedTag.value.name,
|
orgShowField: selectedTag?.value?.name,
|
||||||
},
|
},
|
||||||
tagFk: selectedTag.value.tagFk,
|
tagFk: selectedTag?.value?.tagFk,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
search();
|
search();
|
||||||
|
@ -155,12 +156,6 @@ const onOrderFieldChange = (value, params, search) => {
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOrderChange = (value, params, search) => {
|
|
||||||
const orderBy = Object.assign({}, orderByParam.value, { way: value.way });
|
|
||||||
params.orderBy = JSON.stringify(orderBy);
|
|
||||||
search();
|
|
||||||
};
|
|
||||||
|
|
||||||
const setCategoryList = (data) => {
|
const setCategoryList = (data) => {
|
||||||
categoryList.value = (data || [])
|
categoryList.value = (data || [])
|
||||||
.filter((category) => category.display)
|
.filter((category) => category.display)
|
||||||
|
@ -168,6 +163,10 @@ const setCategoryList = (data) => {
|
||||||
...category,
|
...category,
|
||||||
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
||||||
}));
|
}));
|
||||||
|
const _moreFields = ['ASC', 'DESC'];
|
||||||
|
const _moreFieldsTypes = ['Relevancy', 'ColorAndPrice', 'Name', 'Price'];
|
||||||
|
moreFields.value = useLang(_moreFields);
|
||||||
|
moreFieldsOrder.value = useLang(_moreFieldsTypes);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCategoryClass = (category, params) => {
|
const getCategoryClass = (category, params) => {
|
||||||
|
@ -175,6 +174,20 @@ const getCategoryClass = (category, params) => {
|
||||||
return 'active';
|
return 'active';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const useLang = (values) => {
|
||||||
|
const { models } = validationsStore;
|
||||||
|
const properties = models.Item?.properties || {};
|
||||||
|
return values.map((name) => {
|
||||||
|
let prop = properties[name];
|
||||||
|
const label = t(`params.${name}`);
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
type: prop ? prop.type : null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -184,7 +197,6 @@ const getCategoryClass = (category, params) => {
|
||||||
:hidden-tags="['orderFk', 'orderBy']"
|
:hidden-tags="['orderFk', 'orderBy']"
|
||||||
:expr-builder="exprBuilder"
|
:expr-builder="exprBuilder"
|
||||||
:custom-tags="['tagGroups']"
|
:custom-tags="['tagGroups']"
|
||||||
@init="onFilterInit"
|
|
||||||
@remove="clearFilter"
|
@remove="clearFilter"
|
||||||
>
|
>
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
|
@ -274,17 +286,13 @@ const getCategoryClass = (category, params) => {
|
||||||
<QItem class="q-my-md">
|
<QItem class="q-my-md">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('params.order')"
|
:label="t('Order')"
|
||||||
v-model="selectedOrder"
|
v-model="selectedOrder"
|
||||||
:options="orderList || []"
|
:options="moreFields"
|
||||||
option-value="way"
|
option-label="label"
|
||||||
option-label="name"
|
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
:emit-value="false"
|
|
||||||
use-input
|
|
||||||
:is-clearable="false"
|
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => onOrderChange(value, params, searchFn)
|
(value) => onOrderChange(value, params, searchFn)
|
||||||
"
|
"
|
||||||
|
@ -294,17 +302,14 @@ const getCategoryClass = (category, params) => {
|
||||||
<QItem class="q-mb-md">
|
<QItem class="q-mb-md">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('params.order')"
|
:label="t('Order by')"
|
||||||
v-model="selectedOrderField"
|
v-model="selectedOrderField"
|
||||||
:options="OrderFields || []"
|
:options="moreFieldsOrder"
|
||||||
option-value="field"
|
option-label="label"
|
||||||
option-label="name"
|
option-value="name"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
:emit-value="false"
|
|
||||||
use-input
|
|
||||||
:is-clearable="false"
|
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => onOrderFieldChange(value, params, searchFn)
|
(value) => onOrderFieldChange(value, params, searchFn)
|
||||||
"
|
"
|
||||||
|
@ -341,10 +346,9 @@ const getCategoryClass = (category, params) => {
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-else
|
|
||||||
:label="t('params.value')"
|
:label="t('params.value')"
|
||||||
v-model="value.value"
|
v-model="value.value"
|
||||||
:options="tagOptions || []"
|
:options="tagValue || []"
|
||||||
option-value="value"
|
option-value="value"
|
||||||
option-label="value"
|
option-label="value"
|
||||||
dense
|
dense
|
||||||
|
@ -352,17 +356,18 @@ const getCategoryClass = (category, params) => {
|
||||||
rounded
|
rounded
|
||||||
emit-value
|
emit-value
|
||||||
use-input
|
use-input
|
||||||
:disable="!selectedTag"
|
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
/>
|
@new-value="createValue"
|
||||||
|
>
|
||||||
|
</VnSelect>
|
||||||
<FetchData
|
<FetchData
|
||||||
v-if="selectedTag && !selectedTag.isFree"
|
v-if="selectedTag"
|
||||||
:url="`Tags/${selectedTag?.id}/filterValue`"
|
:url="`Tags/${selectedTag}/filterValue`"
|
||||||
limit="30"
|
limit="30"
|
||||||
auto-load
|
auto-load
|
||||||
@on-fetch="(data) => (tagOptions = data)"
|
@on-fetch="(data) => (tagOptions = data)"
|
||||||
/>
|
/>
|
||||||
|
{{ console.log('selectedTag: ', selectedTag) }}
|
||||||
|
|
||||||
<QIcon
|
<QIcon
|
||||||
name="delete"
|
name="delete"
|
||||||
|
@ -388,7 +393,6 @@ const getCategoryClass = (category, params) => {
|
||||||
rounded
|
rounded
|
||||||
type="button"
|
type="button"
|
||||||
unelevated
|
unelevated
|
||||||
:disable="isButtonDisabled"
|
|
||||||
@click.stop="applyTagFilter(params, searchFn)"
|
@click.stop="applyTagFilter(params, searchFn)"
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -453,6 +457,12 @@ en:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
value: Value
|
value: Value
|
||||||
order: Order
|
order: Order
|
||||||
|
ASC: Ascendant
|
||||||
|
DESC: Descendant
|
||||||
|
Relevancy: Relevancy
|
||||||
|
ColorAndPrice: Color and price
|
||||||
|
Name: Name
|
||||||
|
Price: Price
|
||||||
es:
|
es:
|
||||||
params:
|
params:
|
||||||
type: Tipo
|
type: Tipo
|
||||||
|
@ -460,6 +470,14 @@ es:
|
||||||
tag: Etiqueta
|
tag: Etiqueta
|
||||||
value: Valor
|
value: Valor
|
||||||
order: Orden
|
order: Orden
|
||||||
|
ASC: Ascendiente
|
||||||
|
DESC: Descendiente
|
||||||
|
Relevancy: Relevancia
|
||||||
|
ColorAndPrice: Color y precio
|
||||||
|
Name: Nombre
|
||||||
|
Price: Precio
|
||||||
|
Order: Orden
|
||||||
|
Order by: Ordenar por
|
||||||
Plant: Planta
|
Plant: Planta
|
||||||
Flower: Flor
|
Flower: Flor
|
||||||
Handmade: Confección
|
Handmade: Confección
|
||||||
|
|
|
@ -59,7 +59,10 @@ const dialog = ref(null);
|
||||||
</template>
|
</template>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="price">
|
<div class="price">
|
||||||
<p>{{ item.available }} {{ t('to') }} {{ item.price }}</p>
|
<p>
|
||||||
|
{{ item.available }} {{ t('to') }}
|
||||||
|
{{ toCurrency(item.price) }}
|
||||||
|
</p>
|
||||||
<QIcon name="add_circle" class="icon">
|
<QIcon name="add_circle" class="icon">
|
||||||
<QTooltip>{{ t('globals.add') }}</QTooltip>
|
<QTooltip>{{ t('globals.add') }}</QTooltip>
|
||||||
<QPopupProxy ref="dialog">
|
<QPopupProxy ref="dialog">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { reactive, ref, onMounted } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useState } from 'composables/useState';
|
import { useState } from 'composables/useState';
|
||||||
|
@ -16,6 +16,7 @@ const route = useRoute();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const ORDER_MODEL = 'order';
|
const ORDER_MODEL = 'order';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const isNew = Boolean(!route.params.id);
|
const isNew = Boolean(!route.params.id);
|
||||||
const initialFormState = reactive({
|
const initialFormState = reactive({
|
||||||
clientFk: null,
|
clientFk: null,
|
||||||
|
@ -26,21 +27,20 @@ const initialFormState = reactive({
|
||||||
const clientList = ref([]);
|
const clientList = ref([]);
|
||||||
const agencyList = ref([]);
|
const agencyList = ref([]);
|
||||||
const addressList = ref([]);
|
const addressList = ref([]);
|
||||||
|
const clientId = ref(null);
|
||||||
|
|
||||||
const onClientsFetched = async (data) => {
|
const onClientsFetched = (data) => {
|
||||||
try {
|
|
||||||
clientList.value = data;
|
clientList.value = data;
|
||||||
initialFormState.clientFk = Number(route.query?.clientFk) || null;
|
initialFormState.clientFk = Number(route.query?.clientFk) || null;
|
||||||
|
clientId.value = initialFormState.clientFk;
|
||||||
|
|
||||||
if (initialFormState.clientFk) {
|
const client = clientList.value.find(
|
||||||
const { defaultAddressFk } = clientList.value.find(
|
|
||||||
(client) => client.id === initialFormState.clientFk
|
(client) => client.id === initialFormState.clientFk
|
||||||
);
|
);
|
||||||
|
if (client && client.defaultAddressFk) {
|
||||||
if (defaultAddressFk) await fetchAddressList(defaultAddressFk);
|
fetchAddressList(client.defaultAddressFk);
|
||||||
}
|
} else {
|
||||||
} catch (err) {
|
throw new Error(t(`No default address found for the client`));
|
||||||
console.error('Error fetching clients', err);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ const fetchAddressList = async (addressId) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
addressList.value = data;
|
addressList.value = data;
|
||||||
// Set address by default
|
|
||||||
if (addressList.value?.length === 1) {
|
if (addressList.value?.length === 1) {
|
||||||
state.get(ORDER_MODEL).addressFk = addressList.value[0].id;
|
state.get(ORDER_MODEL).addressFk = addressList.value[0].id;
|
||||||
}
|
}
|
||||||
|
@ -121,6 +120,21 @@ const orderFilter = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onClientChange = async (clientId) => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get(`Clients/${clientId}`);
|
||||||
|
console.log('info cliente: ', data);
|
||||||
|
|
||||||
|
await fetchAddressList(data.defaultAddressFk);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error al cambiar el cliente:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function onDataSaved(data) {
|
||||||
|
await router.push({ path: `/order/${data}/catalog` });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -134,13 +148,15 @@ const orderFilter = {
|
||||||
<div class="q-pa-md">
|
<div class="q-pa-md">
|
||||||
<FormModel
|
<FormModel
|
||||||
:url="!isNew ? `Orders/${route.params.id}` : null"
|
:url="!isNew ? `Orders/${route.params.id}` : null"
|
||||||
:url-create="isNew ? 'Orders/new' : null"
|
:url-create="'Orders/new'"
|
||||||
|
@on-data-saved="onDataSaved"
|
||||||
:model="ORDER_MODEL"
|
:model="ORDER_MODEL"
|
||||||
:form-initial-data="isNew ? initialFormState : null"
|
:form-initial-data="isNew ? initialFormState : null"
|
||||||
:observe-form-changes="!isNew"
|
:observe-form-changes="!isNew"
|
||||||
:mapper="isNew ? orderMapper : null"
|
:mapper="isNew ? orderMapper : null"
|
||||||
:filter="orderFilter"
|
:filter="orderFilter"
|
||||||
@on-fetch="fetchOrderDetails"
|
@on-fetch="fetchOrderDetails"
|
||||||
|
auto-load
|
||||||
>
|
>
|
||||||
<template #form="{ data }">
|
<template #form="{ data }">
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
@ -151,9 +167,7 @@ const orderFilter = {
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
hide-selected
|
hide-selected
|
||||||
@update:model-value="
|
@update:model-value="onClientChange"
|
||||||
(client) => fetchAddressList(client.defaultAddressFk)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -170,12 +184,10 @@ const orderFilter = {
|
||||||
v-model="data.addressFk"
|
v-model="data.addressFk"
|
||||||
:options="addressList"
|
:options="addressList"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="nickname"
|
option-label="street"
|
||||||
hide-selected
|
hide-selected
|
||||||
:disable="!addressList?.length"
|
:disable="!addressList?.length"
|
||||||
@update:model-value="
|
@update:model-value="onAddressChange"
|
||||||
() => fetchAgencyList(data.landed, data.addressFk)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -216,3 +228,8 @@ const orderFilter = {
|
||||||
</FormModel>
|
</FormModel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
No default address found for the client: No hay ninguna dirección asociada a este cliente.
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -35,6 +35,20 @@ function extractTags(items) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
tags.value = resultTags;
|
tags.value = resultTags;
|
||||||
|
extractValueTags(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagValue = ref([]);
|
||||||
|
|
||||||
|
function extractValueTags(items) {
|
||||||
|
const resultValueTags = items.flatMap((x) =>
|
||||||
|
Object.keys(x)
|
||||||
|
.filter((k) => /^value\d+$/.test(k))
|
||||||
|
.map((v) => x[v])
|
||||||
|
.filter((v) => v)
|
||||||
|
.sort()
|
||||||
|
);
|
||||||
|
tagValue.value = resultValueTags;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -66,7 +80,11 @@ function extractTags(items) {
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<QScrollArea class="fit text-grey-8">
|
<QScrollArea class="fit text-grey-8">
|
||||||
<OrderCatalogFilter data-key="OrderCatalogList" :tags="tags" />
|
<OrderCatalogFilter
|
||||||
|
data-key="OrderCatalogList"
|
||||||
|
:tag-value="tagValue"
|
||||||
|
:tags="tags"
|
||||||
|
/>
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
<QPage class="column items-center q-pa-md">
|
<QPage class="column items-center q-pa-md">
|
||||||
|
|
|
@ -7,13 +7,13 @@ import { useQuasar } from 'quasar';
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
import CardList from 'components/ui/CardList.vue';
|
|
||||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
|
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import { useSession } from 'composables/useSession';
|
import { useSession } from 'composables/useSession';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import ItemDescriptorProxy from '../Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -43,6 +43,7 @@ function confirmRemove(item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remove(item) {
|
async function remove(item) {
|
||||||
|
console.log('item: ', item);
|
||||||
await axios.post('OrderRows/removes', {
|
await axios.post('OrderRows/removes', {
|
||||||
actualOrderId: route.params.id,
|
actualOrderId: route.params.id,
|
||||||
rows: [item.id],
|
rows: [item.id],
|
||||||
|
@ -61,6 +62,35 @@ async function confirmOrder() {
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const detailsColumns = ref([
|
||||||
|
{
|
||||||
|
name: 'item',
|
||||||
|
label: t('order.summary.item'),
|
||||||
|
field: (row) => row?.item?.id,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: t('globals.description'),
|
||||||
|
field: (row) => row?.item?.name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'quantity',
|
||||||
|
label: t('order.summary.quantity'),
|
||||||
|
field: (row) => row?.quantity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'price',
|
||||||
|
label: t('order.summary.price'),
|
||||||
|
field: (row) => toCurrency(row?.price),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'amount',
|
||||||
|
label: t('order.summary.amount'),
|
||||||
|
field: (row) => toCurrency(row?.quantity * row?.price),
|
||||||
|
},
|
||||||
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -83,11 +113,13 @@ async function confirmOrder() {
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<QPage :key="componentKey" class="column items-center q-pa-md">
|
<QPage :key="componentKey" class="column items-center q-pa-md">
|
||||||
<div class="vn-card-list">
|
<div class="order-list">
|
||||||
<div v-if="!orderSummary.total" class="no-result">
|
<div v-if="!orderSummary.total" class="no-result">
|
||||||
{{ t('globals.noResults') }}
|
{{ t('globals.noResults') }}
|
||||||
</div>
|
</div>
|
||||||
<QCard v-else class="order-lines-summary q-pa-lg">
|
|
||||||
|
<QDrawer side="right" :width="300" show-if-above>
|
||||||
|
<QCard class="order-lines-summary q-pa-lg">
|
||||||
<p class="header text-right block">
|
<p class="header text-right block">
|
||||||
{{ t('summary') }}
|
{{ t('summary') }}
|
||||||
</p>
|
</p>
|
||||||
|
@ -107,6 +139,7 @@ async function confirmOrder() {
|
||||||
:value="toCurrency(orderSummary?.total)"
|
:value="toCurrency(orderSummary?.total)"
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
|
</QDrawer>
|
||||||
<VnPaginate
|
<VnPaginate
|
||||||
data-key="OrderLines"
|
data-key="OrderLines"
|
||||||
url="OrderRows"
|
url="OrderRows"
|
||||||
|
@ -125,74 +158,108 @@ async function confirmOrder() {
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<div class="catalog-list q-mt-xl">
|
<div class="q-pa-md">
|
||||||
<CardList
|
<QTable
|
||||||
v-for="row in rows"
|
:columns="detailsColumns"
|
||||||
:key="row.id"
|
:rows="rows"
|
||||||
:id="row.id"
|
flat
|
||||||
:title="row?.item?.name"
|
style="text-align: center"
|
||||||
class="cursor-inherit"
|
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #header="props">
|
||||||
<div class="flex items-center">
|
<QTr :props="props" class="tr-header">
|
||||||
<div class="image-wrapper q-mr-md">
|
<QTh></QTh>
|
||||||
|
<QTh auto-width>{{ t('item') }}</QTh>
|
||||||
|
<QTh>{{ t('globals.description') }}</QTh>
|
||||||
|
<QTh>{{ t('warehouse') }}</QTh>
|
||||||
|
<QTh>{{ t('shipped') }}</QTh>
|
||||||
|
<QTh auto-width>
|
||||||
|
{{ t('order.summary.quantity') }}
|
||||||
|
</QTh>
|
||||||
|
<QTh auto-width>{{ t('order.summary.price') }}</QTh>
|
||||||
|
<QTh auto-width>{{ t('amount') }}</QTh>
|
||||||
|
<QTh></QTh>
|
||||||
|
</QTr>
|
||||||
|
</template>
|
||||||
|
<template #body="props">
|
||||||
|
<QTr :props="props">
|
||||||
|
<QTd>
|
||||||
|
{{ console.log('props: ', props.row.item.id) }}
|
||||||
<QImg
|
<QImg
|
||||||
:src="`/api/Images/catalog/50x50/${row?.item?.id}/download?access_token=${token}`"
|
:src="`/api/Images/catalog/50x50/${props.row.item?.id}/download?access_token=${token}`"
|
||||||
spinner-color="primary"
|
spinner-color="primary"
|
||||||
:ratio="1"
|
:ratio="1"
|
||||||
height="50"
|
height="50"
|
||||||
width="50"
|
width="50"
|
||||||
class="image"
|
class="image-wrapper"
|
||||||
|
style="cursor: pointer"
|
||||||
|
/>
|
||||||
|
</QTd>
|
||||||
|
<QTd key="item" :props="props" class="item">
|
||||||
|
<span class="link">
|
||||||
|
<QBtn flat>
|
||||||
|
{{ props.row.item?.id }}
|
||||||
|
</QBtn>
|
||||||
|
<ItemDescriptorProxy
|
||||||
|
:id="props.row.item?.id"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="title text-primary text-weight-bold text-h5"
|
|
||||||
>
|
|
||||||
{{ row?.item?.name }}
|
|
||||||
</div>
|
|
||||||
<QChip class="q-chip-color" outline size="sm">
|
|
||||||
{{ t('ID') }}: {{ row.id }}
|
|
||||||
</QChip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #list-items>
|
|
||||||
<div class="q-mb-sm">
|
|
||||||
<span class="text-uppercase subname">
|
|
||||||
{{ row.item.subName }}
|
|
||||||
</span>
|
</span>
|
||||||
<fetched-tags :item="row.item" :max-length="5" />
|
</QTd>
|
||||||
|
<QTd
|
||||||
|
key="description"
|
||||||
|
:props="props"
|
||||||
|
class="description-cell"
|
||||||
|
>
|
||||||
|
<div class="row full-width justify-between">
|
||||||
|
{{ props.row.item.name }}
|
||||||
|
<div
|
||||||
|
v-if="props.row.item.subName"
|
||||||
|
class="subName"
|
||||||
|
>
|
||||||
|
{{ props.row.item.subName.toUpperCase() }}
|
||||||
</div>
|
</div>
|
||||||
<VnLv :label="t('item')" :value="String(row.item.id)" />
|
</div>
|
||||||
<VnLv
|
<FetchedTags
|
||||||
:label="t('warehouse')"
|
:item="props.row.item"
|
||||||
:value="row.warehouse.name"
|
:max-length="6"
|
||||||
|
class="fetched-tags"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
</QTd>
|
||||||
:label="t('shipped')"
|
<QTd>
|
||||||
:value="toDate(row.shipped)"
|
{{ props.row.warehouse.name }}
|
||||||
/>
|
</QTd>
|
||||||
<VnLv
|
<QTd>
|
||||||
:label="t('quantity')"
|
{{ toDate(props.row.shipped) }}
|
||||||
:value="String(row.quantity)"
|
</QTd>
|
||||||
/>
|
<QTd key="quantity" :props="props">
|
||||||
<VnLv
|
{{ props.row.quantity }}
|
||||||
:label="t('price')"
|
</QTd>
|
||||||
:value="toCurrency(row.price)"
|
<QTd key="price" :props="props">
|
||||||
/>
|
{{ toCurrency(props.row.price) }}
|
||||||
<VnLv
|
</QTd>
|
||||||
:label="t('amount')"
|
<QTd key="amount" :props="props">
|
||||||
:value="toCurrency(row.price * row.quantity)"
|
{{
|
||||||
/>
|
toCurrency(
|
||||||
</template>
|
props.row?.quantity * props.row?.price
|
||||||
<template #actions v-if="!order?.isConfirmed">
|
)
|
||||||
<QBtn
|
}}
|
||||||
:label="t('remove')"
|
</QTd>
|
||||||
@click.stop="confirmRemove(row)"
|
<QTd>
|
||||||
|
<QIcon
|
||||||
|
name="delete"
|
||||||
color="primary"
|
color="primary"
|
||||||
style="margin-top: 15px"
|
size="sm"
|
||||||
/>
|
class="cursor-pointer"
|
||||||
|
@click.stop="confirmRemove(props.row)"
|
||||||
|
style="margin-left: 40%"
|
||||||
|
>
|
||||||
|
<QTooltip>{{
|
||||||
|
t('Remove thermograph')
|
||||||
|
}}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</QTd>
|
||||||
|
</QTr>
|
||||||
</template>
|
</template>
|
||||||
</CardList>
|
</QTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VnPaginate>
|
</VnPaginate>
|
||||||
|
@ -239,14 +306,7 @@ async function confirmOrder() {
|
||||||
.image-wrapper {
|
.image-wrapper {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
|
||||||
.image {
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.subname {
|
|
||||||
color: var(--vn-label-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-result {
|
.no-result {
|
||||||
|
@ -255,6 +315,38 @@ async function confirmOrder() {
|
||||||
color: var(--vn-label-color);
|
color: var(--vn-label-color);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: left;
|
||||||
|
height: auto;
|
||||||
|
padding-top: 12px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-cell {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
.fetched-tags {
|
||||||
|
max-width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subName {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--vn-label-color);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
en:
|
||||||
|
|
Loading…
Reference in New Issue