diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index eaf461a..79802dd 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -26,6 +26,7 @@ export default { userMenuHome: 'Homepage', userMenuEmployeeList: 'Employee Directory', userMenuShiftValidation: 'Timesheet Approval', + userMenuTimesheetTemp: 'Timesheet', userMenuProfile: 'Profile', userMenuHelp: 'Help', userMenuLogout: 'Log Out', @@ -248,7 +249,35 @@ export default { timeSheets: 'Time sheet', timeSheetValidations: 'Time sheet approvals', }, - timeSheet: { + timesheet: { + //employee's timesheet page + days: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], + nav_button: { + calendar_date_picker:'Calendar', + current_week:'This week', + next_week:'Next week', + previous_week:'Previous week', + }, + save_button:'Save', + cancel_button:'Cancel', + remote_button: 'Remote work', + add_shift:'Add Shift', + shift_types_label: 'Shift`s Type', + shift_types: { + EMERGENCY: 'Emergency', + EVENING: 'Evening', + HOLIDAY: 'Holiday', + REGULAR: 'Regular', + SICK: 'Sick Leave', + VACATION: 'Vacation', + }, + fields: { + start:'Start', + end:'End', + header_comment:'Shift`s comment', + textarea_comment: 'Leave a comment here', + }, + //rest timeSheetTab_1: 'Shifts', timeSheetTab_2: 'Expenses', templateButton: 'Apply Templates', diff --git a/src/i18n/fr-ca/index.ts b/src/i18n/fr-ca/index.ts index 873ab03..f7cd6e9 100644 --- a/src/i18n/fr-ca/index.ts +++ b/src/i18n/fr-ca/index.ts @@ -165,6 +165,7 @@ export default { userMenuHome: 'Accueil', userMenuEmployeeList: 'Répertoire employés', userMenuShiftValidation: 'Valider les heures', + userMenuTimesheetTemp: 'Carte de temps', userMenuProfile: 'Profil', userMenuHelp: 'Aide', userMenuLogout: 'Déconnexion', @@ -298,7 +299,36 @@ export default { noResultsLabel: 'Le filtre n’a révélé aucun résultat', noDataLabel: 'Je n’ai rien trouvé pour toi', }, - timeSheet: { + timesheet: { + //employee's timesheet page + days: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'], + nav_button: { + calendar_date_picker:'Calendrier', + current_week:'Semaine actuelle', + next_week:'Prochaine semaine', + previous_week:'Semaine précédente', + }, + save_button:'Enregistrer', + cancel_button:'Annuler', + remote_button: 'Télétravail', + + add_shift:'Ajouter une quart', + shift_types_label: 'Type de quart', + shift_types: { + EMERGENCY: 'Urgence', + EVENING: 'Soir', + HOLIDAY: 'Férier', + SICK: 'Absence', + REGULAR: 'Régulier', + VACATION: 'Vacance', + }, + fields: { + start:'Entrée', + end:'Sortie', + header_comment:'Commentaire du Quart', + textarea_comment:'Laissez votre commentaire', + }, + //rest timeSheetTab_1: 'Quarts de travail', timeSheetTab_2: 'Dépenses', templateButton: 'Appliquer le modèle', diff --git a/src/modules/shared/components/navigation/right-drawer.vue b/src/modules/shared/components/navigation/right-drawer.vue index e1352b1..875f3d4 100644 --- a/src/modules/shared/components/navigation/right-drawer.vue +++ b/src/modules/shared/components/navigation/right-drawer.vue @@ -62,6 +62,17 @@ + + + + + + + {{ $t('navBar.userMenuTimesheetTemp') }} + + + diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue index 9382ccd..7d78a9c 100644 --- a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue @@ -32,12 +32,12 @@ expenses_dataset.value = [ { - label: t('timeSheet.refund'), + label: t('timesheet.refund'), data: all_costs, backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-primary').trim(), }, { - label: t('timeSheet.mileage'), + label: t('timesheet.mileage'), data: all_mileage, backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-info').trim(), } diff --git a/src/modules/timesheet-approval/pages/timesheet-approval-employee-details.vue b/src/modules/timesheet-approval/pages/timesheet-approval-employee-details.vue index 048b5a7..94c8f5c 100644 --- a/src/modules/timesheet-approval/pages/timesheet-approval-employee-details.vue +++ b/src/modules/timesheet-approval/pages/timesheet-approval-employee-details.vue @@ -40,16 +40,16 @@ import { colors } from 'quasar'; const shift_type_legend: shiftColor[] = [ { - type: t('timeSheet.shiftRegular'), + type: t('timesheet.shift_types.REGULAR'), color: 'secondary', text_color: 'grey-8', }, { - type: t('timeSheet.shiftEvening'), + type: t('timesheet.shift_types.EVENING'), color: 'warning', }, { - type: t('timeSheet.shiftEmergency'), + type: t('timesheet.shift_types.EMERGENCY'), color: 'amber-10', }, { @@ -57,15 +57,15 @@ import { colors } from 'quasar'; color: 'negative', }, { - type: t('timeSheet.shiftVacation'), + type: t('timesheet.shift_types.VACATION'), color: 'purple-10', }, { - type: t('timeSheet.shiftHoliday'), + type: t('timesheet.shift_types.HOLIDAY'), color: 'purple-8', }, { - type: t('timeSheet.shiftSick'), + type: t('timesheet.shift_types.SICK'), color: 'grey-8', }, ] diff --git a/src/modules/timesheet-approval/pages/timesheet-approval.vue b/src/modules/timesheet-approval/pages/timesheet-approval.vue index c924c24..a9fa76a 100644 --- a/src/modules/timesheet-approval/pages/timesheet-approval.vue +++ b/src/modules/timesheet-approval/pages/timesheet-approval.vue @@ -48,7 +48,7 @@ class="text-grey-8 text-uppercase q-mx-md" :class="$q.screen.lt.md ? 'text-weight-medium text-caption' : 'text-weight-bold'" > - {{ $t('timeSheet.dateRangesTo') }} + {{ $t('timesheet.dateRangesTo') }}
+import { ref } from 'vue'; +/* eslint-disable */ +const props = defineProps<{ + commentString: string; +}>(); + +const emit = defineEmits<{ + clickClose: []; + clickSave: [comment: string]; +}>(); + +const text = ref(props.commentString); + +const close = ()=> { + emit('clickClose'); + text.value = ''; +} + +const save = ()=> { + emit('clickSave',text.value); + close(); +} + + + \ No newline at end of file diff --git a/src/modules/timesheets/components/timesheet/time-sheet-shift-list-row.vue b/src/modules/timesheets/components/timesheet/time-sheet-shift-list-row.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/timesheets/components/timesheet/time-sheet-shift-list.vue b/src/modules/timesheets/components/timesheet/time-sheet-shift-list.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/timesheets/components/timesheet/time-sheet.vue b/src/modules/timesheets/components/timesheet/time-sheet.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/timesheets/components/timesheet/timesheet-navigation.vue b/src/modules/timesheets/components/timesheet/timesheet-navigation.vue new file mode 100644 index 0000000..1a1136b --- /dev/null +++ b/src/modules/timesheets/components/timesheet/timesheet-navigation.vue @@ -0,0 +1,109 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheets/components/timesheet/timesheet-save-payload.vue b/src/modules/timesheets/components/timesheet/timesheet-save-payload.vue new file mode 100644 index 0000000..c71840b --- /dev/null +++ b/src/modules/timesheets/components/timesheet/timesheet-save-payload.vue @@ -0,0 +1,64 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheets/components/timesheet/timesheet-shift-form.vue b/src/modules/timesheets/components/timesheet/timesheet-shift-form.vue new file mode 100644 index 0000000..e9e3afc --- /dev/null +++ b/src/modules/timesheets/components/timesheet/timesheet-shift-form.vue @@ -0,0 +1,266 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheets/composables/use-timesheet-api.ts b/src/modules/timesheets/composables/use-timesheet-api.ts index e69de29..8b5eefb 100644 --- a/src/modules/timesheets/composables/use-timesheet-api.ts +++ b/src/modules/timesheets/composables/use-timesheet-api.ts @@ -0,0 +1,60 @@ +import { useAuthStore } from "src/stores/auth-store"; +import { useTimesheetStore } from "src/stores/timesheet-store" +import { ref } from "vue"; +import { timesheetTempService } from "../services/timesheet-services"; +import type { CreateShiftPayload } from "../types/timesheet-shift-interface"; + + +export const useTimesheetApi = () => { + const timesheet_store = useTimesheetStore(); + const auth_store = useAuthStore(); + const week_offset = ref(0); + + const fetchWeek = async (offset = week_offset.value) => { + const email = auth_store.user?.email; + if(!email) return; + try{ + timesheet_store.is_loading = true; + const timesheet = await timesheetTempService.getTimesheetsByEmail(email, offset); + timesheet_store.current_timesheet = timesheet; + week_offset.value = offset; + }catch (err) { + console.error('fetch week error', err); + timesheet_store.current_timesheet = { ...timesheet_store.current_timesheet, shifts: [], expenses: [] }; + } finally { + timesheet_store.is_loading = false; + } + }; + + const this_week = async () => fetchWeek(0); + const next_week = async () => fetchWeek(week_offset.value + 1); + const previous_week = async () => fetchWeek(week_offset.value - 1); + + const saveTimesheetShifts = async (shifts: CreateShiftPayload[]) => { + const email = auth_store.user?.email; + if(!email || shifts.length === 0) return; + await timesheet_store.createTimesheetShifts(email, shifts, week_offset.value); + }; + + const weekStart = (date: Date) => { + const x = new Date(date); + x.setHours(0, 0, 0, 0); + x.setDate(x.getDate() - x.getDay()); + return x; + }; + + const getCurrentWeekTimesheetOverview = async (when: Date = new Date()) => { + const off = Math.trunc((weekStart(when).getTime() - weekStart(new Date()).getTime()) / 604800000); + await fetchWeek(off); + } + + return { + week_offset, + fetchWeek, + this_week, + next_week, + previous_week, + saveTimesheetShifts, + getCurrentWeekTimesheetOverview, + }; +}; \ No newline at end of file diff --git a/src/modules/timesheets/pages/timesheet-temp-page.vue b/src/modules/timesheets/pages/timesheet-temp-page.vue index e69de29..dd2c731 100644 --- a/src/modules/timesheets/pages/timesheet-temp-page.vue +++ b/src/modules/timesheets/pages/timesheet-temp-page.vue @@ -0,0 +1,86 @@ + + + + \ No newline at end of file diff --git a/src/modules/timesheets/services/timesheet-services.ts b/src/modules/timesheets/services/timesheet-services.ts index e69de29..d96bef5 100644 --- a/src/modules/timesheets/services/timesheet-services.ts +++ b/src/modules/timesheets/services/timesheet-services.ts @@ -0,0 +1,18 @@ +import { api } from "src/boot/axios"; +import type {Timesheet} from "src/modules/timesheets/types/timesheet-interface"; +import type { CreateShiftPayload, CreateWeekShiftPayload } from "../types/timesheet-shift-interface"; + +export const timesheetTempService = { + //GET + getTimesheetsByEmail: async ( email: string, offset = 0): Promise => { + const response = await api.get(`/timesheets/${encodeURIComponent(email)}`, {params: offset ? { offset } : undefined}); + return response.data as Timesheet; + }, + + //POST + createTimesheetShifts: async ( email: string, shifts: CreateShiftPayload[], offset = 0): Promise => { + const payload: CreateWeekShiftPayload = { shifts }; + const response = await api.post(`/timesheets/shifts/${encodeURIComponent(email)}`, payload, { params: offset ? { offset }: undefined }); + return response.data as Timesheet; + } +}; \ No newline at end of file diff --git a/src/modules/timesheets/timesheet-constants.ts b/src/modules/timesheets/timesheet-constants.ts index e69de29..7ca8ae2 100644 --- a/src/modules/timesheets/timesheet-constants.ts +++ b/src/modules/timesheets/timesheet-constants.ts @@ -0,0 +1 @@ +//mock data \ No newline at end of file diff --git a/src/modules/timesheets/types/timesheet-details-interface.ts b/src/modules/timesheets/types/timesheet-details-interface.ts index daf3874..21b42ee 100644 --- a/src/modules/timesheets/types/timesheet-details-interface.ts +++ b/src/modules/timesheets/types/timesheet-details-interface.ts @@ -38,7 +38,12 @@ interface TimesheetDetailsDailyExpenses { [otherType: string]: Expense[]; //for possible future types of expenses } - +//employee timesheet template +export interface EmployeeTimesheetDetailsWeek { + is_approved: boolean; + shifts: WeekDay; + expenses: WeekDay; +} // empty default builder const makeWeek = (factory: () => T): WeekDay => ({ sun: factory(), diff --git a/src/modules/timesheets/types/timesheet-interface.ts b/src/modules/timesheets/types/timesheet-interface.ts new file mode 100644 index 0000000..927cfd0 --- /dev/null +++ b/src/modules/timesheets/types/timesheet-interface.ts @@ -0,0 +1,28 @@ +export interface Timesheet { + is_approved: boolean; + start_day: string; + end_day: string; + label: string; + shifts: Shifts[]; + expenses: Expenses[]; +} + +type Shifts = { + bank_type: string; + date: string; + start_time: string; + end_time: string; + description: string; + is_approved: boolean; + is_remote: boolean; +} + +type Expenses = { + bank_type: string; + date: string; + amount: number; + km: number; + description: string; + supervisor_comment: string; + is_approved: boolean; +} \ No newline at end of file diff --git a/src/modules/timesheets/types/timesheet-shift-interface.ts b/src/modules/timesheets/types/timesheet-shift-interface.ts index 8438cfc..b57aecf 100644 --- a/src/modules/timesheets/types/timesheet-shift-interface.ts +++ b/src/modules/timesheets/types/timesheet-shift-interface.ts @@ -1,9 +1,24 @@ +export interface CreateShiftPayload { + date: string; + type: string; + start_time: string; + end_time: string; + description?: string; + is_remote?: boolean; +}; + +export interface CreateWeekShiftPayload { + shifts: CreateShiftPayload[]; +} + export interface Shift { - date : string; - start_time : string; - end_time : string; - type : string; - is_approved : boolean; + date : string; + type : string; + start_time : string; + end_time : string; + comment : string; + is_approved: boolean; + is_remote : boolean; } export const default_shift: Shift = { @@ -11,5 +26,7 @@ export const default_shift: Shift = { start_time: '--:--', end_time: '--:--', type: '', + comment: '', is_approved: false, -} \ No newline at end of file + is_remote: false, +} diff --git a/src/router/router-constants.ts b/src/router/router-constants.ts index b264bf2..b24aa80 100644 --- a/src/router/router-constants.ts +++ b/src/router/router-constants.ts @@ -6,4 +6,5 @@ export enum RouteNames { TIMESHEET_APPROVALS = 'timesheet-approvals', EMPLOYEE_LIST = 'employee-list', PROFILE = 'user/profile', + TIMESHEET_TEMP = 'timesheet-temp' } \ No newline at end of file diff --git a/src/router/routes.ts b/src/router/routes.ts index 564f357..33cb2a6 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -22,6 +22,11 @@ const routes: RouteRecordRaw[] = [ name: RouteNames.EMPLOYEE_LIST, component: () => import('src/modules/employee-list/pages/supervisor-crew-page.vue'), }, + { + path: 'timesheet-temp', + name: RouteNames.TIMESHEET_TEMP, + component: () => import('src/modules/timesheets/pages/timesheet-temp-page.vue') + } ], }, diff --git a/src/stores/timesheet-store.ts b/src/stores/timesheet-store.ts index ad97173..72b48d8 100644 --- a/src/stores/timesheet-store.ts +++ b/src/stores/timesheet-store.ts @@ -1,10 +1,13 @@ import { defineStore } from 'pinia'; import { ref } from 'vue'; import { timesheetApprovalService } from 'src/modules/timesheet-approval/services/services-timesheet-approval'; +import { timesheetTempService } from 'src/modules/timesheets/services/timesheet-services'; import type { PayPeriod } from 'src/modules/shared/types/pay-period-interface'; import type { PayPeriodOverviewEmployee } from "src/modules/timesheet-approval/types/timesheet-approval-pay-period-overview-employee-interface"; import { default_pay_period_employee_details, type PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-employee-details-interface'; import type { PayPeriodReportFilters } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-report-interface'; +import type { Timesheet } from 'src/modules/timesheets/types/timesheet-interface'; +import type { CreateShiftPayload } from 'src/modules/timesheets/types/timesheet-shift-interface'; const default_pay_period: PayPeriod = { pay_period_no: -1, @@ -15,6 +18,16 @@ const default_pay_period: PayPeriod = { label: '' }; + //employee timesheet + const default_timesheet: Timesheet = { + start_day: '', + end_day: '', + label: '', + is_approved: false, + shifts: [], + expenses: [], + }; + export const useTimesheetStore = defineStore('timesheet', () => { const is_loading = ref(false); const current_pay_period = ref(default_pay_period); @@ -23,6 +36,9 @@ export const useTimesheetStore = defineStore('timesheet', () => { const pay_period_employee_details = ref(default_pay_period_employee_details); const pay_period_report = ref(); + //employee timesheet + const current_timesheet = ref(default_timesheet); + const getPayPeriodByDate = async (date_string: string): Promise => { is_loading.value = true; @@ -85,6 +101,32 @@ export const useTimesheetStore = defineStore('timesheet', () => { is_loading.value = false; }; + //employee timesheet + const getTimesheetByEmail = async (employee_email: string) => { + is_loading.value = true; + try{ + const response = await timesheetTempService.getTimesheetsByEmail(employee_email); + current_timesheet.value = response; + }catch (error) { + console.error('There was an error retrieving timesheet details for this employee: ', error); + current_timesheet.value = { ...default_timesheet } + } finally { + is_loading.value = false; + } + } + //employee timesheet + const createTimesheetShifts = async (employee_email: string, shifts: CreateShiftPayload[], offset = 0) => { + is_loading.value = true; + try{ + const timesheet = await timesheetTempService.createTimesheetShifts(employee_email, shifts, offset); + current_timesheet.value = timesheet; + } catch (err) { + console.error('createTimesheetShifts error: ', err); + } finally { + is_loading.value = false; + } + }; + const getTimesheetsByPayPeriodAndEmail = async (employee_email: string) => { is_loading.value = true; @@ -126,8 +168,11 @@ export const useTimesheetStore = defineStore('timesheet', () => { pay_period_overview_employees, pay_period_overview_employee_approval_statuses, pay_period_employee_details, + current_timesheet, is_loading, getPayPeriodByDate, + getTimesheetByEmail, + createTimesheetShifts, getPayPeriodByYearAndPeriodNumber, getTimesheetApprovalPayPeriodEmployeeOverviews, getTimesheetsByPayPeriodAndEmail,