forked from verdnatura/salix-front
Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6553-workerBusiness
This commit is contained in:
commit
8363f813de
|
@ -83,6 +83,10 @@ const $props = defineProps({
|
||||||
default: '',
|
default: '',
|
||||||
description: 'It is used for redirect on click "save and continue"',
|
description: 'It is used for redirect on click "save and continue"',
|
||||||
},
|
},
|
||||||
|
reload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['onFetch', 'onDataSaved']);
|
const emit = defineEmits(['onFetch', 'onDataSaved']);
|
||||||
const modelValue = computed(
|
const modelValue = computed(
|
||||||
|
@ -201,6 +205,7 @@ async function save() {
|
||||||
if ($props.urlCreate) notify('globals.dataCreated', 'positive');
|
if ($props.urlCreate) notify('globals.dataCreated', 'positive');
|
||||||
|
|
||||||
updateAndEmit('onDataSaved', formData.value, response?.data);
|
updateAndEmit('onDataSaved', formData.value, response?.data);
|
||||||
|
if ($props.reload) await arrayData.fetch({});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
notify('errors.writeRequest', 'negative');
|
notify('errors.writeRequest', 'negative');
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, onMounted } from 'vue';
|
||||||
|
import { useSession } from 'src/composables/useSession';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
collection: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 'Images',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: '200x200',
|
||||||
|
},
|
||||||
|
zoomSize: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: 'lg',
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const show = ref(false);
|
||||||
|
const token = useSession().getTokenMultimedia();
|
||||||
|
const timeStamp = ref(`timestamp=${Date.now()}`);
|
||||||
|
const url = computed(
|
||||||
|
() =>
|
||||||
|
`/api/${$props.collection}/catalog/${$props.size}/${$props.id}/download?access_token=${token}&${timeStamp.value}`
|
||||||
|
);
|
||||||
|
const emits = defineEmits(['refresh']);
|
||||||
|
const reload = (emit = false) => {
|
||||||
|
timeStamp.value = `timestamp=${Date.now()}`;
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
reload,
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<QImg :src="url" v-bind="$attrs" @click="show = !show" spinner-color="primary" />
|
||||||
|
<QDialog v-model="show" v-if="$props.zoomSize">
|
||||||
|
<QImg :src="url" class="img_zoom" v-bind="$attrs" spinner-color="primary" />
|
||||||
|
</QDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.q-img {
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
.rounded {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.img_zoom {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 0%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -17,26 +17,6 @@ const { t } = useI18n();
|
||||||
const { getTokenMultimedia } = useSession();
|
const { getTokenMultimedia } = useSession();
|
||||||
const token = getTokenMultimedia();
|
const token = getTokenMultimedia();
|
||||||
|
|
||||||
const claimFilter = {
|
|
||||||
fields: [
|
|
||||||
'id',
|
|
||||||
'clientFk',
|
|
||||||
'created',
|
|
||||||
'workerFk',
|
|
||||||
'claimStateFk',
|
|
||||||
'packages',
|
|
||||||
'pickup',
|
|
||||||
],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'client',
|
|
||||||
scope: {
|
|
||||||
fields: ['name'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const claimStates = ref([]);
|
const claimStates = ref([]);
|
||||||
const claimStatesCopy = ref([]);
|
const claimStatesCopy = ref([]);
|
||||||
const optionsList = ref([]);
|
const optionsList = ref([]);
|
||||||
|
@ -87,11 +67,10 @@ const statesFilter = {
|
||||||
/>
|
/>
|
||||||
<FetchData url="ClaimStates" @on-fetch="setClaimStates" auto-load />
|
<FetchData url="ClaimStates" @on-fetch="setClaimStates" auto-load />
|
||||||
<FormModel
|
<FormModel
|
||||||
:url="`Claims/${route.params.id}`"
|
model="Claim"
|
||||||
:url-update="`Claims/updateClaim/${route.params.id}`"
|
:url-update="`Claims/updateClaim/${route.params.id}`"
|
||||||
:filter="claimFilter"
|
|
||||||
model="claim"
|
|
||||||
auto-load
|
auto-load
|
||||||
|
:reload="true"
|
||||||
>
|
>
|
||||||
<template #form="{ data, validate, filter }">
|
<template #form="{ data, validate, filter }">
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import VnCard from 'components/common/VnCard.vue';
|
import VnCard from 'components/common/VnCard.vue';
|
||||||
import ClaimDescriptor from './ClaimDescriptor.vue';
|
import ClaimDescriptor from './ClaimDescriptor.vue';
|
||||||
import ClaimFilter from '../ClaimFilter.vue';
|
import ClaimFilter from '../ClaimFilter.vue';
|
||||||
|
import filter from './ClaimFilter.js';
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnCard
|
<VnCard
|
||||||
|
@ -13,5 +14,6 @@ import ClaimFilter from '../ClaimFilter.vue';
|
||||||
search-url="Claims/filter"
|
search-url="Claims/filter"
|
||||||
searchbar-label="Search claim"
|
searchbar-label="Search claim"
|
||||||
searchbar-info="You can search by claim id or customer name"
|
searchbar-info="You can search by claim id or customer name"
|
||||||
|
:filter="filter"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -12,6 +12,7 @@ import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
|
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
|
||||||
|
import filter from './ClaimFilter.js';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -29,49 +30,6 @@ const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'client',
|
|
||||||
scope: {
|
|
||||||
include: [
|
|
||||||
{ relation: 'salesPersonUser' },
|
|
||||||
{
|
|
||||||
relation: 'claimsRatio',
|
|
||||||
scope: {
|
|
||||||
fields: ['claimingRate'],
|
|
||||||
limit: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'claimState',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'ticket',
|
|
||||||
scope: {
|
|
||||||
include: [
|
|
||||||
{ relation: 'zone' },
|
|
||||||
{
|
|
||||||
relation: 'address',
|
|
||||||
scope: {
|
|
||||||
include: { relation: 'province' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'worker',
|
|
||||||
scope: {
|
|
||||||
include: { relation: 'user' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const STATE_COLOR = {
|
const STATE_COLOR = {
|
||||||
pending: 'warning',
|
pending: 'warning',
|
||||||
incomplete: 'info',
|
incomplete: 'info',
|
||||||
|
@ -101,7 +59,7 @@ onMounted(async () => {
|
||||||
:title="data.title"
|
:title="data.title"
|
||||||
:subtitle="data.subtitle"
|
:subtitle="data.subtitle"
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
data-key="claimData"
|
data-key="Claim"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<ClaimDescriptorMenu :claim="entity" />
|
<ClaimDescriptorMenu :claim="entity" />
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
'id',
|
||||||
|
'clientFk',
|
||||||
|
'created',
|
||||||
|
'workerFk',
|
||||||
|
'claimStateFk',
|
||||||
|
'packages',
|
||||||
|
'pickup',
|
||||||
|
'ticketFk',
|
||||||
|
],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'client',
|
||||||
|
scope: {
|
||||||
|
include: [
|
||||||
|
{ relation: 'salesPersonUser' },
|
||||||
|
{
|
||||||
|
relation: 'claimsRatio',
|
||||||
|
scope: {
|
||||||
|
fields: ['claimingRate'],
|
||||||
|
limit: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'claimState',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'ticket',
|
||||||
|
scope: {
|
||||||
|
include: [
|
||||||
|
{ relation: 'zone' },
|
||||||
|
{
|
||||||
|
relation: 'address',
|
||||||
|
scope: {
|
||||||
|
include: { relation: 'province' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'worker',
|
||||||
|
scope: {
|
||||||
|
include: { relation: 'user' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -22,7 +22,7 @@ const balanceDueTotal = ref(0);
|
||||||
const selected = ref([]);
|
const selected = ref([]);
|
||||||
|
|
||||||
const tableColumnComponents = {
|
const tableColumnComponents = {
|
||||||
client: {
|
clientFk: {
|
||||||
component: QBtn,
|
component: QBtn,
|
||||||
props: () => ({ flat: true, class: 'link', noCaps: true }),
|
props: () => ({ flat: true, class: 'link', noCaps: true }),
|
||||||
event: () => {},
|
event: () => {},
|
||||||
|
@ -40,7 +40,7 @@ const tableColumnComponents = {
|
||||||
props: () => ({ flat: true, class: 'link', noCaps: true }),
|
props: () => ({ flat: true, class: 'link', noCaps: true }),
|
||||||
event: () => {},
|
event: () => {},
|
||||||
},
|
},
|
||||||
department: {
|
departmentName: {
|
||||||
component: 'span',
|
component: 'span',
|
||||||
props: () => {},
|
props: () => {},
|
||||||
event: () => {},
|
event: () => {},
|
||||||
|
@ -102,12 +102,12 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'clientName',
|
field: 'clientName',
|
||||||
label: t('Client'),
|
label: t('Client'),
|
||||||
name: 'client',
|
name: 'clientFk',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'isWorker',
|
field: ({ isWorker }) => Boolean(isWorker),
|
||||||
label: t('Is worker'),
|
label: t('Is worker'),
|
||||||
name: 'isWorker',
|
name: 'isWorker',
|
||||||
},
|
},
|
||||||
|
@ -122,7 +122,7 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'departmentName',
|
field: 'departmentName',
|
||||||
label: t('Department'),
|
label: t('Department'),
|
||||||
name: 'department',
|
name: 'departmentName',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -204,48 +204,24 @@ const viewAddObservation = (rowsSelected) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const departments = ref(new Map());
|
|
||||||
|
|
||||||
const onFetch = async (data) => {
|
const onFetch = async (data) => {
|
||||||
const salesPersonFks = data.map((item) => item.salesPersonFk);
|
|
||||||
const departmentNames = salesPersonFks.map(async (salesPersonFk) => {
|
|
||||||
try {
|
|
||||||
const { data: workerDepartment } = await axios.get(
|
|
||||||
`WorkerDepartments/${salesPersonFk}`
|
|
||||||
);
|
|
||||||
const { data: department } = await axios.get(
|
|
||||||
`Departments/${workerDepartment.departmentFk}`
|
|
||||||
);
|
|
||||||
departments.value.set(salesPersonFk, department.name);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Err: ', error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const recoveryData = await axios.get('Recoveries');
|
const recoveryData = await axios.get('Recoveries');
|
||||||
|
|
||||||
const recoveries = recoveryData.data.map(({ clientFk, finished }) => ({
|
const recoveries = recoveryData.data.map(({ clientFk, finished }) => ({
|
||||||
clientFk,
|
clientFk,
|
||||||
finished,
|
finished,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await Promise.all(departmentNames);
|
|
||||||
|
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
item.departmentName = departments.value.get(item.salesPersonFk);
|
|
||||||
item.isWorker = item.businessTypeFk === 'worker';
|
|
||||||
const recovery = recoveries.find(({ clientFk }) => clientFk === item.clientFk);
|
const recovery = recoveries.find(({ clientFk }) => clientFk === item.clientFk);
|
||||||
item.finished = recovery?.finished === null;
|
item.finished = recovery?.finished === null;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const element of data) element.isWorker = element.businessTypeFk === 'worker';
|
|
||||||
|
|
||||||
balanceDueTotal.value = data.reduce((acc, { amount = 0 }) => acc + amount, 0);
|
balanceDueTotal.value = data.reduce((acc, { amount = 0 }) => acc + amount, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
function exprBuilder(param, value) {
|
function exprBuilder(param, value) {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 'clientFk':
|
case 'clientFk':
|
||||||
return { [`d.${param}`]: value?.id };
|
return { [`d.${param}`]: value };
|
||||||
case 'creditInsurance':
|
case 'creditInsurance':
|
||||||
case 'amount':
|
case 'amount':
|
||||||
case 'workerFk':
|
case 'workerFk':
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
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 VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
@ -16,14 +15,13 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const clients = ref();
|
|
||||||
const salespersons = ref();
|
const salespersons = ref();
|
||||||
const countries = ref();
|
const countries = ref();
|
||||||
const authors = ref();
|
const authors = ref();
|
||||||
|
const departments = ref();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData @on-fetch="(data) => (clients = data)" auto-load url="Clients" />
|
|
||||||
<FetchData
|
<FetchData
|
||||||
:filter="{ where: { role: 'salesPerson' } }"
|
:filter="{ where: { role: 'salesPerson' } }"
|
||||||
@on-fetch="(data) => (salespersons = data)"
|
@on-fetch="(data) => (salespersons = data)"
|
||||||
|
@ -36,6 +34,7 @@ const authors = ref();
|
||||||
auto-load
|
auto-load
|
||||||
url="Workers/activeWithInheritedRole"
|
url="Workers/activeWithInheritedRole"
|
||||||
/>
|
/>
|
||||||
|
<FetchData @on-fetch="(data) => (departments = data)" auto-load url="Departments" />
|
||||||
|
|
||||||
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
|
@ -47,29 +46,22 @@ const authors = ref();
|
||||||
|
|
||||||
<template #body="{ params, searchFn }">
|
<template #body="{ params, searchFn }">
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection v-if="clients">
|
<VnSelect
|
||||||
<VnSelect
|
:label="t('Client')"
|
||||||
:label="t('Client')"
|
url="Clients"
|
||||||
:options="clients"
|
dense
|
||||||
dense
|
option-label="name"
|
||||||
emit-value
|
option-value="id"
|
||||||
hide-selected
|
outlined
|
||||||
map-options
|
rounded
|
||||||
option-label="name"
|
emit-value
|
||||||
option-value="id"
|
hide-selected
|
||||||
outlined
|
map-options
|
||||||
rounded
|
v-model="params.clientFk"
|
||||||
use-input
|
use-input
|
||||||
v-model="params.clientFk"
|
@update:model-value="searchFn()"
|
||||||
@update:model-value="searchFn()"
|
/>
|
||||||
auto-load
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
<QItemSection v-else>
|
|
||||||
<QSkeleton class="full-width" type="QInput" />
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection v-if="salespersons">
|
<QItemSection v-if="salespersons">
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
@ -93,6 +85,29 @@ const authors = ref();
|
||||||
<QSkeleton class="full-width" type="QInput" />
|
<QSkeleton class="full-width" type="QInput" />
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection v-if="departments">
|
||||||
|
<VnSelect
|
||||||
|
:input-debounce="0"
|
||||||
|
:label="t('Departments')"
|
||||||
|
:options="departments"
|
||||||
|
dense
|
||||||
|
emit-value
|
||||||
|
hide-selected
|
||||||
|
map-options
|
||||||
|
option-label="name"
|
||||||
|
option-value="id"
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
use-input
|
||||||
|
v-model="params.departmentFk"
|
||||||
|
@update:model-value="searchFn()"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection v-else>
|
||||||
|
<QSkeleton class="full-width" type="QInput" />
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection v-if="countries">
|
<QItemSection v-if="countries">
|
||||||
|
|
|
@ -11,9 +11,9 @@ import VnInput from 'src/components/common/VnInput.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 ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
|
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
import { toCurrency } from 'src/filters';
|
import { toCurrency } from 'src/filters';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
@ -22,7 +22,6 @@ const quasar = useQuasar();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const stateStore = useStateStore();
|
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
|
||||||
const rowsSelected = ref([]);
|
const rowsSelected = ref([]);
|
||||||
|
@ -312,20 +311,22 @@ const lockIconType = (groupingMode, mode) => {
|
||||||
auto-load
|
auto-load
|
||||||
@on-fetch="(data) => (packagingsOptions = data)"
|
@on-fetch="(data) => (packagingsOptions = data)"
|
||||||
/>
|
/>
|
||||||
<Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown()">
|
<VnSubToolbar>
|
||||||
<QBtnGroup push style="column-gap: 10px">
|
<template #st-actions>
|
||||||
<slot name="moreBeforeActions" />
|
<QBtnGroup push style="column-gap: 10px">
|
||||||
<QBtn
|
<slot name="moreBeforeActions" />
|
||||||
:label="t('globals.remove')"
|
<QBtn
|
||||||
color="primary"
|
:label="t('globals.remove')"
|
||||||
icon="delete"
|
color="primary"
|
||||||
flat
|
icon="delete"
|
||||||
@click="openRemoveDialog()"
|
flat
|
||||||
:disable="!rowsSelected?.length"
|
@click="openRemoveDialog()"
|
||||||
:title="t('globals.remove')"
|
:disable="!rowsSelected?.length"
|
||||||
/>
|
:title="t('globals.remove')"
|
||||||
</QBtnGroup>
|
/>
|
||||||
</Teleport>
|
</QBtnGroup>
|
||||||
|
</template>
|
||||||
|
</VnSubToolbar>
|
||||||
<VnPaginate
|
<VnPaginate
|
||||||
ref="entryBuysPaginateRef"
|
ref="entryBuysPaginateRef"
|
||||||
data-key="EntryBuys"
|
data-key="EntryBuys"
|
||||||
|
|
|
@ -3,8 +3,7 @@ import { ref, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import EditPictureForm from 'components/EditPictureForm.vue';
|
import EditPictureForm from 'components/EditPictureForm.vue';
|
||||||
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
|
@ -27,19 +26,12 @@ const $props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getTokenMultimedia } = useSession();
|
|
||||||
|
|
||||||
const image = ref(null);
|
const image = ref(null);
|
||||||
const editPhotoFormDialog = ref(null);
|
const editPhotoFormDialog = ref(null);
|
||||||
const showEditPhotoForm = ref(false);
|
const showEditPhotoForm = ref(false);
|
||||||
const warehouseName = ref(null);
|
const warehouseName = ref(null);
|
||||||
|
|
||||||
const getItemAvatar = async () => {
|
|
||||||
const token = getTokenMultimedia();
|
|
||||||
const timeStamp = `timestamp=${Date.now()}`;
|
|
||||||
image.value = `/api/Images/catalog/200x200/${$props.entityId}/download?access_token=${token}&${timeStamp}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleEditPictureForm = () => {
|
const toggleEditPictureForm = () => {
|
||||||
showEditPhotoForm.value = !showEditPhotoForm.value;
|
showEditPhotoForm.value = !showEditPhotoForm.value;
|
||||||
};
|
};
|
||||||
|
@ -62,14 +54,17 @@ const getWarehouseName = async (warehouseFk) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
getItemAvatar();
|
|
||||||
getItemConfigs();
|
getItemConfigs();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handlePhotoUpdated = (evt = false) => {
|
||||||
|
image.value.reload(evt);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative-position">
|
<div class="relative-position">
|
||||||
<QImg :src="image" spinner-color="primary" style="min-height: 256px">
|
<VnImg ref="image" :id="$props.entityId" @refresh="handlePhotoUpdated(true)">
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="absolute-full picture text-center q-pa-md flex flex-center">
|
<div class="absolute-full picture text-center q-pa-md flex flex-center">
|
||||||
<div>
|
<div>
|
||||||
|
@ -82,7 +77,7 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</QImg>
|
</VnImg>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="showEditButton"
|
v-if="showEditButton"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
@ -97,7 +92,7 @@ onMounted(async () => {
|
||||||
collection="catalog"
|
collection="catalog"
|
||||||
:id="entityId"
|
:id="entityId"
|
||||||
@close-form="toggleEditPictureForm()"
|
@close-form="toggleEditPictureForm()"
|
||||||
@on-photo-uploaded="getItemAvatar()"
|
@on-photo-uploaded="handlePhotoUpdated"
|
||||||
/>
|
/>
|
||||||
</QDialog>
|
</QDialog>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
|
|
|
@ -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 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';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
|
||||||
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,10 +97,7 @@ 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) => {
|
||||||
if (!tagValues.value?.length) {
|
if (!tagValues.value?.length) {
|
||||||
|
@ -125,12 +110,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();
|
||||||
|
@ -147,20 +132,52 @@ const removeTagChip = (selection, params, search) => {
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderByParam = ref(null);
|
const onOrderChange = (value, params) => {
|
||||||
|
const tagObj = JSON.parse(params.orderBy);
|
||||||
const onOrderFieldChange = (value, params, search) => {
|
tagObj.way = value.name;
|
||||||
const orderBy = Object.assign({}, orderByParam.value, { field: value.field });
|
params.orderBy = JSON.stringify(tagObj);
|
||||||
params.orderBy = JSON.stringify(orderBy);
|
|
||||||
search();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOrderChange = (value, params, search) => {
|
const onOrderFieldChange = (value, params) => {
|
||||||
const orderBy = Object.assign({}, orderByParam.value, { way: value.way });
|
const tagObj = JSON.parse(params.orderBy); // esto donde va
|
||||||
params.orderBy = JSON.stringify(orderBy);
|
const fields = {
|
||||||
search();
|
Relevancy: (value) => value + ' DESC, name',
|
||||||
|
ColorAndPrice: 'showOrder, price',
|
||||||
|
Name: 'name',
|
||||||
|
Price: 'price',
|
||||||
|
};
|
||||||
|
let tagField = fields[value];
|
||||||
|
if (!tagField) return;
|
||||||
|
|
||||||
|
if (typeof tagField === 'function') tagField = tagField(value);
|
||||||
|
tagObj.field = tagField;
|
||||||
|
params.orderBy = JSON.stringify(tagObj);
|
||||||
|
switch (value) {
|
||||||
|
case 'Relevancy':
|
||||||
|
tagObj.field = value + ' DESC, name';
|
||||||
|
params.orderBy = JSON.stringify(tagObj);
|
||||||
|
console.log('params: ', params);
|
||||||
|
break;
|
||||||
|
case 'ColorAndPrice':
|
||||||
|
tagObj.field = 'showOrder, price';
|
||||||
|
params.orderBy = JSON.stringify(tagObj);
|
||||||
|
console.log('params: ', params);
|
||||||
|
break;
|
||||||
|
case 'Name':
|
||||||
|
tagObj.field = 'name';
|
||||||
|
params.orderBy = JSON.stringify(tagObj);
|
||||||
|
console.log('params: ', params);
|
||||||
|
break;
|
||||||
|
case 'Price':
|
||||||
|
tagObj.field = 'price';
|
||||||
|
params.orderBy = JSON.stringify(tagObj);
|
||||||
|
console.log('params: ', params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _moreFields = ['ASC', 'DESC'];
|
||||||
|
const _moreFieldsTypes = ['Relevancy', 'ColorAndPrice', 'Name', 'Price'];
|
||||||
const setCategoryList = (data) => {
|
const setCategoryList = (data) => {
|
||||||
categoryList.value = (data || [])
|
categoryList.value = (data || [])
|
||||||
.filter((category) => category.display)
|
.filter((category) => category.display)
|
||||||
|
@ -168,6 +185,8 @@ const setCategoryList = (data) => {
|
||||||
...category,
|
...category,
|
||||||
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
||||||
}));
|
}));
|
||||||
|
moreFields.value = useLang(_moreFields);
|
||||||
|
moreFieldsOrder.value = useLang(_moreFieldsTypes);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCategoryClass = (category, params) => {
|
const getCategoryClass = (category, params) => {
|
||||||
|
@ -175,6 +194,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>
|
||||||
|
@ -182,9 +215,9 @@ const getCategoryClass = (category, params) => {
|
||||||
<VnFilterPanel
|
<VnFilterPanel
|
||||||
:data-key="props.dataKey"
|
:data-key="props.dataKey"
|
||||||
:hidden-tags="['orderFk', 'orderBy']"
|
:hidden-tags="['orderFk', 'orderBy']"
|
||||||
|
:unremovable-params="['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,40 +307,29 @@ 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"
|
@update:model-value="(value) => onOrderChange(value, params)"
|
||||||
use-input
|
|
||||||
:is-clearable="false"
|
|
||||||
@update:model-value="
|
|
||||||
(value) => onOrderChange(value, params, searchFn)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<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"
|
@update:model-value="(value) => onOrderFieldChange(value, params)"
|
||||||
use-input
|
|
||||||
:is-clearable="false"
|
|
||||||
@update:model-value="
|
|
||||||
(value) => onOrderFieldChange(value, params, searchFn)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
@ -333,15 +355,30 @@ const getCategoryClass = (category, params) => {
|
||||||
:key="value"
|
:key="value"
|
||||||
class="q-mt-md filter-value"
|
class="q-mt-md filter-value"
|
||||||
>
|
>
|
||||||
<VnInput
|
<FetchData
|
||||||
v-if="selectedTag?.isFree"
|
v-if="selectedTag"
|
||||||
v-model="value.value"
|
:url="`Tags/${selectedTag}/filterValue`"
|
||||||
:label="t('params.value')"
|
limit="30"
|
||||||
is-outlined
|
auto-load
|
||||||
class="filter-input"
|
@on-fetch="(data) => (tagOptions = data)"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-else
|
v-if="!selectedTag"
|
||||||
|
:label="t('params.value')"
|
||||||
|
v-model="value.value"
|
||||||
|
:options="tagValue || []"
|
||||||
|
option-value="value"
|
||||||
|
option-label="value"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
emit-value
|
||||||
|
use-input
|
||||||
|
class="filter-input"
|
||||||
|
@new-value="createValue"
|
||||||
|
/>
|
||||||
|
<VnSelect
|
||||||
|
v-else-if="selectedTag === 1"
|
||||||
:label="t('params.value')"
|
:label="t('params.value')"
|
||||||
v-model="value.value"
|
v-model="value.value"
|
||||||
:options="tagOptions || []"
|
:options="tagOptions || []"
|
||||||
|
@ -352,18 +389,18 @@ const getCategoryClass = (category, params) => {
|
||||||
rounded
|
rounded
|
||||||
emit-value
|
emit-value
|
||||||
use-input
|
use-input
|
||||||
:disable="!selectedTag"
|
class="filter-input"
|
||||||
|
@new-value="createValue"
|
||||||
|
/>
|
||||||
|
<VnInput
|
||||||
|
v-else
|
||||||
|
:label="t('params.value')"
|
||||||
|
v-model="value.value"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FetchData
|
|
||||||
v-if="selectedTag && !selectedTag.isFree"
|
|
||||||
:url="`Tags/${selectedTag?.id}/filterValue`"
|
|
||||||
limit="30"
|
|
||||||
auto-load
|
|
||||||
@on-fetch="(data) => (tagOptions = data)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<QIcon
|
<QIcon
|
||||||
name="delete"
|
name="delete"
|
||||||
class="filter-icon"
|
class="filter-icon"
|
||||||
|
@ -388,7 +425,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 +489,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 +502,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
|
||||||
|
|
|
@ -3,16 +3,14 @@ import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
import OrderCatalogItemDialog from 'pages/Order/Card/OrderCatalogItemDialog.vue';
|
import OrderCatalogItemDialog from 'pages/Order/Card/OrderCatalogItemDialog.vue';
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
|
||||||
import { useSession } from 'composables/useSession';
|
|
||||||
import toCurrency from '../../../filters/toCurrency';
|
import toCurrency from '../../../filters/toCurrency';
|
||||||
|
|
||||||
const DEFAULT_PRICE_KG = 0;
|
const DEFAULT_PRICE_KG = 0;
|
||||||
|
|
||||||
const { getTokenMultimedia } = useSession();
|
|
||||||
const token = getTokenMultimedia();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
|
@ -29,14 +27,7 @@ const dialog = ref(null);
|
||||||
<div class="container order-catalog-item overflow-hidden">
|
<div class="container order-catalog-item overflow-hidden">
|
||||||
<QCard class="card shadow-6">
|
<QCard class="card shadow-6">
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
<QImg
|
<VnImg :id="item.id" class="image" />
|
||||||
:src="`/api/Images/catalog/200x200/${item.id}/download?access_token=${token}`"
|
|
||||||
spinner-color="primary"
|
|
||||||
:ratio="1"
|
|
||||||
height="192"
|
|
||||||
width="192"
|
|
||||||
class="image"
|
|
||||||
/>
|
|
||||||
<div v-if="item.hex" class="item-color-container">
|
<div v-if="item.hex" class="item-color-container">
|
||||||
<div
|
<div
|
||||||
class="item-color"
|
class="item-color"
|
||||||
|
@ -59,7 +50,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,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { reactive, ref } 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';
|
||||||
|
@ -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,22 +27,19 @@ 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?.defaultAddressFk)
|
||||||
|
throw new Error(t(`No default address found for the client`));
|
||||||
if (defaultAddressFk) await fetchAddressList(defaultAddressFk);
|
fetchAddressList(client.defaultAddressFk);
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error fetching clients', err);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchAddressList = async (addressId) => {
|
const fetchAddressList = async (addressId) => {
|
||||||
|
@ -55,7 +53,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 +118,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 +146,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 +165,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 +182,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 +226,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>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { useRoute } from 'vue-router';
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
|
||||||
import OrderCatalogItem from 'pages/Order/Card/OrderCatalogItem.vue';
|
import OrderCatalogItem from 'pages/Order/Card/OrderCatalogItem.vue';
|
||||||
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
|
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
|
||||||
|
|
||||||
|
@ -35,38 +34,31 @@ 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>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Teleport to="#searchbar" v-if="stateStore.isHeaderMounted()">
|
|
||||||
<VnSearchbar
|
|
||||||
data-key="OrderCatalogList"
|
|
||||||
url="Orders/CatalogFilter"
|
|
||||||
:limit="50"
|
|
||||||
:user-params="catalogParams"
|
|
||||||
:static-params="['orderFk', 'orderBy']"
|
|
||||||
:redirect="false"
|
|
||||||
/>
|
|
||||||
</Teleport>
|
|
||||||
<Teleport v-if="stateStore.isHeaderMounted()" to="#actions-append">
|
|
||||||
<div class="row q-gutter-x-sm">
|
|
||||||
<QBtn
|
|
||||||
flat
|
|
||||||
@click.stop="stateStore.toggleRightDrawer()"
|
|
||||||
round
|
|
||||||
dense
|
|
||||||
icon="menu"
|
|
||||||
>
|
|
||||||
<QTooltip bottom anchor="bottom right">
|
|
||||||
{{ t('globals.collapseMenu') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QBtn>
|
|
||||||
</div>
|
|
||||||
</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,19 +7,17 @@ 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 VnImg from 'components/ui/VnImg.vue';
|
||||||
|
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
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();
|
||||||
const { getTokenMultimedia } = useSession();
|
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const token = getTokenMultimedia();
|
|
||||||
const orderSummary = ref({
|
const orderSummary = ref({
|
||||||
total: null,
|
total: null,
|
||||||
vat: null,
|
vat: null,
|
||||||
|
@ -61,6 +59,56 @@ async function confirmOrder() {
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const detailsColumns = ref([
|
||||||
|
{
|
||||||
|
name: 'img',
|
||||||
|
label: '',
|
||||||
|
field: (row) => row?.item?.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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: 'warehouse',
|
||||||
|
label: t('warehouse'),
|
||||||
|
field: (row) => row?.warehouse?.name,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'shipped',
|
||||||
|
label: t('shipped'),
|
||||||
|
field: (row) => toDate(row?.shipped),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
label: '',
|
||||||
|
field: (row) => row?.id,
|
||||||
|
},
|
||||||
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -83,30 +131,33 @@ 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 full-width">
|
||||||
<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">
|
|
||||||
<p class="header text-right block">
|
<QDrawer side="right" :width="270" show-if-above>
|
||||||
{{ t('summary') }}
|
<QCard class="order-lines-summary q-pa-lg">
|
||||||
</p>
|
<p class="header text-right block">
|
||||||
<VnLv
|
{{ t('summary') }}
|
||||||
v-if="orderSummary.vat && orderSummary.total"
|
</p>
|
||||||
:label="t('subtotal')"
|
<VnLv
|
||||||
:value="toCurrency(orderSummary.total - orderSummary.vat)"
|
v-if="orderSummary.vat && orderSummary.total"
|
||||||
/>
|
:label="t('subtotal')"
|
||||||
<VnLv
|
:value="toCurrency(orderSummary.total - orderSummary.vat)"
|
||||||
v-if="orderSummary.vat"
|
/>
|
||||||
:label="t('VAT')"
|
<VnLv
|
||||||
:value="toCurrency(orderSummary?.vat)"
|
v-if="orderSummary.vat"
|
||||||
/>
|
:label="t('VAT')"
|
||||||
<VnLv
|
:value="toCurrency(orderSummary?.vat)"
|
||||||
v-if="orderSummary.total"
|
/>
|
||||||
:label="t('total')"
|
<VnLv
|
||||||
:value="toCurrency(orderSummary?.total)"
|
v-if="orderSummary.total"
|
||||||
/>
|
:label="t('total')"
|
||||||
</QCard>
|
:value="toCurrency(orderSummary?.total)"
|
||||||
|
/>
|
||||||
|
</QCard>
|
||||||
|
</QDrawer>
|
||||||
<VnPaginate
|
<VnPaginate
|
||||||
data-key="OrderLines"
|
data-key="OrderLines"
|
||||||
url="OrderRows"
|
url="OrderRows"
|
||||||
|
@ -125,74 +176,71 @@ 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"
|
class="full-width"
|
||||||
class="cursor-inherit"
|
style="text-align: center"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #header="props">
|
||||||
<div class="flex items-center">
|
<QTr class="tr-header" :props="props">
|
||||||
<div class="image-wrapper q-mr-md">
|
<QTh
|
||||||
<QImg
|
v-for="col in props.cols"
|
||||||
:src="`/api/Images/catalog/50x50/${row?.item?.id}/download?access_token=${token}`"
|
:key="col.name"
|
||||||
spinner-color="primary"
|
:props="props"
|
||||||
:ratio="1"
|
style="text-align: center"
|
||||||
height="50"
|
|
||||||
width="50"
|
|
||||||
class="image"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="title text-primary text-weight-bold text-h5"
|
|
||||||
>
|
>
|
||||||
{{ row?.item?.name }}
|
{{ t(col.label) }}
|
||||||
|
</QTh>
|
||||||
|
</QTr>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-img="{ value }">
|
||||||
|
<QTd>
|
||||||
|
<div class="image-wrapper">
|
||||||
|
<VnImg :id="value" class="rounded" />
|
||||||
</div>
|
</div>
|
||||||
<QChip class="q-chip-color" outline size="sm">
|
</QTd>
|
||||||
{{ t('ID') }}: {{ row.id }}
|
|
||||||
</QChip>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #list-items>
|
<template #body-cell-item="{ value }">
|
||||||
<div class="q-mb-sm">
|
<QTd class="item">
|
||||||
<span class="text-uppercase subname">
|
<span class="link">
|
||||||
{{ row.item.subName }}
|
<QBtn flat>
|
||||||
|
{{ value }}
|
||||||
|
</QBtn>
|
||||||
|
<ItemDescriptorProxy :id="value" />
|
||||||
</span>
|
</span>
|
||||||
<FetchedTags :item="row.item" :max-length="5" />
|
</QTd>
|
||||||
</div>
|
|
||||||
<VnLv :label="t('item')" :value="String(row.item.id)" />
|
|
||||||
<VnLv
|
|
||||||
:label="t('warehouse')"
|
|
||||||
:value="row.warehouse.name"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('shipped')"
|
|
||||||
:value="toDate(row.shipped)"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('quantity')"
|
|
||||||
:value="String(row.quantity)"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('price')"
|
|
||||||
:value="toCurrency(row.price)"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('amount')"
|
|
||||||
:value="toCurrency(row.price * row.quantity)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #actions v-if="!order?.isConfirmed">
|
<template #body-cell-description="{ row, value }">
|
||||||
<QBtn
|
<QTd>
|
||||||
:label="t('remove')"
|
<div
|
||||||
@click.stop="confirmRemove(row)"
|
class="row column full-width justify-between items-start"
|
||||||
color="primary"
|
>
|
||||||
style="margin-top: 15px"
|
{{ value }}
|
||||||
/>
|
<div v-if="value" class="subName">
|
||||||
|
{{ value.toUpperCase() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<FetchedTags :item="row.item" :max-length="6" />
|
||||||
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
</CardList>
|
|
||||||
|
<template #body-cell-actions="{ value }">
|
||||||
|
<QTd>
|
||||||
|
<QIcon
|
||||||
|
name="delete"
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click.stop="confirmRemove(value)"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('Remove thermograph') }}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VnPaginate>
|
</VnPaginate>
|
||||||
|
@ -239,14 +287,7 @@ async function confirmOrder() {
|
||||||
.image-wrapper {
|
.image-wrapper {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
margin-left: 30%;
|
||||||
.image {
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.subname {
|
|
||||||
color: var(--vn-label-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-result {
|
.no-result {
|
||||||
|
@ -255,6 +296,11 @@ async function confirmOrder() {
|
||||||
color: var(--vn-label-color);
|
color: var(--vn-label-color);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subName {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--vn-label-color);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
en:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount, computed, ref } from 'vue';
|
import { onBeforeMount, onMounted, computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { Notify } from 'quasar';
|
import { Notify } from 'quasar';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -10,10 +10,12 @@ import CmrFilter from './CmrFilter.vue';
|
||||||
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||||
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
|
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
|
import { useStateStore } from 'src/stores/useStateStore';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getTokenMultimedia } = useSession();
|
const { getTokenMultimedia } = useSession();
|
||||||
const token = getTokenMultimedia();
|
const token = getTokenMultimedia();
|
||||||
|
const state = useStateStore();
|
||||||
const selected = ref([]);
|
const selected = ref([]);
|
||||||
const warehouses = ref([]);
|
const warehouses = ref([]);
|
||||||
|
|
||||||
|
@ -81,6 +83,9 @@ onBeforeMount(async () => {
|
||||||
const { data } = await axios.get('Warehouses');
|
const { data } = await axios.get('Warehouses');
|
||||||
warehouses.value = data;
|
warehouses.value = data;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(() => (state.rightDrawer = true));
|
||||||
|
|
||||||
function getApiUrl() {
|
function getApiUrl() {
|
||||||
return new URL(window.location).origin;
|
return new URL(window.location).origin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ const { t } = useI18n();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const entityId = computed(() => $props.id || route.params.id);
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
const URL_KEY = 'NotificationSubscriptions';
|
const URL_KEY = 'NotificationSubscriptions';
|
||||||
const active = ref();
|
const active = ref(new Map());
|
||||||
const available = ref();
|
const available = ref(new Map());
|
||||||
|
|
||||||
async function toggleNotification(notification) {
|
async function toggleNotification(notification) {
|
||||||
try {
|
try {
|
||||||
|
@ -56,6 +56,7 @@ const swapEntry = (from, to, key) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function setNotifications(data) {
|
function setNotifications(data) {
|
||||||
|
console.log('data: ', data);
|
||||||
active.value = new Map(data.active);
|
active.value = new Map(data.active);
|
||||||
available.value = new Map(data.available);
|
available.value = new Map(data.available);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue