QCalendar implementation WIP
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
William Buezas 2024-03-26 15:38:06 -03:00
parent 5964189a83
commit 0a74b2a96e
7 changed files with 197 additions and 47 deletions

View File

@ -32,6 +32,7 @@
"@intlify/unplugin-vue-i18n": "^0.8.1",
"@pinia/testing": "^0.1.2",
"@quasar/app-vite": "^1.7.3",
"@quasar/quasar-app-extension-qcalendar": "4.0.0-beta.15",
"@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
"@vue/test-utils": "^2.4.4",
"autoprefixer": "^10.4.14",

View File

@ -49,6 +49,9 @@ devDependencies:
'@quasar/app-vite':
specifier: ^1.7.3
version: 1.7.3(eslint@8.56.0)(pinia@2.1.7)(quasar@2.14.5)(vue-router@4.2.5)(vue@3.4.19)
'@quasar/quasar-app-extension-qcalendar':
specifier: 4.0.0-beta.15
version: 4.0.0-beta.15
'@quasar/quasar-app-extension-testing-unit-vitest':
specifier: ^0.4.0
version: 0.4.0(@vue/test-utils@2.4.4)(quasar@2.14.5)(vite@5.1.4)(vitest@0.31.4)(vue@3.4.19)
@ -912,6 +915,13 @@ packages:
resolution: {integrity: sha512-SlOhwzXyPQHWgQIS2ncyDdYdksCJvUYNtgsDQqzAKEG3r3d/ejOxvThle79HTK3Q6HB+gQWFG21Ux00Osr5XSw==}
dev: false
/@quasar/quasar-app-extension-qcalendar@4.0.0-beta.15:
resolution: {integrity: sha512-i6hQkcP70LXLfVMPZMKQjSg3681gjZmASV3vq6ULzc0LhtBiPneLdVNNtH2itkWxAmaUj+1heQDI5Pa0F7VKLQ==}
engines: {node: '>= 10.0.0', npm: '>= 5.6.0', yarn: '>= 1.6.0'}
dependencies:
'@quasar/quasar-ui-qcalendar': 4.0.0-beta.16
dev: true
/@quasar/quasar-app-extension-testing-unit-vitest@0.4.0(@vue/test-utils@2.4.4)(quasar@2.14.5)(vite@5.1.4)(vitest@0.31.4)(vue@3.4.19):
resolution: {integrity: sha512-eyzdUdmZiCueNS+5nedjMmzdbpCetSrtdGIwW6KplW1dTzRbLiNvYUjpBOxQGmJCgEhWy9zuswJ7MZ/bTql24Q==}
engines: {node: '>= 12.22.1', npm: '>= 6.14.12', yarn: '>= 1.17.3'}
@ -939,6 +949,10 @@ packages:
- vite
dev: true
/@quasar/quasar-ui-qcalendar@4.0.0-beta.16:
resolution: {integrity: sha512-KVbFJD1HQp91tiklv+6XsG7bq8FKK6mhhnoVzmjgoyhUAEb9csfbDPbpegy1/FzXy3o0wITe6mmRZ8nbaiMEZg==}
dev: true
/@quasar/render-ssr-error@1.0.3:
resolution: {integrity: sha512-A8RF99q6/sOSe1Ighnh5syEIbliD3qUYEJd2HyfFyBPSMF+WYGXon5dmzg4nUoK662NgOggInevkDyBDJcZugg==}
engines: {node: '>= 16'}

View File

@ -3,5 +3,6 @@
"options": [
"scripts"
]
}
},
"@quasar/qcalendar": {}
}

View File

