forked from verdnatura/salix-front
Abstract ZoneCalendarGrid in a component and reuse it
This commit is contained in:
parent
f52f5df78b
commit
62443ff44b
|
@ -1,31 +1,21 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref, watch, onUnmounted } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import ZoneEventsPanel from './ZoneEventsPanel.vue';
|
import ZoneEventsPanel from './ZoneEventsPanel.vue';
|
||||||
import ZoneCalendar from '../ZoneCalendar.vue';
|
import ZoneCalendarGrid from '../ZoneCalendarGrid.vue';
|
||||||
import ZoneEventInclusionForm from './ZoneEventInclusionForm.vue';
|
import ZoneEventInclusionForm from './ZoneEventInclusionForm.vue';
|
||||||
import ZoneEventExclusionForm from './ZoneEventExclusionForm.vue';
|
import ZoneEventExclusionForm from './ZoneEventExclusionForm.vue';
|
||||||
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
|
||||||
import { nextTick } from 'vue';
|
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const weekdayStore = useWeekdayStore();
|
|
||||||
|
|
||||||
const nMonths = ref(4);
|
|
||||||
const _date = ref(Date.vnNew());
|
|
||||||
const _data = ref(null);
|
|
||||||
const firstDay = ref(null);
|
const firstDay = ref(null);
|
||||||
const lastDay = ref(null);
|
const lastDay = ref(null);
|
||||||
const months = ref([]);
|
|
||||||
const days = ref({});
|
|
||||||
const exclusions = ref({});
|
|
||||||
const geoExclusions = ref({});
|
|
||||||
const events = ref([]);
|
const events = ref([]);
|
||||||
const formModeName = ref('include');
|
const formModeName = ref('include');
|
||||||
const showZoneEventForm = ref(false);
|
const showZoneEventForm = ref(false);
|
||||||
|
@ -34,149 +24,8 @@ const zoneEventsFormProps = reactive({
|
||||||
date: null,
|
date: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const arrayData = useArrayData('ZoneEvents');
|
const openForm = (data) => {
|
||||||
const { store } = arrayData;
|
const { date, isNewMode, event, eventType, geoIds = [] } = data;
|
||||||
|
|
||||||
const refreshEvents = () => {
|
|
||||||
days.value = {};
|
|
||||||
if (!data.value) return;
|
|
||||||
|
|
||||||
let day = new Date(firstDay.value.getTime());
|
|
||||||
|
|
||||||
while (day <= lastDay.value) {
|
|
||||||
let stamp = day.getTime();
|
|
||||||
let wday = day.getDay();
|
|
||||||
let dayEvents = [];
|
|
||||||
let _exclusions = exclusions.value[stamp] || [];
|
|
||||||
|
|
||||||
if (events.value) {
|
|
||||||
for (let event of events.value) {
|
|
||||||
let match;
|
|
||||||
switch (event.type) {
|
|
||||||
case 'day':
|
|
||||||
match = event.dated == stamp;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
match =
|
|
||||||
event.wdays[wday] &&
|
|
||||||
(!event.started || stamp >= event.started) &&
|
|
||||||
(!event.ended || stamp <= event.ended);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (match && !_exclusions.find((e) => e.zoneFk == event.zoneFk)) {
|
|
||||||
dayEvents.push(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dayEvents.length) days.value[stamp] = dayEvents;
|
|
||||||
|
|
||||||
day.setDate(day.getDate() + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const date = computed({
|
|
||||||
get: () => _date.value,
|
|
||||||
set: (value) => {
|
|
||||||
_date.value = value;
|
|
||||||
let stamp = value.getTime();
|
|
||||||
|
|
||||||
firstDay.value = new Date(stamp);
|
|
||||||
firstDay.value.setDate(1);
|
|
||||||
|
|
||||||
lastDay.value = new Date(stamp);
|
|
||||||
lastDay.value.setMonth(lastDay.value.getMonth() + nMonths.value);
|
|
||||||
lastDay.value.setDate(0);
|
|
||||||
|
|
||||||
months.value = [];
|
|
||||||
for (let i = 0; i < nMonths.value; i++) {
|
|
||||||
let monthDate = new Date(stamp);
|
|
||||||
monthDate.setMonth(value.getMonth() + i);
|
|
||||||
months.value.push(monthDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshEvents();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = computed({
|
|
||||||
get: () => {
|
|
||||||
return _data.value;
|
|
||||||
},
|
|
||||||
set: (value) => {
|
|
||||||
_data.value = value;
|
|
||||||
|
|
||||||
value = value || {};
|
|
||||||
|
|
||||||
events.value = value.events;
|
|
||||||
function toStamp(date) {
|
|
||||||
return date && new Date(date).setHours(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
exclusions.value = {};
|
|
||||||
let _exclusions = value.exclusions;
|
|
||||||
|
|
||||||
if (_exclusions) {
|
|
||||||
for (let exclusion of _exclusions) {
|
|
||||||
let stamp = toStamp(exclusion.dated);
|
|
||||||
if (!exclusions[stamp]) exclusions.value[stamp] = [];
|
|
||||||
exclusions.value[stamp].push(exclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
geoExclusions.value = {};
|
|
||||||
let _geoExclusions = value.geoExclusions;
|
|
||||||
if (_geoExclusions) {
|
|
||||||
for (let geoExclusion of _geoExclusions) {
|
|
||||||
let stamp = toStamp(geoExclusion.dated);
|
|
||||||
if (!geoExclusions.value[stamp]) geoExclusions.value[stamp] = [];
|
|
||||||
geoExclusions.value[stamp].push(geoExclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _events = value.events;
|
|
||||||
if (_events) {
|
|
||||||
for (let event of _events) {
|
|
||||||
event.dated = toStamp(event.dated);
|
|
||||||
event.ended = toStamp(event.ended);
|
|
||||||
event.started = toStamp(event.started);
|
|
||||||
event.wdays = weekdayStore.fromSet(event.weekDays || '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshEvents();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => store.data,
|
|
||||||
(value) => {
|
|
||||||
data.value = value;
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const getMonthNameAndYear = (date) => {
|
|
||||||
const monthName = weekdayStore.getLocaleMonths[date.getMonth()].locale;
|
|
||||||
const year = date.getFullYear();
|
|
||||||
return `${monthName} ${year}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const headerTitle = computed(() => {
|
|
||||||
if (!months.value?.length) return;
|
|
||||||
|
|
||||||
const firstMonth = getMonthNameAndYear(months.value[0]);
|
|
||||||
const lastMonth = getMonthNameAndYear(months.value[months.value.length - 1]);
|
|
||||||
|
|
||||||
return `${firstMonth} - ${lastMonth}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const step = (direction) => {
|
|
||||||
const _date = new Date(date.value);
|
|
||||||
_date.setMonth(_date.getMonth() + nMonths.value * direction);
|
|
||||||
date.value = _date;
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -190,18 +39,6 @@ const onZoneEventFormClose = () => {
|
||||||
showZoneEventForm.value = false;
|
showZoneEventForm.value = false;
|
||||||
zoneEventsFormProps.value = {};
|
zoneEventsFormProps.value = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
let initialDate = Date.vnNew();
|
|
||||||
initialDate.setDate(1);
|
|
||||||
initialDate.setHours(0, 0, 0, 0);
|
|
||||||
date.value = initialDate;
|
|
||||||
weekdayStore.initStore();
|
|
||||||
await nextTick();
|
|
||||||
stateStore.rightDrawer = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => arrayData.destroy());
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -234,39 +71,13 @@ onUnmounted(() => arrayData.destroy());
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
<QPage class="q-pa-md flex justify-center">
|
<QPage class="q-pa-md flex justify-center">
|
||||||
<QCard style="height: max-content">
|
<ZoneCalendarGrid
|
||||||
<div class="calendars-header">
|
v-model:events="events"
|
||||||
<QBtn
|
v-model:firstDay="firstDay"
|
||||||
icon="arrow_left"
|
v-model:lastDay="lastDay"
|
||||||
size="sm"
|
data-key="ZoneEvents"
|
||||||
flat
|
@on-date-selected="openForm"
|
||||||
class="full-height"
|
|
||||||
@click="step(-1)"
|
|
||||||
/>
|
/>
|
||||||
<span>{{ headerTitle }}</span>
|
|
||||||
<QBtn
|
|
||||||
icon="arrow_right"
|
|
||||||
size="sm"
|
|
||||||
flat
|
|
||||||
class="full-height"
|
|
||||||
@click="step(1)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="calendars-container">
|
|
||||||
<ZoneCalendar
|
|
||||||
v-for="(month, index) in months"
|
|
||||||
:key="index"
|
|
||||||
:month="month.getMonth() + 1"
|
|
||||||
:year="month.getFullYear()"
|
|
||||||
:month-date="month"
|
|
||||||
:geo-exclusions="geoExclusions"
|
|
||||||
:exclusions="exclusions"
|
|
||||||
:days-map="days"
|
|
||||||
:form-mode-name="formModeName"
|
|
||||||
@open-zone-form="openForm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</QCard>
|
|
||||||
<QDialog v-model="showZoneEventForm" @hide="onZoneEventFormClose()">
|
<QDialog v-model="showZoneEventForm" @hide="onZoneEventFormClose()">
|
||||||
<ZoneEventInclusionForm
|
<ZoneEventInclusionForm
|
||||||
v-if="formModeName === 'include'"
|
v-if="formModeName === 'include'"
|
||||||
|
@ -281,22 +92,3 @@ onUnmounted(() => arrayData.destroy());
|
||||||
</QDialog>
|
</QDialog>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.calendars-header {
|
|
||||||
height: 45px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
background-color: $primary;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendars-container {
|
|
||||||
max-width: 800px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, watch, computed, nextTick } from 'vue';
|
import { onMounted, watch, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
@ -56,19 +56,10 @@ const arrayData = useArrayData('ZoneEvents', {
|
||||||
url: `Zones/getEventsFiltered`,
|
url: `Zones/getEventsFiltered`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const startParamsWatcher = () => {
|
|
||||||
watch(
|
|
||||||
params,
|
|
||||||
async () => {
|
|
||||||
await fetchData();
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
if (!params.value.zoneFk || !params.value.started || !params.value.ended) return;
|
if (!params.value.zoneFk || !params.value.started || !params.value.ended) return;
|
||||||
|
|
||||||
await arrayData.applyFilter({
|
await arrayData.applyFilter({
|
||||||
params: params.value,
|
params: params.value,
|
||||||
});
|
});
|
||||||
|
@ -77,6 +68,14 @@ const fetchData = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
params,
|
||||||
|
async () => {
|
||||||
|
await fetchData();
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
const formatWdays = (event) => {
|
const formatWdays = (event) => {
|
||||||
if (!event.weekDays) return;
|
if (!event.weekDays) return;
|
||||||
|
|
||||||
|
@ -108,9 +107,6 @@ const openIncludeForm = (event) => {
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
weekdayStore.initStore();
|
weekdayStore.initStore();
|
||||||
await nextTick();
|
|
||||||
await fetchData();
|
|
||||||
startParamsWatcher();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import ZoneClosingTable from './ZoneClosingTable.vue';
|
import ZoneClosingTable from './ZoneClosingTable.vue';
|
||||||
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
|
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
|
||||||
|
@ -36,19 +37,12 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
isZoneDeliveryView: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
formModeName: {
|
|
||||||
type: String,
|
|
||||||
default: 'include',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['openZoneForm']);
|
const emit = defineEmits(['onDateSelected']);
|
||||||
|
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const calendarRef = ref(null);
|
const calendarRef = ref(null);
|
||||||
const weekdayStore = useWeekdayStore();
|
const weekdayStore = useWeekdayStore();
|
||||||
|
@ -62,8 +56,10 @@ const todayTimestamp = computed(() => {
|
||||||
});
|
});
|
||||||
const _monthDate = computed(() => date.formatDate(props.monthDate, 'YYYY-MM-DD'));
|
const _monthDate = computed(() => date.formatDate(props.monthDate, 'YYYY-MM-DD'));
|
||||||
|
|
||||||
|
const isZoneDeliveryView = computed(() => route.name === 'ZoneDeliveryDays');
|
||||||
|
|
||||||
const onEventSelection = async ({ year, month, day }) => {
|
const onEventSelection = async ({ year, month, day }) => {
|
||||||
if (!props.isZoneDeliveryView) return;
|
if (!isZoneDeliveryView.value) return;
|
||||||
|
|
||||||
const date = new Date(year, month - 1, day);
|
const date = new Date(year, month - 1, day);
|
||||||
const stamp = date.getTime();
|
const stamp = date.getTime();
|
||||||
|
@ -125,7 +121,7 @@ const calendarHeaderTitle = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDateClick = (timestamp) => {
|
const handleDateClick = (timestamp) => {
|
||||||
if (props.isZoneDeliveryView) return;
|
if (isZoneDeliveryView.value) return;
|
||||||
|
|
||||||
const event = getEventByTimestamp(timestamp);
|
const event = getEventByTimestamp(timestamp);
|
||||||
const { year, month, day } = timestamp;
|
const { year, month, day } = timestamp;
|
||||||
|
@ -137,7 +133,7 @@ const handleDateClick = (timestamp) => {
|
||||||
if (eventType === 'geoExclusion')
|
if (eventType === 'geoExclusion')
|
||||||
geoIds = props.geoExclusions[stamp].map((geoExclusion) => geoExclusion.geoFk);
|
geoIds = props.geoExclusions[stamp].map((geoExclusion) => geoExclusion.geoFk);
|
||||||
|
|
||||||
emit('openZoneForm', {
|
emit('onDateSelected', {
|
||||||
date,
|
date,
|
||||||
isNewMode: !event,
|
isNewMode: !event,
|
||||||
event: event && event.length > 0 ? event[0] : null,
|
event: event && event.length > 0 ? event[0] : null,
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, onMounted, ref, watch, onUnmounted, nextTick } from 'vue';
|
||||||
|
|
||||||
|
import ZoneCalendar from './ZoneCalendar.vue';
|
||||||
|
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
'update:firstDay',
|
||||||
|
'update:lastDay',
|
||||||
|
'update:events',
|
||||||
|
'onDateSelected',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const weekdayStore = useWeekdayStore();
|
||||||
|
|
||||||
|
const nMonths = ref(4);
|
||||||
|
const _date = ref(Date.vnNew());
|
||||||
|
const _data = ref(null);
|
||||||
|
const firstDay = ref(null);
|
||||||
|
const lastDay = ref(null);
|
||||||
|
const months = ref([]);
|
||||||
|
const days = ref({});
|
||||||
|
const exclusions = ref({});
|
||||||
|
const geoExclusions = ref({});
|
||||||
|
const events = ref([]);
|
||||||
|
|
||||||
|
const arrayData = useArrayData(props.dataKey);
|
||||||
|
const { store } = arrayData;
|
||||||
|
|
||||||
|
const refreshEvents = () => {
|
||||||
|
days.value = {};
|
||||||
|
if (!data.value) return;
|
||||||
|
|
||||||
|
let day = new Date(firstDay.value.getTime());
|
||||||
|
|
||||||
|
while (day <= lastDay.value) {
|
||||||
|
let stamp = day.getTime();
|
||||||
|
let wday = day.getDay();
|
||||||
|
let dayEvents = [];
|
||||||
|
let _exclusions = exclusions.value[stamp] || [];
|
||||||
|
|
||||||
|
if (events.value) {
|
||||||
|
for (let event of events.value) {
|
||||||
|
let match;
|
||||||
|
switch (event.type) {
|
||||||
|
case 'day':
|
||||||
|
match = event.dated == stamp;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
match =
|
||||||
|
event.wdays[wday] &&
|
||||||
|
(!event.started || stamp >= event.started) &&
|
||||||
|
(!event.ended || stamp <= event.ended);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (match && !_exclusions.find((e) => e.zoneFk == event.zoneFk)) {
|
||||||
|
dayEvents.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dayEvents.length) days.value[stamp] = dayEvents;
|
||||||
|
|
||||||
|
day.setDate(day.getDate() + 1);
|
||||||
|
}
|
||||||
|
emit('update:events', events.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const date = computed({
|
||||||
|
get: () => _date.value,
|
||||||
|
set: (value) => {
|
||||||
|
_date.value = value;
|
||||||
|
let stamp = value.getTime();
|
||||||
|
|
||||||
|
firstDay.value = new Date(stamp);
|
||||||
|
firstDay.value.setDate(1);
|
||||||
|
|
||||||
|
lastDay.value = new Date(stamp);
|
||||||
|
lastDay.value.setMonth(lastDay.value.getMonth() + nMonths.value);
|
||||||
|
lastDay.value.setDate(0);
|
||||||
|
|
||||||
|
months.value = [];
|
||||||
|
for (let i = 0; i < nMonths.value; i++) {
|
||||||
|
let monthDate = new Date(stamp);
|
||||||
|
monthDate.setMonth(value.getMonth() + i);
|
||||||
|
months.value.push(monthDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('update:firstDay', firstDay.value);
|
||||||
|
emit('update:lastDay', lastDay.value);
|
||||||
|
refreshEvents();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = computed({
|
||||||
|
get: () => {
|
||||||
|
return _data.value;
|
||||||
|
},
|
||||||
|
set: (value) => {
|
||||||
|
_data.value = value;
|
||||||
|
|
||||||
|
value = value || {};
|
||||||
|
|
||||||
|
events.value = value.events;
|
||||||
|
function toStamp(date) {
|
||||||
|
return date && new Date(date).setHours(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exclusions.value = {};
|
||||||
|
let _exclusions = value.exclusions;
|
||||||
|
|
||||||
|
if (_exclusions) {
|
||||||
|
for (let exclusion of _exclusions) {
|
||||||
|
let stamp = toStamp(exclusion.dated);
|
||||||
|
if (!exclusions[stamp]) exclusions.value[stamp] = [];
|
||||||
|
exclusions.value[stamp].push(exclusion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
geoExclusions.value = {};
|
||||||
|
let _geoExclusions = value.geoExclusions;
|
||||||
|
if (_geoExclusions) {
|
||||||
|
for (let geoExclusion of _geoExclusions) {
|
||||||
|
let stamp = toStamp(geoExclusion.dated);
|
||||||
|
if (!geoExclusions.value[stamp]) geoExclusions.value[stamp] = [];
|
||||||
|
geoExclusions.value[stamp].push(geoExclusion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _events = value.events;
|
||||||
|
if (_events) {
|
||||||
|
for (let event of _events) {
|
||||||
|
event.dated = toStamp(event.dated);
|
||||||
|
event.ended = toStamp(event.ended);
|
||||||
|
event.started = toStamp(event.started);
|
||||||
|
event.wdays = weekdayStore.fromSet(event.weekDays || '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshEvents();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => store.data,
|
||||||
|
(value) => {
|
||||||
|
data.value = value;
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const getMonthNameAndYear = (date) => {
|
||||||
|
const monthName = weekdayStore.getLocaleMonths[date.getMonth()].locale;
|
||||||
|
const year = date.getFullYear();
|
||||||
|
return `${monthName} ${year}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerTitle = computed(() => {
|
||||||
|
if (!months.value?.length) return;
|
||||||
|
|
||||||
|
const firstMonth = getMonthNameAndYear(months.value[0]);
|
||||||
|
const lastMonth = getMonthNameAndYear(months.value[months.value.length - 1]);
|
||||||
|
|
||||||
|
return `${firstMonth} - ${lastMonth}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const step = (direction) => {
|
||||||
|
const _date = new Date(date.value);
|
||||||
|
_date.setMonth(_date.getMonth() + nMonths.value * direction);
|
||||||
|
date.value = _date;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDateSelected = (data) => emit('onDateSelected', data);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
let initialDate = Date.vnNew();
|
||||||
|
initialDate.setDate(1);
|
||||||
|
initialDate.setHours(0, 0, 0, 0);
|
||||||
|
date.value = initialDate;
|
||||||
|
weekdayStore.initStore();
|
||||||
|
await nextTick();
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => arrayData.destroy());
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QCard style="height: max-content">
|
||||||
|
<div class="calendars-header">
|
||||||
|
<QBtn
|
||||||
|
icon="arrow_left"
|
||||||
|
size="sm"
|
||||||
|
flat
|
||||||
|
class="full-height"
|
||||||
|
@click="step(-1)"
|
||||||
|
/>
|
||||||
|
<span>{{ headerTitle }}</span>
|
||||||
|
<QBtn
|
||||||
|
icon="arrow_right"
|
||||||
|
size="sm"
|
||||||
|
flat
|
||||||
|
class="full-height"
|
||||||
|
@click="step(1)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="calendars-container">
|
||||||
|
<ZoneCalendar
|
||||||
|
v-for="(month, index) in months"
|
||||||
|
:key="index"
|
||||||
|
:month="month.getMonth() + 1"
|
||||||
|
:year="month.getFullYear()"
|
||||||
|
:month-date="month"
|
||||||
|
:geo-exclusions="geoExclusions"
|
||||||
|
:exclusions="exclusions"
|
||||||
|
:days-map="days"
|
||||||
|
@on-date-selected="onDateSelected"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</QCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.calendars-header {
|
||||||
|
height: 45px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: $primary;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendars-container {
|
||||||
|
max-width: 800px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,182 +1,18 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref, watch, onUnmounted } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import ZoneDeliveryPanel from './ZoneDeliveryPanel.vue';
|
import ZoneDeliveryPanel from './ZoneDeliveryPanel.vue';
|
||||||
import ZoneCalendar from './ZoneCalendar.vue';
|
import ZoneCalendarGrid from './ZoneCalendarGrid.vue';
|
||||||
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const weekdayStore = useWeekdayStore();
|
|
||||||
|
|
||||||
const nMonths = ref(4);
|
|
||||||
const _date = ref(Date.vnNew());
|
|
||||||
const _data = ref(null);
|
|
||||||
const firstDay = ref(null);
|
const firstDay = ref(null);
|
||||||
const lastDay = ref(null);
|
const lastDay = ref(null);
|
||||||
const months = ref([]);
|
|
||||||
const days = ref({});
|
|
||||||
const exclusions = ref({});
|
|
||||||
const geoExclusions = ref({});
|
|
||||||
const events = ref([]);
|
const events = ref([]);
|
||||||
const arrayData = useArrayData('ZoneDeliveryDays', {
|
|
||||||
url: 'Zones/getEvents',
|
|
||||||
});
|
|
||||||
const { store } = arrayData;
|
|
||||||
|
|
||||||
const refreshEvents = () => {
|
|
||||||
days.value = {};
|
|
||||||
if (!data.value) return;
|
|
||||||
|
|
||||||
let day = new Date(firstDay.value.getTime());
|
|
||||||
|
|
||||||
while (day <= lastDay.value) {
|
|
||||||
let stamp = day.getTime();
|
|
||||||
let wday = day.getDay();
|
|
||||||
let dayEvents = [];
|
|
||||||
let _exclusions = exclusions.value[stamp] || [];
|
|
||||||
|
|
||||||
if (events.value) {
|
|
||||||
for (let event of events.value) {
|
|
||||||
let match;
|
|
||||||
switch (event.type) {
|
|
||||||
case 'day':
|
|
||||||
match = event.dated == stamp;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
match =
|
|
||||||
event.wdays[wday] &&
|
|
||||||
(!event.started || stamp >= event.started) &&
|
|
||||||
(!event.ended || stamp <= event.ended);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (match && !_exclusions.find((e) => e.zoneFk == event.zoneFk)) {
|
|
||||||
dayEvents.push(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dayEvents.length) days.value[stamp] = dayEvents;
|
|
||||||
|
|
||||||
day.setDate(day.getDate() + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const date = computed({
|
|
||||||
get: () => _date.value,
|
|
||||||
set: (value) => {
|
|
||||||
_date.value = value;
|
|
||||||
let stamp = value.getTime();
|
|
||||||
|
|
||||||
firstDay.value = new Date(stamp);
|
|
||||||
firstDay.value.setDate(1);
|
|
||||||
|
|
||||||
lastDay.value = new Date(stamp);
|
|
||||||
lastDay.value.setMonth(lastDay.value.getMonth() + nMonths.value);
|
|
||||||
lastDay.value.setDate(0);
|
|
||||||
|
|
||||||
months.value = [];
|
|
||||||
for (let i = 0; i < nMonths.value; i++) {
|
|
||||||
let monthDate = new Date(stamp);
|
|
||||||
monthDate.setMonth(value.getMonth() + i);
|
|
||||||
months.value.push(monthDate);
|
|
||||||
}
|
|
||||||
refreshEvents();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = computed({
|
|
||||||
get: () => {
|
|
||||||
return _data.value;
|
|
||||||
},
|
|
||||||
set: (value) => {
|
|
||||||
_data.value = value;
|
|
||||||
|
|
||||||
value = value || {};
|
|
||||||
|
|
||||||
events.value = value.events;
|
|
||||||
function toStamp(date) {
|
|
||||||
return date && new Date(date).setHours(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
exclusions.value = {};
|
|
||||||
let _exclusions = value.exclusions;
|
|
||||||
|
|
||||||
if (_exclusions) {
|
|
||||||
for (let exclusion of _exclusions) {
|
|
||||||
let stamp = toStamp(exclusion.dated);
|
|
||||||
if (!exclusions[stamp]) exclusions.value[stamp] = [];
|
|
||||||
exclusions.value[stamp].push(exclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
geoExclusions.value = {};
|
|
||||||
let _geoExclusions = value.geoExclusions;
|
|
||||||
|
|
||||||
if (_geoExclusions) {
|
|
||||||
for (let geoExclusion of _geoExclusions) {
|
|
||||||
let stamp = toStamp(geoExclusion.dated);
|
|
||||||
if (!geoExclusions[stamp]) geoExclusions.value[stamp] = [];
|
|
||||||
geoExclusions.value[stamp].push(geoExclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _events = value.events;
|
|
||||||
if (_events) {
|
|
||||||
for (let event of _events) {
|
|
||||||
event.dated = toStamp(event.dated);
|
|
||||||
event.ended = toStamp(event.ended);
|
|
||||||
event.started = toStamp(event.started);
|
|
||||||
event.wdays = weekdayStore.fromSet(event.weekDays || '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshEvents();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => store.data,
|
|
||||||
(value) => {
|
|
||||||
data.value = value;
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const getMonthNameAndYear = (date) => {
|
|
||||||
const monthName = weekdayStore.getLocaleMonths[date.getMonth()].locale;
|
|
||||||
const year = date.getFullYear();
|
|
||||||
return `${monthName} ${year}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const headerTitle = computed(() => {
|
|
||||||
if (!months.value?.length) return;
|
|
||||||
|
|
||||||
const firstMonth = getMonthNameAndYear(months.value[0]);
|
|
||||||
const lastMonth = getMonthNameAndYear(months.value[months.value.length - 1]);
|
|
||||||
|
|
||||||
return `${firstMonth} - ${lastMonth}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const step = (direction) => {
|
|
||||||
const _date = new Date(date.value);
|
|
||||||
_date.setMonth(_date.getMonth() + nMonths.value * direction);
|
|
||||||
date.value = _date;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
stateStore.rightDrawer = true;
|
|
||||||
let initialDate = Date.vnNew();
|
|
||||||
initialDate.setDate(1);
|
|
||||||
initialDate.setHours(0, 0, 0, 0);
|
|
||||||
date.value = initialDate;
|
|
||||||
weekdayStore.initStore();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => arrayData.destroy());
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -203,56 +39,11 @@ onUnmounted(() => arrayData.destroy());
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
<QPage class="q-pa-md flex justify-center">
|
<QPage class="q-pa-md flex justify-center">
|
||||||
<QCard style="height: max-content">
|
<ZoneCalendarGrid
|
||||||
<div class="calendars-header">
|
v-model:events="events"
|
||||||
<QBtn
|
v-model:firstDay="firstDay"
|
||||||
icon="arrow_left"
|
v-model:lastDay="lastDay"
|
||||||
size="sm"
|
data-key="ZoneDeliveryDays"
|
||||||
flat
|
|
||||||
class="full-height"
|
|
||||||
@click="step(-1)"
|
|
||||||
/>
|
/>
|
||||||
<span>{{ headerTitle }}</span>
|
|
||||||
<QBtn
|
|
||||||
icon="arrow_right"
|
|
||||||
size="sm"
|
|
||||||
flat
|
|
||||||
class="full-height"
|
|
||||||
@click="step(1)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="calendars-container">
|
|
||||||
<ZoneCalendar
|
|
||||||
v-for="(month, index) in months"
|
|
||||||
:key="index"
|
|
||||||
:month="month.getMonth() + 1"
|
|
||||||
:year="month.getFullYear()"
|
|
||||||
:month-date="month"
|
|
||||||
:geo-exclusions="geoExclusions"
|
|
||||||
:exclusions="exclusions"
|
|
||||||
:days-map="days"
|
|
||||||
is-zone-delivery-view
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</QCard>
|
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.calendars-header {
|
|
||||||
height: 45px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
background-color: $primary;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendars-container {
|
|
||||||
max-width: 800px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { onMounted, ref, reactive } from 'vue';
|
import { onMounted, ref, reactive } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
|
Loading…
Reference in New Issue