0
0
Fork 0

Zone exclude form and tree implementation

This commit is contained in:
William Buezas 2024-05-26 17:17:58 -03:00
parent a1fde3f645
commit 097197b8dc
7 changed files with 151 additions and 70 deletions

View File

@ -9,7 +9,6 @@ import ZoneLocationsTree from './ZoneLocationsTree.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import { useArrayData } from 'src/composables/useArrayData';
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
import { useVnConfirm } from 'composables/useVnConfirm';
import axios from 'axios';
@ -27,9 +26,13 @@ const props = defineProps({
type: Boolean,
default: true,
},
isExclusion: {
type: Boolean,
default: true,
eventType: {
type: String,
default: '',
},
geoIds: {
type: Array,
default: () => [],
},
});
@ -37,11 +40,11 @@ const emit = defineEmits(['onSubmit', 'closeForm']);
const route = useRoute();
const { t } = useI18n();
const weekdayStore = useWeekdayStore();
const { openConfirmationModal } = useVnConfirm();
const isNew = computed(() => props.isNewMode);
const dated = ref(null);
const tickedNodes = ref();
const _excludeType = ref('all');
const excludeType = computed({
@ -55,7 +58,21 @@ const arrayData = useArrayData('ZoneEvents');
const exclusionGeoCreate = async () => {
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) {
console.error('Error creating exclusion geo: ', err);
}
@ -86,7 +103,9 @@ const onSubmit = async () => {
const deleteEvent = async () => {
try {
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();
} catch (err) {
console.error('Error deleting event: ', err);
@ -104,7 +123,8 @@ onMounted(() => {
console.log('props.event', props.event);
if (props.event) {
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;
});
</script>
@ -138,6 +158,13 @@ onMounted(() => {
:label="t('eventsExclusionForm.specificLocations')"
/>
</div>
<div v-if="excludeType === 'specificLocations'">
<ZoneLocationsTree
:toggle-indeterminate="false"
:root-label="t('eventsExclusionForm.rootTreeLabel')"
v-model:tickedNodes="tickedNodes"
/>
</div>
</template>
<template #custom-buttons>
<QBtn
@ -148,7 +175,9 @@ onMounted(() => {
v-close-popup
/>
<QBtn
v-if="!isNew && isExclusion"
v-if="
!isNew && (eventType === 'exclusion' || eventType === 'geoExclusion')
"
:label="t('globals.delete')"
color="primary"
flat

View File

@ -29,7 +29,7 @@ const props = defineProps({
type: Boolean,
default: true,
},
isExclusion: {
eventType: {
type: Boolean,
default: true,
},
@ -45,11 +45,11 @@ const { openConfirmationModal } = useVnConfirm();
const isNew = computed(() => props.isNewMode);
const eventInclusionFormData = ref({});
const _eventType = ref('day');
const eventType = computed({
get: () => _eventType.value,
const _inclusionType = ref('day');
const inclusionType = computed({
get: () => _inclusionType.value,
set: (val) => {
_eventType.value = val;
_inclusionType.value = val;
eventInclusionFormData.value.type = val;
},
});
@ -62,10 +62,10 @@ const createEvent = async () => {
eventInclusionFormData.value.wdays
);
if (eventType.value == 'day') eventInclusionFormData.value.weekDays = '';
if (inclusionType.value == 'day') eventInclusionFormData.value.weekDays = '';
else eventInclusionFormData.value.dated = null;
if (eventType.value != 'range') {
if (inclusionType.value != 'range') {
eventInclusionFormData.value.started = null;
eventInclusionFormData.value.ended = null;
}
@ -110,7 +110,7 @@ const refetchEvents = async () => {
onMounted(() => {
if (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;
});
</script>
@ -127,19 +127,19 @@ onMounted(() => {
<template #form-inputs>
<div class="column q-gutter-y-sm q-mb-md">
<QRadio
v-model="eventType"
v-model="inclusionType"
dense
val="day"
:label="t('eventsInclusionForm.oneDay')"
/>
<QRadio
v-model="eventType"
v-model="inclusionType"
dense
val="indefinitely"
:label="t('eventsInclusionForm.indefinitely')"
/>
<QRadio
v-model="eventType"
v-model="inclusionType"
dense
val="range"
:label="t('eventsInclusionForm.rangeOfDates')"
@ -149,7 +149,7 @@ onMounted(() => {
<VnRow class="row q-gutter-md q-mb-md">
<div class="col flex justify-center">
<VnInputDate
v-if="eventType === 'day'"
v-if="inclusionType === 'day'"
:label="t('eventsInclusionForm.day')"
v-model="eventInclusionFormData.dated"
class="full-width"
@ -160,7 +160,7 @@ onMounted(() => {
/>
</div>
</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
:label="t('eventsInclusionForm.from')"
v-model="eventInclusionFormData.started"
@ -214,7 +214,7 @@ onMounted(() => {
v-close-popup
/>
<QBtn
v-if="!isNew && !isExclusion"
v-if="!isNew && isExclusion === 'event'"
:label="t('globals.delete')"
color="primary"
flat

View File

@ -127,11 +127,10 @@ const data = computed({
geoExclusions.value = {};
let _geoExclusions = value.geoExclusions;
if (_geoExclusions) {
for (let geoExclusion of _geoExclusions) {
let stamp = toStamp(geoExclusion.dated);
if (!geoExclusions[stamp]) geoExclusions.value[stamp] = [];
if (!geoExclusions.value[stamp]) geoExclusions.value[stamp] = [];
geoExclusions.value[stamp].push(geoExclusion);
}
}
@ -179,11 +178,13 @@ const step = (direction) => {
date.value = _date;
};
const openForm = ({ date, isNewMode, event, isExclusion }) => {
const openForm = ({ date, isNewMode, event, eventType, geoIds = [] }) => {
zoneEventsFormProps.date = date;
zoneEventsFormProps.isNewMode = isNewMode;
zoneEventsFormProps.event = event;
zoneEventsFormProps.isExclusion = isExclusion;
zoneEventsFormProps.eventType = eventType;
if (geoIds.length) zoneEventsFormProps.geoIds = geoIds;
showZoneEventForm.value = true;
};

View File

@ -1,5 +1,5 @@
<script setup>
import { onMounted, ref, computed, watch } from 'vue';
import { onMounted, ref, computed, watch, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
@ -7,6 +7,27 @@ import { useState } from 'src/composables/useState';
import axios from 'axios';
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 route = useRoute();
const state = useState();
@ -21,9 +42,20 @@ const { store } = arrayData;
const storeData = computed(() => store.data);
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 onNodeExpanded = async (nodeKeysArray) => {
@ -46,6 +78,10 @@ const onNodeExpanded = async (nodeKeysArray) => {
};
const formatNodeSelected = (node) => {
if (!props.isZoneLocationsView) {
node.selected = false;
return;
}
if (node.selected === 1) node.selected = true;
else if (node.selected === 0) node.selected = false;
};
@ -83,6 +119,7 @@ const fetchNodeLeaves = async (nodeKey) => {
const onSelected = async (val, node) => {
try {
if (!props.isZoneLocationsView) return;
if (val === null) val = undefined;
const params = { geoId: node.id, isIncluded: val };
await axios.post(`Zones/${route.params.id}/toggleIsIncluded`, params);
@ -141,45 +178,49 @@ onMounted(async () => {
}
}, 1000);
});
onUnmounted(() => {
state.set('Tree', undefined);
});
</script>
<template>
<QCard class="full-width" style="max-width: 800px">
<QTree
ref="treeRef"
:nodes="nodes"
node-key="id"
label-key="name"
v-model:expanded="expanded"
@update:expanded="onNodeExpanded($event)"
:default-expand-all="true"
>
<template #default-header="{ node }">
<div
:id="node.id"
class="qtr row justify-between full-width q-pr-md cursor-pointer"
>
<span v-if="!node.id">{{ node.name }}</span>
<QCheckbox
v-else
v-model="node.selected"
:label="node.name"
@update:model-value="($event) => onSelected($event, node)"
toggle-indeterminate
color="transparent"
:class="[
'checkbox',
node.selected
? '--checked'
: node.selected == false
? '--unchecked'
: '--indeterminate',
]"
/>
</div>
</template>
</QTree>
</QCard>
<QTree
ref="treeRef"
:nodes="nodes"
node-key="id"
label-key="name"
v-model:expanded="expanded"
tick-strategy="strict"
v-model:ticked="_tickedNodes"
@update:expanded="onNodeExpanded($event)"
:default-expand-all="true"
>
<template #default-header="{ node }">
<div
:id="node.id"
class="qtr row justify-between full-width q-pr-md cursor-pointer"
>
<span v-if="!isZoneLocationsView">{{ node.name }}</span>
<QCheckbox
v-else
v-model="node.selected"
:label="node.name"
@update:model-value="($event) => onSelected($event, node)"
toggle-indeterminate
color="transparent"
:class="[
'checkbox',
node.selected
? '--checked'
: node.selected == false
? '--unchecked'
: '--indeterminate',
]"
/>
</div>
</template>
</QTree>
</template>
<style lang="scss">

View File

@ -93,10 +93,11 @@ const getEventByTimestamp = ({ year, month, day }) => {
);
};
const eventIsAnyExclusion = ({ year, month, day }) => {
if (!event) return false;
const getEventType = ({ year, month, day }) => {
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 }) => {
@ -127,14 +128,21 @@ const handleDateClick = (timestamp) => {
if (props.isZoneDeliveryView) return;
const event = getEventByTimestamp(timestamp);
console.log('eventTTTTTTTT: ', event);
const { year, month, day } = timestamp;
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', {
date,
isNewMode: !event,
event: event && event.length > 0 ? event[0] : null,
isExclusion: eventIsAnyExclusion(timestamp),
eventType,
geoIds,
});
};
</script>

View File

@ -85,6 +85,7 @@ eventsExclusionForm:
day: Day
all: All
specificLocations: Specific locations
rootTreeLabel: Locations where it is not distributed
eventsInclusionForm:
addEvent: Add event
editEvent: Edit event

View File

@ -87,6 +87,7 @@ eventsExclusionForm:
day: Día
all: Todo
specificLocations: Localizaciones concretas
rootTreeLabel: Localizaciones en las que no se reparte
eventsInclusionForm:
addEvent: Añadir evento
editEvent: Editar evento