WIP
This commit is contained in:
parent
d12fa85d73
commit
7ff8bc642e
|
@ -0,0 +1,123 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import axios from 'axios';
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
hour: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
direction: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onHourEntryDeleted']);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
|
||||
const directionIconTooltip = computed(() => {
|
||||
const tooltipDictionary = {
|
||||
in: t('Entrada'),
|
||||
out: t('Salida'),
|
||||
};
|
||||
return tooltipDictionary[$props.direction] || null;
|
||||
});
|
||||
|
||||
const directionIconName = computed(() => {
|
||||
const tooltipDictionary = {
|
||||
in: 'arrow_forward',
|
||||
out: 'arrow_back',
|
||||
};
|
||||
return tooltipDictionary[$props.direction] || null;
|
||||
});
|
||||
|
||||
const deleteHourEntry = async () => {
|
||||
try {
|
||||
const { data } = await axios.post(
|
||||
`WorkerTimeControls/${$props.id}/deleteTimeEntry`
|
||||
);
|
||||
|
||||
if (!data) return;
|
||||
emit('onHourEntryDeleted');
|
||||
notify('Entry removed', 'positive');
|
||||
} catch (err) {
|
||||
console.error('Error deleting hour entry');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row items-center no-wrap">
|
||||
<QIcon class="direction-icon" :name="directionIconName" size="sm">
|
||||
<QTooltip>{{ directionIconTooltip }}</QTooltip>
|
||||
</QIcon>
|
||||
<QBadge rounded class="chip">
|
||||
<QIcon name="edit" size="sm" class="fill-icon">
|
||||
<QTooltip>{{ t('Edit') }}</QTooltip></QIcon
|
||||
>
|
||||
<span class="q-px-sm text-subtitle2 text-weight-regular">{{ hour }}</span>
|
||||
<QIcon
|
||||
name="cancel"
|
||||
class="remove-icon"
|
||||
size="sm"
|
||||
@click="
|
||||
openConfirmationModal(
|
||||
t('This time entry will be deleted'),
|
||||
t('Are you sure you want to delete this entry?'),
|
||||
deleteHourEntry
|
||||
)
|
||||
"
|
||||
/>
|
||||
</QBadge>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.chip {
|
||||
height: 28px;
|
||||
color: var(--vn-dark);
|
||||
cursor: pointer;
|
||||
background-color: $primary;
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.direction-icon {
|
||||
color: var(--vn-label);
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.remove-icon {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
font-variation-settings: 'FILL' 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Entrada: Entrada
|
||||
Salida: Salida
|
||||
Edit: Editar
|
||||
This time entry will be deleted: Se eliminará la hora fichada
|
||||
Are you sure you want to delete this entry?: ¿Seguro que quieres eliminarla?
|
||||
Entry removed: Fichada borrada
|
||||
</i18n>
|
|
@ -0,0 +1,23 @@
|
|||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
||||
export function useVnConfirm() {
|
||||
const quasar = useQuasar();
|
||||
|
||||
const openConfirmationModal = (title, message, promise, successFn) => {
|
||||
quasar
|
||||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
title: title,
|
||||
message: message,
|
||||
promise: promise,
|
||||
},
|
||||
})
|
||||
.onOk(async () => {
|
||||
if (successFn) successFn();
|
||||
});
|
||||
};
|
||||
|
||||
return { openConfirmationModal };
|
||||
}
|
|
@ -97,6 +97,10 @@ select:-webkit-autofill {
|
|||
background-color: var(--vn-light-gray);
|
||||
}
|
||||
|
||||
.fill-icon {
|
||||
font-variation-settings: 'FILL' 1;
|
||||
}
|
||||
|
||||
/* Estilo para el asterisco en campos requeridos */
|
||||
.q-field.required .q-field__label:after {
|
||||
content: ' *';
|
||||
|
|
|
@ -1,121 +1,404 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { onMounted, ref, computed, onBeforeMount } from 'vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import { onMounted, ref, computed, onBeforeMount, nextTick } from 'vue';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import WorkerTimeHourChip from 'components/WorkerTimeHourChip.vue';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import axios from 'axios';
|
||||
import { useRole } from 'src/composables/useRole';
|
||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { useState } from 'src/composables/useState';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
// const { notify } = useNotify();
|
||||
const { hasAny } = useRole();
|
||||
const state = useState();
|
||||
const user = state.getUser();
|
||||
const stateStore = useStateStore();
|
||||
const weekdayStore = useWeekdayStore();
|
||||
const weekDays = ref([]);
|
||||
// const entryDirections = [
|
||||
// { code: 'in', description: t('Entrada') },
|
||||
// { code: 'middle', description: t('Intermedio') },
|
||||
// { code: 'out', description: t('Salida') },
|
||||
// ];
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
const { hasAny } = useRole();
|
||||
const _state = useState();
|
||||
const user = _state.getUser();
|
||||
const stateStore = useStateStore();
|
||||
const weekdayStore = useWeekdayStore();
|
||||
const weekDays = ref([]);
|
||||
|
||||
const isHr = computed(() => hasAny(['hr']));
|
||||
|
||||
const isHimSelf = computed(() => user.value.id === route.params.id);
|
||||
|
||||
const columns = computed(() => {
|
||||
return weekdayStore.localeWeekdays?.map((day) => {
|
||||
return weekdayStore.localeWeekdays?.map((day, index) => {
|
||||
const obj = {
|
||||
label: day.locale,
|
||||
formattedDate: getHeaderFormattedDate(weekDays.value[index]?.dated),
|
||||
name: day.name,
|
||||
align: 'left',
|
||||
colIndex: index,
|
||||
dayData: weekDays.value[index],
|
||||
};
|
||||
return obj;
|
||||
});
|
||||
});
|
||||
|
||||
const fetchWorkerTimeControlRef = 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);
|
||||
const state = ref(null);
|
||||
const reason = ref(null);
|
||||
const canResend = ref(null);
|
||||
const weekTotalHours = ref(null);
|
||||
const workerTimeControlMails = ref(null);
|
||||
|
||||
onMounted(() => setDate(Date.vnNew()));
|
||||
|
||||
const getHeaderFormattedDate = (date) => {
|
||||
//TODO:: Ver si se puede hacer una funcion reutilizable o complementar a utils de dates
|
||||
const newDate = new Date(date);
|
||||
const day = String(newDate.getDate()).padStart(2, '0');
|
||||
const monthName = newDate.toLocaleString('es-ES', { month: 'long' });
|
||||
return `${day} ${monthName}`;
|
||||
};
|
||||
|
||||
const getChipFormattedHour = (date) => {
|
||||
//TODO:: Ver si se puede hacer una funcion reutilizable o complementar a utils de dates
|
||||
const newDate = new Date(date);
|
||||
const hour = newDate.getHours();
|
||||
const min = newDate.getMinutes();
|
||||
return `${hour < 10 ? '0' + hour : hour}:${min < 10 ? '0' + min : min}`;
|
||||
};
|
||||
|
||||
const formatHours = (timestamp = 0) => {
|
||||
//TODO:: Ver si se puede hacer una funcion reutilizable o complementar a utils de dates
|
||||
let hour = Math.floor(timestamp / 3600);
|
||||
let min = Math.floor(timestamp / 60 - 60 * hour);
|
||||
|
||||
if (hour < 10) hour = `0${hour}`;
|
||||
if (min < 10) min = `0${min}`;
|
||||
|
||||
return `${hour}:${min}`;
|
||||
};
|
||||
|
||||
const formattedWeekTotalHours = computed(() => formatHours(weekTotalHours.value));
|
||||
|
||||
const defaultDate = computed(() => {
|
||||
const date = Date.vnNew();
|
||||
return `${date.getFullYear()}/${(date.getMonth() + 1).toString().padStart(2, '0')}`;
|
||||
});
|
||||
|
||||
const handleDateSelection = async (dates, _, selectedDateDetails) => {
|
||||
const onInputChange = async (dates, _, selectedDateDetails) => {
|
||||
if (!dates.length || !selectedDateDetails) return;
|
||||
|
||||
const { year, month, day } = selectedDateDetails;
|
||||
const selectedDate = new Date(year, month - 1, day);
|
||||
|
||||
startOfWeek.value = getStartOfWeek(selectedDate);
|
||||
endOfWeek.value = getEndOfWeek(startOfWeek.value);
|
||||
|
||||
getWeekDates(startOfWeek.value, endOfWeek.value);
|
||||
|
||||
await fetchWorkerTimeControl();
|
||||
const date = new Date(year, month - 1, day);
|
||||
setDate(date);
|
||||
};
|
||||
|
||||
const setDate = async (date) => {
|
||||
if (!date) return;
|
||||
selectedDate.value = date;
|
||||
selectedDate.value.setHours(0, 0, 0, 0);
|
||||
|
||||
const newStartOfWeek = getStartOfWeek(selectedDate.value); // Obtener el día de inicio de la semana a partir de la fecha seleccionada
|
||||
const newEndOfWeek = getEndOfWeek(newStartOfWeek); // Obtener el fin de la semana a partir de la fecha de inicio de la semana
|
||||
|
||||
startOfWeek.value = newStartOfWeek;
|
||||
endOfWeek.value = newEndOfWeek;
|
||||
selectedWeekNumber.value = getWeekNumber(newStartOfWeek); // Asignar el número de la semana
|
||||
console.log('selectedWeekNumber:: ', selectedWeekNumber.value);
|
||||
|
||||
getWeekDates(newStartOfWeek, newEndOfWeek);
|
||||
|
||||
await nextTick(); // Esperar actualización del DOM y luego fetchear data necesaria
|
||||
await fetchHours();
|
||||
await fetchWeekData();
|
||||
};
|
||||
|
||||
// Función para obtener el inicio de la semana a partir de una fecha
|
||||
const getStartOfWeek = (selectedDate) => {
|
||||
const dayOfWeek = selectedDate.getDay();
|
||||
const dayOfWeek = selectedDate.getDay(); // Obtener el día de la semana de la fecha seleccionada
|
||||
const startOfWeek = new Date(selectedDate);
|
||||
startOfWeek.setDate(selectedDate.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1));
|
||||
startOfWeek.setDate(selectedDate.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1)); // Calcular el inicio de la semana
|
||||
return startOfWeek;
|
||||
};
|
||||
|
||||
// Función para obtener el fin de la semana a partir del inicio de la semana
|
||||
const getEndOfWeek = (startOfWeek) => {
|
||||
const endOfWeek = new Date(startOfWeek);
|
||||
endOfWeek.setDate(startOfWeek.getDate() + 6);
|
||||
endOfWeek.setHours(23, 59, 59, 59);
|
||||
endOfWeek.setDate(startOfWeek.getDate() + 6); // Calcular el fin de la semana sumando 6 días al inicio de la semana
|
||||
return endOfWeek;
|
||||
};
|
||||
|
||||
// Función para obtener las fechas de la semana seleccionada
|
||||
const getWeekDates = (startOfWeek, endOfWeek) => {
|
||||
selectedCalendarDates.value = [];
|
||||
selectedCalendarDates.value = []; // Limpiar las fechas seleccionadas previamente usadas por QDate
|
||||
weekDays.value = []; // Limpiar la información de las fechas seleccionadas previamente
|
||||
let currentDate = new Date(startOfWeek);
|
||||
|
||||
while (currentDate <= endOfWeek) {
|
||||
selectedCalendarDates.value.push(formatDate(currentDate));
|
||||
weekDays.value.push({
|
||||
dated: new Date(currentDate.getTime()),
|
||||
});
|
||||
currentDate = new Date(currentDate.setDate(currentDate.getDate() + 1));
|
||||
// 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
|
||||
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'
|
||||
const formatDate = (date) => {
|
||||
return date.toISOString().slice(0, 10);
|
||||
};
|
||||
|
||||
const workerTimeControlsFilter = computed(() => ({
|
||||
const workerHoursFilter = computed(() => ({
|
||||
where: {
|
||||
and: [{ timed: { gte: startOfWeek.value } }, { timed: { lte: endOfWeek.value } }],
|
||||
},
|
||||
}));
|
||||
|
||||
const fetchWorkerTimeControl = async () => {
|
||||
const getWeekNumber = (date) => {
|
||||
if (!date) return;
|
||||
const startOfYear = new Date(date.getFullYear(), 0, 1);
|
||||
const dayOfWeek = startOfYear.getDay();
|
||||
const offset = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
||||
const firstWeekMilliseconds = startOfYear.getTime() - offset * 24 * 60 * 60 * 1000;
|
||||
const dateMilliseconds = date.getTime();
|
||||
const weekNumber =
|
||||
Math.floor(
|
||||
(dateMilliseconds - firstWeekMilliseconds) / (7 * 24 * 60 * 60 * 1000)
|
||||
) + 1;
|
||||
return weekNumber;
|
||||
};
|
||||
|
||||
const getWorkedHours = async (from, to) => {
|
||||
weekTotalHours.value = null;
|
||||
let _weekTotalHours = 0;
|
||||
let params = {
|
||||
from: from,
|
||||
id: route.params.id,
|
||||
to: to,
|
||||
};
|
||||
|
||||
const { data } = await axios.get(`Workers/${route.params.id}/getWorkedHours`, {
|
||||
params,
|
||||
});
|
||||
|
||||
const workDays = data;
|
||||
const map = new Map();
|
||||
|
||||
for (const workDay of workDays) {
|
||||
workDay.dated = new Date(workDay.dated);
|
||||
map.set(workDay.dated, workDay);
|
||||
_weekTotalHours += workDay.workedHours;
|
||||
}
|
||||
|
||||
for (const weekDay of weekDays.value) {
|
||||
const workDay = workDays.find((day) => {
|
||||
let from = new Date(day.dated);
|
||||
from.setHours(0, 0, 0, 0);
|
||||
|
||||
let to = new Date(day.dated);
|
||||
to.setHours(23, 59, 59, 59);
|
||||
|
||||
return weekDay.dated >= from && weekDay.dated <= to;
|
||||
});
|
||||
|
||||
if (workDay) {
|
||||
weekDay.expectedHours = workDay.expectedHours;
|
||||
weekDay.workedHours = workDay.workedHours;
|
||||
}
|
||||
}
|
||||
|
||||
weekTotalHours.value = _weekTotalHours;
|
||||
};
|
||||
|
||||
const getAbsences = async () => {
|
||||
const params = {
|
||||
workerFk: route.params.id,
|
||||
businessFk: null,
|
||||
year: startOfWeek.value.getFullYear(),
|
||||
};
|
||||
|
||||
const { data } = await axios.get('Calendars/absences', { params });
|
||||
console.log('absenses:: ', data);
|
||||
if (data) addEvents(data);
|
||||
};
|
||||
|
||||
const hasEvents = (day) => {
|
||||
return day >= startOfWeek.value && day < endOfWeek.value;
|
||||
};
|
||||
|
||||
const addEvents = (data) => {
|
||||
console.log('ADD EVENTS:: ');
|
||||
const events = {};
|
||||
|
||||
const addEvent = (day, event) => {
|
||||
events[new Date(day).getTime()] = event;
|
||||
};
|
||||
|
||||
if (data.holidays) {
|
||||
data.holidays.forEach((holiday) => {
|
||||
const holidayDetail = holiday.detail && holiday.detail.description;
|
||||
const holidayType = holiday.type && holiday.type.name;
|
||||
const holidayName = holidayDetail || holidayType;
|
||||
|
||||
addEvent(holiday.dated, {
|
||||
name: holidayName,
|
||||
color: '#ff0',
|
||||
});
|
||||
});
|
||||
}
|
||||
if (data.absences) {
|
||||
data.absences.forEach((absence) => {
|
||||
const type = absence.absenceType;
|
||||
addEvent(absence.dated, {
|
||||
name: type.name,
|
||||
color: type.rgb,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
weekDays.value.forEach((day) => {
|
||||
const timestamp = day.dated.getTime();
|
||||
if (events[timestamp]) day.event = events[timestamp];
|
||||
});
|
||||
console.log('weekdays after events:: ', weekDays.value);
|
||||
};
|
||||
|
||||
const fetchHours = async () => {
|
||||
try {
|
||||
await fetchWorkerTimeControlRef.value.fetch();
|
||||
await workerHoursRef.value.fetch();
|
||||
await getWorkedHours(startOfWeek.value, endOfWeek.value);
|
||||
await getAbsences();
|
||||
} catch (err) {
|
||||
console.error('Error fetching worker time control');
|
||||
console.error('Error fetching worker hours');
|
||||
}
|
||||
};
|
||||
|
||||
const setWorkerTimeControls = (data) => {
|
||||
console.log('worker time controls:: ', data);
|
||||
const fetchWorkerTimeControlMails = async (filter) => {
|
||||
try {
|
||||
const { data } = await axios.get('WorkerTimeControlMails', {
|
||||
params: { filter: JSON.stringify(filter) },
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (err) {
|
||||
console.error('Error fetching worker time control mails');
|
||||
}
|
||||
};
|
||||
|
||||
console.log('columns:: ', columns.value);
|
||||
const fetchWeekData = async () => {
|
||||
try {
|
||||
const filter = {
|
||||
where: {
|
||||
workerFk: route.params.id,
|
||||
year: selectedDate.value ? selectedDate.value?.getFullYear() : null,
|
||||
week: getWeekNumber(selectedDate.value),
|
||||
},
|
||||
};
|
||||
|
||||
const data = await fetchWorkerTimeControlMails(filter);
|
||||
|
||||
if (!data.length) {
|
||||
state.value = null;
|
||||
} else {
|
||||
const [mail] = data;
|
||||
state.value = mail.state;
|
||||
reason.value.value = mail.reason;
|
||||
}
|
||||
|
||||
await canBeResend();
|
||||
} catch (err) {
|
||||
console.error('Error fetching week data');
|
||||
}
|
||||
};
|
||||
|
||||
const canBeResend = async () => {
|
||||
canResend.value = false;
|
||||
|
||||
const filter = {
|
||||
where: {
|
||||
year: selectedDate.value.getFullYear(),
|
||||
week: getWeekNumber(selectedDate.value),
|
||||
},
|
||||
limit: 1,
|
||||
};
|
||||
|
||||
const data = await fetchWorkerTimeControlMails(filter);
|
||||
|
||||
if (data.length) canResend.value = true;
|
||||
};
|
||||
|
||||
const setHours = (data) => {
|
||||
for (const weekDay of weekDays.value) {
|
||||
if (data) {
|
||||
let day = weekDay.dated.getDay();
|
||||
weekDay.hours = data
|
||||
.filter((hour) => new Date(hour.timed).getDay() == day)
|
||||
.sort((a, b) => new Date(a.timed) - new Date(b.timed));
|
||||
} else weekDay.hours = null;
|
||||
}
|
||||
};
|
||||
const getFinishTime = () => {
|
||||
if (!weekDays.value || weekDays.value.length === 0) return;
|
||||
|
||||
let today = Date.vnNew();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
let todayInWeek = weekDays.value.find(
|
||||
(day) => day.dated.getTime() === today.getTime()
|
||||
);
|
||||
|
||||
if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
|
||||
const remainingTime = todayInWeek.workedHours
|
||||
? (todayInWeek.expectedHours - todayInWeek.workedHours) * 1000
|
||||
: null;
|
||||
const lastKnownEntry = todayInWeek.hours[todayInWeek.hours.length - 1];
|
||||
const lastKnownTime = new Date(lastKnownEntry.timed).getTime();
|
||||
const finishTimeStamp =
|
||||
lastKnownTime && remainingTime ? lastKnownTime + remainingTime : null;
|
||||
|
||||
if (finishTimeStamp) {
|
||||
let finishDate = new Date(finishTimeStamp);
|
||||
let hour = finishDate.getHours();
|
||||
let minute = finishDate.getMinutes();
|
||||
|
||||
if (hour < 10) hour = `0${hour}`;
|
||||
if (minute < 10) minute = `0${minute}`;
|
||||
return `${hour}:${minute} h.`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onHourEntryDeleted = async () => {
|
||||
await fetchHours();
|
||||
await getMailStates(selectedDate.value);
|
||||
};
|
||||
|
||||
const getMailStates = async (date) => {
|
||||
const params = {
|
||||
month: date.getMonth() + 1,
|
||||
year: date.getFullYear(),
|
||||
};
|
||||
|
||||
const { data } = await axios.get(
|
||||
`WorkerTimeControls/${route.params.id}/getMailStates`,
|
||||
{ params }
|
||||
);
|
||||
workerTimeControlMails.value = data;
|
||||
console.log('workerTimeControlMails: ', workerTimeControlMails.value);
|
||||
// await repaint();
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
weekdayStore.initStore();
|
||||
|
@ -129,40 +412,149 @@ onMounted(async () => {
|
|||
|
||||
<template>
|
||||
<FetchData
|
||||
ref="fetchWorkerTimeControlRef"
|
||||
ref="workerHoursRef"
|
||||
url="WorkerTimeControls/filter"
|
||||
:filter="workerTimeControlsFilter"
|
||||
:filter="workerHoursFilter"
|
||||
:params="{
|
||||
workerFk: route.params.id,
|
||||
}"
|
||||
@on-fetch="(data) => setWorkerTimeControls(data)"
|
||||
@on-fetch="(data) => setHours(data)"
|
||||
/>
|
||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="300" show-if-above>
|
||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="260" class="q-pa-md">
|
||||
<div class="q-pa-md q-mb-md" style="border: 2px solid black">
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('Hours') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="column items-center" horizontal>
|
||||
<div>
|
||||
<span class="details-label">{{ t('Total semana') }} </span>
|
||||
<span>: {{ formattedWeekTotalHours }} h.</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="details-label">{{ t('Termina a las') }}:</span>
|
||||
<span>{{ dashIfEmpty(getFinishTime()) }}</span>
|
||||
</div>
|
||||
|
||||
<span></span>
|
||||
</QCardSection>
|
||||
</div>
|
||||
<QDate
|
||||
ref="calendarRef"
|
||||
:model-value="selectedCalendarDates"
|
||||
@update:model-value="handleDateSelection"
|
||||
@update:model-value="onInputChange"
|
||||
mask="YYYY-MM-DD"
|
||||
color="primary"
|
||||
minimal
|
||||
multiple
|
||||
bordered
|
||||
dense
|
||||
:default-year-month="defaultDate"
|
||||
/>
|
||||
<pre>date range: {{ selectedDates }}</pre>
|
||||
<pre>date range: {{ selectedCalendarDates }}</pre>
|
||||
</QDrawer>
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<QCard class="full-width">
|
||||
<QTable :columns="columns"> </QTable>
|
||||
<QTable :columns="columns" :rows="['']" hide-bottom>
|
||||
<template #header="props">
|
||||
<QTr :props="props">
|
||||
<QTh
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
auto-width
|
||||
>
|
||||
<div class="column-title-container">
|
||||
<span class="text-primary">{{ t(col.label) }}</span>
|
||||
<span>{{ t(col.formattedDate) }}</span>
|
||||
</div>
|
||||
</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<QTr>
|
||||
<QTd
|
||||
v-for="(day, index) in props.cols"
|
||||
:key="index"
|
||||
style="padding: 20px 0 20px 0 !important"
|
||||
>
|
||||
<div
|
||||
v-for="(hour, index) in day.dayData?.hours"
|
||||
:key="index"
|
||||
:props="props"
|
||||
class="hour-chip"
|
||||
>
|
||||
<WorkerTimeHourChip
|
||||
:hour="getChipFormattedHour(hour.timed)"
|
||||
:direction="hour.direction"
|
||||
:id="hour.id"
|
||||
@on-hour-entry-deleted="onHourEntryDeleted()"
|
||||
/>
|
||||
</div>
|
||||
</QTd>
|
||||
</QTr>
|
||||
<QTr>
|
||||
<QTd v-for="(day, index) in props.cols" :key="index">
|
||||
<div class="column items-center justify-center">
|
||||
<span class="q-mb-md text-sm text-body1">
|
||||
{{ formatHours(day.dayData?.workedHours) }} h.
|
||||
</span>
|
||||
<QIcon
|
||||
name="add_circle"
|
||||
color="primary"
|
||||
class="fill-icon cursor-pointer"
|
||||
size="sm"
|
||||
>
|
||||
<QTooltip>{{ t('Add time') }}</QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
<pre>{{ columns }}</pre>
|
||||
<!-- <pre>{{ weekDays }}</pre> -->
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style lang="scss">
|
||||
.column-title-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.details-label {
|
||||
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;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Entrada: Entrada
|
||||
Intermedio: Intermedio
|
||||
Salida: Salida
|
||||
Hours: Horas
|
||||
Total semana: Total semana
|
||||
Termina a las: Termina a las
|
||||
Add time: Añadir hora
|
||||
</i18n>
|
||||
|
|
Loading…
Reference in New Issue