feat: #8443 created vehicle events #1379
|
@ -0,0 +1,152 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { date } from 'quasar';
|
||||||
|
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.scss';
|
||||||
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
|
import useWeekdaysOrder from 'src/composables/getWeekdays';
|
||||||
|
|
||||||
|
const formatDate = (dateToFormat, format = 'YYYY-MM-DD') => (
|
||||||
provira marked this conversation as resolved
Outdated
|
|||||||
|
date.formatDate(dateToFormat, format)
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
He creado redmine para estandarizar esta función/lógica ya que hay 17 resultados en 9 archivos He creado redmine para estandarizar esta función/lógica ya que hay 17 resultados en 9 archivos
jsegarra
commented
https://redmine.verdnatura.es/issues/8836
|
|||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
year: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
monthDate: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
daysMap: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['onDateSelected']);
|
||||||
|
|
||||||
provira marked this conversation as resolved
jsegarra
commented
Si esta linea y la 42 son iguales, quizás extraer una función Si esta linea y la 42 son iguales, quizás extraer una función
|
|||||||
|
const { locale } = useI18n();
|
||||||
|
const weekdayStore = useWeekdayStore();
|
||||||
|
const weekDays = useWeekdaysOrder();
|
||||||
|
const calendarRef = ref(null);
|
||||||
|
const today = ref(formatDate(Date.vnNew()));
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Esto también lo incluyo en el redmine porque hay 7 y 7 Esto también lo incluyo en el redmine porque hay 7 y 7
|
|||||||
|
const todayTimestamp = computed(() => {
|
||||||
|
const date = Date.vnNew();
|
||||||
|
date.setHours(0, 0, 0, 0);
|
||||||
|
return date.getTime();
|
||||||
|
});
|
||||||
|
const _monthDate = computed(() => formatDate(props.monthDate));
|
||||||
|
|
||||||
provira marked this conversation as resolved
jsegarra
commented
Aqui no has destructurado pero en la siguiente si, unificar criterio. Propuesta, mejor como getEventByTimestamp Aqui no has destructurado pero en la siguiente si, unificar criterio. Propuesta, mejor como getEventByTimestamp
|
|||||||
|
const calendarHeaderTitle = computed(() => {
|
||||||
|
return `${weekdayStore.getLocaleMonths[props.month - 1].locale} ${props.year}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isToday = (timestamp) => {
|
||||||
|
const { year, month, day } = timestamp;
|
||||||
|
return todayTimestamp.value === new Date(year, month - 1, day).getTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEventByTimestamp = ({ year, month, day }) => {
|
||||||
|
const stamp = new Date(year, month - 1, day).getTime();
|
||||||
|
return props.daysMap?.[stamp] || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDateClick = (timestamp) => {
|
||||||
|
const event = getEventByTimestamp(timestamp);
|
||||||
|
const { year, month, day } = timestamp;
|
||||||
|
const date = new Date(year, month - 1, day);
|
||||||
|
emit('onDateSelected', {
|
||||||
|
date,
|
||||||
|
isNewMode: !event,
|
||||||
|
event: event?.[0] || null
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEventAttrs = (timestamp) => {
|
||||||
|
return {
|
||||||
|
class: '--event',
|
||||||
|
label: timestamp.day,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ getEventByTimestamp, handleDateClick });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QCalendarMonthWrapper
|
||||||
jsegarra
commented
De los 4 usos que le damos a este componente, solo 1 no lo tiene, curioso De los 4 usos que le damos a este componente, solo 1 no lo tiene, curioso
Te parece que definamos una regla CSS global para este componente?
jsegarra
commented
Se que antes estaba, pero lo podemos dejar mejor Se que antes estaba, pero lo podemos dejar mejor
provira
commented
El que no tiene estilo es porque es el calendario de semanas del Time Control de Worker. Si se le ponen los mismos estilos no cabe en el menú lateral El que no tiene estilo es porque es el calendario de semanas del Time Control de Worker. Si se le ponen los mismos estilos no cabe en el menú lateral
|
|||||||
|
style="height: 290px; width: 290px"
|
||||||
|
transparent-background
|
||||||
|
view-customization="workerCalendar"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<span class="full-width text-center text-body1 q-py-sm">{{
|
||||||
|
calendarHeaderTitle
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
<template #calendar>
|
||||||
|
<QCalendarMonth
|
||||||
|
ref="calendarRef"
|
||||||
|
:model-value="_monthDate"
|
||||||
|
show-work-weeks
|
||||||
|
no-outside-days
|
||||||
|
no-active-date
|
||||||
|
:weekdays="weekDays"
|
||||||
|
short-weekday-label
|
||||||
|
:locale="locale"
|
||||||
|
:now="today"
|
||||||
|
@click-date="handleDateClick($event.scope.timestamp)"
|
||||||
|
mini-mode
|
||||||
|
>
|
||||||
|
<template #day="{ scope: { timestamp } }">
|
||||||
|
<slot name="day" :timestamp="timestamp" :getEventAttrs="getEventAttrs">
|
||||||
|
<QBtn
|
||||||
|
v-if="getEventByTimestamp(timestamp)"
|
||||||
|
v-bind="{ ...getEventAttrs(timestamp) }"
|
||||||
|
@click="handleDateClick(timestamp)"
|
||||||
|
rounded
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
class="calendar-event"
|
||||||
|
:class="{ '--today': isToday(timestamp) }"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</QCalendarMonth>
|
||||||
|
</template>
|
||||||
|
</QCalendarMonthWrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.calendar-event {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.715em;
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&.--today {
|
||||||
|
border: 2px solid $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.--event {
|
||||||
|
background-color: $positive;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,126 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, onMounted, ref, onUnmounted, nextTick } from '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,
|
||||||
|
},
|
||||||
|
calendarComponent: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
additionalProps: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const weekdayStore = useWeekdayStore();
|
||||||
|
const nMonths = ref(4);
|
||||||
|
const _date = ref(Date.vnNew());
|
||||||
|
const firstDay = ref(Date.vnNew());
|
||||||
|
const lastDay = ref(Date.vnNew());
|
||||||
|
const months = ref([]);
|
||||||
|
const arrayData = useArrayData(props.dataKey);
|
||||||
|
onMounted(async () => {
|
||||||
provira marked this conversation as resolved
jsegarra
commented
store no se usa store no se usa
|
|||||||
|
const initialDate = Date.vnNew();
|
||||||
|
initialDate.setDate(1);
|
||||||
|
initialDate.setHours(0, 0, 0, 0);
|
||||||
|
date.value = initialDate;
|
||||||
|
await nextTick();
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => arrayData.destroy());
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
'update:firstDay',
|
||||||
|
'update:lastDay',
|
||||||
|
'update:events',
|
||||||
|
'onDateSelected',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const date = computed({
|
||||||
|
get: () => _date.value,
|
||||||
|
set: (value) => {
|
||||||
|
if (!(value instanceof Date)) return;
|
||||||
|
_date.value = value;
|
||||||
|
const 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++) {
|
||||||
|
const monthDate = new Date(stamp);
|
||||||
|
monthDate.setMonth(value.getMonth() + i);
|
||||||
|
months.value.push(monthDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('update:firstDay', firstDay.value);
|
||||||
|
emit('update:lastDay', lastDay.value);
|
||||||
|
emit('refresh-events');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const headerTitle = computed(() => {
|
||||||
|
if (!months.value?.length) return '';
|
||||||
|
const getMonthName = date =>
|
||||||
|
`${weekdayStore.getLocaleMonths[date.getMonth()].locale} ${date.getFullYear()}`;
|
||||||
|
return `${getMonthName(months.value[0])} - ${getMonthName(months.value[months.value.length - 1])}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const step = (direction) => {
|
||||||
|
const newDate = new Date(date.value);
|
||||||
|
newDate.setMonth(newDate.getMonth() + nMonths.value * direction);
|
||||||
|
date.value = newDate;
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
firstDay,
|
||||||
|
lastDay
|
||||||
|
});
|
||||||
|
</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">
|
||||||
|
<component
|
||||||
|
:is="calendarComponent"
|
||||||
|
v-for="(month, index) in months"
|
||||||
|
:key="index"
|
||||||
|
:month="month.getMonth() + 1"
|
||||||
|
:year="month.getFullYear()"
|
||||||
|
:month-date="month"
|
||||||
|
v-bind="additionalProps"
|
||||||
|
@on-date-selected="data => emit('onDateSelected', data)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</QCard>
|
||||||
|
</template>
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
export default function useWeekdaysOrder() {
|
||||||
|
|
||||||
|
const firstDay = moment().weekday(1).day();
|
||||||
|
const weekdays = [...Array(7).keys()].map(i => (i + firstDay) % 7);
|
||||||
|
|
||||||
|
return ref(weekdays);
|
||||||
|
}
|
|
@ -343,3 +343,20 @@ input::-webkit-inner-spin-button {
|
||||||
.q-item__section--main ~ .q-item__section--side {
|
.q-item__section--main ~ .q-item__section--side {
|
||||||
padding-inline: 0;
|
padding-inline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
<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 VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
import axios from 'axios';
|
||||||
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
event: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
isNewMode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
eventType: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
firstDay: {
|
||||||
|
type: Date,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
lastDay: {
|
||||||
|
type: Date,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['onSubmit', 'closeForm', 'refresh-events']);
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
const state = useState();
|
||||||
|
const user = state.getUser();
|
||||||
|
|
||||||
|
const isNew = computed(() => props.isNewMode);
|
||||||
|
const vehicleFormData = ref({
|
||||||
|
started: null,
|
||||||
|
finished: null,
|
||||||
|
vehicleStateFk: null,
|
||||||
|
description: '',
|
||||||
|
vehicleFk: null,
|
||||||
|
userFk: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const arrayData = useArrayData('VehicleEvents');
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.event) {
|
||||||
|
vehicleFormData.value = props.event;
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Esto es lo mismo que props.event, no? Esto es lo mismo que props.event, no?
provira
commented
Si, es lo mismo. Ahora se usa directamente props.event. Si, es lo mismo. Ahora se usa directamente props.event.
|
|||||||
|
}
|
||||||
|
});
|
||||||
provira marked this conversation as resolved
Outdated
jsegarra
commented
revisa esta condicion porque hay codigo repeidto que se puede evitar revisa esta condicion porque hay codigo repeidto que se puede evitar
|
|||||||
|
|
||||||
|
const createVehicleEvent = async () => {
|
||||||
|
vehicleFormData.value.vehicleFk = route.params.id;
|
||||||
|
vehicleFormData.value.userFk = user.value.id;
|
||||||
|
|
||||||
|
if (isNew.value) {
|
||||||
|
await axios.post(`VehicleEvents`, vehicleFormData.value);
|
||||||
|
} else {
|
||||||
|
await axios.patch(
|
||||||
|
`VehicleEvents/${props.event?.id}`,
|
||||||
|
vehicleFormData.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await refetchEvents();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteVehicleEvent = async () => {
|
||||||
provira marked this conversation as resolved
Outdated
jsegarra
commented
Estas 3 líneas son iguales a la de arriba, una función que las incluya? Estas 3 líneas son iguales a la de arriba, una función que las incluya?
|
|||||||
|
if (!props.event) return;
|
||||||
|
await axios.delete(`VehicleEvents/${props.event?.id}`);
|
||||||
|
await refetchEvents();
|
||||||
|
};
|
||||||
|
|
||||||
|
const refetchEvents = async () => {
|
||||||
|
await arrayData.refresh({
|
||||||
|
append: false,
|
||||||
|
params: {
|
||||||
|
filter: {
|
||||||
|
where: {
|
||||||
|
vehicleFk: route.params.id,
|
||||||
|
and: [
|
||||||
|
{
|
||||||
|
or: [
|
||||||
|
{ started: { lte: props.lastDay?.toISOString() } },
|
||||||
|
{ started: null }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
or: [
|
||||||
|
{ finished: { gte: props.firstDay?.toISOString() } },
|
||||||
|
{ finished: null }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit('refresh-events');
|
||||||
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
|
emit('closeForm');
|
||||||
provira marked this conversation as resolved
Outdated
jsegarra
commented
onMounted no lo dejamos al final onMounted no lo dejamos al final
https://vuejs.org/style-guide/rules-recommended
|
|||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FormPopup
|
||||||
|
:title="isNew ? t('Add vehicle event') : t('Edit vehicle event')"
|
||||||
|
:default-cancel-button="false"
|
||||||
|
:default-submit-button="false"
|
||||||
|
>
|
||||||
|
<template #form-inputs>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<VnInputDate :label="t('Started')" v-model="vehicleFormData.started" />
|
||||||
|
<VnInputDate :label="t('Finished')" v-model="vehicleFormData.finished" />
|
||||||
|
<VnSelect
|
||||||
|
url="VehicleStates"
|
||||||
|
v-model="vehicleFormData.vehicleStateFk"
|
||||||
provira marked this conversation as resolved
jsegarra
commented
Sacar descripcion de Vnrow Sacar descripcion de Vnrow
|
|||||||
|
:label="t('globals.state')"
|
||||||
|
option-label="state"
|
||||||
|
data-cy="State_input"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
|
<VnInput
|
||||||
|
v-model="vehicleFormData.description"
|
||||||
|
:label="t('globals.description')"
|
||||||
provira marked this conversation as resolved
jsegarra
commented
No es necesario el text No es necesario el text
|
|||||||
|
/>
|
||||||
|
</template>
|
||||||
provira marked this conversation as resolved
Outdated
jsegarra
commented
esta linea no hace falta esta linea no hace falta
|
|||||||
|
<template #custom-buttons>
|
||||||
|
<QBtn
|
||||||
|
:label="t('globals.cancel')"
|
||||||
|
color="primary"
|
||||||
|
flat
|
||||||
|
class="q-mr-sm"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
v-if="!isNew"
|
||||||
|
:label="t('globals.delete')"
|
||||||
|
color="primary"
|
||||||
|
flat
|
||||||
|
class="q-mr-sm"
|
||||||
|
@click="
|
||||||
|
openConfirmationModal(
|
||||||
|
t('vehicle.deleteTitle'),
|
||||||
|
t('vehicle.deleteSubtitle'),
|
||||||
|
() => deleteVehicleEvent(),
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
:label="isNew ? t('globals.save') : t('globals.add')"
|
||||||
|
@click="createVehicleEvent"
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</FormPopup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Started: Inicio
|
||||||
|
Finished: Fin
|
||||||
|
Add vehicle event: Agregar evento
|
||||||
|
Edit vehicle event: Editar evento
|
||||||
|
</i18n>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import VehicleEventsPanel from './VehicleEventsPanel.vue';
|
||||||
|
import VehicleCalendarGrid from '../VehicleCalendarGrid.vue';
|
||||||
|
import VehicleEventInclusionForm from './VehicleEventInclusionForm.vue';
|
||||||
|
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
|
||||||
|
const firstDay = ref();
|
||||||
|
const lastDay = ref();
|
||||||
|
const events = ref([]);
|
||||||
|
const vehicleEventsPanelRef = ref(null);
|
||||||
|
const showVehicleEventForm = ref(false);
|
||||||
|
const vehicleEventsFormProps = reactive({
|
||||||
|
isNewMode: true,
|
||||||
|
date: null,
|
||||||
|
event: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshEvents = async () => {
|
||||||
|
await vehicleEventsPanelRef.value.fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const openForm = (data) => {
|
||||||
|
const { date = null, isNewMode, event } = data;
|
||||||
|
Object.assign(vehicleEventsFormProps, { date, isNewMode, event });
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
No me acaba de convencer pero que te parece la solucion
No me acaba de convencer pero que te parece la solucion
```
({ date = null, isNewMode, event } = data);
Object.assign(vehicleEventsFormProps, { date, isNewMode, event });
```
provira
commented
Me gusta más así que antes, funciona igual y queda mas limpio Me gusta más así que antes, funciona igual y queda mas limpio
|
|||||||
|
|
||||||
|
showVehicleEventForm.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onVehicleEventFormClose = () => {
|
||||||
|
showVehicleEventForm.value = false;
|
||||||
|
vehicleEventsFormProps.value = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<RightMenu>
|
||||||
|
<template #right-panel v-if="stateStore.isHeaderMounted()">
|
||||||
|
<VehicleEventsPanel
|
||||||
|
ref="vehicleEventsPanelRef"
|
||||||
|
:first-day="firstDay"
|
||||||
|
:last-day="lastDay"
|
||||||
|
:events="events"
|
||||||
|
@update:events="events = $event"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</RightMenu>
|
||||||
|
<QPage class="q-pa-md flex justify-center">
|
||||||
|
<VehicleCalendarGrid
|
||||||
|
v-model:events="events"
|
||||||
|
v-model:firstDay="firstDay"
|
||||||
|
v-model:lastDay="lastDay"
|
||||||
|
data-key="VehicleEvents"
|
||||||
|
@on-date-selected="openForm"
|
||||||
|
/>
|
||||||
|
<QDialog v-model="showVehicleEventForm" @hide="onVehicleEventFormClose()">
|
||||||
|
<VehicleEventInclusionForm
|
||||||
|
v-bind="vehicleEventsFormProps"
|
||||||
|
:first-day="firstDay"
|
||||||
|
:last-day="lastDay"
|
||||||
|
@close-form="onVehicleEventFormClose()"
|
||||||
|
@refresh-events="refreshEvents()"
|
||||||
|
/>
|
||||||
|
</QDialog>
|
||||||
|
<QPageSticky :offset="[20, 20]">
|
||||||
|
<QBtn
|
||||||
|
@click="openForm({ isNewMode: true }, true)"
|
||||||
|
color="primary"
|
||||||
|
fab
|
||||||
|
icon="add"
|
||||||
|
v-shortcut="'+'"
|
||||||
|
/>
|
||||||
|
<QTooltip class="text-no-wrap">
|
||||||
|
{{ t('eventsInclusionForm.addEvent') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QPageSticky>
|
||||||
|
</QPage>
|
||||||
|
</template>
|
|
@ -0,0 +1,196 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, watch, computed, ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { toDateFormat } from 'src/filters/date.js';
|
||||||
|
import { dashIfEmpty } from 'src/filters';
|
||||||
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
firstDay: {
|
||||||
|
type: Date,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
lastDay: {
|
||||||
|
type: Date,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['openVehicleForm']);
|
||||||
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
const weekdayStore = useWeekdayStore();
|
||||||
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
const vehicleStates = ref({});
|
||||||
|
const fetchVehicleState = async () => {
|
||||||
|
const vehicles = await axios.get('VehicleStates');
|
||||||
|
vehicleStates.value = vehicles.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getVehicleStateName = (id) => {
|
||||||
|
return vehicleStates.value[id - 1] ?? dashIfEmpty(id - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = computed(() => ({
|
||||||
|
vehicleFk: route.params.id,
|
||||||
|
started: props.firstDay,
|
||||||
|
finished: props.lastDay,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const arrayData = useArrayData('VehicleEvents', {
|
||||||
|
params: params,
|
||||||
|
url: `VehicleEvents`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
if (!params.value.vehicleFk || !props.firstDay || !props.lastDay) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await arrayData.applyFilter({
|
||||||
|
params: {
|
||||||
|
filter: {
|
||||||
|
where: {
|
||||||
|
vehicleFk: route.params.id,
|
||||||
|
and: [
|
||||||
|
{ or: [
|
||||||
|
{ started: { lte: props.lastDay } },
|
||||||
|
{ started: null }
|
||||||
|
]},
|
||||||
|
{ or: [
|
||||||
|
{ finished: { gte: props.firstDay } },
|
||||||
|
{ finished: null }
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit('update:events', arrayData.store.data || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching events:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
params,
|
||||||
|
async () => {
|
||||||
|
await fetchData();
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.events,
|
||||||
|
(newEvents) => {
|
||||||
|
emit('update:events', newEvents);
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const deleteEvent = async (id) => {
|
||||||
|
if (!id) return;
|
||||||
|
await axios.delete(`VehicleEvents/${id}`);
|
||||||
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
|
await fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const openInclusionForm = (event) => {
|
||||||
|
emit('openVehicleForm', {
|
||||||
|
date: event.dated,
|
||||||
|
event,
|
||||||
|
isNewMode: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
weekdayStore.initStore();
|
||||||
|
await fetchVehicleState();
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
fetchData
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QForm @submit="onSubmit()">
|
||||||
jsegarra marked this conversation as resolved
jsegarra
commented
Porque no FormModel? Porque no FormModel?
|
|||||||
|
<div class="column q-pa-md q-gutter-y-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 class="q-mb-xs">
|
||||||
|
<span
|
||||||
|
>({{ toDateFormat(event.started) }} -
|
||||||
|
{{ toDateFormat(event.finished) }})</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<span class="color-vn-label"
|
||||||
|
>{{ t('globals.description') }}:
|
||||||
|
<span class="color-vn-text q-ml-xs">{{
|
||||||
|
dashIfEmpty(event.description)
|
||||||
|
}}</span>
|
||||||
|
</span>
|
||||||
|
<span class="color-vn-label"
|
||||||
|
>{{ t('globals.state') }}:
|
||||||
|
<span class="color-vn-text">{{
|
||||||
|
getVehicleStateName(event.vehicleStateFk).state
|
||||||
|
}}</span>
|
||||||
|
</span>
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection side @click="openInclusionForm(event)">
|
||||||
|
<QBtn
|
||||||
|
icon="delete"
|
||||||
|
data-cy="delete_event"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
size="md"
|
||||||
|
color="primary"
|
||||||
|
@click.stop="
|
||||||
|
openConfirmationModal(
|
||||||
|
t('vehicle.deleteTitle'),
|
||||||
|
t('vehicle.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>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script setup>
|
||||||
jsegarra marked this conversation as resolved
jsegarra
commented
Uff...esto está duplicado de ZoneCalendar, al 80% Uff...esto está duplicado de ZoneCalendar, al 80%
jsegarra
commented
Habría que proponer de extraer la funcionalidad común y/o un componente común. Habría que proponer de extraer la funcionalidad común y/o un componente común.
Ahora son 2 casos, pero en el futuro quien sabe
@jgallego Lo dejamos así y crear tarea para ZoneCalendar y VehicleCalendar o abordamos en esta y creamos tarea "Refactor" para ZoneCalendar?
jgallego
commented
Si esta repetido, directamente hagamos bien la seccion Si esta repetido, directamente hagamos bien la seccion
jsegarra
commented
He creado la tarea a posterior de esta https://redmine.verdnatura.es/issues/8797 He creado la tarea a posterior de esta https://redmine.verdnatura.es/issues/8797
jsegarra
commented
@provira Te propongo lo siguiente: dejar los test ✅, y una vez conseguidos, hacer el cambio en Vehicle* > Si esta repetido, directamente hagamos bien la sección
@provira Te propongo lo siguiente: dejar los test ✅, y una vez conseguidos, hacer el cambio en Vehicle*
|
|||||||
|
import EntityCalendar from 'src/components/EntityCalendar.vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['onDateSelected']);
|
||||||
|
|
||||||
|
</script>
|
||||||
provira marked this conversation as resolved
Outdated
jsegarra
commented
revisamos revisamos
jsegarra
commented
Quitar Quitar
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<EntityCalendar
|
||||||
|
v-bind="$props"
|
||||||
|
@onDateSelected="(e) => emit('onDateSelected', e)"
|
||||||
|
/>
|
||||||
|
</template>
|
|
@ -0,0 +1,97 @@
|
||||||
|
<script setup>
|
||||||
jsegarra marked this conversation as resolved
jsegarra
commented
3/4 de lo mismo que antes 3/4 de lo mismo que antes
|
|||||||
|
import { ref, watch } from 'vue';
|
||||||
provira marked this conversation as resolved
Outdated
jsegarra
commented
onMounted no se usa onMounted no se usa
|
|||||||
|
import EntityCalendarGrid from 'src/components/EntityCalendarGrid.vue';
|
||||||
|
import VehicleCalendar from './VehicleCalendar.vue';
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const firstDay = ref(new Date());
|
||||||
|
const lastDay = ref(new Date());
|
||||||
|
const entityCalendarRef = ref(null);
|
||||||
|
|
||||||
|
const arrayData = useArrayData(props.dataKey);
|
||||||
|
const { store } = arrayData;
|
||||||
|
const _data = ref(null);
|
||||||
|
const days = ref({});
|
||||||
|
const events = ref([]);
|
||||||
|
|
||||||
|
const refreshEvents = () => {
|
||||||
|
days.value = {};
|
||||||
|
if (!events.value?.length || !firstDay.value || !lastDay.value) return;
|
||||||
|
|
||||||
|
let day = new Date(firstDay.value.getTime());
|
||||||
|
let endDate = new Date(lastDay.value.getTime());
|
||||||
|
|
||||||
|
while (day <= endDate) {
|
||||||
|
let stamp = day.getTime();
|
||||||
|
let dayEvents = [];
|
||||||
|
|
||||||
|
for (let event of events.value) {
|
||||||
|
const eventStart = event.started ? new Date(event.started).getTime() : null;
|
||||||
|
const eventEnd = event.finished ? new Date(event.finished).getTime() : null;
|
||||||
|
|
||||||
|
let match = (!eventStart || stamp >= eventStart) &&
|
||||||
|
(!eventEnd || stamp <= eventEnd);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
dayEvents.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dayEvents.length) {
|
||||||
|
days.value[stamp] = dayEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
day.setDate(day.getDate() + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => store.data,
|
||||||
|
(value) => {
|
||||||
|
_data.value = value;
|
||||||
|
events.value = Array.isArray(value) ? value : [];
|
||||||
|
|
||||||
|
function toStamp(date) {
|
||||||
|
return date && new Date(date).setHours(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.value) {
|
||||||
|
for (let event of events.value) {
|
||||||
|
event.dated = toStamp(event.dated);
|
||||||
|
event.finished = toStamp(event.finished);
|
||||||
|
event.started = toStamp(event.started);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshEvents();
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(() => entityCalendarRef.value?.firstDay, (newVal) => {
|
||||||
|
if (newVal) firstDay.value = new Date(newVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => entityCalendarRef.value?.lastDay, (newVal) => {
|
||||||
|
if (newVal) lastDay.value = new Date(newVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<EntityCalendarGrid
|
||||||
|
ref="entityCalendarRef"
|
||||||
|
:data-key="dataKey"
|
||||||
|
:calendar-component="VehicleCalendar"
|
||||||
|
:additional-props="{ daysMap: days }"
|
||||||
|
@refresh-events="refreshEvents"
|
||||||
|
v-bind="$attrs"
|
||||||
|
/>
|
||||||
|
</template>
|
|
@ -15,6 +15,8 @@ vehicle:
|
||||||
remove: Vehicle removed
|
remove: Vehicle removed
|
||||||
search: Search Vehicle
|
search: Search Vehicle
|
||||||
searchInfo: Search by id or number plate
|
searchInfo: Search by id or number plate
|
||||||
|
deleteTitle: This item will be deleted
|
||||||
|
deleteSubtitle: Are you sure you want to continue?
|
||||||
params:
|
params:
|
||||||
vehicleTypeFk: Type
|
vehicleTypeFk: Type
|
||||||
vehicleStateFk: State
|
vehicleStateFk: State
|
||||||
|
|
|
@ -15,6 +15,8 @@ vehicle:
|
||||||
remove: Vehículo eliminado
|
remove: Vehículo eliminado
|
||||||
search: Buscar Vehículo
|
search: Buscar Vehículo
|
||||||
searchInfo: Buscar por id o matrícula
|
searchInfo: Buscar por id o matrícula
|
||||||
|
deleteTitle: Este elemento será eliminado
|
||||||
|
deleteSubtitle: ¿Seguro que quieres continuar?
|
||||||
params:
|
params:
|
||||||
vehicleTypeFk: Tipo
|
vehicleTypeFk: Tipo
|
||||||
vehicleStateFk: Estado
|
vehicleStateFk: Estado
|
||||||
|
|
|
@ -11,6 +11,7 @@ import '@quasar/quasar-ui-qcalendar/src/QCalendarVariables.scss';
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import useWeekdaysOrder from 'src/composables/getWeekdays';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
year: {
|
year: {
|
||||||
|
@ -44,6 +45,7 @@ const { locale } = useI18n();
|
||||||
|
|
||||||
const calendarRef = ref(null);
|
const calendarRef = ref(null);
|
||||||
const weekdayStore = useWeekdayStore();
|
const weekdayStore = useWeekdayStore();
|
||||||
|
const weekDays = useWeekdaysOrder();
|
||||||
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'));
|
||||||
|
@ -182,7 +184,7 @@ watch(_year, (newValue) => {
|
||||||
no-outside-days
|
no-outside-days
|
||||||
:selected-dates="calendarEventDates"
|
:selected-dates="calendarEventDates"
|
||||||
no-active-date
|
no-active-date
|
||||||
:weekdays="[1, 2, 3, 4, 5, 6, 0]"
|
:weekdays="weekDays"
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Asi es como estaba en la docu de quasar, pero el cambio lo veo bien Asi es como estaba en la docu de quasar, pero el cambio lo veo bien
|
|||||||
short-weekday-label
|
short-weekday-label
|
||||||
:locale="locale"
|
:locale="locale"
|
||||||
:now="today"
|
:now="today"
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { QCalendarMonth } from '@quasar/quasar-ui-qcalendar/src/index.js';
|
import { QCalendarMonth } from '@quasar/quasar-ui-qcalendar/src/index.js';
|
||||||
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
|
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
|
||||||
|
import useWeekdaysOrder from 'src/composables/getWeekdays';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -32,6 +34,7 @@ const emit = defineEmits(['update:modelValue', 'clickDate', 'onMoved']);
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
|
|
||||||
const calendarRef = ref(null);
|
const calendarRef = ref(null);
|
||||||
|
const weekDays = useWeekdaysOrder();
|
||||||
|
|
||||||
const stateClasses = {
|
const stateClasses = {
|
||||||
CONFIRMED: {
|
CONFIRMED: {
|
||||||
|
@ -135,7 +138,7 @@ const paintWorkWeeks = async () => {
|
||||||
ref="calendarRef"
|
ref="calendarRef"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
show-work-weeks
|
show-work-weeks
|
||||||
:weekdays="[1, 2, 3, 4, 5, 6, 0]"
|
:weekdays="weekDays"
|
||||||
:selected-dates="selectedDates"
|
:selected-dates="selectedDates"
|
||||||
:min-weekday-label="1"
|
:min-weekday-label="1"
|
||||||
:locale="locale"
|
:locale="locale"
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { QCalendarMonth } from '@quasar/quasar-ui-qcalendar/src/index.js';
|
||||||
import '@quasar/quasar-ui-qcalendar/src/QCalendarVariables.scss';
|
import '@quasar/quasar-ui-qcalendar/src/QCalendarVariables.scss';
|
||||||
|
|
||||||
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
|
||||||
|
import useWeekdaysOrder from 'src/composables/getWeekdays';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -46,6 +47,7 @@ const route = useRoute();
|
||||||
|
|
||||||
const calendarRef = ref(null);
|
const calendarRef = ref(null);
|
||||||
const weekdayStore = useWeekdayStore();
|
const weekdayStore = useWeekdayStore();
|
||||||
|
const weekDays = useWeekdaysOrder();
|
||||||
const showZoneClosingTable = ref(false);
|
const showZoneClosingTable = ref(false);
|
||||||
const zoneClosingData = ref(null);
|
const zoneClosingData = ref(null);
|
||||||
const today = ref(date.formatDate(Date.vnNew(), 'YYYY-MM-DD'));
|
const today = ref(date.formatDate(Date.vnNew(), 'YYYY-MM-DD'));
|
||||||
|
@ -161,7 +163,7 @@ const handleDateClick = (timestamp) => {
|
||||||
show-work-weeks
|
show-work-weeks
|
||||||
no-outside-days
|
no-outside-days
|
||||||
no-active-date
|
no-active-date
|
||||||
:weekdays="[1, 2, 3, 4, 5, 6, 0]"
|
:weekdays="weekDays"
|
||||||
short-weekday-label
|
short-weekday-label
|
||||||
:locale="locale"
|
:locale="locale"
|
||||||
:now="today"
|
:now="today"
|
||||||
|
|
|
@ -229,22 +229,3 @@ onUnmounted(() => arrayData.destroy());
|
||||||
</div>
|
</div>
|
||||||
</QCard>
|
</QCard>
|
||||||
</template>
|
</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>
|
|
||||||
|
|
|
@ -170,6 +170,7 @@ const vehicleCard = {
|
||||||
'VehicleBasicData',
|
'VehicleBasicData',
|
||||||
'VehicleNotes',
|
'VehicleNotes',
|
||||||
'VehicleDms',
|
'VehicleDms',
|
||||||
|
'VehicleEvents'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -209,6 +210,15 @@ const vehicleCard = {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Route/Vehicle/VehicleDms.vue'),
|
component: () => import('src/pages/Route/Vehicle/VehicleDms.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'VehicleEvents',
|
||||||
|
path: 'events',
|
||||||
|
meta: {
|
||||||
|
title: 'calendar',
|
||||||
|
icon: 'vn:calendar',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Route/Vehicle/Card/VehicleEvents.vue'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
describe('Vehicle', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1920, 1080);
|
||||||
|
cy.login('deliveryAssistant');
|
||||||
|
cy.visit(`/#/route/vehicle/3/events`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add, edit and delete a vehicle event', () => {
|
||||||
|
cy.get('.q-page-sticky > div > .q-btn').click();
|
||||||
|
cy.dataCy('Started_inputDate').type('01/01/2001');
|
||||||
|
cy.dataCy('Finished_inputDate').type('08/02/2001');
|
||||||
provira marked this conversation as resolved
Outdated
jgallego
commented
selector muy largo usar cy sin depender del resto de la ruta selector muy largo usar cy sin depender del resto de la ruta
|
|||||||
|
cy.get(':nth-child(5)').find('[data-cy="Description_input"]').clear().type('Test');
|
||||||
|
cy.selectOption('[data-cy="State_input"]', 3);
|
||||||
|
cy.get('.q-mt-lg > .q-btn--standard').click();
|
||||||
|
|
||||||
|
cy.get('.q-current-day > .q-calendar-month__day--content > .q-btn').click();
|
||||||
|
cy.dataCy('Started_inputDate').clear().type('03/02/2001');
|
||||||
|
cy.dataCy('Finished_inputDate').clear().type('15/03/2001');
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Simplificar con cy.get(':nth-child(5)').find([data-cy]), se puede? Simplificar con cy.get(':nth-child(5)').find([data-cy]), se puede?
provira
commented
Si, se puede, ya esta cambiado Si, se puede, ya esta cambiado
|
|||||||
|
cy.get(':nth-child(5)').find('[data-cy="Description_input"]').clear().type('Test2');
|
||||||
|
cy.selectOption('[data-cy="State_input"]', 5);
|
||||||
|
cy.get('.q-mt-lg > .q-btn--standard').click();
|
||||||
|
|
||||||
|
cy.dataCy('delete_event').eq(0).click();
|
||||||
|
cy.dataCy('VnConfirm_confirm').click();
|
||||||
|
});
|
||||||
provira marked this conversation as resolved
jgallego
commented
los it dependen unos de otros, haz uno, que cree, consulte, y borre. los it dependen unos de otros, haz uno, que cree, consulte, y borre.
Así evitas tb el tener que hacer login cada vez.
@alexm ho veus ok?
alexm
commented
Sii millor junt, aixina no depenen uns dels altres Sii millor junt, aixina no depenen uns dels altres
|
|||||||
|
});
|
si haces ({...}) queda mas elegante. Los parentesis es sinonimo de hacer return
NOTA: los 3 puntos(...) corresponden al contenido existente