import ngModule from '../module'; import Section from 'salix/components/section'; import './style.scss'; class Controller extends Section { constructor($element, $, vnWeekDays) { super($element, $); this.weekDays = []; this.weekdayNames = vnWeekDays.locales; this.entryDirections = [ {code: 'in', description: this.$t('In')}, {code: 'middle', description: this.$t('Intermediate')}, {code: 'out', description: this.$t('Out')} ]; } $postLink() { this.date = new Date(); } get worker() { return this._worker; } set worker(value) { this._worker = value; if (value) { this.getActiveContract() .then(() => this.getAbsences()); } } /** * The current selected date */ get date() { return this._date; } set date(value) { this._date = value; value.setHours(0, 0, 0, 0); let weekOffset = value.getDay() - 1; if (weekOffset < 0) weekOffset = 6; let started = new Date(value.getTime()); started.setDate(started.getDate() - weekOffset); this.started = started; let ended = new Date(started.getTime()); ended.setHours(23, 59, 59, 59); ended.setDate(ended.getDate() + 6); this.ended = ended; this.weekDays = []; let dayIndex = new Date(started.getTime()); while (dayIndex < ended) { this.weekDays.push({ dated: new Date(dayIndex.getTime()) }); dayIndex.setDate(dayIndex.getDate() + 1); } this.fetchHours(); } /** * Worker hours data */ get hours() { return this._hours; } set hours(value) { this._hours = value; for (const weekDay of this.weekDays) { if (value) { let day = weekDay.dated.getDay(); weekDay.hours = value .filter(hour => new Date(hour.timed).getDay() == day) .sort((a, b) => new Date(a.timed) - new Date(b.timed)); } else weekDay.hours = null; } } getActiveContract() { return this.$http.get(`Workers/${this.worker.id}/activeContract`) .then(res => this.businessId = res.data.businessFk); } fetchHours() { const params = {workerFk: this.$params.id}; const filter = { where: {and: [ {timed: {gte: this.started}}, {timed: {lte: this.ended}} ]} }; this.$.model.applyFilter(filter, params).then(() => { this.getWorkedHours(this.started, this.ended); }); } hasEvents(day) { return day >= this.started && day < this.ended; } getAbsences() { const fullYear = this.started.getFullYear(); let params = { businessFk: this.businessId, year: fullYear }; return this.$http.get(`Calendars/absences`, {params}) .then(res => this.onData(res.data)); } onData(data) { const events = {}; let 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 }); }); } this.weekDays.forEach(day => { const timestamp = day.dated.getTime(); if (events[timestamp]) day.event = events[timestamp]; }); } getWorkedHours(from, to) { this.weekTotalHours = null; let weekTotalHours = 0; let params = { id: this.$params.id, from: from, to: to }; const query = `Workers/${this.$params.id}/getWorkedHours`; return this.$http.get(query, {params}).then(res => { const workDays = res.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 this.weekDays) { 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; } } this.weekTotalHours = weekTotalHours; }); } getFinishTime() { if (!this.weekDays) return; let today = new Date(); today.setHours(0, 0, 0, 0); let todayInWeek = this.weekDays.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.`; } } } set weekTotalHours(totalHours) { this._weekTotalHours = this.formatHours(totalHours); } get weekTotalHours() { return this._weekTotalHours; } formatHours(timestamp = 0) { 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}`; } showAddTimeDialog(weekday) { const timed = new Date(weekday.dated.getTime()); timed.setHours(0, 0, 0, 0); this.newTimeEntry = { workerFk: this.$params.id, timed: timed }; this.selectedWeekday = weekday; this.$.addTimeDialog.show(); } addTime() { try { const entry = this.newTimeEntry; if (!entry.direction) throw new Error(`The entry type can't be empty`); const query = `WorkerTimeControls/${this.worker.id}/addTimeEntry`; this.$http.post(query, entry) .then(() => this.fetchHours()); } catch (e) { this.vnApp.showError(this.$t(e.message)); return false; } return true; } showDeleteDialog($event, hour) { $event.preventDefault(); this.timeEntryToDelete = hour; this.$.deleteEntryDialog.show(); } deleteTimeEntry() { const entryId = this.timeEntryToDelete.id; this.$http.post(`WorkerTimeControls/${entryId}/deleteTimeEntry`).then(() => { this.fetchHours(); this.vnApp.showSuccess(this.$t('Entry removed')); }); } edit($event, hour) { if ($event.defaultPrevented) return; this.selectedRow = hour; this.$.editEntry.show($event); } save() { try { const entry = this.selectedRow; if (!entry.direction) throw new Error(`The entry type can't be empty`); const query = `WorkerTimeControls/${entry.id}/updateTimeEntry`; this.$http.post(query, {direction: entry.direction}) .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))) .then(() => this.$.editEntry.hide()) .then(() => this.fetchHours()); } catch (e) { this.vnApp.showError(this.$t(e.message)); } } } Controller.$inject = ['$element', '$scope', 'vnWeekDays']; ngModule.vnComponent('vnWorkerTimeControl', { template: require('./index.html'), controller: Controller, bindings: { worker: '<' } });