Merge pull request 'Zone Calendar' (!411) from hyervoni/salix-front-mindshore:feature/ZoneCalendar into dev
gitea/salix-front/pipeline/head This commit looks good
Details
gitea/salix-front/pipeline/head This commit looks good
Details
Reviewed-on: #411 Reviewed-by: Javier Segarra <jsegarra@verdnatura.es> Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
commit
b54cb73c91
|
@ -74,7 +74,7 @@ const closeForm = () => {
|
|||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
/>
|
||||
<slot name="customButtons" />
|
||||
<slot name="custom-buttons" />
|
||||
</div>
|
||||
</QCard>
|
||||
</QForm>
|
||||
|
|
|
@ -22,6 +22,7 @@ const props = defineProps({
|
|||
searchbarInfo: { type: String, default: '' },
|
||||
searchCustomRouteRedirect: { type: String, default: undefined },
|
||||
searchRedirect: { type: Boolean, default: true },
|
||||
searchMakeFetch: { type: Boolean, default: true },
|
||||
});
|
||||
|
||||
const stateStore = useStateStore();
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||
|
||||
const props = defineProps({
|
||||
wdays: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:wdays']);
|
||||
|
||||
const weekdayStore = useWeekdayStore();
|
||||
|
||||
const selectedWDays = computed({
|
||||
get: () => props.wdays,
|
||||
set: (value) => emit('update:wdays', value),
|
||||
});
|
||||
|
||||
const toggleDay = (index) => (selectedWDays.value[index] = !selectedWDays.value[index]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="q-gutter-x-sm" style="width: max-content">
|
||||
<QBtn
|
||||
v-for="(weekday, index) in weekdayStore.getLocalesMap"
|
||||
:key="index"
|
||||
:label="weekday.localeChar"
|
||||
rounded
|
||||
style="max-width: 36px"
|
||||
:color="selectedWDays[weekday.index] ? 'primary' : ''"
|
||||
@click="toggleDay(weekday.index)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
|
@ -147,7 +147,7 @@ const containerClasses = computed(() => {
|
|||
.q-calendar-month__head--workweek,
|
||||
.q-calendar-month__head--weekday.q-calendar__center.q-calendar__ellipsis {
|
||||
text-transform: capitalize;
|
||||
color: var(---color-font-secondary);
|
||||
color: $color-font-secondary;
|
||||
font-weight: bold;
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
|
|
|
@ -67,6 +67,10 @@ const props = defineProps({
|
|||
type: String,
|
||||
default: '',
|
||||
},
|
||||
makeFetch: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
let arrayData = useArrayData(props.dataKey, { ...props });
|
||||
|
@ -94,6 +98,8 @@ async function search() {
|
|||
([key, value]) => value && (props.staticParams || []).includes(key)
|
||||
);
|
||||
store.skip = 0;
|
||||
|
||||
if (props.makeFetch)
|
||||
await arrayData.applyFilter({
|
||||
params: {
|
||||
...Object.fromEntries(staticParams),
|
||||
|
|
|
@ -6,7 +6,7 @@ import { buildFilter } from 'filters/filterPanel';
|
|||
|
||||
const arrayDataStore = useArrayDataStore();
|
||||
|
||||
export function useArrayData(key, userOptions) {
|
||||
export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
||||
if (!key) throw new Error('ArrayData: A key is required to use this composable');
|
||||
|
||||
if (!arrayDataStore.get(key)) arrayDataStore.set(key);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import toCurrency from './toCurrency';
|
||||
|
||||
export default function (value) {
|
||||
if (value == null || value === '') return () => '-';
|
||||
return () => toCurrency(value);
|
||||
}
|
|
@ -10,6 +10,7 @@ import toLowerCamel from './toLowerCamel';
|
|||
import dashIfEmpty from './dashIfEmpty';
|
||||
import dateRange from './dateRange';
|
||||
import toHour from './toHour';
|
||||
import dashOrCurrency from './dashOrCurrency';
|
||||
|
||||
export {
|
||||
toLowerCase,
|
||||
|
@ -17,6 +18,7 @@ export {
|
|||
toDate,
|
||||
toHour,
|
||||
toDateString,
|
||||
dashOrCurrency,
|
||||
toDateHourMin,
|
||||
toDateHourMinSec,
|
||||
toRelativeDate,
|
||||
|
|
|
@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n';
|
|||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { toDate } from 'filters/index';
|
||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||
|
@ -14,7 +13,6 @@ import ClaimSummary from './Card/ClaimSummary.vue';
|
|||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
|
||||
const stateStore = useStateStore();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
|
|
|
@ -19,7 +19,7 @@ const { t } = useI18n();
|
|||
const dms = ref({});
|
||||
const route = useRoute();
|
||||
const editDownloadDisabled = ref(false);
|
||||
const invoiceIn = computed(() => useArrayData(route.meta.moduleName).store.data);
|
||||
const invoiceIn = computed(() => useArrayData().store.data);
|
||||
const userConfig = ref(null);
|
||||
const invoiceId = computed(() => +route.params.id);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import { toCurrency } from 'src/filters';
|
|||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const arrayData = useArrayData(route.meta.moduleName);
|
||||
const arrayData = useArrayData();
|
||||
const invoiceIn = computed(() => arrayData.store.data);
|
||||
|
||||
const rowsSelected = ref([]);
|
||||
|
|
|
@ -11,9 +11,7 @@ import { useArrayData } from 'src/composables/useArrayData';
|
|||
const { t } = useI18n();
|
||||
|
||||
const route = useRoute();
|
||||
const currency = computed(
|
||||
() => useArrayData(route.meta.moduleName).store.data?.currency?.code
|
||||
);
|
||||
const currency = computed(() => useArrayData().store.data?.currency?.code);
|
||||
const invoceInIntrastat = ref([]);
|
||||
const rowsSelected = ref([]);
|
||||
const countries = ref([]);
|
||||
|
|
|
@ -16,7 +16,7 @@ const { t } = useI18n();
|
|||
const route = useRoute();
|
||||
|
||||
const entityId = computed(() => props.id || +route.params.id);
|
||||
const invoiceIn = computed(() => useArrayData(route.meta.moduleName).store.data);
|
||||
const invoiceIn = computed(() => useArrayData().store.data);
|
||||
const currency = computed(() => invoiceIn.value?.currency?.code);
|
||||
const invoiceInUrl = ref();
|
||||
const amountsNotMatch = ref(null);
|
||||
|
|
|
@ -11,13 +11,12 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
|||
import CrudModel from 'src/components/CrudModel.vue';
|
||||
import VnCurrency from 'src/components/common/VnCurrency.vue';
|
||||
|
||||
const router = useRoute();
|
||||
const { t } = useI18n();
|
||||
const quasar = useQuasar();
|
||||
|
||||
const arrayData = useArrayData(router.meta.moduleName);
|
||||
const arrayData = useArrayData();
|
||||
const invoiceIn = computed(() => arrayData.store.data);
|
||||
const invoiceId = +router.params.id;
|
||||
const invoiceId = +useRoute().params.id;
|
||||
const currency = computed(() => invoiceIn.value?.currency?.code);
|
||||
const expenses = ref([]);
|
||||
const sageTaxTypes = ref([]);
|
||||
|
|
|
@ -10,7 +10,7 @@ const { t } = useI18n();
|
|||
|
||||
defineExpose({ checkToBook });
|
||||
|
||||
const { store } = useArrayData(useRoute().meta.moduleName);
|
||||
const { store } = useArrayData();
|
||||
|
||||
async function checkToBook(id) {
|
||||
let directBooking = true;
|
||||
|
|
|
@ -11,13 +11,10 @@ import VnInputDate from 'components/common/VnInputDate.vue';
|
|||
import VnInput from 'components/common/VnInput.vue';
|
||||
import axios from 'axios';
|
||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||
import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const stateStore = useStateStore();
|
||||
const shelvingId = ref(route.params?.id || null);
|
||||
const isNew = Boolean(!shelvingId.value);
|
||||
const defaultInitialData = {
|
||||
|
|
|
@ -15,14 +15,11 @@ import VnConfirm from 'components/ui/VnConfirm.vue';
|
|||
import FetchData from 'components/FetchData.vue';
|
||||
import { openBuscaman } from 'src/utils/buscaman';
|
||||
import SendSmsDialog from 'components/common/SendSmsDialog.vue';
|
||||
import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
|
||||
const { t } = useI18n();
|
||||
const quasar = useQuasar();
|
||||
const route = useRoute();
|
||||
|
||||
const stateStore = useStateStore();
|
||||
const selectedRows = ref([]);
|
||||
const columns = computed(() => [
|
||||
{
|
||||
|
|
|
@ -136,13 +136,6 @@ const getEventByTimestamp = ({ year, month, day }) => {
|
|||
return props.events[stamp] || null;
|
||||
};
|
||||
|
||||
const isFestive = (timestamp) => {
|
||||
const event = getEventByTimestamp(timestamp);
|
||||
if (!event) return false;
|
||||
|
||||
const { isFestive } = event;
|
||||
return isFestive;
|
||||
};
|
||||
const getEventAttrs = (timestamp) => {
|
||||
const event = getEventByTimestamp(timestamp);
|
||||
if (!event) return {};
|
||||
|
|
|
@ -14,10 +14,12 @@ const customRouteRedirectName = computed(() => {
|
|||
if (routeName.value === 'ZoneLocations') return null;
|
||||
return routeName.value;
|
||||
});
|
||||
const searchbarMakeFetch = computed(() => routeName.value !== 'ZoneEvents');
|
||||
const searchBarDataKeys = {
|
||||
ZoneWarehouses: 'ZoneWarehouses',
|
||||
ZoneSummary: 'ZoneSummary',
|
||||
ZoneLocations: 'ZoneLocations',
|
||||
ZoneEvents: 'ZoneEvents',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
@ -27,6 +29,7 @@ const searchBarDataKeys = {
|
|||
:search-data-key="searchBarDataKeys[routeName]"
|
||||
:search-custom-route-redirect="customRouteRedirectName"
|
||||
:search-redirect="!!customRouteRedirectName"
|
||||
:search-make-fetch="searchbarMakeFetch"
|
||||
:searchbar-label="t('list.searchZone')"
|
||||
:searchbar-info="t('list.searchInfo')"
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import FormPopup from 'components/FormPopup.vue';
|
||||
import ZoneLocationsTree from './ZoneLocationsTree.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import axios from 'axios';
|
||||
|
||||
const props = defineProps({
|
||||
date: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
event: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
isNewMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
eventType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
geoIds: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onSubmit', 'closeForm']);
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
|
||||
const isNew = computed(() => props.isNewMode);
|
||||
const dated = ref(null);
|
||||
const tickedNodes = ref();
|
||||
|
||||
const _excludeType = ref('all');
|
||||
const excludeType = computed({
|
||||
get: () => _excludeType.value,
|
||||
set: (val) => {
|
||||
_excludeType.value = val;
|
||||
},
|
||||
});
|
||||
|
||||
const arrayData = useArrayData('ZoneEvents');
|
||||
|
||||
const exclusionGeoCreate = async () => {
|
||||
try {
|
||||
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?.zoneExclusionFk,
|
||||
geoIds: tickedNodes.value,
|
||||
};
|
||||
await axios.post('Zones/updateExclusionGeo', params);
|
||||
}
|
||||
await refetchEvents();
|
||||
} catch (err) {
|
||||
console.error('Error creating exclusion geo: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
const exclusionCreate = async () => {
|
||||
try {
|
||||
if (isNew.value)
|
||||
await axios.post(`Zones/${route.params.id}/exclusions`, [
|
||||
{ dated: dated.value },
|
||||
]);
|
||||
else
|
||||
await axios.put(`Zones/${route.params.id}/exclusions/${props.event?.id}`, {
|
||||
dated: dated.value,
|
||||
});
|
||||
|
||||
await refetchEvents();
|
||||
} catch (err) {
|
||||
console.error('Error creating exclusion: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (excludeType.value === 'all') exclusionCreate();
|
||||
else exclusionGeoCreate();
|
||||
};
|
||||
|
||||
const deleteEvent = async () => {
|
||||
try {
|
||||
if (!props.event) return;
|
||||
const exclusionId = props.event?.zoneExclusionFk || props.event?.id;
|
||||
await axios.delete(`Zones/${route.params.id}/exclusions/${exclusionId}`);
|
||||
await refetchEvents();
|
||||
} catch (err) {
|
||||
console.error('Error deleting event: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
const closeForm = () => emit('closeForm');
|
||||
|
||||
const refetchEvents = async () => {
|
||||
await arrayData.refresh({ append: false });
|
||||
closeForm();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (props.event) {
|
||||
dated.value = props.event?.dated;
|
||||
excludeType.value =
|
||||
props.eventType === 'geoExclusion' ? 'specificLocations' : 'all';
|
||||
tickedNodes.value = props.geoIds || [];
|
||||
} else if (props.date) dated.value = props.date;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormPopup
|
||||
:title="
|
||||
isNew
|
||||
? t('eventsExclusionForm.addExclusion')
|
||||
: t('eventsExclusionForm.editExclusion')
|
||||
"
|
||||
@on-submit="onSubmit()"
|
||||
:default-cancel-button="false"
|
||||
:default-submit-button="false"
|
||||
>
|
||||
<template #form-inputs>
|
||||
<VnRow class="row q-gutter-md q-mb-lg">
|
||||
<VnInputDate :label="t('eventsInclusionForm.day')" v-model="dated" />
|
||||
</VnRow>
|
||||
<div class="column q-gutter-y-sm q-mb-md">
|
||||
<QRadio
|
||||
v-model="excludeType"
|
||||
dense
|
||||
val="all"
|
||||
:label="t('eventsExclusionForm.all')"
|
||||
/>
|
||||
<QRadio
|
||||
v-model="excludeType"
|
||||
dense
|
||||
val="specificLocations"
|
||||
:label="t('eventsExclusionForm.specificLocations')"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="excludeType === 'specificLocations'"
|
||||
style="min-height: 60vh; overflow-y: scroll"
|
||||
>
|
||||
<ZoneLocationsTree
|
||||
:root-label="t('eventsExclusionForm.rootTreeLabel')"
|
||||
v-model:tickedNodes="tickedNodes"
|
||||
show-search-bar
|
||||
show-default-checkboxes
|
||||
>
|
||||
<template #content="{ node }">
|
||||
<span>{{ node.name }}</span>
|
||||
</template>
|
||||
</ZoneLocationsTree>
|
||||
</div>
|
||||
</template>
|
||||
<template #custom-buttons>
|
||||
<QBtn
|
||||
:label="t('globals.cancel')"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-mr-sm"
|
||||
v-close-popup
|
||||
/>
|
||||
<QBtn
|
||||
v-if="
|
||||
!isNew && (eventType === 'exclusion' || eventType === 'geoExclusion')
|
||||
"
|
||||
:label="t('globals.delete')"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-mr-sm"
|
||||
@click="
|
||||
openConfirmationModal(
|
||||
t('eventsPanel.deleteTitle'),
|
||||
t('eventsPanel.deleteSubtitle'),
|
||||
() => deleteEvent()
|
||||
)
|
||||
"
|
||||
/>
|
||||
<QBtn
|
||||
:label="isNew ? t('globals.add') : t('globals.save')"
|
||||
type="submit"
|
||||
color="primary"
|
||||
/>
|
||||
</template>
|
||||
</FormPopup>
|
||||
</template>
|
|
@ -0,0 +1,240 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import FormPopup from 'components/FormPopup.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnWeekdayPicker from 'src/components/common/VnWeekdayPicker.vue';
|
||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import axios from 'axios';
|
||||
|
||||
const props = defineProps({
|
||||
date: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
event: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
isNewMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
eventType: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onSubmit', 'closeForm']);
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const weekdayStore = useWeekdayStore();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
|
||||
const isNew = computed(() => props.isNewMode);
|
||||
const eventInclusionFormData = ref({ wdays: [] });
|
||||
|
||||
const _inclusionType = ref('indefinitely');
|
||||
const inclusionType = computed({
|
||||
get: () => _inclusionType.value,
|
||||
set: (val) => {
|
||||
_inclusionType.value = val;
|
||||
eventInclusionFormData.value.type = val;
|
||||
},
|
||||
});
|
||||
|
||||
const arrayData = useArrayData('ZoneEvents');
|
||||
|
||||
const createEvent = async () => {
|
||||
try {
|
||||
eventInclusionFormData.value.weekDays = weekdayStore.toSet(
|
||||
eventInclusionFormData.value.wdays
|
||||
);
|
||||
|
||||
if (inclusionType.value == 'day') eventInclusionFormData.value.weekDays = '';
|
||||
else eventInclusionFormData.value.dated = null;
|
||||
|
||||
if (inclusionType.value != 'range') {
|
||||
eventInclusionFormData.value.started = null;
|
||||
eventInclusionFormData.value.ended = null;
|
||||
}
|
||||
|
||||
if (isNew.value)
|
||||
await axios.post(
|
||||
`Zones/${route.params.id}/events`,
|
||||
eventInclusionFormData.value
|
||||
);
|
||||
else
|
||||
await axios.put(
|
||||
`Zones/${route.params.id}/events/${props.event?.id}`,
|
||||
eventInclusionFormData.value
|
||||
);
|
||||
|
||||
await refetchEvents();
|
||||
emit('onSubmit');
|
||||
} catch (err) {
|
||||
console.error('Error creating event', err);
|
||||
}
|
||||
};
|
||||
|
||||
const deleteEvent = async () => {
|
||||
try {
|
||||
if (!props.event) return;
|
||||
await axios.delete(`Zones/${route.params.id}/events/${props.event?.id}`);
|
||||
await refetchEvents();
|
||||
} catch (err) {
|
||||
console.error('Error deleting event: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
const closeForm = () => {
|
||||
emit('closeForm');
|
||||
};
|
||||
|
||||
const refetchEvents = async () => {
|
||||
await arrayData.refresh({ append: false });
|
||||
closeForm();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (props.event) {
|
||||
eventInclusionFormData.value = { ...props.event };
|
||||
inclusionType.value = props.event?.type || 'day';
|
||||
} else if (props.date) {
|
||||
eventInclusionFormData.value.dated = props.date;
|
||||
inclusionType.value = 'day';
|
||||
} else inclusionType.value = 'indefinitely';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormPopup
|
||||
:title="
|
||||
isNew ? t('eventsInclusionForm.addEvent') : t('eventsInclusionForm.editEvent')
|
||||
"
|
||||
@on-submit="createEvent()"
|
||||
:default-cancel-button="false"
|
||||
:default-submit-button="false"
|
||||
>
|
||||
<template #form-inputs>
|
||||
<div class="column q-gutter-y-sm q-mb-md">
|
||||
<QRadio
|
||||
v-model="inclusionType"
|
||||
dense
|
||||
val="day"
|
||||
:label="t('eventsInclusionForm.oneDay')"
|
||||
/>
|
||||
<QRadio
|
||||
v-model="inclusionType"
|
||||
dense
|
||||
val="indefinitely"
|
||||
:label="t('eventsInclusionForm.indefinitely')"
|
||||
/>
|
||||
<QRadio
|
||||
v-model="inclusionType"
|
||||
dense
|
||||
val="range"
|
||||
:label="t('eventsInclusionForm.rangeOfDates')"
|
||||
class="q-mb-sm"
|
||||
/>
|
||||
</div>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col flex justify-center">
|
||||
<VnInputDate
|
||||
v-if="inclusionType === 'day'"
|
||||
:label="t('eventsInclusionForm.day')"
|
||||
v-model="eventInclusionFormData.dated"
|
||||
class="full-width"
|
||||
/>
|
||||
<VnWeekdayPicker
|
||||
v-else
|
||||
v-model:wdays="eventInclusionFormData.wdays"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow v-if="inclusionType === 'range'" class="row q-gutter-md q-mb-md">
|
||||
<VnInputDate
|
||||
:label="t('eventsInclusionForm.from')"
|
||||
v-model="eventInclusionFormData.started"
|
||||
/>
|
||||
<VnInputDate
|
||||
:label="t('eventsInclusionForm.to')"
|
||||
v-model="eventInclusionFormData.ended"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnInputTime
|
||||
v-model="eventInclusionFormData.hour"
|
||||
:label="t('eventsInclusionForm.closing')"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="eventInclusionFormData.travelingDays"
|
||||
:label="t('eventsInclusionForm.travelingDays')"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnInput
|
||||
v-model="eventInclusionFormData.price"
|
||||
:label="t('eventsInclusionForm.price')"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="eventInclusionFormData.bonus"
|
||||
:label="t('eventsInclusionForm.bonus')"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnInput
|
||||
v-model="eventInclusionFormData.m3Max"
|
||||
:label="t('eventsInclusionForm.m3Max')"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
</VnRow>
|
||||
</template>
|
||||
<template #custom-buttons>
|
||||
<QBtn
|
||||
:label="t('globals.cancel')"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-mr-sm"
|
||||
v-close-popup
|
||||
/>
|
||||
<QBtn
|
||||
v-if="!isNew && eventType === 'event'"
|
||||
:label="t('globals.delete')"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-mr-sm"
|
||||
@click="
|
||||
openConfirmationModal(
|
||||
t('eventsPanel.deleteTitle'),
|
||||
t('eventsPanel.deleteSubtitle'),
|
||||
() => deleteEvent()
|
||||
)
|
||||
"
|
||||
/>
|
||||
<QBtn
|
||||
:label="isNew ? t('globals.save') : t('globals.add')"
|
||||
type="submit"
|
||||
color="primary"
|
||||
/>
|
||||
</template>
|
||||
</FormPopup>
|
||||
</template>
|
|
@ -0,0 +1,111 @@
|
|||
<script setup>
|
||||
import { ref, onUnmounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import ZoneEventsPanel from './ZoneEventsPanel.vue';
|
||||
import ZoneCalendarGrid from '../ZoneCalendarGrid.vue';
|
||||
import ZoneEventInclusionForm from './ZoneEventInclusionForm.vue';
|
||||
import ZoneEventExclusionForm from './ZoneEventExclusionForm.vue';
|
||||
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const stateStore = useStateStore();
|
||||
|
||||
const firstDay = ref(null);
|
||||
const lastDay = ref(null);
|
||||
|
||||
const events = ref([]);
|
||||
const formModeName = ref('include');
|
||||
const showZoneEventForm = ref(false);
|
||||
const zoneEventsFormProps = reactive({
|
||||
isNewMode: true,
|
||||
date: null,
|
||||
});
|
||||
|
||||
const openForm = (data) => {
|
||||
const { date = null, isNewMode, event, eventType, geoIds = [] } = data;
|
||||
zoneEventsFormProps.date = date;
|
||||
zoneEventsFormProps.isNewMode = isNewMode;
|
||||
zoneEventsFormProps.event = event;
|
||||
zoneEventsFormProps.eventType = eventType;
|
||||
if (geoIds.length) zoneEventsFormProps.geoIds = geoIds;
|
||||
|
||||
showZoneEventForm.value = true;
|
||||
};
|
||||
|
||||
const onZoneEventFormClose = () => {
|
||||
showZoneEventForm.value = false;
|
||||
zoneEventsFormProps.value = {};
|
||||
};
|
||||
|
||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="stateStore.isHeaderMounted()">
|
||||
<Teleport to="#actions-append">
|
||||
<div class="row q-gutter-x-sm">
|
||||
<QBtn
|
||||
flat
|
||||
@click="stateStore.toggleRightDrawer()"
|
||||
round
|
||||
dense
|
||||
icon="menu"
|
||||
>
|
||||
<QTooltip bottom anchor="bottom right">
|
||||
{{ t('globals.collapseMenu') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||
<QScrollArea class="fit text-grey-8">
|
||||
<ZoneEventsPanel
|
||||
:first-day="firstDay"
|
||||
:last-day="lastDay"
|
||||
:events="events"
|
||||
v-model:formModeName="formModeName"
|
||||
@open-zone-form="openForm"
|
||||
/>
|
||||
</QScrollArea>
|
||||
</QDrawer>
|
||||
<QPage class="q-pa-md flex justify-center">
|
||||
<ZoneCalendarGrid
|
||||
v-model:events="events"
|
||||
v-model:firstDay="firstDay"
|
||||
v-model:lastDay="lastDay"
|
||||
data-key="ZoneEvents"
|
||||
@on-date-selected="openForm"
|
||||
/>
|
||||
<QDialog v-model="showZoneEventForm" @hide="onZoneEventFormClose()">
|
||||
<ZoneEventInclusionForm
|
||||
v-if="formModeName === 'include'"
|
||||
v-bind="zoneEventsFormProps"
|
||||
@close-form="onZoneEventFormClose()"
|
||||
/>
|
||||
<ZoneEventExclusionForm
|
||||
v-else
|
||||
v-bind="zoneEventsFormProps"
|
||||
@close-form="onZoneEventFormClose()"
|
||||
/>
|
||||
</QDialog>
|
||||
<QPageSticky :offset="[20, 20]">
|
||||
<QBtn
|
||||
@click="
|
||||
openForm({
|
||||
isNewMode: true,
|
||||
})
|
||||
"
|
||||
color="primary"
|
||||
fab
|
||||
icon="add"
|
||||
/>
|
||||
<QTooltip class="text-no-wrap">
|
||||
{{ t('eventsInclusionForm.addEvent') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
</QPage>
|
||||
</template>
|
|
@ -0,0 +1,221 @@
|
|||
<script setup>
|
||||
import { onMounted, watch, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import axios from 'axios';
|
||||
import { toDateFormat, toTimeFormat } from 'src/filters/date.js';
|
||||
import { dashOrCurrency, toCurrency } from 'filters/index';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
|
||||
const props = defineProps({
|
||||
firstDay: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
lastDay: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
events: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
formModeName: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'include',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['openZoneForm', 'update:formModeName']);
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const weekdayStore = useWeekdayStore();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
|
||||
const formName = computed({
|
||||
get: () => props.formModeName,
|
||||
set: (value) => emit('update:formModeName', value),
|
||||
});
|
||||
|
||||
const params = computed(() => ({
|
||||
zoneFk: route.params.id,
|
||||
started: props.firstDay,
|
||||
ended: props.lastDay,
|
||||
}));
|
||||
const arrayData = useArrayData('ZoneEvents', {
|
||||
params: params,
|
||||
url: `Zones/getEventsFiltered`,
|
||||
});
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
if (!params.value.zoneFk || !params.value.started || !params.value.ended) return;
|
||||
|
||||
await arrayData.applyFilter({
|
||||
params: params.value,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error fetching events: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
params,
|
||||
async () => {
|
||||
await fetchData();
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
const formatWdays = (event) => {
|
||||
if (!event.weekDays) return;
|
||||
|
||||
let abrWdays = event.weekDays
|
||||
.split(',')
|
||||
.map((wday) => weekdayStore.getLocalesMap[wday].localeAbr);
|
||||
|
||||
return abrWdays.length < 7 ? abrWdays.join(', ') : t('eventsPanel.everyday');
|
||||
};
|
||||
|
||||
const deleteEvent = async (id) => {
|
||||
try {
|
||||
if (!id) return;
|
||||
await axios.delete(`Zones/${route.params.id}/events/${id}`);
|
||||
await fetchData();
|
||||
} catch (err) {
|
||||
console.error('Error deleting event: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
const openInclusionForm = (event) => {
|
||||
formName.value = 'include';
|
||||
emit('openZoneForm', {
|
||||
date: event.dated,
|
||||
event,
|
||||
isNewMode: false,
|
||||
eventType: 'event',
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
weekdayStore.initStore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QForm @submit="onSubmit()">
|
||||
<div class="column q-pa-md q-gutter-y-sm">
|
||||
<span class="color-vn-label text-subtitle1">{{
|
||||
t('eventsPanel.editMode')
|
||||
}}</span>
|
||||
<QRadio
|
||||
v-model="formName"
|
||||
dense
|
||||
val="include"
|
||||
:label="t('eventsPanel.include')"
|
||||
/>
|
||||
<QRadio
|
||||
v-model="formName"
|
||||
dense
|
||||
val="exclude"
|
||||
:label="t('eventsPanel.exclude')"
|
||||
class="q-mb-sm"
|
||||
/>
|
||||
</div>
|
||||
<span class="color-vn-label text-subtitle1 q-px-md">{{
|
||||
t('eventsPanel.events')
|
||||
}}</span>
|
||||
<QList>
|
||||
<QItem v-for="(event, index) in events" :key="index" class="event-card">
|
||||
<QItemSection left @click="openInclusionForm(event)">
|
||||
<div v-if="event.type == 'day'" class="q-mb-xs">
|
||||
{{ toDateFormat(event.dated) }}
|
||||
</div>
|
||||
<div v-if="event.type != 'day'" class="q-mb-xs">
|
||||
<span v-if="event.weekDays">
|
||||
{{ formatWdays(event) }}
|
||||
</span>
|
||||
<span v-if="event.type == 'range'">
|
||||
({{ toDateFormat(event.started) }} -
|
||||
{{ toDateFormat(event.ended) }})
|
||||
</span>
|
||||
</div>
|
||||
<span class="color-vn-label">
|
||||
{{ t('eventsPanel.closing') }}:
|
||||
<span class="color-vn-text q-ml-xs">
|
||||
{{ dashIfEmpty(toTimeFormat(event.hour)) }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="color-vn-label">
|
||||
{{ t('eventsPanel.travelingDays') }}:
|
||||
<span class="color-vn-text">
|
||||
{{ dashIfEmpty(event.travelingDays) }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="color-vn-label">
|
||||
{{ t('eventsPanel.price') }}:
|
||||
<span class="color-vn-text">
|
||||
{{ dashOrCurrency(event.price)() }}</span
|
||||
>
|
||||
</span>
|
||||
<span class="color-vn-label">
|
||||
{{ t('eventsPanel.bonus') }}:
|
||||
<span class="color-vn-text">
|
||||
{{ dashOrCurrency(event.bonus)() }}</span
|
||||
>
|
||||
</span>
|
||||
<span class="color-vn-label">
|
||||
{{ t('eventsPanel.m3Max') }}:
|
||||
<span class="color-vn-text"> {{ dashIfEmpty(event.m3Max) }}</span>
|
||||
</span>
|
||||
</QItemSection>
|
||||
<QItemSection side @click="openInclusionForm(event)">
|
||||
<QBtn
|
||||
icon="delete"
|
||||
flat
|
||||
dense
|
||||
size="md"
|
||||
color="primary"
|
||||
@click.stop="
|
||||
openConfirmationModal(
|
||||
t('eventsPanel.deleteTitle'),
|
||||
t('eventsPanel.deleteSubtitle'),
|
||||
() => deleteEvent(event.id)
|
||||
)
|
||||
"
|
||||
>
|
||||
<QTooltip>{{ t('eventsPanel.delete') }}</QTooltip>
|
||||
</QBtn>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<span
|
||||
v-if="!events.length"
|
||||
class="flex justify-center text-h5 color-vn-label"
|
||||
>
|
||||
{{ t('globals.noResults') }}
|
||||
</span>
|
||||
</QList>
|
||||
</QForm>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.event-card {
|
||||
display: flex;
|
||||
border-bottom: $border-thin-light;
|
||||
margin: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--vn-accent-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -24,7 +24,8 @@ const onSelected = async (val, node) => {
|
|||
<QPage class="column items-center q-pa-md">
|
||||
<QCard class="full-width q-pa-md" style="max-width: 800px">
|
||||
<ZoneLocationsTree :root-label="t('zoneLocations.locations')">
|
||||
<template #checkbox="{ node }">
|
||||
<template #content="{ node }">
|
||||
<span v-if="!node.id">{{ node.name }}</span>
|
||||
<QCheckbox
|
||||
v-if="node.id"
|
||||
v-model="node.selected"
|
||||
|
|
|
@ -1,12 +1,34 @@
|
|||
<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';
|
||||
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
|
||||
import { useState } from 'src/composables/useState';
|
||||
import axios from 'axios';
|
||||
import { useArrayData } from 'composables/useArrayData';
|
||||
import { onUnmounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
rootLabel: {
|
||||
type: String,
|
||||
default: 'Locations',
|
||||
},
|
||||
tickedNodes: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
showSearchBar: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showDefaultCheckboxes: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:tickedNodes']);
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
|
@ -22,9 +44,21 @@ const { store } = arrayData;
|
|||
const storeData = computed(() => store.data);
|
||||
|
||||
const nodes = ref([
|
||||
{ id: null, name: t('zoneLocations.locations'), sons: true, childs: [{}] },
|
||||
{
|
||||
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) => {
|
||||
|
@ -107,17 +141,19 @@ watch(storeData, async (val) => {
|
|||
formatNodeSelected(n);
|
||||
});
|
||||
} else {
|
||||
for (let n of state.get('Tree')) {
|
||||
await fetchNodeLeaves(n);
|
||||
}
|
||||
for (let n of state.get('Tree')) await fetchNodeLeaves(n);
|
||||
expanded.value = [null, ...fetchedNodeKeys];
|
||||
}
|
||||
previousExpandedNodes.value = new Set(expanded.value);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if (store.userParams?.search) {
|
||||
const reFetch = async () => {
|
||||
await arrayData.fetch({ append: false });
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
if (store.userParams?.search && !props.showSearchBar) {
|
||||
await reFetch();
|
||||
return;
|
||||
}
|
||||
const stateTree = state.get('Tree');
|
||||
|
@ -140,6 +176,7 @@ onMounted(async () => {
|
|||
}
|
||||
}, 1000);
|
||||
|
||||
expanded.value.unshift(null);
|
||||
previousExpandedNodes.value = new Set(expanded.value);
|
||||
});
|
||||
|
||||
|
@ -149,14 +186,26 @@ onUnmounted(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<VnInput
|
||||
v-if="showSearchBar"
|
||||
v-model="store.userParams.search"
|
||||
:placeholder="t('globals.search')"
|
||||
@keydown.enter.prevent="reFetch()"
|
||||
>
|
||||
<template #prepend>
|
||||
<QIcon class="cursor-pointer" name="search" />
|
||||
</template>
|
||||
</VnInput>
|
||||
<QTree
|
||||
ref="treeRef"
|
||||
:nodes="nodes"
|
||||
node-key="id"
|
||||
label-key="name"
|
||||
children-key="childs"
|
||||
:tick-strategy="props.showDefaultCheckboxes ? 'strict' : 'none'"
|
||||
v-model:expanded="expanded"
|
||||
@update:expanded="onNodeExpanded($event)"
|
||||
v-model:ticked="_tickedNodes"
|
||||
:default-expand-all="true"
|
||||
>
|
||||
<template #default-header="{ node }">
|
||||
|
@ -164,8 +213,7 @@ onUnmounted(() => {
|
|||
:id="node.id"
|
||||
class="qtr row justify-between full-width q-pr-md cursor-pointer"
|
||||
>
|
||||
<span v-if="!node.id">{{ node.name }}</span>
|
||||
<slot name="checkbox" :node="node" />
|
||||
<slot name="content" :node="node" />
|
||||
</div>
|
||||
</template>
|
||||
</QTree>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import { ref, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { date } from 'quasar';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import ZoneClosingTable from './ZoneClosingTable.vue';
|
||||
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
|
||||
|
@ -38,7 +39,10 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onDateSelected']);
|
||||
|
||||
const { locale } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
const calendarRef = ref(null);
|
||||
const weekdayStore = useWeekdayStore();
|
||||
|
@ -52,7 +56,11 @@ const todayTimestamp = computed(() => {
|
|||
});
|
||||
const _monthDate = computed(() => date.formatDate(props.monthDate, 'YYYY-MM-DD'));
|
||||
|
||||
const isZoneDeliveryView = computed(() => route.name === 'ZoneDeliveryDays');
|
||||
|
||||
const onEventSelection = async ({ year, month, day }) => {
|
||||
if (!isZoneDeliveryView.value) return;
|
||||
|
||||
const date = new Date(year, month - 1, day);
|
||||
const stamp = date.getTime();
|
||||
const events = props.daysMap[stamp];
|
||||
|
@ -81,6 +89,13 @@ const getEventByTimestamp = ({ year, month, day }) => {
|
|||
);
|
||||
};
|
||||
|
||||
const getEventType = ({ year, month, day }) => {
|
||||
const stamp = new Date(year, month - 1, day).getTime();
|
||||
if (props.exclusions[stamp]) return 'exclusion';
|
||||
if (props.geoExclusions[stamp]) return 'geoExclusion';
|
||||
return 'event';
|
||||
};
|
||||
|
||||
const getEventAttrs = ({ year, month, day }) => {
|
||||
const stamp = new Date(year, month - 1, day).getTime();
|
||||
|
||||
|
@ -104,6 +119,28 @@ const isToday = (timestamp) => {
|
|||
const calendarHeaderTitle = computed(() => {
|
||||
return `${weekdayStore.getLocaleMonths[props.month - 1].locale} ${props.year}`;
|
||||
});
|
||||
|
||||
const handleDateClick = (timestamp) => {
|
||||
if (isZoneDeliveryView.value) return;
|
||||
|
||||
const event = getEventByTimestamp(timestamp);
|
||||
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('onDateSelected', {
|
||||
date,
|
||||
isNewMode: !event,
|
||||
event: event && event.length > 0 ? event[0] : null,
|
||||
eventType,
|
||||
geoIds,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -128,6 +165,7 @@ const calendarHeaderTitle = computed(() => {
|
|||
short-weekday-label
|
||||
:locale="locale"
|
||||
:now="today"
|
||||
@click-date="handleDateClick($event.scope.timestamp)"
|
||||
mini-mode
|
||||
>
|
||||
<template #day="{ scope: { timestamp } }">
|
||||
|
@ -135,7 +173,11 @@ const calendarHeaderTitle = computed(() => {
|
|||
<QBtn
|
||||
v-if="getEventByTimestamp(timestamp)"
|
||||
v-bind="{ ...getEventAttrs(timestamp) }"
|
||||
@click="onEventSelection(timestamp)"
|
||||
@click="
|
||||
isZoneDeliveryView
|
||||
? onEventSelection(timestamp)
|
||||
: handleDateClick(timestamp)
|
||||
"
|
||||
rounded
|
||||
dense
|
||||
flat
|
||||
|
@ -144,7 +186,7 @@ const calendarHeaderTitle = computed(() => {
|
|||
'--today': isToday(timestamp),
|
||||
}"
|
||||
>
|
||||
<QPopupProxy>
|
||||
<QPopupProxy v-if="isZoneDeliveryView">
|
||||
<ZoneClosingTable
|
||||
v-if="zoneClosingData && zoneClosingData.length"
|
||||
:rows="zoneClosingData"
|
|
@ -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: String,
|
||||
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,181 +1,12 @@
|
|||
<script setup>
|
||||
import { computed, onMounted, ref, watch, onUnmounted } from 'vue';
|
||||
|
||||
import { ref } from 'vue';
|
||||
import ZoneDeliveryPanel from './ZoneDeliveryPanel.vue';
|
||||
import ZoneDeliveryCalendar from './ZoneDeliveryCalendar.vue';
|
||||
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import ZoneCalendarGrid from './ZoneCalendarGrid.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
|
||||
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('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>
|
||||
|
||||
<template>
|
||||
|
@ -185,55 +16,11 @@ onUnmounted(() => arrayData.destroy());
|
|||
</template>
|
||||
</RightMenu>
|
||||
<QPage class="q-pa-md flex justify-center">
|
||||
<QCard style="height: max-content">
|
||||
<div class="calendars-header">
|
||||
<QBtn
|
||||
icon="arrow_left"
|
||||
size="sm"
|
||||
flat
|
||||
class="full-height"
|
||||
@click="step(-1)"
|
||||
<ZoneCalendarGrid
|
||||
v-model:events="events"
|
||||
v-model:firstDay="firstDay"
|
||||
v-model:lastDay="lastDay"
|
||||
data-key="ZoneDeliveryDays"
|
||||
/>
|
||||
<span>{{ headerTitle }}</span>
|
||||
<QBtn
|
||||
icon="arrow_right"
|
||||
size="sm"
|
||||
flat
|
||||
class="full-height"
|
||||
@click="step(1)"
|
||||
/>
|
||||
</div>
|
||||
<div class="calendars-container">
|
||||
<ZoneDeliveryCalendar
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
</QCard>
|
||||
</QPage>
|
||||
</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 { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
|
|
|
@ -7,6 +7,7 @@ zone:
|
|||
deliveryDays: Delivery days
|
||||
upcomingDeliveries: Upcoming deliveries
|
||||
warehouses: Warehouses
|
||||
calendar: Calendar
|
||||
list:
|
||||
clone: Clone
|
||||
id: Id
|
||||
|
@ -66,6 +67,41 @@ warehouses:
|
|||
deleteSubtitle: Are you sure you want to continue?
|
||||
warehouse: Warehouse
|
||||
add: Add
|
||||
eventsPanel:
|
||||
editMode: Edit mode
|
||||
include: Include
|
||||
exclude: Exclude
|
||||
events: Events
|
||||
closing: Closing
|
||||
travelingDays: Traveling days
|
||||
price: Price
|
||||
bonus: Bonus
|
||||
m3Max: Max m³
|
||||
everyday: Everyday
|
||||
delete: Delete
|
||||
deleteTitle: This item will be deleted
|
||||
deleteSubtitle: Are you sure you want to continue?
|
||||
eventsExclusionForm:
|
||||
addExclusion: Add exclusion
|
||||
editExclusion: Edit exclusion
|
||||
day: Day
|
||||
all: All
|
||||
specificLocations: Specific locations
|
||||
rootTreeLabel: Locations where it is not distributed
|
||||
eventsInclusionForm:
|
||||
addEvent: Add event
|
||||
editEvent: Edit event
|
||||
oneDay: One day
|
||||
indefinitely: Indefinitely
|
||||
rangeOfDates: Range of dates
|
||||
day: Day
|
||||
closing: Closing
|
||||
travelingDays: Traveling days
|
||||
price: Price
|
||||
bonus: Bonus
|
||||
m3Max: Max m³
|
||||
from: From
|
||||
to: To
|
||||
upcomingDeliveries:
|
||||
province: Province
|
||||
closing: Closing
|
||||
|
|
|
@ -7,6 +7,7 @@ zone:
|
|||
deliveryDays: Días de entrega
|
||||
upcomingDeliveries: Próximos repartos
|
||||
warehouses: Almacenes
|
||||
calendar: Calendario
|
||||
list:
|
||||
clone: Clonar
|
||||
id: Id
|
||||
|
@ -68,6 +69,41 @@ warehouses:
|
|||
deleteSubtitle: ¿Seguro que quieres continuar?
|
||||
warehouse: Almacén
|
||||
add: Añadir
|
||||
eventsPanel:
|
||||
editMode: Modo edición
|
||||
include: Incluir
|
||||
exclude: Excluir
|
||||
events: Eventos
|
||||
closing: Cierre
|
||||
travelingDays: Días de viaje
|
||||
price: Precio
|
||||
bonus: Bonificación
|
||||
m3Max: Meidida máxima
|
||||
everyday: Todos los días
|
||||
delete: Eliminar
|
||||
deleteTitle: Este elemento será eliminado
|
||||
deleteSubtitle: ¿Seguro que quieres continuar?
|
||||
eventsExclusionForm:
|
||||
addExclusion: Añadir exclusión
|
||||
editExclusion: Editar exclusión
|
||||
day: Día
|
||||
all: Todo
|
||||
specificLocations: Localizaciones concretas
|
||||
rootTreeLabel: Localizaciones en las que no se reparte
|
||||
eventsInclusionForm:
|
||||
addEvent: Añadir evento
|
||||
editEvent: Editar evento
|
||||
oneDay: Un día
|
||||
indefinitely: Indefinido
|
||||
rangeOfDates: Rango de fechas
|
||||
day: Día
|
||||
closing: Cierre
|
||||
travelingDays: Días de viaje
|
||||
price: Precio
|
||||
bonus: Bonificación
|
||||
m3Max: Medida máxima
|
||||
from: Desde
|
||||
to: Hasta
|
||||
upcomingDeliveries:
|
||||
province: Provincia
|
||||
closing: Cierre
|
||||
|
|
|
@ -39,146 +39,6 @@ export default {
|
|||
},
|
||||
component: () => import('src/pages/Account/Role/AccountRoles.vue'),
|
||||
},
|
||||
{
|
||||
path: 'alias',
|
||||
name: 'AccountAlias',
|
||||
meta: {
|
||||
title: 'alias',
|
||||
icon: 'email',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountAlias.vue'),
|
||||
},
|
||||
{
|
||||
path: 'accounts',
|
||||
name: 'AccountAccounts',
|
||||
meta: {
|
||||
title: 'accounts',
|
||||
icon: 'accessibility',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountAccounts.vue'),
|
||||
},
|
||||
{
|
||||
path: 'ldap',
|
||||
name: 'AccountLdap',
|
||||
meta: {
|
||||
title: 'ldap',
|
||||
icon: 'account_tree',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountLdap.vue'),
|
||||
},
|
||||
{
|
||||
path: 'samba',
|
||||
name: 'AccountSamba',
|
||||
meta: {
|
||||
title: 'samba',
|
||||
icon: 'preview',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountSamba.vue'),
|
||||
},
|
||||
{
|
||||
path: 'acls',
|
||||
name: 'AccountAcls',
|
||||
meta: {
|
||||
title: 'acls',
|
||||
icon: 'check',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountAcls.vue'),
|
||||
},
|
||||
{
|
||||
path: 'connections',
|
||||
name: 'AccountConnections',
|
||||
meta: {
|
||||
title: 'connections',
|
||||
icon: 'check',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountConnections.vue'),
|
||||
},
|
||||
|
||||
{
|
||||
path: 'create',
|
||||
name: 'AccountCreate',
|
||||
meta: {
|
||||
title: 'accountCreate',
|
||||
icon: 'add',
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountCreate.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'AccountCard',
|
||||
path: ':id',
|
||||
component: () => import('src/pages/Account/Card/AccountCard.vue'),
|
||||
redirect: { name: 'AccountSummary' },
|
||||
children: [
|
||||
{
|
||||
name: 'AccountSummary',
|
||||
path: 'summary',
|
||||
meta: {
|
||||
title: 'summary',
|
||||
icon: 'launch',
|
||||
},
|
||||
component: () => import('src/pages/Account/Card/AccountSummary.vue'),
|
||||
},
|
||||
{
|
||||
name: 'AccountBasicData',
|
||||
path: 'basic-data',
|
||||
meta: {
|
||||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Account/Card/AccountBasicData.vue'),
|
||||
},
|
||||
{
|
||||
name: 'AccountInheritedRoles',
|
||||
path: 'inherited-oles',
|
||||
meta: {
|
||||
title: 'inheritedRoles',
|
||||
icon: 'group',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Account/Card/AccountInheritedRoles.vue'),
|
||||
},
|
||||
{
|
||||
name: 'AccountMailForwarding',
|
||||
path: 'mail-forwarding',
|
||||
meta: {
|
||||
title: 'mailForwarding',
|
||||
icon: 'forward',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Account/Card/AccountMailForwarding.vue'),
|
||||
},
|
||||
{
|
||||
name: 'AccountMailAlias',
|
||||
path: 'mail-alias',
|
||||
meta: {
|
||||
title: 'mailAlias',
|
||||
icon: 'email',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Account/Card/AccountMailAlias.vue'),
|
||||
},
|
||||
{
|
||||
name: 'AccountPrivileges',
|
||||
path: 'privileges',
|
||||
meta: {
|
||||
title: 'privileges',
|
||||
icon: 'badge',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Account/Card/AccountPrivileges.vue'),
|
||||
},
|
||||
{
|
||||
name: 'AccountLog',
|
||||
path: 'log',
|
||||
meta: {
|
||||
title: 'log',
|
||||
icon: 'history',
|
||||
},
|
||||
component: () => import('src/pages/Account/Card/AccountLog.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -11,8 +11,19 @@ export default {
|
|||
component: RouterView,
|
||||
redirect: { name: 'ZoneMain' },
|
||||
menus: {
|
||||
main: ['ZoneList', 'ZoneDeliveryDays', 'ZoneUpcomingDeliveries'],
|
||||
card: ['ZoneBasicData', 'ZoneWarehouses', 'ZoneHistory', 'ZoneLocations'],
|
||||
main: [
|
||||
'ZoneList',
|
||||
'ZoneDeliveryDays',
|
||||
'ZoneUpcomingList',
|
||||
'ZoneUpcomingDeliveries',
|
||||
],
|
||||
card: [
|
||||
'ZoneBasicData',
|
||||
'ZoneWarehouses',
|
||||
'ZoneHistory',
|
||||
'ZoneLocations',
|
||||
'ZoneEvents',
|
||||
],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -128,6 +139,15 @@ export default {
|
|||
},
|
||||
component: () => import('src/pages/Zone/Card/ZoneLog.vue'),
|
||||
},
|
||||
{
|
||||
name: 'ZoneEvents',
|
||||
path: 'events',
|
||||
meta: {
|
||||
title: 'calendar',
|
||||
icon: 'vn:calendar',
|
||||
},
|
||||
component: () => import('src/pages/Zone/Card/ZoneEvents.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -73,6 +73,22 @@ export const useWeekdayStore = defineStore('weekdayStore', () => {
|
|||
return locales;
|
||||
});
|
||||
|
||||
const getLocalesMap = computed(() => {
|
||||
const locales = {};
|
||||
for (let code of localeOrder.es) {
|
||||
const weekDay = weekdaysMap[code];
|
||||
const locale = t(`weekdays.${weekdaysMap[code].code}`);
|
||||
const obj = {
|
||||
...weekDay,
|
||||
locale,
|
||||
localeChar: locale.substr(0, 1),
|
||||
localeAbr: locale.substr(0, 3),
|
||||
};
|
||||
locales[weekDay.code] = obj;
|
||||
}
|
||||
return locales;
|
||||
});
|
||||
|
||||
const getLocaleMonths = computed(() => {
|
||||
const locales = [];
|
||||
for (let code of monthCodes) {
|
||||
|
@ -106,6 +122,28 @@ export const useWeekdayStore = defineStore('weekdayStore', () => {
|
|||
return wdays;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the inverse operation of fromSet() method. Transforms an
|
||||
* array whose indexes are weekday index with selected days set to %true to
|
||||
* weekday codes separated by commas.
|
||||
*
|
||||
* @param {Array<Boolean>} _weekDays Array with selected days set to %true
|
||||
* @return {String} weekDays Weekday codes separated by commas
|
||||
*/
|
||||
const toSet = (_weekDays) => {
|
||||
let wdays = [];
|
||||
|
||||
if (_weekDays) {
|
||||
for (let i = 0; i < _weekDays.length; i++) {
|
||||
if (!_weekDays[i]) continue;
|
||||
let data = weekdays[i];
|
||||
if (data) wdays.push(data.code);
|
||||
}
|
||||
}
|
||||
|
||||
return wdays.join(',');
|
||||
};
|
||||
|
||||
return {
|
||||
initStore,
|
||||
weekdaysMap,
|
||||
|
@ -115,5 +153,7 @@ export const useWeekdayStore = defineStore('weekdayStore', () => {
|
|||
monthCodes,
|
||||
getLocaleMonths,
|
||||
fromSet,
|
||||
toSet,
|
||||
getLocalesMap,
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue