0
0
Fork 0

Last changes

This commit is contained in:
William Buezas 2024-04-06 14:10:08 -03:00
parent dae08c322d
commit 4b6038d1d2
4 changed files with 147 additions and 69 deletions

View File

@ -23,7 +23,8 @@ const businessFk = ref(null);
const year = ref(Date.vnNew().getFullYear()); const year = ref(Date.vnNew().getFullYear());
const contractHolidays = ref(null); const contractHolidays = ref(null);
const yearHolidays = ref(null); const yearHolidays = ref(null);
const events = ref({}); const eventsMap = ref({});
const festiveEventsMap = ref({});
const onFetchActiveContract = (data) => { const onFetchActiveContract = (data) => {
if (!data) return; if (!data) return;
@ -31,21 +32,27 @@ const onFetchActiveContract = (data) => {
hasWorkCenter.value = Boolean(data?.workCenterFk); hasWorkCenter.value = Boolean(data?.workCenterFk);
}; };
const addEvent = (day, newEvent) => { const addEvent = (day, newEvent, isFestive = false) => {
const timestamp = new Date(day).getTime(); const timestamp = new Date(day).getTime();
let event = events.value[timestamp]; let event = eventsMap.value[timestamp];
if (event) { if (!event) {
eventsMap.value[timestamp] = newEvent;
if (isFestive)
festiveEventsMap.value[timestamp] = JSON.parse(JSON.stringify(newEvent));
} else {
const oldName = event.name; const oldName = event.name;
const oldEventWasFestive = event.isFestive;
Object.assign(event, newEvent); Object.assign(event, newEvent);
event.isFestive = oldEventWasFestive;
event.name = `${oldName}, ${event.name}`; event.name = `${oldName}, ${event.name}`;
} else events.value[timestamp] = newEvent; }
}; };
const onFetchAbsences = (data) => { const onFetchAbsences = (data) => {
if (!data) return; if (!data) return;
events.value = {}; eventsMap.value = {};
if (data.holidays) { if (data.holidays) {
data.holidays.forEach((holiday) => { data.holidays.forEach((holiday) => {
@ -53,10 +60,14 @@ const onFetchAbsences = (data) => {
const holidayType = holiday.type && holiday.type.name; const holidayType = holiday.type && holiday.type.name;
const holidayName = holidayDetail || holidayType; const holidayName = holidayDetail || holidayType;
addEvent(holiday.dated, { addEvent(
name: holidayName, holiday.dated,
className: 'festive', {
}); name: holidayName,
isFestive: true,
},
true
);
}); });
} }
if (data.absences) { if (data.absences) {
@ -67,10 +78,10 @@ const onFetchAbsences = (data) => {
color: type.rgb, color: type.rgb,
type: type.code, type: type.code,
absenceId: absence.id, absenceId: absence.id,
isFestive: false,
}); });
}); });
} }
console.log('events:: ', events.value);
}; };
const getAbsences = async () => { const getAbsences = async () => {
@ -120,7 +131,10 @@ const refreshData = () => {
}; };
const onDeletedEvent = (timestamp) => { const onDeletedEvent = (timestamp) => {
delete events.value[timestamp]; delete eventsMap.value[timestamp];
// Si el evento que eliminamos se encontraba dentro de un dia festivo, volvemos a agregar el evento festivo
if (festiveEventsMap.value[timestamp])
eventsMap.value[timestamp] = festiveEventsMap.value[timestamp];
}; };
watch([year, businessFk], () => refreshData()); watch([year, businessFk], () => refreshData());
@ -161,6 +175,8 @@ watch([year, businessFk], () => refreshData());
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"
:contract-holidays="contractHolidays"
:year-holidays="yearHolidays"
/> />
</QScrollArea> </QScrollArea>
</QDrawer> </QDrawer>
@ -195,7 +211,7 @@ watch([year, businessFk], () => refreshData());
:month="month" :month="month"
:absence-type="absenceType" :absence-type="absenceType"
:business-fk="businessFk" :business-fk="businessFk"
:events="events" :events="eventsMap"
@refresh="refreshData" @refresh="refreshData"
@on-deleted-event="onDeletedEvent" @on-deleted-event="onDeletedEvent"
/> />

View File

@ -20,7 +20,15 @@ const props = defineProps({
default: null, default: null,
}, },
absenceType: { absenceType: {
type: Number, type: Object,
default: null,
},
contractHolidays: {
type: Object,
default: null,
},
yearHolidays: {
type: Object,
default: null, default: null,
}, },
}); });
@ -29,10 +37,7 @@ const emit = defineEmits(['update:businessFk', 'update:year', 'update:absenceTyp
const selectedBusinessFk = computed({ const selectedBusinessFk = computed({
get: () => props.businessFk, get: () => props.businessFk,
set: (value) => { set: (value) => emit('update:businessFk', value),
console.log('businessFk', value);
emit('update:businessFk', value);
},
}); });
const selectedYear = computed({ const selectedYear = computed({
@ -76,42 +81,61 @@ const yearList = ref(generateYears());
@on-fetch="(data) => (contractList = data)" @on-fetch="(data) => (contractList = data)"
auto-load auto-load
/> />
<QItem v-if="contractHolidays" class="q-py-md">
<QItemSection class="text-center"> <div
<p class="holiday-title q-mb-sm"> v-if="contractHolidays"
class="q-pa-md q-mb-md q-ma-md color-vn-text"
style="border: 2px solid black"
>
<QCardSection horizontal>
<span class="text-weight-bold text-subtitle1 text-center full-width">
{{ t('Contract') }} #{{ selectedBusinessFk }} {{ t('Contract') }} #{{ selectedBusinessFk }}
</p> </span>
<div> </QCardSection>
<QCardSection class="column items-center" horizontal>
<span>
{{ t('Used') }} {{ contractHolidays.holidaysEnjoyed || 0 }} {{ t('of') }} {{ t('Used') }} {{ contractHolidays.holidaysEnjoyed || 0 }} {{ t('of') }}
{{ contractHolidays.totalHolidays || 0 }} {{ contractHolidays.totalHolidays || 0 }}
{{ t('days') }} {{ t('days') }}
</div> </span>
<div> </QCardSection>
<QCardSection class="column items-center" horizontal>
<span>
{{ t('Spent') }} {{ contractHolidays.hoursEnjoyed || 0 }} {{ t('of') }} {{ t('Spent') }} {{ contractHolidays.hoursEnjoyed || 0 }} {{ t('of') }}
{{ contractHolidays.totalHours || 0 }} {{ t('hours') }} {{ contractHolidays.totalHours || 0 }} {{ t('hours') }}
</div> </span>
<div> </QCardSection>
<QCardSection class="column items-center" horizontal>
<span>
{{ t('Paid holidays') }} {{ t('Paid holidays') }}
{{ contractHolidays.payedHolidays || 0 }} {{ contractHolidays.payedHolidays || 0 }}
{{ t('days') }} {{ t('days') }}
</div> </span>
</QItemSection> </QCardSection>
</QItem> </div>
<QSeparator /> <div
<QItem v-if="yearHolidays" class="q-py-md"> v-if="contractHolidays"
<QItemSection class="text-center"> class="q-pa-md q-mb-md q-ma-md color-vn-text"
<p class="holiday-title q-mb-sm">{{ t('Year') }} {{ selectedYear }}</p> style="border: 2px solid black"
<div> >
<QCardSection horizontal>
<span class="text-weight-bold text-subtitle1 text-center full-width">
{{ t('Year') }} {{ selectedYear }}
</span>
</QCardSection>
<QCardSection class="column items-center" horizontal>
<span>
{{ t('Used') }} {{ yearHolidays.holidaysEnjoyed || 0 }} {{ t('of') }} {{ t('Used') }} {{ yearHolidays.holidaysEnjoyed || 0 }} {{ t('of') }}
{{ yearHolidays.totalHolidays || 0 }} {{ t('days') }} {{ yearHolidays.totalHolidays || 0 }} {{ t('days') }}
</div> </span>
<div> </QCardSection>
<QCardSection class="column items-center" horizontal>
<span>
{{ t('Spent') }} {{ yearHolidays.hoursEnjoyed || 0 }} {{ t('of') }} {{ t('Spent') }} {{ yearHolidays.hoursEnjoyed || 0 }} {{ t('of') }}
{{ yearHolidays.totalHours || 0 }} {{ t('hours') }} {{ yearHolidays.totalHours || 0 }} {{ t('hours') }}
</div> </span>
</QItemSection> </QCardSection>
</QItem> </div>
<QSeparator />
<QList dense class="list q-gutter-y-sm q-my-lg"> <QList dense class="list q-gutter-y-sm q-my-lg">
<QItem> <QItem>
<QItemSection> <QItemSection>
@ -172,17 +196,18 @@ const yearList = ref(generateYears());
</QItem> </QItem>
</QList> </QList>
<QSeparator /> <QSeparator />
<QList dense class="list q-my-lg"> <QList dense class="list q-my-lg no-pointer-events">
<QItem> <QItem>
<WorkerDateLabel avatar-class="worker-calendar-festive"> <WorkerDateLabel avatar-class="worker-calendar-festive">
Festive {{ t('Festive') }}
</WorkerDateLabel> </WorkerDateLabel>
<WorkerDateLabel avatar-class="worker-calendar-today"> <WorkerDateLabel avatar-class="worker-calendar-today">
Current day {{ t('Current day') }}
</WorkerDateLabel> </WorkerDateLabel>
</QItem> </QItem>
</QList> </QList>
</template> </template>
<style lang="scss"> <style lang="scss">
.worker-calendar-festive { .worker-calendar-festive {
border: 2px solid $negative; border: 2px solid $negative;
@ -192,12 +217,6 @@ const yearList = ref(generateYears());
border: 2px solid $info; border: 2px solid $info;
} }
</style> </style>
<style lang="scss" scoped>
.holiday-title {
font-size: 16px;
font-weight: bold;
}
</style>
<i18n> <i18n>
es: es:

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { onBeforeMount, ref, watch } from 'vue'; import { onBeforeMount, ref, watch, 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 { useRoute } from 'vue-router';
@ -48,6 +48,12 @@ const weekdayStore = useWeekdayStore();
const selectedDate = ref(); const selectedDate = ref();
const calendarEventDates = []; const calendarEventDates = [];
const today = ref(date.formatDate(Date.vnNew(), 'YYYY-MM-DD')); const today = ref(date.formatDate(Date.vnNew(), 'YYYY-MM-DD'));
const todayTimestamp = computed(() => {
const date = Date.vnNew();
date.setHours(0, 0, 0, 0);
return date.getTime();
});
const _year = computed(() => props.year);
const updateSelectedDate = (year) => { const updateSelectedDate = (year) => {
const _date = new Date(year, props.month - 1, 1); const _date = new Date(year, props.month - 1, 1);
@ -67,10 +73,9 @@ const createEvent = async (date) => {
params params
); );
console.log('CREATE data:: ', data);
if (data) emit('refresh'); if (data) emit('refresh');
} catch (error) { } catch (error) {
console.log('error creating event:: ', error); console.error('error creating event:: ', error);
} }
}; };
@ -88,12 +93,11 @@ const editEvent = async (event) => {
if (data) emit('refresh'); if (data) emit('refresh');
} catch (error) { } catch (error) {
console.log('error editing event:: ', error); console.error('error editing event:: ', error);
} }
}; };
const deleteEvent = async (event, date) => { const deleteEvent = async (event, date) => {
console.log('deleteEvent:: ', event);
const params = { absenceId: event.absenceId }; const params = { absenceId: event.absenceId };
const { data } = await axios.delete(`Workers/${route.params.id}/deleteAbsence`, { const { data } = await axios.delete(`Workers/${route.params.id}/deleteAbsence`, {
params, params,
@ -117,8 +121,14 @@ const handleDateSelected = (date) => {
}; };
const handleEventSelected = (event, { year, month, day }) => { const handleEventSelected = (event, { year, month, day }) => {
if (!props.absenceType) {
notify(t('Choose an absence type from the right menu'), 'warning');
return;
}
const date = new Date(year, month - 1, day); const date = new Date(year, month - 1, day);
if (event.type == props.absenceType.code) deleteEvent(event, date); if (!event.absenceId) createEvent(date);
else if (event.type == props.absenceType.code) deleteEvent(event, date);
else editEvent(event); else editEvent(event);
}; };
@ -131,20 +141,34 @@ const getEventAttrs = (timestamp) => {
const event = getEventByTimestamp(timestamp); const event = getEventByTimestamp(timestamp);
if (!event) return {}; if (!event) return {};
const { name, color } = event; const { name, color, isFestive } = event;
// Atributos a asignar a cada slot que representa un evento en el calendario // Atributos a asignar a cada slot que representa un evento en el calendario
return {
const attrs = {
title: name, title: name,
style: `background-color: ${color};`, style: color ? `background-color: ${color};` : '',
label: timestamp.day,
}; };
if (isFestive) {
attrs.class = '--festive';
attrs.label = event.absenceId ? timestamp.day : '';
}
return attrs;
};
const isToday = (timestamp) => {
const { year, month, day } = timestamp;
return todayTimestamp.value === new Date(year, month - 1, day).getTime();
}; };
onBeforeMount(() => { onBeforeMount(() => {
updateSelectedDate(props.year); updateSelectedDate(_year.value);
}); });
watch(props.year, (newValue) => { watch(_year, (newValue) => {
updateSelectedDate(newValue); updateSelectedDate(newValue);
}); });
</script> </script>
@ -173,16 +197,20 @@ watch(props.year, (newValue) => {
> >
<template #day="{ scope: { timestamp } }"> <template #day="{ scope: { timestamp } }">
<!-- Este slot representa cada día del calendario y muestra un botón representando el correspondiente evento --> <!-- Este slot representa cada día del calendario y muestra un botón representando el correspondiente evento -->
<QButton <QBtn
v-if="getEventByTimestamp(timestamp)" v-if="getEventByTimestamp(timestamp)"
v-bind="{ ...getEventAttrs(timestamp) }" v-bind="{ ...getEventAttrs(timestamp) }"
@click=" @click="
handleEventSelected(getEventByTimestamp(timestamp), timestamp) handleEventSelected(getEventByTimestamp(timestamp), timestamp)
" "
rounded
dense
flat
class="calendar-event" class="calendar-event"
> :class="{
{{ timestamp.day }} '--today': isToday(timestamp),
</QButton> }"
/>
</template> </template>
</QCalendarMonth> </QCalendarMonth>
</template> </template>
@ -190,6 +218,11 @@ watch(props.year, (newValue) => {
</template> </template>
<style lang="scss"> <style lang="scss">
:root {
--calendar-border-current-dark: #84d0e2 2px solid;
--calendar-border-current: #84d0e2 2px solid;
}
.q-calendar__button { .q-calendar__button {
&:hover { &:hover {
background-color: var(--vn-accent-color); background-color: var(--vn-accent-color);
@ -197,6 +230,10 @@ watch(props.year, (newValue) => {
} }
} }
.q-calendar__button--bordered {
color: $info !important;
}
.q-calendar-month__day--content { .q-calendar-month__day--content {
position: absolute; position: absolute;
top: 1; top: 1;
@ -213,13 +250,20 @@ watch(props.year, (newValue) => {
.calendar-event { .calendar-event {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center;
width: 2em; width: 2em;
height: 2em; height: 2em;
font-size: 0.75em; font-size: 0.75em;
line-height: 1.715em; line-height: 1.715em;
border-radius: 50%;
cursor: pointer; cursor: pointer;
color: white;
&.--today {
border: 2px solid $info;
}
&.--festive {
border: 2px solid $negative;
}
&:hover { &:hover {
opacity: 0.8; opacity: 0.8;

View File

@ -18,7 +18,7 @@ defineEmits(['update:selected']);
<template> <template>
<QChip <QChip
class="chip glossy" class="chip"
:selected="selected" :selected="selected"
:style="selected ? { backgroundColor: color } : null" :style="selected ? { backgroundColor: color } : null"
@update:selected="$emit('update:selected', $event)" @update:selected="$emit('update:selected', $event)"
@ -26,7 +26,6 @@ defineEmits(['update:selected']);
<QAvatar <QAvatar
:color="color" :color="color"
:class="avatarClass" :class="avatarClass"
class="glossy"
:style="{ backgroundColor: color }" :style="{ backgroundColor: color }"
/> />
<slot /> <slot />