-
-
-
- {{ $t('timesheet_approvals.print_report.options') }}
-
+
+
+ {{ $t('timesheet_approvals.print_report.type') }}
+
-
-
diff --git a/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts b/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts
index 3189d34..2c3a4d3 100644
--- a/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts
+++ b/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts
@@ -1,58 +1,72 @@
import { useTimesheetStore } from "src/stores/timesheet-store";
-import type { TimesheetApprovalCSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
+import type { CSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
+import { fromEnToFrShiftType } from "src/utils/translator";
export const useTimesheetApprovalApi = () => {
- const timesheet_store = useTimesheetStore();
+ const timesheetStore = useTimesheetStore();
const DATE_REGEX = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
const getTimesheetOverviews = async (date?: string) => {
- timesheet_store.is_loading = true;
+ timesheetStore.is_loading = true;
- const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date);
- if (success) await timesheet_store.getTimesheetOverviews();
+ const success = await timesheetStore.getPayPeriodByDateOrYearAndNumber(date);
+ if (success) await timesheetStore.getTimesheetOverviews();
- timesheet_store.is_loading = false;
+ timesheetStore.is_loading = false;
}
const getTimesheetOverviewsByDate = async (date: string) => {
const valid_date = DATE_REGEX.test(date);
- timesheet_store.is_loading = true;
+ timesheetStore.is_loading = true;
if (valid_date) {
- const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date);
- if (success) await timesheet_store.getTimesheetOverviews();
+ const success = await timesheetStore.getPayPeriodByDateOrYearAndNumber(date);
+ if (success) await timesheetStore.getTimesheetOverviews();
}
- timesheet_store.is_loading = false;
+ timesheetStore.is_loading = false;
};
const toggleTimesheetsApprovalByEmployeeEmail = async (email: string, approval_status: boolean) => {
- timesheet_store.is_loading = true;
+ timesheetStore.is_loading = true;
- const success = await timesheet_store.getTimesheetsByOptionalEmployeeEmail(email);
+ const success = await timesheetStore.getTimesheetsByOptionalEmployeeEmail(email);
if (success) {
- const approval_success = await timesheet_store.toggleTimesheetsApprovalByEmployeeEmail(email, approval_status);
- const overview = timesheet_store.pay_period_overviews.find(overview => overview.email === email);
+ const approval_success = await timesheetStore.toggleTimesheetsApprovalByEmployeeEmail(email, approval_status);
+ const overview = timesheetStore.pay_period_overviews.find(overview => overview.email === email);
if (overview && approval_success) {
overview.is_approved = approval_status;
- await timesheet_store.getTimesheetsByOptionalEmployeeEmail(email);
+ await timesheetStore.getTimesheetsByOptionalEmployeeEmail(email);
}
}
- timesheet_store.is_loading = false;
+ timesheetStore.is_loading = false;
};
- const getTimesheetApprovalCSVReport = async (report_filter_company: boolean[], report_filter_type: boolean[]) => {
- if (timesheet_store.pay_period === undefined) return;
+ const getTimesheetApprovalCSVReport = async (selectedFilters: CSVReportFilters): Promise<{file: Blob, fileName: string} | undefined> => {
+ if (timesheetStore.pay_period === undefined) return;
- const [targo, solucom] = report_filter_company;
- const [shifts, expenses, holiday, vacation] = report_filter_type;
- const options = {
- shifts, expenses, holiday, vacation, targo, solucom
- } as TimesheetApprovalCSVReportFilters;
+ const success = await timesheetStore.getPayPeriodReport(selectedFilters);
+ if (!success) return;
- await timesheet_store.getPayPeriodReport(options);
+ // const year = timesheetStore.pay_period?.pay_year;
+ // const number = timesheetStore.pay_period?.pay_period_no;
+ const startDate = timesheetStore.pay_period?.period_start;
+ const endDate = timesheetStore.pay_period?.period_end;
+ const content: string[] = [];
+
+ selectedFilters.shiftTypes.forEach(type => content.push(fromEnToFrShiftType(type)));
+ content.push(selectedFilters.companyName);
+
+ if (selectedFilters.includeExpenses) content.push('Dépenses');
+
+ // const fileName = `${year}-${number}_${content.join('_')}.csv`;
+ const fileName = `${startDate}_AU_${endDate}_${content.join('_')}.csv`;
+
+ if (!timesheetStore.payPeriodReport) return;
+
+ return {file: timesheetStore.payPeriodReport, fileName};
};
return {
diff --git a/src/modules/timesheet-approval/models/timesheet-approval-csv-report.models.ts b/src/modules/timesheet-approval/models/timesheet-approval-csv-report.models.ts
index 921605a..7209090 100644
--- a/src/modules/timesheet-approval/models/timesheet-approval-csv-report.models.ts
+++ b/src/modules/timesheet-approval/models/timesheet-approval-csv-report.models.ts
@@ -1,18 +1,28 @@
-export class TimesheetApprovalCSVReportFilters {
- shifts: boolean;
- expenses: boolean;
- holiday: boolean;
- vacation: boolean;
- targo: boolean;
- solucom: boolean;
+import type { ShiftType } from "src/modules/timesheets/models/shift.models";
+import type { CompanyNames } from "src/modules/employee-list/models/employee-profile.models";
+
+export class CSVReportFilters {
+ companyName: CompanyNames;
+ includeExpenses: boolean;
+ shiftTypes: ShiftType[];
constructor() {
- this.shifts = true;
- this.expenses = true;
- this.holiday = true;
- this.vacation = true;
- this.targo = true;
- this.solucom = false;
- };
-}
+ this.companyName = 'Targo';
+ this.includeExpenses = false;
+ this.shiftTypes = ['REGULAR', 'EVENING', 'EMERGENCY', 'SICK']
+ }
+};
+export const companyOptions: {label: string, value: CompanyNames}[] = [
+ { label: 'timesheet_approvals.print_report.targo', value: 'Targo' },
+ { label: 'timesheet_approvals.print_report.solucom', value: 'Solucom' },
+];
+
+export const typeOptions: {label: string, value: ShiftType}[] = [
+ { label: 'shared.shift_type.regular', value: 'REGULAR' },
+ { label: 'shared.shift_type.evening', value: 'EVENING' },
+ { label: 'shared.shift_type.emergency', value: 'EMERGENCY' },
+ { label: 'shared.shift_type.sick', value: 'SICK' },
+ { label: 'shared.shift_type.holiday', value: 'HOLIDAY' },
+ { label: 'shared.shift_type.vacation', value: 'VACATION' },
+];
diff --git a/src/modules/timesheet-approval/services/timesheet-approval-service.ts b/src/modules/timesheet-approval/services/timesheet-approval-service.ts
index f2162d8..6fcacc1 100644
--- a/src/modules/timesheet-approval/services/timesheet-approval-service.ts
+++ b/src/modules/timesheet-approval/services/timesheet-approval-service.ts
@@ -1,6 +1,6 @@
import { api } from "src/boot/axios";
import type { BackendResponse } from "src/modules/shared/models/backend-response.models";
-import type { TimesheetApprovalCSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
+import type { CSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
import type { PayPeriodOverviewResponse } from "src/modules/timesheet-approval/models/timesheet-overview.models";
export const timesheetApprovalService = {
@@ -9,13 +9,13 @@ export const timesheetApprovalService = {
return response.data.data;
},
- getPayPeriodReportByYearAndPeriodNumber: async (year: number, period_number: number, filters?: TimesheetApprovalCSVReportFilters) => {
- const response = await api.get(`exports/csv/${year}/${period_number}`, { params: filters, responseType: 'arraybuffer' });
- return response;
+ getPayPeriodReportByYearAndPeriodNumber: async (year: number, period_number: number, filters?: CSVReportFilters): Promise
=> {
+ const response = await api.post(`exports/csv/${year}/${period_number}`, filters, { responseType: 'blob' });
+ return response.data;
},
- updateTimesheetsApprovalStatus: async (email: string, timesheet_ids: number[], is_approved: boolean): Promise> => {
- const response = await api.patch>('pay-periods/pay-period-approval', { email, timesheet_ids, is_approved});
+ updateTimesheetsApprovalStatus: async (email: string, timesheet_ids: number[], is_approved: boolean): Promise> => {
+ const response = await api.patch>('pay-periods/pay-period-approval', { email, timesheet_ids, is_approved });
return response.data;
},
diff --git a/src/modules/timesheets/components/expense-dialog-form.vue b/src/modules/timesheets/components/expense-dialog-form.vue
index 0876388..11ea0b6 100644
--- a/src/modules/timesheets/components/expense-dialog-form.vue
+++ b/src/modules/timesheets/components/expense-dialog-form.vue
@@ -6,7 +6,6 @@
import { useI18n } from 'vue-i18n';
import { computed, onMounted, ref } from 'vue';
- import { useUiStore } from 'src/stores/ui-store';
import { useExpensesStore } from 'src/stores/expense-store';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { useExpensesApi } from 'src/modules/timesheets/composables/use-expense-api';
@@ -28,7 +27,6 @@
}>();
const { t } = useI18n();
- const ui_store = useUiStore();
const timesheetStore = useTimesheetStore();
const expenseStore = useExpensesStore();
const expensesApi = useExpensesApi();
@@ -168,7 +166,6 @@
{
expenseStore.isShowingAttachmentDialog = true;
await expenseStore.getAttachmentURL(expense.value.attachment_key);
- console.log('image url: ', expenseStore.attachmentURL);
}
const hideUpdateForm = () => {
diff --git a/src/modules/timesheets/components/mobile/expense-dialog-form-mobile.vue b/src/modules/timesheets/components/mobile/expense-dialog-form-mobile.vue
index 5119ecc..773a19a 100644
--- a/src/modules/timesheets/components/mobile/expense-dialog-form-mobile.vue
+++ b/src/modules/timesheets/components/mobile/expense-dialog-form-mobile.vue
@@ -4,7 +4,6 @@
>
import { computed, ref, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
- import { useUiStore } from 'src/stores/ui-store';
import { useExpensesStore } from 'src/stores/expense-store';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { useExpensesApi } from 'src/modules/timesheets/composables/use-expense-api';
@@ -26,7 +25,6 @@
}>();
const { t } = useI18n();
- const ui_store = useUiStore();
const timesheet_store = useTimesheetStore();
const expenses_store = useExpensesStore();
const auth_store = useAuthStore();
@@ -168,8 +166,7 @@
();
- const ui_store = useUiStore();
+ const uiStore = useUiStore();
const shiftTypeSelected = ref(SHIFT_OPTIONS.find(option => option.value == shift.value.type));
- const select_ref = ref(null);
- const is_showing_comment_popup = ref(false);
- const error_message = ref('');
+ const selectRef = ref(null);
+ const isShowingCommentPopup = ref(false);
+ const errorMessageRow = ref('');
const isShowingPredefinedTime = ref(shift.value.type === 'HOLIDAY');
const predefinedHoursString = ref('');
const predefinedHoursBgColor = ref(`bg-${shiftTypeSelected.value?.icon_color ?? ''}`);
@@ -63,10 +63,10 @@
const onTimeFieldBlur = (time_string: string) => {
if (time_string.length < 1 || !time_string) {
shift.value.has_error = true;
- error_message.value = 'timesheet.errors.SHIFT_TIME_REQUIRED';
+ errorMessageRow.value = 'timesheet.errors.SHIFT_TIME_REQUIRED';
} else {
shift.value.has_error = false;
- error_message.value = '';
+ errorMessageRow.value = '';
emit('onTimeFieldBlur');
}
}
@@ -86,7 +86,6 @@
if (option.value === 'SICK' || option.value === 'VACATION') {
const workedMinutes = getCurrentDailyMinutesWorked(currentShifts);
- console.log('worked minutes: ', workedMinutes);
const expectedWorkedMinutes = expectedDailyHours * 60;
const leftOverMinutes = expectedWorkedMinutes - workedMinutes;
@@ -102,15 +101,15 @@
}
onMounted(() => {
- if (ui_store.focus_next_component) {
- select_ref.value?.focus();
- select_ref.value?.showPopup();
+ if (uiStore.focusNextComponent) {
+ selectRef.value?.focus();
+ selectRef.value?.showPopup();
shiftTypeSelected.value = undefined;
- ui_store.focus_next_component = false;
+ uiStore.focusNextComponent = false;
}
if (errorMessage)
- error_message.value = errorMessage;
+ errorMessageRow.value = errorMessage;
});
@@ -120,13 +119,13 @@
-
+
+ import ShiftListDay from 'src/modules/timesheets/components/shift-list-day.vue';
+ import ShiftListDateWidget from 'src/modules/timesheets/components/shift-list-date-widget.vue';
+
+ import { date, useQuasar } from 'quasar';
+ import { ref, computed, watch, onMounted, inject } from 'vue';
+ import { useUiStore } from 'src/stores/ui-store';
+ import { useTimesheetStore } from 'src/stores/timesheet-store';
+ import { Shift } from 'src/modules/timesheets/models/shift.models';
+ import { useTimesheetApi } from 'src/modules/timesheets/composables/use-timesheet-api';
+ import type { TimesheetDay } from 'src/modules/timesheets/models/timesheet.models';
+ import { useI18n } from 'vue-i18n';
+
+ // ========== constants ========================================
+
+ const CURRENT_DATE_STRING = new Date().toISOString().slice(0, 10);
+
+ // ========== state ========================================
+
+ const emit = defineEmits<{
+ 'onCurrentDayComponentFound': [component: HTMLElement | undefined];
+ }>();
+
+ const q = useQuasar();
+ const { extractDate } = date;
+ const { locale } = useI18n();
+ const uiStore = useUiStore();
+ const timesheetApi = useTimesheetApi();
+ const timesheetStore = useTimesheetStore();
+
+ const mobileAnimationDirection = ref('fadeInLeft');
+ const currentDayComponent = ref(null);
+ const currentDayComponentWatcher = ref(currentDayComponent);
+ const employeeEmail = inject('employeeEmail');
+
+ // ========== computed ========================================
+
+ const animationStyle = computed(() => q.platform.is.mobile ? mobileAnimationDirection.value : 'fadeInDown');
+
+ // ========== methods ========================================
+
+ // const timesheetRows = computed(() => timesheetStore.timesheets);
+
+ const addNewShift = (day_shifts: Shift[], date: string, timesheet_id: number) => {
+ uiStore.focusNextComponent = true;
+ const newShift = new Shift;
+ newShift.date = date;
+ newShift.timesheet_id = timesheet_id;
+ day_shifts.push(newShift);
+ };
+
+ const deleteUnsavedShift = (timesheet_index: number, day_index: number) => {
+ if (timesheetStore.timesheets !== undefined) {
+ const day = timesheetStore.timesheets[timesheet_index]!.days[day_index]!;
+ const shifts_without_deleted_shift = day.shifts.filter(shift => shift.id !== 0);
+ day.shifts = shifts_without_deleted_shift;
+ }
+ };
+
+ const getDayApproval = (day: TimesheetDay) => {
+ if (day.shifts.length < 1) return false;
+ return day.shifts.every(shift => shift.is_approved === true);
+ };
+
+ const getMobileDayRef = (iso_date_string: string): string => {
+ return iso_date_string === CURRENT_DATE_STRING ? 'currentDayComponent' : '';
+ };
+
+ const getHolidayName = (date: string) => {
+ const holiday = timesheetStore.federal_holidays.find(holiday => holiday.date === date);
+ if (!holiday) return;
+
+ if (locale.value === 'fr-FR')
+ return holiday.nameFr;
+
+ else if (locale.value === 'en-CA')
+ return holiday.nameEn;
+ };
+
+ const onClickApplyWeeklyPreset = async (timesheet_id: number) => {
+ await timesheetApi.applyPreset(timesheet_id, undefined, undefined, employeeEmail);
+ }
+
+ onMounted(async () => {
+ await timesheetStore.getCurrentFederalHolidays();
+ });
+
+ watch(currentDayComponentWatcher, () => {
+ if (currentDayComponent.value && q.platform.is.mobile) {
+ emit('onCurrentDayComponentFound', currentDayComponent.value[0])
+ }
+ });
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getHolidayName(day.date) }}
+
+
+
+
+
+
+ {{ $d(extractDate(day.date, 'YYYY-MM-DD'), {
+ weekday: 'long', day: 'numeric', month:
+ 'long'
+ }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/timesheets/components/shift-list-date-widget.vue b/src/modules/timesheets/components/shift-list-date-widget.vue
index 47946bc..4ce59c2 100644
--- a/src/modules/timesheets/components/shift-list-date-widget.vue
+++ b/src/modules/timesheets/components/shift-list-date-widget.vue
@@ -32,7 +32,7 @@
:class="approved ? 'text-white' : ''"
:style="'font-size: ' + weekday_font_size"
>
- {{ $d(display_date, { weekday: $q.screen.lt.md ? 'short' : 'long'}) }}
+ {{ $d(display_date, { weekday: $q.platform.is.mobile ? 'short' : 'long'}) }}
- {{ $d(display_date, { month: $q.screen.lt.md ? 'short' : 'long' }) }}
+ {{ $d(display_date, { month: $q.platform.is.mobile ? 'short' : 'long' }) }}
\ No newline at end of file
diff --git a/src/modules/timesheets/components/shift-list-day-row.vue b/src/modules/timesheets/components/shift-list-day-row.vue
index 35142f7..3cbfa62 100644
--- a/src/modules/timesheets/components/shift-list-day-row.vue
+++ b/src/modules/timesheets/components/shift-list-day-row.vue
@@ -2,9 +2,11 @@
setup
lang="ts"
>
+ import DetailsDialogShiftMenu from 'src/modules/timesheet-approval/components/details-dialog-shift-menu.vue';
+
import { useI18n } from 'vue-i18n';
import { computed, inject, onMounted, ref } from 'vue';
- import { QSelect, QInput, useQuasar, type QSelectProps, QPopupProxy } from 'quasar';
+ import { QSelect, QInput, useQuasar, type QSelectProps } from 'quasar';
import { useUiStore } from 'src/stores/ui-store';
import { useAuthStore } from 'src/stores/auth-store';
import { getCurrentDailyMinutesWorked, getShiftOptions, getTimeStringFromMinutes, SHIFT_OPTIONS } from 'src/modules/timesheets/utils/shift.util';
@@ -41,7 +43,7 @@
const q = useQuasar();
const { t } = useI18n();
- const ui_store = useUiStore();
+ const uiStore = useUiStore();
const authStore = useAuthStore();
const mode = inject<'normal' | 'approval'>('mode');
@@ -51,7 +53,6 @@
const shiftErrorMessage = ref();
const is_showing_delete_confirm = ref(false);
const isShowingPredefinedTime = ref(shift.value.type === 'HOLIDAY');
- const popupProxyRef = ref(null);
const predefinedHoursString = ref('');
const predefinedHoursBgColor = ref(`bg-${shiftTypeSelected.value?.icon_color ?? ''}`);
@@ -59,12 +60,6 @@
const hasPTO = computed(() => currentShifts.some(shift => SHIFT_TYPES_WITH_PREDEFINED_TIMES.includes(shift.type)));
- const rightClickMenuIcon = computed(() => shift.value.is_approved ? 'lock_open' : 'lock');
-
- const rightClickMenuLabel = computed(() => shift.value.is_approved ?
- t('timesheet_approvals.tooltip.unapprove') :
- t('timesheet_approvals.tooltip.approve'));
-
const timeInputProps = computed(() => ({
dense: true,
borderless: shift.value.is_approved && isTimesheetApproved,
@@ -88,7 +83,7 @@
dense: true,
borderless: shift.value.is_approved && isTimesheetApproved,
readonly: shift.value.is_approved && isTimesheetApproved,
- optionsDense: !ui_store.is_mobile_mode,
+ optionsDense: !q.platform.is.mobile,
hideDropdownIcon: true,
menuOffset: [0, 10],
menuAnchor: "bottom middle",
@@ -136,12 +131,9 @@
is_showing_delete_confirm.value = state;
}
- const onRightClickApprove = () => {
+ const onclickToogleApproval = () => {
if (authStore.user?.user_module_access.includes('timesheets_approval'))
shift.value.is_approved = !shift.value.is_approved;
-
- if (popupProxyRef.value)
- popupProxyRef.value.hide();
}
const onShiftTypeChange = (option: ShiftOption) => {
@@ -153,7 +145,6 @@
if (option.value === 'SICK' || option.value === 'VACATION') {
const workedMinutes = getCurrentDailyMinutesWorked(currentShifts);
- console.log('worked minutes: ', workedMinutes);
const expectedWorkedMinutes = expectedDailyHours * 60;
const leftOverMinutes = expectedWorkedMinutes - workedMinutes;
@@ -169,42 +160,17 @@
}
onMounted(() => {
- if (ui_store.focus_next_component) {
+ if (uiStore.focusNextComponent) {
selectRef.value?.focus();
selectRef.value?.showPopup();
shiftTypeSelected.value = undefined;
- ui_store.focus_next_component = false;
+ uiStore.focusNextComponent = false;
}
});
-
-
-
-
-
-
-
- {{ rightClickMenuLabel }}
-
-
-
-
-
diff --git a/src/modules/timesheets/components/shift-list-weekly-overview.vue b/src/modules/timesheets/components/shift-list-weekly-overview.vue
index 11bd417..27791df 100644
--- a/src/modules/timesheets/components/shift-list-weekly-overview.vue
+++ b/src/modules/timesheets/components/shift-list-weekly-overview.vue
@@ -10,6 +10,7 @@
const { mode = 'totals', timesheetMode = 'normal', totalHours = 0, totalExpenses = 0 } = defineProps<{
mode: 'total-hours' | 'off-hours';
timesheetMode: 'approval' | 'normal';
+ weeklyHours?: number[];
totalHours?: number;
totalExpenses?: number;
}>();
@@ -18,8 +19,8 @@
const timesheetStore = useTimesheetStore();
const is_management = auth_store.user?.user_module_access.includes('timesheets_approval');
- const vacationHours = computed(() => timesheetStore.paid_time_off_totals.vacation_hours);
- const sickHours = computed(() => timesheetStore.paid_time_off_totals.sick_hours);
+ const vacationHours = computed(() => timesheetStore.paid_time_off_totals.vacation_hours);
+ const sickHours = computed(() => timesheetStore.paid_time_off_totals.sick_hours);
const bankedHours = computed(() => timesheetStore.paid_time_off_totals.banked_hours);
onMounted(async () => {
@@ -37,6 +38,18 @@
v-if="mode === 'total-hours'"
class="col column full-width"
>
+
+
+ {{ $t(`timesheet_approvals.table.weekly_hours_${index + 1}`) }}
+
+
+ {{ getHoursMinutesStringFromHoursFloat(hours) }}
+
+
{{ $t('timesheet.total_hours') }}
diff --git a/src/modules/timesheets/components/shift-list.vue b/src/modules/timesheets/components/shift-list.vue
index ef0cc42..2fbce33 100644
--- a/src/modules/timesheets/components/shift-list.vue
+++ b/src/modules/timesheets/components/shift-list.vue
@@ -27,32 +27,32 @@
const q = useQuasar();
const { extractDate } = date;
const { locale } = useI18n();
- const ui_store = useUiStore();
- const timesheet_api = useTimesheetApi();
- const timesheet_store = useTimesheetStore();
+ const uiStore = useUiStore();
+ const timesheetApi = useTimesheetApi();
+ const timesheetStore = useTimesheetStore();
- const mobile_animation_direction = ref('fadeInLeft');
+ const mobileAnimationDirection = ref('fadeInLeft');
const currentDayComponent = ref(null);
const currentDayComponentWatcher = ref(currentDayComponent);
const employeeEmail = inject('employeeEmail');
// ========== computed ========================================
- const animation_style = computed(() => ui_store.is_mobile_mode ? mobile_animation_direction.value : 'fadeInDown');
+ const animationStyle = computed(() => q.platform.is.mobile ? mobileAnimationDirection.value : 'fadeInDown');
// ========== methods ========================================
const addNewShift = (day_shifts: Shift[], date: string, timesheet_id: number) => {
- ui_store.focus_next_component = true;
- const new_shift = new Shift;
- new_shift.date = date;
- new_shift.timesheet_id = timesheet_id;
- day_shifts.push(new_shift);
+ uiStore.focusNextComponent = true;
+ const newShift = new Shift;
+ newShift.date = date;
+ newShift.timesheet_id = timesheet_id;
+ day_shifts.push(newShift);
};
const deleteUnsavedShift = (timesheet_index: number, day_index: number) => {
- if (timesheet_store.timesheets !== undefined) {
- const day = timesheet_store.timesheets[timesheet_index]!.days[day_index]!;
+ if (timesheetStore.timesheets !== undefined) {
+ const day = timesheetStore.timesheets[timesheet_index]!.days[day_index]!;
const shifts_without_deleted_shift = day.shifts.filter(shift => shift.id !== 0);
day.shifts = shifts_without_deleted_shift;
}
@@ -68,7 +68,7 @@
};
const getHolidayName = (date: string) => {
- const holiday = timesheet_store.federal_holidays.find(holiday => holiday.date === date);
+ const holiday = timesheetStore.federal_holidays.find(holiday => holiday.date === date);
if (!holiday) return;
if (locale.value === 'fr-FR')
@@ -79,11 +79,11 @@
};
const onClickApplyWeeklyPreset = async (timesheet_id: number) => {
- await timesheet_api.applyPreset(timesheet_id, undefined, undefined, employeeEmail);
+ await timesheetApi.applyPreset(timesheet_id, undefined, undefined, employeeEmail);
}
onMounted(async () => {
- await timesheet_store.getCurrentFederalHolidays();
+ await timesheetStore.getCurrentFederalHolidays();
});
watch(currentDayComponentWatcher, () => {
@@ -99,9 +99,9 @@
:class="$q.platform.is.mobile ? 'column no-wrap q-pb-lg' : 'row'"
>
@@ -210,11 +210,11 @@
timesheetStore.all_current_shifts.filter(shift => shift.has_error === true).length > 0);
const isTimesheetsApproved = computed(() => timesheetStore.timesheets.every(timesheet => timesheet.is_approved));
- // const timesheetStore.canSaveTimesheets = computed(() => {
- // /* eslint-disable-next-line */
- // const currentShifts = timesheetStore.timesheets.flatMap(timesheet => timesheet.days.flatMap(day => day.shifts.map(shift => { const { has_error, ...shft } = shift; return shft; })));
- // const initialShifts = timesheetStore.initial_timesheets.flatMap(timesheet => timesheet.days.flatMap(day => day.shifts));
-
- // return JSON.stringify(currentShifts) !== JSON.stringify(initialShifts);
- // });
+ const weeklyHours = computed(() => timesheetStore.timesheets.map(timesheet =>
+ Object.values(timesheet.weekly_hours).reduce((sum, hoursPerType) => sum += hoursPerType, 0) - timesheet.weekly_hours.sick
+ ));
const totalHours = computed(() => timesheetStore.timesheets.reduce((sum, timesheet) =>
sum += timesheet.weekly_hours.regular
+ timesheet.weekly_hours.evening
+ timesheet.weekly_hours.emergency
+ + timesheet.weekly_hours.vacation
+ + timesheet.weekly_hours.holiday
+ timesheet.weekly_hours.overtime,
- 0) //initial value
- );
+ 0 //initial value
+ ));
const totalExpenses = computed(() => timesheetStore.timesheets.reduce((sum, timesheet) =>
sum + timesheet.weekly_expenses.expenses
@@ -131,6 +129,7 @@ import { RouteNames } from 'src/router/router-constants';
diff --git a/src/modules/timesheets/models/timesheet.models.ts b/src/modules/timesheets/models/timesheet.models.ts
index 950d2a8..6e9b839 100644
--- a/src/modules/timesheets/models/timesheet.models.ts
+++ b/src/modules/timesheets/models/timesheet.models.ts
@@ -43,4 +43,9 @@ export interface TotalExpenses {
per_diem: number;
on_call: number;
mileage: number;
+}
+
+export interface TimesheetDayDisplay extends TimesheetDay {
+ timesheet_id: number;
+ i18WeekdayKey: string;
}
\ No newline at end of file
diff --git a/src/pages/dashboard-page.vue b/src/pages/dashboard-page.vue
index 448e56c..2dc185c 100644
--- a/src/pages/dashboard-page.vue
+++ b/src/pages/dashboard-page.vue
@@ -12,68 +12,84 @@
class="q-pa-md justify-center items-stretch bg-secondary"
:class="$q.platform.is.mobile ? 'column' : 'row'"
>
-
-
-
-
-
-
-
+
+
-
-
{{ $t('dashboard.useful_links') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ {{ $t('dashboard.useful_links') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/stores/timesheet-store.ts b/src/stores/timesheet-store.ts
index aa8d19e..83c85ee 100644
--- a/src/stores/timesheet-store.ts
+++ b/src/stores/timesheet-store.ts
@@ -10,7 +10,7 @@ import type { PayPeriod } from 'src/modules/shared/models/pay-period.models';
import type { Timesheet } from 'src/modules/timesheets/models/timesheet.models';
import type { PaidTimeOff } from 'src/modules/employee-list/models/employee-profile.models';
import type { PayPeriodEvent } from 'src/modules/timesheet-approval/models/pay-period-event.models';
-import type { TimesheetApprovalCSVReportFilters } from 'src/modules/timesheet-approval/models/timesheet-approval-csv-report.models';
+import type { CSVReportFilters } from 'src/modules/timesheet-approval/models/timesheet-approval-csv-report.models';
import { type FederalHoliday, TARGO_HOLIDAY_NAMES_FR } from 'src/modules/timesheets/models/federal-holidays.models';
import type { RouteNames } from 'src/router/router-constants';
import type { RouteRecordNameGeneric } from 'vue-router';
@@ -42,7 +42,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
const selected_employee_name = ref
();
const has_timesheet_preset = ref(false);
const current_pay_period_overview = ref();
- const pay_period_report = ref();
+ const payPeriodReport = ref();
const pay_period_observer = ref();
const federal_holidays = ref([]);
@@ -191,12 +191,16 @@ export const useTimesheetStore = defineStore('timesheet', () => {
return false;
}
- const getPayPeriodReport = async (report_filters: TimesheetApprovalCSVReportFilters) => {
+ const getPayPeriodReport = async (filters: CSVReportFilters): Promise => {
try {
if (!pay_period.value) return false;
- const response = await timesheetApprovalService.getPayPeriodReportByYearAndPeriodNumber(pay_period.value.pay_year, pay_period.value.pay_period_no, report_filters);
- pay_period_report.value = response;
- return response.data;
+
+ const response = await timesheetApprovalService.getPayPeriodReportByYearAndPeriodNumber(pay_period.value.pay_year, pay_period.value.pay_period_no, filters);
+
+ if (response){
+ payPeriodReport.value = response;
+ return true;
+ }
} catch (error) {
console.error('There was an error retrieving the report CSV: ', error);
// TODO: More in-depth error-handling here
@@ -256,6 +260,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
return {
is_loading,
is_report_dialog_open,
+ payPeriodReport,
is_details_dialog_open,
pay_period,
pay_period_overviews,
diff --git a/src/stores/ui-store.ts b/src/stores/ui-store.ts
index 96e75e2..e77921a 100644
--- a/src/stores/ui-store.ts
+++ b/src/stores/ui-store.ts
@@ -1,33 +1,27 @@
+import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { defineStore } from 'pinia';
-import { computed, ref } from 'vue';
-import { LocalStorage, useQuasar, Dark } from 'quasar';
+import { LocalStorage, Dark } from 'quasar';
import { Preferences } from 'src/modules/profile/models/preferences.models';
import { ProfileService } from 'src/modules/profile/services/profile-service';
-import { RouteNames } from 'src/router/router-constants';
-
export const useUiStore = defineStore('ui', () => {
- const q = useQuasar();
const { locale } = useI18n();
- const is_left_drawer_open = ref(true);
- const focus_next_component = ref(false);
- const is_mobile_mode = computed(() => q.screen.lt.md);
- const user_preferences = ref(new Preferences);
- const current_page = ref(RouteNames.DASHBOARD);
-
+ const isLeftDrawerOpen = ref(true);
+ const focusNextComponent = ref(false);
+ const userPreferences = ref(new Preferences);
const toggleRightDrawer = () => {
- is_left_drawer_open.value = !is_left_drawer_open.value;
+ isLeftDrawerOpen.value = !isLeftDrawerOpen.value;
};
const getUserPreferences = async () => {
try {
- const local_user_preferences = LocalStorage.getItem('user_preferences');
+ const local_userPreferences = LocalStorage.getItem('userPreferences');
- if (local_user_preferences !== null) {
- if (local_user_preferences.id !== -1) {
- Object.assign(user_preferences.value, local_user_preferences);
+ if (local_userPreferences !== null) {
+ if (local_userPreferences.id !== -1) {
+ Object.assign(userPreferences.value, local_userPreferences);
setPreferences();
return;
}
@@ -36,24 +30,24 @@ export const useUiStore = defineStore('ui', () => {
const response = await ProfileService.getUserPreferences();
if (response.success && response.data) {
- LocalStorage.setItem('user_preferences', response.data);
- Object.assign(user_preferences.value, response.data);
+ LocalStorage.setItem('userPreferences', response.data);
+ Object.assign(userPreferences.value, response.data);
setPreferences();
}
} catch (error) {
- user_preferences.value = new Preferences;
+ userPreferences.value = new Preferences;
console.error('Could not retrieve user preferences: ', error);
}
};
const updateUserPreferences = async () => {
try {
- if (user_preferences.value.id === -1) return;
+ if (userPreferences.value.id === -1) return;
- const response = await ProfileService.updateUserPreferences(user_preferences.value);
+ const response = await ProfileService.updateUserPreferences(userPreferences.value);
if (response.success && response.data) {
- Object.assign(user_preferences.value, response.data);
- LocalStorage.setItem('user_preferences', response.data);
+ Object.assign(userPreferences.value, response.data);
+ LocalStorage.setItem('userPreferences', response.data);
setPreferences();
return;
}
@@ -63,19 +57,17 @@ export const useUiStore = defineStore('ui', () => {
};
const setPreferences = () => {
- if (user_preferences.value !== undefined) {
- // if user_preferences.value.is_dark_mode === null
- Dark.set(user_preferences.value.is_dark_mode ?? "auto");
- locale.value = user_preferences.value.display_language;
+ if (userPreferences.value !== undefined) {
+ // if userPreferences.value.is_dark_mode === null
+ Dark.set(userPreferences.value.is_dark_mode ?? "auto");
+ locale.value = userPreferences.value.display_language;
}
}
return {
- current_page,
- is_mobile_mode,
- focus_next_component,
- is_left_drawer_open,
- user_preferences,
+ focusNextComponent,
+ isLeftDrawerOpen,
+ userPreferences,
toggleRightDrawer,
getUserPreferences,
updateUserPreferences,
diff --git a/src/utils/translator.ts b/src/utils/translator.ts
new file mode 100644
index 0000000..c316f51
--- /dev/null
+++ b/src/utils/translator.ts
@@ -0,0 +1,13 @@
+import type { ShiftType } from "src/modules/timesheets/models/shift.models";
+
+export const fromEnToFrShiftType = (shiftType: ShiftType): string => {
+ switch(shiftType) {
+ case "REGULAR": return 'Régulier';
+ case "EVENING": return 'Soir';
+ case "EMERGENCY": return 'Urgence';
+ case "HOLIDAY": return 'Férié';
+ case "VACATION": return 'Vacances';
+ case "SICK": return 'Maladie';
+ case "WITHDRAW_BANKED": return 'Heures-en-Banque';
+ }
+}
\ No newline at end of file