build(dev): finished timeblocks rework

This commit is contained in:
Matej Glasnák committed 2025-12-08 23:54:35 +01:00
1 parent 1b0a9d5fff
commit 90dd4ee4b6
15 files changed
+194 -166

No files matched your search

@@ -150,6 +150,20 @@ export default {
};
},
watch: {
ends_at_time() {
this._syncDatesTimes();
},
starts_at_time() {
this._syncDatesTimes();
},
datepicker() {
this._syncDatesTimes();
},
},
methods: {
async showModal({ blocker }) {
this.visible = true;
@@ -252,20 +266,6 @@ export default {
.format('YYYY-MM-DD HH:mm');
},
},
watch: {
ends_at_time() {
this._syncDatesTimes();
},
starts_at_time() {
this._syncDatesTimes();
},
datepicker() {
this._syncDatesTimes();
},
},
} /* c8 ignore start */ /* eslint-disable */;
/* istanbul ignore next */
function oo_cm() {
@@ -430,6 +430,57 @@ export default {
};
},
watch: {
editMode() {
this.$nextTick(() => {
this.$refs['description']?.setHTML(this.mastertask.description || '');
if (!this.mastertask?.id) return;
const date = new Date(this.mastertask.deadline);
const hours = date.getHours();
const minutes = date.getMinutes();
this.mastertask._deadline_time = `${hours
.toString()
.padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
});
},
mastertask: {
handler(val) {
if (this.editMode && !this.mastertask?.id) {
localStorage.setItem('mastertaskData', JSON.stringify(val));
}
},
deep: true,
},
'mastertask.team_id': {
handler(value, oldValue) {
if (this.editMode && !value && oldValue) {
// Removes only employees from the old team when team_id is removed
const oldTeamEmployeesIds =
this.teams
.find((team) => team.id == oldValue)
?.employees.map((employee) => employee?.id) || [];
const employeesNotInOldTeam = this.mastertask.employees.filter(
(employee) => !oldTeamEmployeesIds.includes(employee?.id),
);
this.mastertask.employees = employeesNotInOldTeam;
}
},
deep: true,
},
'$route.query': {
handler(_, oldValue) {
if (oldValue?.subtask?.length && this.mastertask?.id) {
this.loadMastertask(this.mastertask.id);
}
},
deep: true,
},
},
mounted() {
this.$events.on('close-both-modals', this.closeBothModals);
@@ -693,57 +744,6 @@ export default {
return isValid;
},
},
watch: {
editMode() {
this.$nextTick(() => {
this.$refs['description']?.setHTML(this.mastertask.description || '');
if (!this.mastertask?.id) return;
const date = new Date(this.mastertask.deadline);
const hours = date.getHours();
const minutes = date.getMinutes();
this.mastertask._deadline_time = `${hours
.toString()
.padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
});
},
mastertask: {
handler(val) {
if (this.editMode && !this.mastertask?.id) {
localStorage.setItem('mastertaskData', JSON.stringify(val));
}
},
deep: true,
},
'mastertask.team_id': {
handler(value, oldValue) {
if (this.editMode && !value && oldValue) {
// Removes only employees from the old team when team_id is removed
const oldTeamEmployeesIds =
this.teams
.find((team) => team.id == oldValue)
?.employees.map((employee) => employee?.id) || [];
const employeesNotInOldTeam = this.mastertask.employees.filter(
(employee) => !oldTeamEmployeesIds.includes(employee?.id),
);
this.mastertask.employees = employeesNotInOldTeam;
}
},
deep: true,
},
'$route.query': {
handler(_, oldValue) {
if (oldValue?.subtask?.length && this.mastertask?.id) {
this.loadMastertask(this.mastertask.id);
}
},
deep: true,
},
},
};
</script>
@@ -392,7 +392,8 @@ export default {
this._update(subtask);
},
deleteTimeblockWithoutId(i) {
deleteTimeblockWithoutId(index) {
console.log(index);
this.$emit('delete-timeblock');
},
@@ -15,25 +15,27 @@
@update:model-value="handleUpdateEmployee"
/>
<v-text-field
:model-value="modelValue.duration"
class="employee-select__duration-field"
variant="solo"
type="number"
label="Časový odhad"
:class="{ error: v$.duration.$error }"
:error-messages="v$.duration.$errors.map((e: any) => String(e.$message))"
append-inner-icon="mdi-clock-outline"
@update:model-value="handleUpdateDuration"
/>
<div class="employee-select__duration-container">
<v-text-field
:model-value="modelValue.duration"
class="employee-select__duration-field"
variant="solo"
type="number"
label="Časový odhad"
:class="{ error: v$.duration.$error }"
:error-messages="v$.duration.$errors.map((e: any) => String(e.$message))"
append-inner-icon="mdi-clock-outline"
@update:model-value="handleUpdateDuration"
/>
<button
class="employee-select__delete-button"
:disabled="!modelValue.id"
@click="handleClearEmployee"
>
<v-icon icon="mdi-close" />
</button>
<button
class="employee-select__delete-button"
:disabled="!modelValue.id"
@click="handleClearEmployee"
>
<v-icon icon="mdi-close" />
</button>
</div>
</div>
</template>
@@ -160,6 +162,16 @@ defineExpose({
align-items: start
gap: 10px
@media (max-width: 768px)
flex-direction: column
gap: 5px
&__duration-container
display: flex
justify-content: space-between
align-items: start
gap: 10px
&__select-field
width: 100%
@@ -73,6 +73,17 @@
hide-details
@input="$emit('updateEndTime', $event)"
/>
<div class="timeblock__time-overview">
<p>
Naplánovaný čas:
<span>{{ plannedTime }}h</span>
</p>
<p>
Volný čas:
<span>{{ freeTime }}h</span>
</p>
</div>
</div>
<div
v-if="!isTimeRangeValid || endTimeErrorMessage"
@@ -115,10 +126,14 @@ interface Props {
hasStartTimeError: boolean;
hasEndTimeError: boolean;
endTimeErrorMessage?: string;
plannedTime: string | number;
freeTime: string | number;
}
const props = withDefaults(defineProps<Props>(), {
endTimeErrorMessage: '',
plannedTime: '',
freeTime: '',
});
defineEmits<{
@@ -231,6 +246,20 @@ const isCurrentDay = computed(() => {
width: 140px !important
flex-grow: 0
.timeblock__time-overview
height: 44px
display: flex
flex-direction: column
justify-content: space-between
p
font-size: 14px
font-weight: 400
span
font-weight: 500
color: #7f39fb
.error-input
::v-deep input
border-bottom: 2px solid #ff5252 !important
@@ -180,13 +180,13 @@ const getTimePosition = (date: Date): number => {
const hour = date.getHours();
const minute = date.getMinutes();
const totalHours = hour + minute / 60;
return (totalHours - props.startHour) * props.hourWidth;
return (totalHours - props.startHour) * props.hourWidth + 1;
};
const getTimeWidth = (start: Date, end: Date): number => {
const startHour = start.getHours() + start.getMinutes() / 60;
const endHour = end.getHours() + end.getMinutes() / 60;
return (endHour - startHour) * props.hourWidth;
return (endHour - startHour) * props.hourWidth - 2;
};
// Expose refs for parent component
@@ -252,6 +252,7 @@ defineExpose({
top: 5px
height: 50px
background: #7f39fb
border: 1px solid #6a1bf7
opacity: 0.6
border-radius: 2px
z-index: 2
@@ -299,4 +300,3 @@ defineExpose({
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3)
pointer-events: none
</style>
@@ -11,6 +11,8 @@
:has-start-time-error="hasStartTimeError"
:has-end-time-error="hasEndTimeError"
:end-time-error-message="endTimeErrorMessage"
:planned-time="_scheduledTime"
:free-time="_freeTime"
@previous-day="previousDay"
@next-day="nextDay"
@update-date="updateDate"
+13 -13
View File
@@ -143,6 +143,19 @@ export default {
};
},
watch: {
employeeSelect(employeeId) {
if (!employeeId) return;
const employee = this.enrichedEmployees.find(
(employee) => employee.id == employeeId,
);
this.team.employees.push(employee);
this.employeeSelect = null;
this.$refs.autocomplete.search = '';
},
},
methods: {
async showModal({ team = null }) {
this.visible = true;
@@ -200,18 +213,5 @@ export default {
return team;
},
},
watch: {
employeeSelect(employeeId) {
if (!employeeId) return;
const employee = this.enrichedEmployees.find(
(employee) => employee.id == employeeId,
);
this.team.employees.push(employee);
this.employeeSelect = null;
this.$refs.autocomplete.search = '';
},
},
};
</script>