@@ -92,11 +91,7 @@
-
-
+
-
+
diff --git a/src/modules/timesheets/models/expense-validation.models.ts b/src/modules/timesheets/models/expense-validation.models.ts
deleted file mode 100644
index fca81ef..0000000
--- a/src/modules/timesheets/models/expense-validation.models.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-// import { type Expense, EXPENSE_TYPE, type ExpenseType } from "src/modules/timesheets/models/expense.models";
-// import type { Normalizer } from "src/utils/normalize-object";
-
-// export interface ApiErrorPayload {
-// status_code: number;
-// error_code?: string;
-// message?: string;
-// context?: Record;
-// };
-
-// export abstract class ApiError extends Error {
-// status_code: number;
-// error_code?: string;
-// context?: Record;
-
-// constructor(payload: ApiErrorPayload, defaultMessage: string) {
-// super(payload.message || defaultMessage);
-// this.status_code = payload.status_code;
-// this.error_code = payload.error_code ?? "unknown";
-// this.context = payload.context ?? {'unknown': 'unknown error has occured', };
-// }
-// };
-
-// export class GenericApiError extends ApiError {
-// constructor(payload: ApiErrorPayload) {
-// super(payload, 'Encountered an error processing request');
-// this.name = 'GenericApiError';
-// }
-// };
-
-// export class ExpensesValidationError extends ApiError {
-// constructor(payload: ApiErrorPayload) {
-// super(payload, 'Invalid expense payload');
-// this.name = 'ExpensesValidationError';
-// }
-// };
-
-// export class ExpensesApiError extends ApiError {
-// constructor(payload: ApiErrorPayload) {
-// super(payload, 'Request failed');
-// this.name = 'ExpensesApiError';
-// }
-// };
-
-// export const expense_validation_schema: Normalizer = {
-// id: v => typeof v === 'number' ? v : -1,
-// date: v => typeof v === 'string' ? v.trim() : '1970-01-01',
-// type: v => EXPENSE_TYPE.includes(v as ExpenseType) ? v as ExpenseType : "EXPENSES",
-// amount: v => typeof v === "number" ? v : -1,
-// mileage: v => typeof v === "number" ? v : undefined,
-// comment: v => typeof v === 'string' ? v.trim() : '',
-// supervisor_comment: v => typeof v === 'string' ? v.trim() : '',
-// is_approved: v => !!v,
-// };
-
-// export function toExpensesError(err: unknown): ExpensesValidationError | ExpensesApiError {
-// if (err instanceof ExpensesValidationError || err instanceof ExpensesApiError) {
-// return err;
-// }
-
-// if (typeof err === 'object' && err !== null && 'status_code' in err) {
-// const payload = err as ApiErrorPayload;
-
-// // Don't know how to differentiate both types of errors, can be updated here
-// if (payload.error_code?.startsWith('API_')) {
-// return new ExpensesApiError(payload);
-// }
-
-// return new ExpensesValidationError(payload);
-// }
-
-// // Fallback with ValidationError as default
-// return new ExpensesValidationError({
-// status_code: 500,
-// message: err instanceof Error ? err.message : 'Unknown error',
-// context: { original: err }
-// });
-// }
diff --git a/src/modules/timesheets/models/shift.models.ts b/src/modules/timesheets/models/shift.models.ts
index 2881a61..b5b082a 100644
--- a/src/modules/timesheets/models/shift.models.ts
+++ b/src/modules/timesheets/models/shift.models.ts
@@ -28,6 +28,7 @@ export class Shift {
comment: string | undefined;
is_approved: boolean;
is_remote: boolean;
+ error?: string;
constructor() {
this.id = -1;
diff --git a/src/modules/timesheets/services/timesheet-service.ts b/src/modules/timesheets/services/timesheet-service.ts
index 1d1cb0f..0371737 100644
--- a/src/modules/timesheets/services/timesheet-service.ts
+++ b/src/modules/timesheets/services/timesheet-service.ts
@@ -5,18 +5,18 @@ import type { TimesheetOverview } from "src/modules/timesheet-approval/models/ti
export const timesheetService = {
getPayPeriodByDate: async (date_string: string): Promise => {
- const response = await api.get(`pay-periods/date/${date_string}`);
- return response.data;
+ const response = await api.get<{success: boolean, data: PayPeriod, error? : string}>(`pay-periods/date/${date_string}`);
+ return response.data.data;
},
getPayPeriodByYearAndPeriodNumber: async (year: number, period_number: number): Promise => {
- const response = await api.get(`pay-periods/${year}/${period_number}`);
- return response.data;
+ const response = await api.get<{success: boolean, data: PayPeriod, error? : string}>(`pay-periods/${year}/${period_number}`);
+ return response.data.data;
},
getTimesheetOverviewsByPayPeriodAndSupervisorEmail: async (year: number, period_number: number, supervisor_email: string): Promise => {
- const response = await api.get(`pay-periods/${year}/${period_number}/${supervisor_email}`);
- return response.data;
+ const response = await api.get<{success: boolean, data: TimesheetOverview[], error? : string}>(`pay-periods/${year}/${period_number}/${supervisor_email}`);
+ return response.data.data;
},
getTimesheetsByPayPeriodAndOptionalEmail: async (year: number, period_number: number, employee_email?: string): Promise => {
diff --git a/src/modules/timesheets/utils/shift.util.ts b/src/modules/timesheets/utils/shift.util.ts
new file mode 100644
index 0000000..1997024
--- /dev/null
+++ b/src/modules/timesheets/utils/shift.util.ts
@@ -0,0 +1,26 @@
+import { date } from "quasar";
+import type { Shift } from "src/modules/timesheets/models/shift.models";
+
+export const isShiftOverlap = (shifts: Shift[]): boolean => {
+ if (shifts.length < 2) return false;
+
+ const parsed_shifts = shifts.map(shift => ({
+ start: date.extractDate(`${shift.date} ${shift.start_time}`, 'YYYY-MM-DD HH:mm').getTime(),
+ end: date.extractDate(`${shift.date} ${shift.end_time}`, 'YYYY-MM-DD HH:mm').getTime(),
+ }));
+
+ for (let i = 0; i < parsed_shifts.length; i++) {
+ for (let j = i + 1; j < parsed_shifts.length; j++) {
+ const parsed_shift_a = parsed_shifts[i];
+ const parsed_shift_b = parsed_shifts[j];
+
+ if (parsed_shift_a === undefined || parsed_shift_b === undefined) continue;
+
+ if (Math.max(parsed_shift_a.start, parsed_shift_b.start) < Math.min(parsed_shift_a.end, parsed_shift_b.end)) {
+ return true; // overlap found
+ }
+ }
+ }
+
+ return false;
+};
diff --git a/src/stores/shift-store.ts b/src/stores/shift-store.ts
index 1b2e699..8ef9ba1 100644
--- a/src/stores/shift-store.ts
+++ b/src/stores/shift-store.ts
@@ -1,3 +1,4 @@
+/* eslint-disable */
import { ref } from "vue";
import { Notify } from "quasar";
import { defineStore } from "pinia";
@@ -20,13 +21,12 @@ export const useShiftStore = defineStore('shift_store', () => {
};
const createNewShifts = async (): Promise => {
- if (timesheet_store.timesheets === undefined) {
- console.log('no changes in existing shifts detected');
- return false;
- }
+ if (timesheet_store.timesheets === undefined) return false;
+ const has_errors = false;
try {
- const new_shifts = timesheet_store.timesheets.flatMap(week => week.days).flatMap(day => day.shifts).filter(shift => shift.id < 0);
+ const days = timesheet_store.timesheets.flatMap(week => week.days);
+ const new_shifts = days.flatMap(day => day.shifts).filter(shift => shift.id < 0);
if (new_shifts?.length > 0) {
const response = await ShiftService.createNewShifts(new_shifts);
@@ -41,7 +41,7 @@ export const useShiftStore = defineStore('shift_store', () => {
}
return false;
} catch (error) {
- console.error('Error creating new shifts: ', error);
+ Notify.create('Error creating new shifts');
return false;
}
};
@@ -60,11 +60,10 @@ export const useShiftStore = defineStore('shift_store', () => {
}
}
- console.log('No shifts to update');
- Notify.create('no shifts to update')
+ Notify.create('No shifts to update')
return false;
} catch (error) {
- console.error('Error updating shifts: ', error);
+ Notify.create('Error updating shifts');
return false;
}
}
diff --git a/src/stores/timesheet-store.ts b/src/stores/timesheet-store.ts
index 04f5833..7aee8ea 100644
--- a/src/stores/timesheet-store.ts
+++ b/src/stores/timesheet-store.ts
@@ -69,6 +69,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
const getTimesheetsByOptionalEmployeeEmail = async (employee_email?: string) => {
if (pay_period.value === undefined) return;
+ console.log('pay period: ', pay_period.value);
is_loading.value = true;
let response;