forked from verdnatura/salix-front
Zone exclude form and tree implementation
This commit is contained in:
parent
a1fde3f645
commit
097197b8dc
|
@ -9,7 +9,6 @@ import ZoneLocationsTree from './ZoneLocationsTree.vue';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
@ -27,9 +26,13 @@ const props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
isExclusion: {
|
eventType: {
|
||||||
type: Boolean,
|
type: String,
|
||||||
default: true,
|
default: '',
|
||||||
|
},
|
||||||
|
geoIds: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -37,11 +40,11 @@ const emit = defineEmits(['onSubmit', 'closeForm']);
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const weekdayStore = useWeekdayStore();
|
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
|
||||||
const isNew = computed(() => props.isNewMode);
|
const isNew = computed(() => props.isNewMode);
|
||||||
const dated = ref(null);
|
const dated = ref(null);
|
||||||
|
const tickedNodes = ref();
|
||||||
|
|
||||||
const _excludeType = ref('all');
|
const _excludeType = ref('all');
|
||||||
const excludeType = computed({
|
const excludeType = computed({
|
||||||
|
@ -55,7 +58,21 @@ const arrayData = useArrayData('ZoneEvents');
|
||||||
|
|
||||||
const exclusionGeoCreate = async () => {
|
const exclusionGeoCreate = async () => {
|
||||||
try {
|
try {
|
||||||
console.log('exclusionGeoCreate');
|
if (isNew.value) {
|
||||||
|
const params = {
|
||||||
|
zoneFk: parseInt(route.params.id),
|
||||||
|
date: dated.value,
|
||||||
|
geoIds: tickedNodes.value,
|
||||||
|
};
|
||||||
|
await axios.post('Zones/exclusionGeo', params);
|
||||||
|
} else {
|
||||||
|
const params = {
|
||||||
|
zoneExclusionFk: props.event?.id,
|
||||||
|
geoIds: tickedNodes.value,
|
||||||
|
};
|
||||||
|
await axios.post('Zones/updateExclusionGeo', params);
|
||||||
|
}
|
||||||
|
await refetchEvents();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error creating exclusion geo: ', err);
|
console.error('Error creating exclusion geo: ', err);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +103,9 @@ const onSubmit = async () => {
|
||||||
const deleteEvent = async () => {
|
const deleteEvent = async () => {
|
||||||
try {
|
try {
|
||||||
if (!props.event) return;
|
if (!props.event) return;
|
||||||
await axios.delete(`Zones/${route.params.id}/exclusions/${props.event?.id}`);
|
await axios.delete(
|
||||||
|
`Zones/${route.params.id}/exclusions/${props.event?.zoneExclusionFk}`
|
||||||
|
);
|
||||||
await refetchEvents();
|
await refetchEvents();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error deleting event: ', err);
|
console.error('Error deleting event: ', err);
|
||||||
|
@ -104,7 +123,8 @@ onMounted(() => {
|
||||||
console.log('props.event', props.event);
|
console.log('props.event', props.event);
|
||||||
if (props.event) {
|
if (props.event) {
|
||||||
dated.value = props.event?.dated;
|
dated.value = props.event?.dated;
|
||||||
excludeType.value = props.event?.type || 'all';
|
excludeType.value = props.geoIds.length ? 'specificLocations' : 'all';
|
||||||
|
tickedNodes.value = props.geoIds || [];
|
||||||
} else if (props.date) dated.value = props.date;
|
} else if (props.date) dated.value = props.date;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -138,6 +158,13 @@ onMounted(() => {
|
||||||
:label="t('eventsExclusionForm.specificLocations')"
|
:label="t('eventsExclusionForm.specificLocations')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="excludeType === 'specificLocations'">
|
||||||
|
<ZoneLocationsTree
|
||||||
|
:toggle-indeterminate="false"
|
||||||
|
:root-label="t('eventsExclusionForm.rootTreeLabel')"
|
||||||
|
v-model:tickedNodes="tickedNodes"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #custom-buttons>
|
<template #custom-buttons>
|
||||||
<QBtn
|
<QBtn
|
||||||
|
@ -148,7 +175,9 @@ onMounted(() => {
|
||||||
v-close-popup
|
v-close-popup
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="!isNew && isExclusion"
|
v-if="
|
||||||
|
!isNew && (eventType === 'exclusion' || eventType === 'geoExclusion')
|
||||||
|
"
|
||||||
:label="t('globals.delete')"
|
:label="t('globals.delete')"
|
||||||
color="primary"
|
color="primary"
|
||||||
flat
|
flat
|
||||||
|
|
|
@ -29,7 +29,7 @@ const props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
isExclusion: {
|
eventType: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
@ -45,11 +45,11 @@ const { openConfirmationModal } = useVnConfirm();
|
||||||
const isNew = computed(() => props.isNewMode);
|
const isNew = computed(() => props.isNewMode);
|
||||||
const eventInclusionFormData = ref({});
|
const eventInclusionFormData = ref({});
|
||||||
|
|
||||||
const _eventType = ref('day');
|
const _inclusionType = ref('day');
|
||||||
const eventType = computed({
|
const inclusionType = computed({
|
||||||
get: () => _eventType.value,
|
get: () => _inclusionType.value,
|
||||||
set: (val) => {
|
set: (val) => {
|
||||||
_eventType.value = val;
|
_inclusionType.value = val;
|
||||||
eventInclusionFormData.value.type = val;
|
eventInclusionFormData.value.type = val;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -62,10 +62,10 @@ const createEvent = async () => {
|
||||||
eventInclusionFormData.value.wdays
|
eventInclusionFormData.value.wdays
|
||||||
);
|
);
|
||||||
|
|
||||||
if (eventType.value == 'day') eventInclusionFormData.value.weekDays = '';
|
if (inclusionType.value == 'day') eventInclusionFormData.value.weekDays = '';
|
||||||
else eventInclusionFormData.value.dated = null;
|
else eventInclusionFormData.value.dated = null;
|
||||||
|
|
||||||
if (eventType.value != 'range') {
|
if (inclusionType.value != 'range') {
|
||||||
eventInclusionFormData.value.started = null;
|
eventInclusionFormData.value.started = null;
|
||||||
eventInclusionFormData.value.ended = null;
|
eventInclusionFormData.value.ended = null;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ const refetchEvents = async () => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.event) {
|
if (props.event) {
|
||||||
eventInclusionFormData.value = { ...props.event };
|
eventInclusionFormData.value = { ...props.event };
|
||||||
eventType.value = props.event?.type || 'day';
|
inclusionType.value = props.event?.type || 'day';
|
||||||
} else if (props.date) eventInclusionFormData.value.dated = props.date;
|
} else if (props.date) eventInclusionFormData.value.dated = props.date;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -127,19 +127,19 @@ onMounted(() => {
|
||||||
<template #form-inputs>
|
<template #form-inputs>
|
||||||
<div class="column q-gutter-y-sm q-mb-md">
|
<div class="column q-gutter-y-sm q-mb-md">
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="eventType"
|
v-model="inclusionType"
|
||||||
dense
|
dense
|
||||||
val="day"
|
val="day"
|
||||||
:label="t('eventsInclusionForm.oneDay')"
|
:label="t('eventsInclusionForm.oneDay')"
|
||||||
/>
|
/>
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="eventType"
|
v-model="inclusionType"
|
||||||
dense
|
dense
|
||||||
val="indefinitely"
|
val="indefinitely"
|
||||||
:label="t('eventsInclusionForm.indefinitely')"
|
:label="t('eventsInclusionForm.indefinitely')"
|
||||||
/>
|
/>
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="eventType"
|
v-model="inclusionType"
|
||||||
dense
|
dense
|
||||||
val="range"
|
val="range"
|
||||||
:label="t('eventsInclusionForm.rangeOfDates')"
|
:label="t('eventsInclusionForm.rangeOfDates')"
|
||||||
|
@ -149,7 +149,7 @@ onMounted(() => {
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
<div class="col flex justify-center">
|
<div class="col flex justify-center">
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
v-if="eventType === 'day'"
|
v-if="inclusionType === 'day'"
|
||||||
:label="t('eventsInclusionForm.day')"
|
:label="t('eventsInclusionForm.day')"
|
||||||
v-model="eventInclusionFormData.dated"
|
v-model="eventInclusionFormData.dated"
|
||||||
class="full-width"
|
class="full-width"
|
||||||
|
@ -160,7 +160,7 @@ onMounted(() => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow v-if="eventType === 'range'" class="row q-gutter-md q-mb-md">
|
<VnRow v-if="inclusionType === 'range'" class="row q-gutter-md q-mb-md">
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
:label="t('eventsInclusionForm.from')"
|
:label="t('eventsInclusionForm.from')"
|
||||||
v-model="eventInclusionFormData.started"
|
v-model="eventInclusionFormData.started"
|
||||||
|
@ -214,7 +214,7 @@ onMounted(() => {
|
||||||
v-close-popup
|
v-close-popup
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="!isNew && !isExclusion"
|
v-if="!isNew && isExclusion === 'event'"
|
||||||
:label="t('globals.delete')"
|
:label="t('globals.delete')"
|
||||||
color="primary"
|
color="primary"
|
||||||
flat
|
flat
|
||||||
|
|
|
@ -127,11 +127,10 @@ const data = computed({
|
||||||
|
|
||||||
geoExclusions.value = {};
|
geoExclusions.value = {};
|
||||||
let _geoExclusions = value.geoExclusions;
|
let _geoExclusions = value.geoExclusions;
|
||||||
|
|
||||||
if (_geoExclusions) {
|
if (_geoExclusions) {
|
||||||
for (let geoExclusion of _geoExclusions) {
|
for (let geoExclusion of _geoExclusions) {
|
||||||
let stamp = toStamp(geoExclusion.dated);
|
let stamp = toStamp(geoExclusion.dated);
|
||||||
if (!geoExclusions[stamp]) geoExclusions.value[stamp] = [];
|
if (!geoExclusions.value[stamp]) geoExclusions.value[stamp] = [];
|
||||||
geoExclusions.value[stamp].push(geoExclusion);
|
geoExclusions.value[stamp].push(geoExclusion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,11 +178,13 @@ const step = (direction) => {
|
||||||
date.value = _date;
|
date.value = _date;
|
||||||
};
|
};
|
||||||
|
|
||||||
const openForm = ({ date, isNewMode, event, isExclusion }) => {
|
const openForm = ({ date, isNewMode, event, eventType, geoIds = [] }) => {
|
||||||
zoneEventsFormProps.date = date;
|
zoneEventsFormProps.date = date;
|
||||||
zoneEventsFormProps.isNewMode = isNewMode;
|
zoneEventsFormProps.isNewMode = isNewMode;
|
||||||
zoneEventsFormProps.event = event;
|
zoneEventsFormProps.event = event;
|
||||||
zoneEventsFormProps.isExclusion = isExclusion;
|
zoneEventsFormProps.eventType = eventType;
|
||||||
|
if (geoIds.length) zoneEventsFormProps.geoIds = geoIds;
|
||||||
|
|
||||||
showZoneEventForm.value = true;
|
showZoneEventForm.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed, watch } from 'vue';
|
import { onMounted, ref, computed, watch, onUnmounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
@ -7,6 +7,27 @@ import { useState } from 'src/composables/useState';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
toggleIndeterminate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isZoneLocationsView: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
rootLabel: {
|
||||||
|
type: String,
|
||||||
|
default: 'Locations',
|
||||||
|
},
|
||||||
|
tickedNodes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:tickedNodes']);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
|
@ -21,9 +42,20 @@ const { store } = arrayData;
|
||||||
const storeData = computed(() => store.data);
|
const storeData = computed(() => store.data);
|
||||||
|
|
||||||
const nodes = ref([
|
const nodes = ref([
|
||||||
{ id: null, name: t('zoneLocations.locations'), sons: true, children: [{}] },
|
{
|
||||||
|
id: null,
|
||||||
|
name: props.rootLabel,
|
||||||
|
sons: true,
|
||||||
|
tickable: false,
|
||||||
|
noTick: true,
|
||||||
|
children: [{}],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const _tickedNodes = computed({
|
||||||
|
get: () => props.tickedNodes,
|
||||||
|
set: (value) => emit('update:tickedNodes', value),
|
||||||
|
});
|
||||||
const previousExpandedNodes = ref(new Set());
|
const previousExpandedNodes = ref(new Set());
|
||||||
|
|
||||||
const onNodeExpanded = async (nodeKeysArray) => {
|
const onNodeExpanded = async (nodeKeysArray) => {
|
||||||
|
@ -46,6 +78,10 @@ const onNodeExpanded = async (nodeKeysArray) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatNodeSelected = (node) => {
|
const formatNodeSelected = (node) => {
|
||||||
|
if (!props.isZoneLocationsView) {
|
||||||
|
node.selected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (node.selected === 1) node.selected = true;
|
if (node.selected === 1) node.selected = true;
|
||||||
else if (node.selected === 0) node.selected = false;
|
else if (node.selected === 0) node.selected = false;
|
||||||
};
|
};
|
||||||
|
@ -83,6 +119,7 @@ const fetchNodeLeaves = async (nodeKey) => {
|
||||||
|
|
||||||
const onSelected = async (val, node) => {
|
const onSelected = async (val, node) => {
|
||||||
try {
|
try {
|
||||||
|
if (!props.isZoneLocationsView) return;
|
||||||
if (val === null) val = undefined;
|
if (val === null) val = undefined;
|
||||||
const params = { geoId: node.id, isIncluded: val };
|
const params = { geoId: node.id, isIncluded: val };
|
||||||
await axios.post(`Zones/${route.params.id}/toggleIsIncluded`, params);
|
await axios.post(`Zones/${route.params.id}/toggleIsIncluded`, params);
|
||||||
|
@ -141,16 +178,21 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
state.set('Tree', undefined);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QCard class="full-width" style="max-width: 800px">
|
|
||||||
<QTree
|
<QTree
|
||||||
ref="treeRef"
|
ref="treeRef"
|
||||||
:nodes="nodes"
|
:nodes="nodes"
|
||||||
node-key="id"
|
node-key="id"
|
||||||
label-key="name"
|
label-key="name"
|
||||||
v-model:expanded="expanded"
|
v-model:expanded="expanded"
|
||||||
|
tick-strategy="strict"
|
||||||
|
v-model:ticked="_tickedNodes"
|
||||||
@update:expanded="onNodeExpanded($event)"
|
@update:expanded="onNodeExpanded($event)"
|
||||||
:default-expand-all="true"
|
:default-expand-all="true"
|
||||||
>
|
>
|
||||||
|
@ -159,7 +201,7 @@ onMounted(async () => {
|
||||||
:id="node.id"
|
:id="node.id"
|
||||||
class="qtr row justify-between full-width q-pr-md cursor-pointer"
|
class="qtr row justify-between full-width q-pr-md cursor-pointer"
|
||||||
>
|
>
|
||||||
<span v-if="!node.id">{{ node.name }}</span>
|
<span v-if="!isZoneLocationsView">{{ node.name }}</span>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
v-else
|
v-else
|
||||||
v-model="node.selected"
|
v-model="node.selected"
|
||||||
|
@ -179,7 +221,6 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</QTree>
|
</QTree>
|
||||||
</QCard>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
|
@ -93,10 +93,11 @@ const getEventByTimestamp = ({ year, month, day }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const eventIsAnyExclusion = ({ year, month, day }) => {
|
const getEventType = ({ year, month, day }) => {
|
||||||
if (!event) return false;
|
|
||||||
const stamp = new Date(year, month - 1, day).getTime();
|
const stamp = new Date(year, month - 1, day).getTime();
|
||||||
return !!props.exclusions[stamp] || !!props.geoExclusions[stamp];
|
if (props.exclusions[stamp]) return 'exclusion';
|
||||||
|
if (props.geoExclusions[stamp]) return 'geoExclusion';
|
||||||
|
return 'event';
|
||||||
};
|
};
|
||||||
|
|
||||||
const getEventAttrs = ({ year, month, day }) => {
|
const getEventAttrs = ({ year, month, day }) => {
|
||||||
|
@ -127,14 +128,21 @@ const handleDateClick = (timestamp) => {
|
||||||
if (props.isZoneDeliveryView) return;
|
if (props.isZoneDeliveryView) return;
|
||||||
|
|
||||||
const event = getEventByTimestamp(timestamp);
|
const event = getEventByTimestamp(timestamp);
|
||||||
console.log('eventTTTTTTTT: ', event);
|
|
||||||
const { year, month, day } = timestamp;
|
const { year, month, day } = timestamp;
|
||||||
const date = new Date(year, month - 1, day);
|
const date = new Date(year, month - 1, day);
|
||||||
|
const stamp = date.getTime();
|
||||||
|
const eventType = getEventType(timestamp);
|
||||||
|
|
||||||
|
let geoIds = [];
|
||||||
|
if (eventType === 'geoExclusion')
|
||||||
|
geoIds = props.geoExclusions[stamp].map((geoExclusion) => geoExclusion.geoFk);
|
||||||
|
|
||||||
emit('openZoneForm', {
|
emit('openZoneForm', {
|
||||||
date,
|
date,
|
||||||
isNewMode: !event,
|
isNewMode: !event,
|
||||||
event: event && event.length > 0 ? event[0] : null,
|
event: event && event.length > 0 ? event[0] : null,
|
||||||
isExclusion: eventIsAnyExclusion(timestamp),
|
eventType,
|
||||||
|
geoIds,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -85,6 +85,7 @@ eventsExclusionForm:
|
||||||
day: Day
|
day: Day
|
||||||
all: All
|
all: All
|
||||||
specificLocations: Specific locations
|
specificLocations: Specific locations
|
||||||
|
rootTreeLabel: Locations where it is not distributed
|
||||||
eventsInclusionForm:
|
eventsInclusionForm:
|
||||||
addEvent: Add event
|
addEvent: Add event
|
||||||
editEvent: Edit event
|
editEvent: Edit event
|
||||||
|
|
|
@ -87,6 +87,7 @@ eventsExclusionForm:
|
||||||
day: Día
|
day: Día
|
||||||
all: Todo
|
all: Todo
|
||||||
specificLocations: Localizaciones concretas
|
specificLocations: Localizaciones concretas
|
||||||
|
rootTreeLabel: Localizaciones en las que no se reparte
|
||||||
eventsInclusionForm:
|
eventsInclusionForm:
|
||||||
addEvent: Añadir evento
|
addEvent: Añadir evento
|
||||||
editEvent: Editar evento
|
editEvent: Editar evento
|
||||||
|
|
Loading…
Reference in New Issue