WIP
This commit is contained in:
parent
fc87bb8293
commit
bfee37b631
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"@quasar/testing-unit-vitest": {
|
"@quasar/testing-unit-vitest": {
|
||||||
"options": [
|
"options": ["scripts"]
|
||||||
"scripts"
|
},
|
||||||
]
|
"@quasar/qcalendar": {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<template>
|
||||||
|
<div :class="['main-container-background', $q.dark.isActive ? '--dark' : '--light']">
|
||||||
|
<div class="nav-container row"><slot name="header" /></div>
|
||||||
|
<slot name="calendar" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.main-container-background {
|
||||||
|
&.--dark {
|
||||||
|
background-color: var(--calendar-background-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.--light {
|
||||||
|
background-color: var(--calendar-background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,6 @@
|
||||||
// app global css in SCSS form
|
// app global css in SCSS form
|
||||||
@import './icons.scss';
|
@import './icons.scss';
|
||||||
|
@import '@quasar/quasar-ui-qcalendar/src/QCalendarMonth.sass';
|
||||||
|
|
||||||
body.body--light {
|
body.body--light {
|
||||||
--fount-color: black;
|
--fount-color: black;
|
||||||
|
@ -120,3 +121,14 @@ input::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clases para modificar el color de fecha seleccionada en componente QCalendarMonth
|
||||||
|
.q-dark div .q-calendar-mini .q-calendar-month__day.q-selected .q-calendar__button {
|
||||||
|
background-color: $primary !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-calendar-mini .q-calendar-month__day.q-selected .q-calendar__button {
|
||||||
|
background-color: $primary !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
|
@ -1225,4 +1225,27 @@ export default {
|
||||||
},
|
},
|
||||||
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789',
|
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789',
|
||||||
},
|
},
|
||||||
|
weekdays: {
|
||||||
|
sun: 'Sunday',
|
||||||
|
mon: 'Monday',
|
||||||
|
tue: 'Tuesday',
|
||||||
|
wed: 'Wednesday',
|
||||||
|
thu: 'Thursday',
|
||||||
|
fri: 'Friday',
|
||||||
|
sat: 'Saturday',
|
||||||
|
},
|
||||||
|
months: {
|
||||||
|
jan: 'January',
|
||||||
|
feb: 'February',
|
||||||
|
mar: 'March',
|
||||||
|
apr: 'April',
|
||||||
|
may: 'May',
|
||||||
|
jun: 'June',
|
||||||
|
jul: 'July',
|
||||||
|
aug: 'August',
|
||||||
|
sep: 'September',
|
||||||
|
oct: 'October',
|
||||||
|
nov: 'November',
|
||||||
|
dec: 'December',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1225,4 +1225,27 @@ export default {
|
||||||
},
|
},
|
||||||
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789',
|
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789',
|
||||||
},
|
},
|
||||||
|
weekdays: {
|
||||||
|
sun: 'Domingo',
|
||||||
|
mon: 'Lunes',
|
||||||
|
tue: 'Martes',
|
||||||
|
wed: 'Miércoles',
|
||||||
|
thu: 'Jueves',
|
||||||
|
fri: 'Viernes',
|
||||||
|
sat: 'Sábado',
|
||||||
|
},
|
||||||
|
months: {
|
||||||
|
jan: 'Enero',
|
||||||
|
feb: 'Febrero',
|
||||||
|
mar: 'Marzo',
|
||||||
|
apr: 'Abril',
|
||||||
|
may: 'Mayo',
|
||||||
|
jun: 'Junio',
|
||||||
|
jul: 'Julio',
|
||||||
|
aug: 'Agosto',
|
||||||
|
sep: 'Septiembre',
|
||||||
|
oct: 'Octubre',
|
||||||
|
nov: 'Noviembre',
|
||||||
|
dec: 'Diciembre',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,26 +1,35 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue';
|
import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue';
|
import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue';
|
||||||
|
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const workerCalendarFilterRef = ref(null);
|
||||||
|
const workerCalendarRef = ref(null);
|
||||||
const businessFk = ref(null);
|
const businessFk = ref(null);
|
||||||
const absenceType = ref(null);
|
const absenceType = ref(null);
|
||||||
const hasWorkCenter = ref(false);
|
const hasWorkCenter = ref(false);
|
||||||
const isSubordinate = ref(false);
|
const isSubordinate = ref(false);
|
||||||
const year = ref(Date.vnNew().getFullYear());
|
const year = ref(Date.vnNew().getFullYear());
|
||||||
|
const events = ref({});
|
||||||
|
|
||||||
const onFetchActiveContract = (data) => {
|
const onFetchActiveContract = (data) => {
|
||||||
businessFk.value = data?.businessFk;
|
businessFk.value = data?.businessFk;
|
||||||
hasWorkCenter.value = Boolean(data?.workCenterFk);
|
hasWorkCenter.value = Boolean(data?.workCenterFk);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onEventsUpdated = (ev) => (events.value = ev);
|
||||||
|
|
||||||
|
const onHandleRefresh = () => workerCalendarFilterRef.value.refreshData();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -35,7 +44,7 @@ const onFetchActiveContract = (data) => {
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<template v-if="stateStore.isHeaderMounted()">
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
<Teleport to="#actions-append">
|
<!-- <Teleport to="#actions-append">
|
||||||
<div class="row q-gutter-x-sm">
|
<div class="row q-gutter-x-sm">
|
||||||
<QBtn
|
<QBtn
|
||||||
flat
|
flat
|
||||||
|
@ -49,14 +58,16 @@ const onFetchActiveContract = (data) => {
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</div>
|
</div>
|
||||||
</Teleport>
|
</Teleport> -->
|
||||||
</template>
|
</template>
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<QScrollArea class="fit text-grey-8">
|
<QScrollArea class="fit text-grey-8">
|
||||||
<WorkerCalendarFilter
|
<WorkerCalendarFilter
|
||||||
|
ref="workerCalendarFilterRef"
|
||||||
v-model:business-fk="businessFk"
|
v-model:business-fk="businessFk"
|
||||||
v-model:year="year"
|
v-model:year="year"
|
||||||
v-model:absence-type="absenceType"
|
v-model:absence-type="absenceType"
|
||||||
|
@update-events="onEventsUpdated"
|
||||||
/>
|
/>
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
|
@ -66,15 +77,39 @@ const onFetchActiveContract = (data) => {
|
||||||
{{ t('Autonomous worker') }}
|
{{ t('Autonomous worker') }}
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="full-width">
|
<QCard v-else class="full-width q-pa-xl">
|
||||||
<QCardSection class="calendar-container">
|
<QIcon
|
||||||
<div v-for="month in 12" :key="month" class="full-width full-height">
|
v-if="isSubordinate"
|
||||||
<WorkerCalendarItem class="full-width" :year="year" :month="month" />
|
name="info"
|
||||||
</div>
|
size="sm"
|
||||||
</QCardSection>
|
class="absolute"
|
||||||
|
style="top: 16px; right: 16px"
|
||||||
|
>
|
||||||
|
<QTooltip max-width="250px">
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
'To start adding absences, click an absence type from the right menu and then on the day you want to add an absence'
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
<div class="calendar-container">
|
||||||
|
<WorkerCalendarItem
|
||||||
|
ref="workerCalendarRef"
|
||||||
|
v-for="month in 12"
|
||||||
|
:key="month"
|
||||||
|
:year="year"
|
||||||
|
:month="month"
|
||||||
|
:absence-type="absenceType"
|
||||||
|
:business-fk="businessFk"
|
||||||
|
:events="events"
|
||||||
|
@refresh="onHandleRefresh"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</QCard>
|
</QCard>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.calendar-container {
|
.calendar-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -88,19 +123,16 @@ const onFetchActiveContract = (data) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $breakpoint-sm) {
|
@media (max-width: $breakpoint-xs) {
|
||||||
.calendar-container {
|
.calendar-container {
|
||||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-item {
|
|
||||||
max-width: 324px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Search worker: Buscar trabajador
|
Search worker: Buscar trabajador
|
||||||
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
||||||
|
To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import FetchData from 'components/FetchData.vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnSelectFilter from 'components/common/VnSelectFilter.vue';
|
import VnSelectFilter from 'components/common/VnSelectFilter.vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch, reactive } from 'vue';
|
||||||
import { toDateFormat } from '../../../filters/date';
|
import { toDateFormat } from '../../../filters/date';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
@ -26,7 +26,12 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:businessFk', 'update:year', 'update:absenceType']);
|
const emit = defineEmits([
|
||||||
|
'update:businessFk',
|
||||||
|
'update:year',
|
||||||
|
'update:absenceType',
|
||||||
|
'updateEvents',
|
||||||
|
]);
|
||||||
|
|
||||||
const selectedBusinessFk = computed({
|
const selectedBusinessFk = computed({
|
||||||
get: () => props.businessFk,
|
get: () => props.businessFk,
|
||||||
|
@ -35,13 +40,18 @@ const selectedBusinessFk = computed({
|
||||||
emit('update:businessFk', value);
|
emit('update:businessFk', value);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedYear = computed({
|
const selectedYear = computed({
|
||||||
get: () => props.year,
|
get: () => props.year,
|
||||||
set: (value) => emit('update:year', value),
|
set: (value) => emit('update:year', value),
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedAbsenceType = computed({
|
const selectedAbsenceType = computed({
|
||||||
get: () => props.absenceType,
|
get: () => props.absenceType,
|
||||||
set: (value) => emit('update:absenceType', value),
|
set: (value) => {
|
||||||
|
if (value === props.absenceType) value = null;
|
||||||
|
emit('update:absenceType', value);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const generateYears = () => {
|
const generateYears = () => {
|
||||||
|
@ -57,11 +67,19 @@ const yearList = ref(generateYears());
|
||||||
|
|
||||||
const contractHolidays = ref(null);
|
const contractHolidays = ref(null);
|
||||||
const yearHolidays = ref(null);
|
const yearHolidays = ref(null);
|
||||||
|
const events = reactive({});
|
||||||
|
const calendar = ref(null);
|
||||||
|
|
||||||
const getHolidays = async (params) => {
|
const getHolidays = async (params) => {
|
||||||
return axios
|
try {
|
||||||
.get(`Workers/${route.params.id}/holidays`, { params })
|
const { data } = await axios.get(`Workers/${route.params.id}/holidays`, {
|
||||||
.then((res) => res.data);
|
params,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching holidays:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateContractHolidays = async () => {
|
const updateContractHolidays = async () => {
|
||||||
|
@ -75,14 +93,80 @@ const updateYearHolidays = async () => {
|
||||||
yearHolidays.value = await getHolidays({ year: selectedYear.value });
|
yearHolidays.value = await getHolidays({ year: selectedYear.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(selectedYear, () => {
|
const getAbsences = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
workerFk: route.params.id,
|
||||||
|
businessFk: props.businessFk,
|
||||||
|
year: props.year,
|
||||||
|
};
|
||||||
|
const { data } = await axios.get('Calendars/absences', { params });
|
||||||
|
if (data) onAbsencesFetched(data);
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching absences:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshData = () => {
|
||||||
updateYearHolidays();
|
updateYearHolidays();
|
||||||
updateContractHolidays();
|
updateContractHolidays();
|
||||||
|
getAbsences();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAbsencesFetched = (data) => {
|
||||||
|
calendar.value = data.calendar;
|
||||||
|
|
||||||
|
let addEvent = (day, newEvent) => {
|
||||||
|
const timestamp = new Date(day).getTime();
|
||||||
|
let event = events[timestamp];
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
const oldName = event.name;
|
||||||
|
Object.assign(event, newEvent);
|
||||||
|
event.name = `${oldName}, ${event.name}`;
|
||||||
|
} else events[timestamp] = newEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data.holidays) {
|
||||||
|
data.holidays.forEach((holiday) => {
|
||||||
|
const holidayDetail = holiday.detail && holiday.detail.name;
|
||||||
|
const holidayType = holiday.type && holiday.type.name;
|
||||||
|
const holidayName = holidayDetail || holidayType;
|
||||||
|
|
||||||
|
addEvent(holiday.dated, {
|
||||||
|
name: holidayName,
|
||||||
|
className: 'festive',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.absences) {
|
||||||
|
data.absences.forEach((absence) => {
|
||||||
|
let type = absence.absenceType;
|
||||||
|
addEvent(absence.dated, {
|
||||||
|
name: type.name,
|
||||||
|
color: type.rgb,
|
||||||
|
type: type.code,
|
||||||
|
absenceId: absence.id,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('updateEvents', events);
|
||||||
|
console.log('events:: ', events);
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(selectedYear, () => {
|
||||||
|
refreshData();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(selectedBusinessFk, () => {
|
watch(selectedBusinessFk, () => {
|
||||||
updateYearHolidays();
|
refreshData();
|
||||||
updateContractHolidays();
|
});
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
refreshData,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount, ref, watch } from 'vue';
|
import { onBeforeMount, ref, watch } from 'vue';
|
||||||
import { QCalendarMonth, today } from '@quasar/quasar-ui-qcalendar/src/index.js';
|
|
||||||
import '@quasar/quasar-ui-qcalendar/src/QCalendarVariables.sass';
|
|
||||||
import '@quasar/quasar-ui-qcalendar/src/QCalendarTransitions.sass';
|
|
||||||
import '@quasar/quasar-ui-qcalendar/src/QCalendarMonth.sass';
|
|
||||||
import { date } from 'quasar';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { date } from 'quasar';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
|
||||||
|
import { QCalendarMonth } from '@quasar/quasar-ui-qcalendar/src/index.js';
|
||||||
|
import '@quasar/quasar-ui-qcalendar/src/QCalendarVariables.sass';
|
||||||
|
import '@quasar/quasar-ui-qcalendar/src/QCalendarMonth.sass';
|
||||||
|
|
||||||
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
year: {
|
year: {
|
||||||
|
@ -16,41 +22,181 @@ const props = defineProps({
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
absenceType: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
businessFk: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { notify } = useNotify();
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
|
|
||||||
const calendarRef = ref(null);
|
const calendarRef = ref(null);
|
||||||
const selectedDate = ref(today());
|
const weekdayStore = useWeekdayStore();
|
||||||
|
const selectedDate = ref(null);
|
||||||
|
const calendarEventDates = [];
|
||||||
|
|
||||||
const updateSelectedDate = (year) => {
|
const updateSelectedDate = (year) => {
|
||||||
const dateObject = Date.vnNew();
|
const _date = new Date(year, props.month - 1, 1);
|
||||||
dateObject.setFullYear(year);
|
selectedDate.value = date.formatDate(_date, 'YYYY-MM-DD');
|
||||||
dateObject.setMonth(props.month - 1);
|
};
|
||||||
selectedDate.value = date.formatDate(dateObject, 'YYYY-MM-DD');
|
|
||||||
console.log(date.formatDate(dateObject, 'YYYY-MM-DD'));
|
const createEvent = async (date) => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
dated: date,
|
||||||
|
absenceTypeId: props.absenceType,
|
||||||
|
businessFk: props.businessFk,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await axios.post(
|
||||||
|
`Workers/${route.params.id}/createAbsence`,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
console.log('data:: ', data);
|
||||||
|
// TODO: Agregar notify success
|
||||||
|
emit('refresh');
|
||||||
|
} catch (error) {
|
||||||
|
console.log('error creating event:: ', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const editEvent = async (event) => {
|
||||||
|
console.log('editEvent');
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteEvent = async (date, event) => {
|
||||||
|
console.log('deleteEvent');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDateSelected = (date) => {
|
||||||
|
if (!props.absenceType) {
|
||||||
|
notify(t('Choose an absence type from the right menu'), 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { year, month, day } = date.scope.timestamp;
|
||||||
|
const _date = new Date(year, month - 1, day);
|
||||||
|
const stamp = _date.getTime();
|
||||||
|
const event = props.events[stamp];
|
||||||
|
|
||||||
|
if (event && event.absenceId) {
|
||||||
|
if (event.type == props.absenceType.code) deleteEvent(_date, event);
|
||||||
|
else editEvent(event);
|
||||||
|
} else createEvent(_date);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEventByTimestamp = ({ year, month, day }) => {
|
||||||
|
const stamp = date.formatDate(new Date(year, month - 1, day), 'x');
|
||||||
|
return props.events[stamp] || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEventAttrs = (timestamp) => {
|
||||||
|
const event = getEventByTimestamp(timestamp);
|
||||||
|
if (!event) return '';
|
||||||
|
|
||||||
|
const { name, color } = event;
|
||||||
|
return {
|
||||||
|
title: name,
|
||||||
|
style: `background-color: ${color};`,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
updateSelectedDate(props.year);
|
updateSelectedDate(props.year);
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(props.year, (newValue) => {
|
||||||
() => props.year,
|
updateSelectedDate(newValue);
|
||||||
(newValue) => {
|
});
|
||||||
updateSelectedDate(newValue);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QCalendarMonth
|
<QCalendarMonthWrapper style="height: 200px">
|
||||||
ref="calendarRef"
|
<template #header>
|
||||||
v-model="selectedDate"
|
<span class="full-width text-center text-body1 q-py-sm">{{
|
||||||
show-work-weeks
|
weekdayStore.getLocaleMonths[$props.month - 1].locale
|
||||||
no-outside-days
|
}}</span>
|
||||||
:selected-dates="[]"
|
</template>
|
||||||
:disabled-weekdays="[0, 6]"
|
<template #calendar>
|
||||||
:locale="locale"
|
<QCalendarMonth
|
||||||
animated
|
ref="calendarRef"
|
||||||
mini-mode
|
v-model="selectedDate"
|
||||||
/>
|
@click-date="handleDateSelected"
|
||||||
|
show-work-weeks
|
||||||
|
no-outside-days
|
||||||
|
:selected-dates="calendarEventDates"
|
||||||
|
no-active-date
|
||||||
|
:weekdays="[1, 2, 3, 4, 5, 6, 0]"
|
||||||
|
:disabled-weekdays="[0, 6]"
|
||||||
|
:locale="locale"
|
||||||
|
mini-mode
|
||||||
|
>
|
||||||
|
<template #day="{ scope: { timestamp } }">
|
||||||
|
<QButton
|
||||||
|
v-if="getEventByTimestamp(timestamp)"
|
||||||
|
v-bind="{ ...getEventAttrs(timestamp) }"
|
||||||
|
class="calendar-event"
|
||||||
|
>
|
||||||
|
{{ timestamp.day }}
|
||||||
|
</QButton>
|
||||||
|
</template>
|
||||||
|
</QCalendarMonth>
|
||||||
|
</template>
|
||||||
|
</QCalendarMonthWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.q-calendar__button {
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--vn-accent-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-calendar-month__day--content {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-outside .calendar-event {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-event {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
font-size: 0.75em;
|
||||||
|
line-height: 1.715em;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
import { reactive, ref, computed } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
export const useWeekdayStore = defineStore('weekdayStore', () => {
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const weekdays = [
|
||||||
|
{ code: 'sun', name: 'Sunday' },
|
||||||
|
{ code: 'mon', name: 'Monday' },
|
||||||
|
{ code: 'tue', name: 'Tuesday' },
|
||||||
|
{ code: 'wed', name: 'Wednesday' },
|
||||||
|
{ code: 'thu', name: 'Thursday' },
|
||||||
|
{ code: 'fri', name: 'Friday' },
|
||||||
|
{ code: 'sat', name: 'Saturday' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const monthCodes = [
|
||||||
|
'jan',
|
||||||
|
'feb',
|
||||||
|
'mar',
|
||||||
|
'apr',
|
||||||
|
'may',
|
||||||
|
'jun',
|
||||||
|
'jul',
|
||||||
|
'aug',
|
||||||
|
'sep',
|
||||||
|
'oct',
|
||||||
|
'nov',
|
||||||
|
'dec',
|
||||||
|
];
|
||||||
|
|
||||||
|
const localeOrder = {
|
||||||
|
es: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'],
|
||||||
|
en: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const weekdaysMap = reactive({});
|
||||||
|
const localeWeekdays = ref([]);
|
||||||
|
|
||||||
|
const initStore = () => {
|
||||||
|
getWeekdaysMap();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getWeekdaysMap = () => {
|
||||||
|
if (Object.keys(weekdaysMap).length > 0) return weekdaysMap;
|
||||||
|
|
||||||
|
weekdays.forEach((day, i) => {
|
||||||
|
const obj = {
|
||||||
|
...day,
|
||||||
|
index: i,
|
||||||
|
char: day.name.substr(0, 1),
|
||||||
|
abr: day.name.substr(0, 3),
|
||||||
|
};
|
||||||
|
weekdaysMap[day.code] = obj;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLocales = computed(() => {
|
||||||
|
// El día de mañana esto permitirá ordenar los weekdays en base a el locale si se lo desea reemplazando localeOrder.es por localeOrder[locale]
|
||||||
|
const locales = [];
|
||||||
|
for (let code of localeOrder.es) {
|
||||||
|
const obj = {
|
||||||
|
...weekdaysMap[code],
|
||||||
|
locale: t(`weekdays.${weekdaysMap[code].code}`),
|
||||||
|
localeChar: t(`weekdays.${weekdaysMap[code].code}`).substr(0, 1),
|
||||||
|
localeAbr: t(`weekdays.${weekdaysMap[code].code}`).substr(0, 3),
|
||||||
|
};
|
||||||
|
locales.push(obj);
|
||||||
|
}
|
||||||
|
return locales;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getLocaleMonths = computed(() => {
|
||||||
|
const locales = [];
|
||||||
|
for (let code of monthCodes) {
|
||||||
|
const obj = {
|
||||||
|
code: code,
|
||||||
|
locale: t(`months.${code}`),
|
||||||
|
};
|
||||||
|
locales.push(obj);
|
||||||
|
}
|
||||||
|
return locales;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
initStore,
|
||||||
|
weekdaysMap,
|
||||||
|
localeWeekdays,
|
||||||
|
getLocales,
|
||||||
|
weekdays,
|
||||||
|
monthCodes,
|
||||||
|
getLocaleMonths,
|
||||||
|
};
|
||||||
|
});
|
Loading…
Reference in New Issue