@ -0,0 +1,149 @@
<script setup>
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { QCalendarMonth } from '@quasar/quasar-ui-qcalendar/src/index.js';
import '@quasar/quasar-ui-qcalendar/src/QCalendarMonth.sass';
import { onMounted } from 'vue';
const $props = defineProps({
modelValue: {
type: String,
default: '',
},
selectedDates: {
type: Array,
default: () => [],
},
showNavigation: {
type: Boolean,
default: true,
},
activeDate: {
type: Boolean,
default: true,
},
workerTimeControlMails: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(['update:modelValue', 'clickDate']);
const { locale } = useI18n();
const calendarRef = ref(null);
const workerTimeControlMailsMap = computed(() => {
if (!$props.workerTimeControlMails || $props.workerTimeControlMails.length === 0)
return {};
const obj = {};
return obj;
});
const value = computed({
get: () => $props.modelValue,
set: (val) => emit('update:modelValue', val),
});
const formattedNavigationLabel = computed(() => {
const [year, month, day] = $props.modelValue.split('-');
const date = new Date(year, month - 1, day);
const _month = date.toLocaleString(locale, { month: 'long' });
return `${_month.charAt(0).toUpperCase() + _month.slice(1)} ${year}`;
});
const onPrev = () => {
calendarRef.value.prev();
};
const onNext = () => {
calendarRef.value.next();
};
const clickDate = (ev) => {
emit('clickDate', ev);
};
const workWeeks = ref(null);
onMounted(async () => {
workWeeks.value = document.getElementsByClassName('q-calendar-month__workweek');
setTimeout(() => {
const firstElement = workWeeks.value[0];
console.log('firstElement:: ', firstElement);
console.log('workWeeks:: ', workWeeks.value);
firstElement.style.backgroundColor = 'lightBlue';
firstElement.style.color = 'red';
}, 1);
});
</script>
<template>
<div :class="['main-container-background', $q.dark.isActive ? '--dark' : '--light']">
<div class="nav-container row">
<QIcon name="arrow_back_ios" class="nav-arrow col" @click="onPrev" />
<span class="col-6 text-no-wrap text-center text-subtitle1">{{
formattedNavigationLabel
}}</span>
<QIcon name="arrow_forward_ios" class="nav-arrow col" @click="onNext" />
</div>
<QCalendarMonth
ref="calendarRef"
show-work-weeks
:weekdays="[1, 2, 3, 4, 5, 6, 0]"
v-model="value"
:selected-dates="selectedDates"
:locale="locale"
mini-mode
enable-outside-days
no-active-date
@click-date="clickDate"
/>
<pre> {{ workerTimeControlMailsMap }}</pre>
</div>
</template>
<style lang="scss">
.main-container-background {
&.--dark {
background-color: var(--calendar-background-dark);
}
&.--light {
background-color: var(--calendar-background);
}
}
.confirmed {
color: #97b92f;
}
.revise {
color: #f61e1e;
}
.sended {
color: #d19b25;
}
.nav-container {
display: flex;
margin-bottom: 8px;
align-items: center;
}
.nav-arrow {
cursor: pointer;
user-select: none;
}
.q-calendar__button {
&:hover {
background-color: var(--vn-accent-color);
cursor: pointer;
}
}
</style>

View File

@ -26,11 +26,11 @@ export function isValidDate(date) {
* // returns "02/12/2022"
* toDateFormat(new Date(2022, 11, 2));
*/
export function toDateFormat(date) {
export function toDateFormat(date, locale = 'es-ES') {
if (!isValidDate(date)) {
return '';
}
return new Date(date).toLocaleDateString('es-ES', {
return new Date(date).toLocaleDateString(locale, {
year: 'numeric',
month: '2-digit',
day: '2-digit',

View File

@ -957,7 +957,7 @@ export default {
roadmap: 'Troncales',
summary: 'Resumen',
basicData: 'Datos básicos',
stops: 'Paradas'
stops: 'Paradas',
},
},
roadmap: {
@ -965,7 +965,7 @@ export default {
roadmap: 'Troncales',
summary: 'Resumen',
basicData: 'Datos básicos',
stops: 'Paradas'
stops: 'Paradas',
},
},
route: {

View File

@ -8,6 +8,7 @@ import WorkerTimeHourChip from 'components/WorkerTimeHourChip.vue';
import WorkerTimeForm from 'components/WorkerTimeForm.vue';
import WorkerTimeReasonForm from 'components/WorkerTimeReasonForm.vue';
import WorkerDateLabel from './WorkerDateLabel.vue';
import VnCalendarMonth from 'components/common/VnCalendarMonth.vue';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
@ -19,6 +20,7 @@ import { dashIfEmpty } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useArrayData } from 'composables/useArrayData';
import { toTimeFormat, secondsToHoursMinutes } from 'filters/date.js';
import toDateString from 'filters/toDateString.js';
const route = useRoute();
const { t, locale } = useI18n();
@ -34,10 +36,7 @@ const { openConfirmationModal } = useVnConfirm();
const workerTimeFormDialogRef = ref(null);
const workerTimeReasonFormDialogRef = ref(null);
const workerHoursRef = ref(null);
const calendarRef = ref(null);
const selectedDate = ref(null);
// Dates formateadas para bindear al componente QDate
const selectedCalendarDates = ref([]);
const startOfWeek = ref(null);
const endOfWeek = ref(null);
const selectedWeekNumber = ref(null);
@ -45,12 +44,17 @@ const state = ref(null);
const reason = ref(null);
const canResend = ref(null);
const weekTotalHours = ref(null);
const workerTimeControlMails = ref(null);
const workerTimeControlMails = ref([]);
const workerTimeFormProps = reactive({
dated: null,
formType: null,
});
// Array utilizado por QCalendar para seleccionar un rango de fechas
const selectedCalendarDates = ref([]);
// Date formateada para bindear al componente QDate
const selectedDateFormatted = ref(toDateString(Date.vnNew()));
const arrayData = useArrayData('workerData');
const worker = computed(() => arrayData.store?.data);
@ -84,17 +88,12 @@ const formattedWeekTotalHours = computed(() =>
secondsToHoursMinutes(weekTotalHours.value)
);
const defaultDate = computed(() => {
const date = Date.vnNew();
return `${date.getFullYear()}/${(date.getMonth() + 1).toString().padStart(2, '0')}`;
});
const onInputChange = async (date) => {
if (!date) return;
const onInputChange = async (dates, _, selectedDateDetails) => {
if (!dates.length || !selectedDateDetails) return;
const { year, month, day } = selectedDateDetails;
const date = new Date(year, month - 1, day);
setDate(date);
const { year, month, day } = date.scope.timestamp;
const _date = new Date(year, month - 1, day);
setDate(_date);
};
const setDate = async (date) => {
@ -134,19 +133,19 @@ const getEndOfWeek = (startOfWeek) => {
// Función para obtener las fechas de la semana seleccionada
const getWeekDates = (startOfWeek, endOfWeek) => {
selectedCalendarDates.value = []; // Limpiar las fechas seleccionadas previamente usadas por QDate
selectedCalendarDates.value = []; // Limpiar las fechas seleccionadas previamente usadas por QCalendar
weekDays.value = []; // Limpiar la información de las fechas seleccionadas previamente
let currentDate = new Date(startOfWeek);
while (currentDate <= endOfWeek) {
// Iterar sobre los días de la semana
selectedCalendarDates.value.push(formatDate(currentDate)); // Agregar fecha formateada para el array de fechas bindeado al componente QDate
selectedCalendarDates.value.push(formatDate(currentDate)); // Agregar fecha formateada para el array de fechas bindeado al componente QCalendar
weekDays.value.push({ dated: new Date(currentDate.getTime()) }); // Agregar el día de la semana al array información de días de la semana
currentDate = new Date(currentDate.setDate(currentDate.getDate() + 1)); // Avanzar al siguiente día
}
};
// Función para Convertir la fecha al formato que acepta el componente QDate: '2001-01-01'
// Función para Convertir la fecha al formato que acepta el componente QCalendar: '2001-01-01'
const formatDate = (date) => {
return date.toISOString().slice(0, 10);
};
@ -223,10 +222,6 @@ const getAbsences = async () => {
if (data) addEvents(data);
};
const hasEvents = (day) => {
return day >= startOfWeek.value && day < endOfWeek.value;
};
const addEvents = (data) => {
const events = {};
@ -278,6 +273,7 @@ const fetchWorkerTimeControlMails = async (filter) => {
params: { filter: JSON.stringify(filter) },
});
console.log('data:: ', data);
return data;
} catch (err) {
console.error('Error fetching worker time control mails');
@ -295,9 +291,9 @@ const fetchWeekData = async () => {
};
const data = await fetchWorkerTimeControlMails(filter);
if (!data.length) {
state.value = null;
return;
} else {
const [mail] = data;
state.value = mail.state;
@ -336,6 +332,7 @@ const setHours = (data) => {
} else weekDay.hours = null;
}
};
const getFinishTime = () => {
if (!weekDays.value || weekDays.value.length === 0) return;
@ -486,7 +483,7 @@ onMounted(async () => {
@click="showReasonForm()"
/>
<QBtn
v-if="isHr && state !== 'CONFIRMED' && canResend"
v-if="isHr && state && state !== 'CONFIRMED' && canResend"
:label="state ? t('Resend') : t('globals.send')"
color="primary"
type="submit"
@ -526,17 +523,12 @@ onMounted(async () => {
<span></span>
</QCardSection>
</div>
<QDate
ref="calendarRef"
:model-value="selectedCalendarDates"
@update:model-value="onInputChange"
mask="YYYY-MM-DD"
color="primary"
minimal
multiple
bordered
dense
:default-year-month="defaultDate"
<VnCalendarMonth
v-model:model-value="selectedDateFormatted"
:selected-dates="selectedCalendarDates"
:active-date="false"
:worker-time-control-mails="workerTimeControlMails"
@click-date="onInputChange"
/>
</QDrawer>
<QPage class="column items-center q-pa-md">
@ -622,7 +614,7 @@ onMounted(async () => {
</QPage>
</template>
<style lang="scss">
<style scoped lang="scss">
.column-title-container {
display: flex;
flex-direction: column;
@ -635,13 +627,6 @@ onMounted(async () => {
color: var(--vn-label);
}
.q-date,
.q-date__content,
.q-date__main {
max-width: 228px !important;
min-width: 228px !important;
}
.hour-chip {
margin-bottom: 16px;