BREAKING(approvals): begin process of merging and DRYing timesheet with timesheet approvals, adjust imports, WIP - DO NOT MERGE
This commit is contained in:
parent
89cce4f73f
commit
655a7ecff1
|
|
@ -1,27 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
/* eslint-disable */
|
||||
import { ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { date} from 'quasar';
|
||||
import type { QDateDetails } from 'src/modules/shared/types/q-date-details';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
|
||||
const timesheet_store = useTimesheetStore();
|
||||
|
||||
const is_showing_calendar_picker = ref(false);
|
||||
const calendar_date = ref(date.formatDate( Date.now(), 'YYYY-MM-DD' ));
|
||||
|
||||
const props = defineProps<{
|
||||
isDisabled?: boolean;
|
||||
isPreviousLimit:boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
'date-selected': [value: string, reason?: string, details?: QDateDetails]
|
||||
'date-selected': [ value: string ]
|
||||
'pressed-previous-button': []
|
||||
'pressed-next-button': []
|
||||
}>();
|
||||
|
||||
const onDateSelected = (value: string, reason: string, details: QDateDetails) => {
|
||||
const is_previous_pay_period_limit = computed( ()=>
|
||||
timesheet_store.pay_period.pay_year === 2024 &&
|
||||
timesheet_store.pay_period.pay_period_no <= 1
|
||||
);
|
||||
|
||||
const onDateSelected = (value: string) => {
|
||||
calendar_date.value = value;
|
||||
is_showing_calendar_picker.value = false;
|
||||
emit('date-selected', value, reason, details);
|
||||
emit('date-selected', value);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -33,39 +34,43 @@
|
|||
icon="keyboard_arrow_left"
|
||||
color="primary"
|
||||
@click="emit('pressed-previous-button')"
|
||||
:disable="props.isPreviousLimit || props.isDisabled"
|
||||
:disable="is_previous_pay_period_limit || timesheet_store.is_loading"
|
||||
class="q-mr-sm q-px-sm"
|
||||
>
|
||||
<q-tooltip
|
||||
anchor="top middle"
|
||||
self="center middle"
|
||||
class="bg-primary text-uppercase text-weight-bold"
|
||||
> {{ $t( 'timesheet.nav_button.previous_week' )}}
|
||||
>
|
||||
{{ $t( 'timesheet.nav_button.previous_week' )}}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<!-- navigation through calendar date picker -->
|
||||
<q-btn
|
||||
push rounded
|
||||
icon="calendar_month"
|
||||
color="primary"
|
||||
@click="is_showing_calendar_picker = true"
|
||||
:disable="props.isDisabled"
|
||||
:disable="timesheet_store.is_loading"
|
||||
class="q-px-lg"
|
||||
>
|
||||
<q-tooltip
|
||||
anchor="top middle"
|
||||
self="center middle"
|
||||
class="bg-primary text-uppercase text-weight-bold"
|
||||
>{{ $t('timesheet.nav_button.calendar_date_picker') }}
|
||||
>
|
||||
{{ $t('timesheet.nav_button.calendar_date_picker') }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<!-- navigation to next week -->
|
||||
<q-btn
|
||||
push rounded
|
||||
icon="keyboard_arrow_right"
|
||||
color="primary"
|
||||
@click="emit('pressed-next-button')"
|
||||
:disable="props.isDisabled"
|
||||
:disable="timesheet_store.is_loading"
|
||||
class="q-ml-sm q-px-sm"
|
||||
>
|
||||
<q-tooltip
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
import { Bar } from 'vue-chartjs';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, TimeScale, type ChartData, type ChartDataset } from 'chart.js';
|
||||
import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/pay-period-employee-details';
|
||||
import type { Expense } from 'src/modules/timesheets/types/expense.interfaces';
|
||||
import type { Expense } from 'src/modules/timesheets/models/expense.models';
|
||||
|
||||
const { t } = useI18n();
|
||||
const $q = useQuasar();
|
||||
|
|
@ -15,44 +15,44 @@
|
|||
ChartJS.defaults.maintainAspectRatio = false;
|
||||
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
|
||||
|
||||
const props = defineProps<{
|
||||
rawData: PayPeriodEmployeeDetails | undefined;
|
||||
defineProps<{
|
||||
|
||||
}>();
|
||||
|
||||
const expenses_dataset = ref<ChartDataset<'bar'>[]>([]);
|
||||
const expenses_labels = ref<string[]>([]);
|
||||
// const expenses_dataset = ref<ChartDataset<'bar'>[]>([]);
|
||||
// const expenses_labels = ref<string[]>([]);
|
||||
|
||||
const getExpensesData = (): ChartData<'bar'> => {
|
||||
if (props.rawData) {
|
||||
const all_weeks = [props.rawData.week1, props.rawData.week2];
|
||||
const all_days = all_weeks.flatMap( week => Object.values(week.expenses));
|
||||
const all_days_dates = all_weeks.flatMap( week => Object.values(week.shifts))
|
||||
// const getExpensesData = (): ChartData<'bar'> => {
|
||||
// if (timesheetDetails) {
|
||||
// const all_weeks = [timesheetDetails.week1, timesheetDetails.week2];
|
||||
// const all_days = all_weeks.flatMap( week => Object.values(week.expenses));
|
||||
// const all_days_dates = all_weeks.flatMap( week => Object.values(week.shifts))
|
||||
|
||||
const all_costs = all_days.map( day => getTotalAmounts(day.cash));
|
||||
const all_mileage = all_days.map( day => getTotalAmounts(day.km));
|
||||
// const all_costs = all_days.map( day => getTotalAmounts(day.cash));
|
||||
// const all_mileage = all_days.map( day => getTotalAmounts(day.km));
|
||||
|
||||
|
||||
expenses_dataset.value = [
|
||||
{
|
||||
label: t('timesheet_approvals.table.expenses'),
|
||||
data: all_costs,
|
||||
backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-primary').trim(),
|
||||
},
|
||||
{
|
||||
label: t('timesheet_approvals.table.mileage'),
|
||||
data: all_mileage,
|
||||
backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-info').trim(),
|
||||
}
|
||||
]
|
||||
// expenses_dataset.value = [
|
||||
// {
|
||||
// label: t('timesheet_approvals.table.expenses'),
|
||||
// data: all_costs,
|
||||
// backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-primary').trim(),
|
||||
// },
|
||||
// {
|
||||
// label: t('timesheet_approvals.table.mileage'),
|
||||
// data: all_mileage,
|
||||
// backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-info').trim(),
|
||||
// }
|
||||
// ]
|
||||
|
||||
expenses_labels.value = all_days_dates.map( day => day.short_date);
|
||||
}
|
||||
// expenses_labels.value = all_days_dates.map( day => day.short_date);
|
||||
// }
|
||||
|
||||
return {
|
||||
datasets: expenses_dataset.value,
|
||||
labels: expenses_labels.value
|
||||
};
|
||||
};
|
||||
// return {
|
||||
// datasets: expenses_dataset.value,
|
||||
// labels: expenses_labels.value
|
||||
// };
|
||||
// };
|
||||
|
||||
const getTotalAmounts = (expenses: Expense[]): number => {
|
||||
let total_amount = 0;
|
||||
|
|
@ -1,25 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import DetailedShiftList from 'src/modules/timesheet-approval/components/detailed-shift-list.vue';
|
||||
import DetailedChartHoursWorked from 'src/modules/timesheet-approval/components/graphs/detailed-chart-hours-worked.vue';
|
||||
import DetailedChartShiftTypes from 'src/modules/timesheet-approval/components/graphs/detailed-chart-shift-types.vue';
|
||||
import DetailedChartExpenses from 'src/modules/timesheet-approval/components/graphs/detailed-chart-expenses.vue';
|
||||
import type { PayPeriodEmployeeOverview } from 'src/modules/timesheet-approval/types/pay-period-employee-overview';
|
||||
import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/pay-period-employee-details';
|
||||
import { shift_type_legend } from 'src/modules/timesheet-approval/types/detailed-shift-color';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
// import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import { shift_type_legend } from 'src/modules/timesheet-approval/models/detailed-dialog-shift-color.model';
|
||||
import DetailedDialogChartHoursWorked from 'src/modules/timesheet-approval/components/graphs/detailed-chart-hours-worked.vue';
|
||||
import DetailedDialogChartShiftTypes from 'src/modules/timesheet-approval/components/graphs/detailed-chart-shift-types.vue';
|
||||
import DetailedDialogChartExpenses from 'src/modules/timesheet-approval/components/graphs/detailed-chart-expenses.vue';
|
||||
import type { TimesheetApprovalOverviewCrewMember } from 'src/modules/timesheet-approval/models/timesheet-approval-overview.models';
|
||||
import type { TimesheetDetails } from 'src/modules/timesheets/models/timesheet.models';
|
||||
|
||||
const dialog_model = defineModel<boolean>('dialog', { default: false });
|
||||
|
||||
defineProps<{
|
||||
isLoading: boolean;
|
||||
employeeOverview: PayPeriodEmployeeOverview;
|
||||
employeeDetails: PayPeriodEmployeeDetails;
|
||||
employeeOverview: TimesheetApprovalOverviewCrewMember;
|
||||
timesheetDetails: TimesheetDetails;
|
||||
}>();
|
||||
|
||||
const timesheet_store = useTimesheetStore();
|
||||
const is_showing_graph = ref<boolean>(true);
|
||||
// const timesheet_store = useTimesheetStore();
|
||||
const is_showing_graph = ref(true);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -54,7 +52,7 @@
|
|||
v-if="!isLoading"
|
||||
class="text-h5 text-weight-bolder text-center text-primary q-pa-none text-uppercase col-auto"
|
||||
>
|
||||
<span> {{ employeeDetails.employee_full_name }} </span>
|
||||
<span> {{ timesheetDetails.employee_full_name }} </span>
|
||||
|
||||
<q-separator
|
||||
spaced
|
||||
|
|
@ -62,7 +60,7 @@
|
|||
/>
|
||||
|
||||
<q-card-actions
|
||||
align="center"
|
||||
align="center"
|
||||
class="q-pa-none"
|
||||
>
|
||||
<q-btn-toggle
|
||||
|
|
@ -78,7 +76,7 @@
|
|||
</q-card-actions>
|
||||
</q-card-section>
|
||||
|
||||
<!-- employee timesheet details edit -->
|
||||
<!-- employee timesheet for supervisor editting -->
|
||||
<q-card-section
|
||||
v-if="!is_showing_graph"
|
||||
class="q-pa-none"
|
||||
|
|
@ -101,10 +99,7 @@
|
|||
:horizontal="$q.screen.gt.sm"
|
||||
class="q-pa-none bg-secondary rounded-10"
|
||||
>
|
||||
<DetailedShiftList
|
||||
:raw-data="employeeDetails"
|
||||
:current-pay-period="timesheet_store.pay_period"
|
||||
/>
|
||||
<!-- IMPORTANT: Timesheet shift list goes here!!! -->
|
||||
</q-card-section>
|
||||
</q-card-section>
|
||||
|
||||
|
|
@ -118,8 +113,8 @@
|
|||
class="q-pa-none col no-wrap"
|
||||
style="min-height: 300px;"
|
||||
>
|
||||
<DetailedChartHoursWorked
|
||||
:raw-data="employeeDetails"
|
||||
<DetailedDialogChartHoursWorked
|
||||
:raw-data="timesheetDetails"
|
||||
class="col-7"
|
||||
/>
|
||||
|
||||
|
|
@ -129,7 +124,7 @@
|
|||
/>
|
||||
|
||||
<div class="column col justify-center no-wrap q-pa-none">
|
||||
<DetailedChartShiftTypes
|
||||
<DetailedDialogChartShiftTypes
|
||||
:raw-data="employeeOverview"
|
||||
class="col-5"
|
||||
/>
|
||||
|
|
@ -139,8 +134,8 @@
|
|||
:vertical="!$q.screen.lt.md"
|
||||
/>
|
||||
|
||||
<DetailedChartExpenses
|
||||
:raw-data="employeeDetails"
|
||||
<DetailedDialogChartExpenses
|
||||
:raw-data="timesheetDetails"
|
||||
class="col"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<template>
|
||||
<q-card-section
|
||||
horizontal
|
||||
class="text-uppercase text-center items-center q-pa-none"
|
||||
>
|
||||
<!-- shift row itself -->
|
||||
<q-card-section class="col q-pa-none">
|
||||
<q-card-section horizontal class="col q-pa-none">
|
||||
<!-- punch-in timestamps -->
|
||||
<q-card-section class="col q-pa-none">
|
||||
<q-item-label class="text-weight-bolder text-primary" style="font-size: 0.7em;">
|
||||
{{ $t('shared.misc.in') }}
|
||||
</q-item-label>
|
||||
</q-card-section>
|
||||
|
||||
<!-- arrows pointing to punch-out timestamps -->
|
||||
<q-card-section class="col q-py-none q-px-sm">
|
||||
</q-card-section>
|
||||
|
||||
<!-- punch-out timestamps -->
|
||||
<q-card-section class="col q-pa-none">
|
||||
<q-item-label class="text-weight-bolder text-primary" style="font-size: 0.7em;">
|
||||
{{ $t('shared.misc.out') }}
|
||||
</q-item-label>
|
||||
</q-card-section>
|
||||
|
||||
<!-- comment button -->
|
||||
<q-card-section class="col column q-pa-none">
|
||||
</q-card-section>
|
||||
</q-card-section>
|
||||
</q-card-section>
|
||||
</q-card-section>
|
||||
</template>
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import type { Shift } from 'src/modules/timesheets/types/shift.interfaces';
|
||||
|
||||
|
||||
const props = defineProps<{
|
||||
shift: Shift;
|
||||
}>();
|
||||
|
||||
const is_showing_time_popup = ref<boolean>(false);
|
||||
|
||||
const getShiftColor = (type: string): string => {
|
||||
switch(type) {
|
||||
case 'REGULAR': return 'secondary';
|
||||
case 'EVENING': return 'warning';
|
||||
case 'EMERGENCY': return 'amber-10';
|
||||
case 'OVERTIME': return 'negative';
|
||||
case 'VACATION': return 'purple-10';
|
||||
case 'HOLIDAY': return 'purple-10';
|
||||
case 'SICK': return 'grey-8';
|
||||
default : return 'transparent';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-card-section
|
||||
horizontal
|
||||
class="q-pa-none text-uppercase text-center items-center cursor-pointer rounded-10"
|
||||
style="line-height: 1;"
|
||||
@click="is_showing_time_popup = true"
|
||||
>
|
||||
<!-- punch-in timestamps -->
|
||||
<q-card-section class="q-pa-none col">
|
||||
<q-item-label
|
||||
class="text-weight-bolder q-pa-xs rounded-5"
|
||||
:class="'bg-' + getShiftColor(props.shift.type) + (!$q.dark.isActive && props.shift.type === 'REGULAR' ? '' : ' text-white')"
|
||||
style="font-size: 1.5em; line-height: 80% !important;"
|
||||
>
|
||||
{{ props.shift.start_time }}
|
||||
</q-item-label>
|
||||
</q-card-section>
|
||||
|
||||
<!-- arrows pointing to punch-out timestamps -->
|
||||
<q-card-section
|
||||
horizontal
|
||||
class="items-center justify-center q-mx-sm col"
|
||||
>
|
||||
<div
|
||||
v-for="icon_data, index in [
|
||||
{ transform: 'transform: translateX(5px);', color: 'accent' },
|
||||
{ transform: 'transform: translateX(-5px);', color: 'primary' }]"
|
||||
:key="index"
|
||||
>
|
||||
<q-icon
|
||||
v-if="props.shift.type"
|
||||
name="double_arrow"
|
||||
:color="icon_data.color"
|
||||
size="24px"
|
||||
:style="icon_data.transform"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<!-- punch-out timestamps -->
|
||||
<q-card-section class="q-pa-none col">
|
||||
<q-item-label
|
||||
class="text-weight-bolder q-pa-xs rounded-5"
|
||||
:class="'bg-' + getShiftColor(props.shift.type) + (!$q.dark.isActive && props.shift.type === 'REGULAR' ? '' : ' text-white')"
|
||||
style="font-size: 1.5em; line-height: 80% !important;"
|
||||
>
|
||||
{{ props.shift.end_time }}
|
||||
</q-item-label>
|
||||
</q-card-section>
|
||||
|
||||
<!-- comment and expenses buttons -->
|
||||
<q-card-section
|
||||
class="col q-pa-none text-right"
|
||||
>
|
||||
<!-- chat_bubble_outline or announcement -->
|
||||
<q-btn
|
||||
v-if="props.shift.type"
|
||||
flat
|
||||
dense
|
||||
icon="chat_bubble_outline"
|
||||
class="q-pa-none"
|
||||
/>
|
||||
|
||||
<!-- insert_drive_file or request_quote -->
|
||||
<q-btn
|
||||
v-if="props.shift.type"
|
||||
flat
|
||||
dense
|
||||
icon="attach_money"
|
||||
class="q-pa-none q-mx-xs"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card-section>
|
||||
</template>
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import DetailedShiftListRow from 'src/modules/timesheet-approval/components/detailed-shift-list-row.vue';
|
||||
import DetailedShiftListHeader from 'src/modules/timesheet-approval/components/detailed-shift-list-header.vue';
|
||||
import type { PayPeriod } from 'src/modules/shared/types/pay-period-interface';
|
||||
import type { Shift } from 'src/modules/timesheets/types/shift.interfaces';
|
||||
import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/pay-period-employee-details';
|
||||
import { default_shift } from 'src/modules/timesheets/types/shift.defaults';
|
||||
|
||||
const { rawData, currentPayPeriod } = defineProps<{
|
||||
rawData: PayPeriodEmployeeDetails;
|
||||
currentPayPeriod: PayPeriod;
|
||||
}>();
|
||||
|
||||
const weeks = [ rawData.week1, rawData.week2 ];
|
||||
|
||||
const shifts_or_placeholder = (shifts: Shift[]): Shift[] => {
|
||||
return shifts.length > 0 ? shifts : [default_shift];
|
||||
};
|
||||
|
||||
const getDate = (shift_date: string): Date => {
|
||||
return new Date(currentPayPeriod.pay_year.toString() + '/' + shift_date);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-for="week, index in weeks"
|
||||
:key="index"
|
||||
class="q-px-xs q-pt-xs rounded-5 col"
|
||||
>
|
||||
<q-card
|
||||
v-for="day, day_index in week.shifts"
|
||||
:key="day_index"
|
||||
flat
|
||||
bordered
|
||||
class="row items-center rounded-10 q-mb-xs"
|
||||
>
|
||||
<q-card-section class="col-auto q-pa-xs text-white">
|
||||
<div
|
||||
class="bg-primary rounded-10 q-pa-xs text-center"
|
||||
:style="$q.screen.lt.md ? '' : 'width: 75px;'"
|
||||
>
|
||||
<q-item-label
|
||||
style="font-size: 0.7em;"
|
||||
class="text-uppercase"
|
||||
>
|
||||
{{ $d(getDate(day.short_date), {weekday: $q.screen.lt.md ? 'short' : 'long'}) }}
|
||||
</q-item-label>
|
||||
<q-item-label
|
||||
class="text-weight-bolder"
|
||||
style="font-size: 2.5em; line-height: 90% !important;"
|
||||
>
|
||||
{{ day.short_date.split('/')[1] }}
|
||||
</q-item-label>
|
||||
<q-item-label
|
||||
style="font-size: 0.7em;"
|
||||
class="text-uppercase"
|
||||
>
|
||||
{{ $d(getDate(day.short_date), {month: $q.screen.lt.md ? 'short' : 'long'}) }}
|
||||
</q-item-label>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="col q-pa-none">
|
||||
<DetailedShiftListHeader />
|
||||
<DetailedShiftListRow
|
||||
v-for="shift, shift_index in shifts_or_placeholder(day.shifts)"
|
||||
:key="shift_index"
|
||||
:shift="shift"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pr-xs col-auto">
|
||||
<q-btn
|
||||
push
|
||||
color="primary"
|
||||
icon="more_time"
|
||||
class="q-pa-sm"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { useTimesheetStore } from "src/stores/timesheet-store";
|
||||
import { useAuthStore } from "src/stores/auth-store";
|
||||
import type { PayPeriodReportFilters } from "src/modules/timesheet-approval/types/pay-period-report";
|
||||
import { default_pay_period_employee_overview, type PayPeriodEmployeeOverview } from "src/modules/timesheet-approval/types/pay-period-employee-overview";
|
||||
import type { TimesheetApprovalCSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
|
||||
import { date } from "quasar";
|
||||
|
||||
export const useTimesheetApprovalApi = () => {
|
||||
|
|
@ -20,10 +19,6 @@ export const useTimesheetApprovalApi = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const getPayPeriodOverviewByEmployeeEmail = (email: string): void => {
|
||||
const employee_overview = timesheet_store.getPayPeriodOverviewByEmployeeEmail(email);
|
||||
};
|
||||
|
||||
/* This method attempts to get the next or previous pay period.
|
||||
It checks if pay period number is within a certain range, adjusts pay period and year accordingly.
|
||||
It then requests the matching pay period object to set as current pay period from server.
|
||||
|
|
@ -56,9 +51,9 @@ export const useTimesheetApprovalApi = () => {
|
|||
const [ targo, solucom ] = report_filter_company;
|
||||
const [ shifts, expenses, holiday, vacation ] = report_filter_type;
|
||||
const options = {
|
||||
company: { targo, solucom },
|
||||
types: { shifts, expenses, holiday, vacation }
|
||||
} as PayPeriodReportFilters;
|
||||
types: { shifts, expenses, holiday, vacation },
|
||||
companies: { targo, solucom },
|
||||
} as TimesheetApprovalCSVReportFilters;
|
||||
|
||||
await timesheet_store.getTimesheetApprovalCSVReport(options);
|
||||
};
|
||||
|
|
@ -66,7 +61,6 @@ export const useTimesheetApprovalApi = () => {
|
|||
return {
|
||||
getPayPeriodOverviewByDate,
|
||||
getNextOrPreviousPayPeriodOverviewList,
|
||||
getPayPeriodOverviewByEmployeeEmail,
|
||||
getTimesheetApprovalCSVReport,
|
||||
}
|
||||
};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
export interface PayPeriodReportFilters {
|
||||
export interface TimesheetApprovalCSVReportFilters {
|
||||
types: {
|
||||
shifts: boolean;
|
||||
expenses: boolean;
|
||||
|
|
@ -9,9 +9,9 @@ export interface PayPeriodReportFilters {
|
|||
targo: boolean;
|
||||
solucom: boolean;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export const default_pay_period_report_filters: PayPeriodReportFilters = {
|
||||
export const default_pay_period_report_filters: TimesheetApprovalCSVReportFilters = {
|
||||
types: {
|
||||
shifts: true,
|
||||
expenses: true,
|
||||
|
|
@ -22,4 +22,4 @@ export const default_pay_period_report_filters: PayPeriodReportFilters = {
|
|||
targo: true,
|
||||
solucom: true,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,14 @@
|
|||
export interface PayPeriodEmployeeOverview {
|
||||
export interface TimesheetApprovalOverviewCrew {
|
||||
pay_period_no: number;
|
||||
pay_year: number;
|
||||
payday: string;
|
||||
period_start: string;
|
||||
period_end: string;
|
||||
label: string;
|
||||
overview_crew: TimesheetApprovalOverviewCrewMember[];
|
||||
};
|
||||
|
||||
export interface TimesheetApprovalOverviewCrewMember {
|
||||
email: string;
|
||||
employee_name: string;
|
||||
regular_hours: number;
|
||||
|
|
@ -11,7 +21,7 @@ export interface PayPeriodEmployeeOverview {
|
|||
is_approved: boolean;
|
||||
};
|
||||
|
||||
export const default_pay_period_employee_overview: PayPeriodEmployeeOverview = {
|
||||
export const default_timesheet_approval_overview_crew_member: TimesheetApprovalOverviewCrewMember = {
|
||||
email: '',
|
||||
employee_name: '',
|
||||
regular_hours: -1,
|
||||
|
|
@ -24,7 +34,17 @@ export const default_pay_period_employee_overview: PayPeriodEmployeeOverview = {
|
|||
is_approved: false
|
||||
}
|
||||
|
||||
export const pay_period_employee_overview_columns = [
|
||||
export const default_timesheet_approval_overview_crew: TimesheetApprovalOverviewCrew = {
|
||||
pay_period_no: -1,
|
||||
pay_year: -1,
|
||||
payday: '',
|
||||
period_start: '',
|
||||
period_end: '',
|
||||
label: '',
|
||||
overview_crew: []
|
||||
}
|
||||
|
||||
export const timesheet_approval_overview_crew_columns = [
|
||||
{
|
||||
name: 'employee_name',
|
||||
label: 'timesheet_approvals.table.full_name',
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
import { date } from 'quasar';
|
||||
import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import EmployeeOverviewList from 'src/modules/timesheet-approval/components/employee-overview/overview-list.vue';
|
||||
import TimesheetApprovalDetailed from 'src/modules/timesheet-approval/pages/timesheet-approval-detailed.vue';
|
||||
import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue';
|
||||
import EmployeeOverviewList from 'src/modules/timesheet-approval/components/employee-overview/overview-list.vue';
|
||||
import DetailedDialog from 'src/modules/timesheet-approval/components/detailed-dialog.vue';
|
||||
|
||||
const timesheet_approval_api = useTimesheetApprovalApi();
|
||||
const timesheet_store = useTimesheetStore();
|
||||
|
|
@ -26,10 +26,10 @@
|
|||
:end-date="timesheet_store.pay_period.period_end"
|
||||
/>
|
||||
|
||||
<TimesheetApprovalDetailed
|
||||
<DetailedDialog
|
||||
:is-loading="timesheet_store.is_loading"
|
||||
:employee-overview="timesheet_store.pay_period_employee_overview"
|
||||
:employee-details="timesheet_store.pay_period_employee_details"
|
||||
:timesheet-details="timesheet_store.pay_period_employee_details"
|
||||
/>
|
||||
|
||||
<EmployeeOverviewList />
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import { defaultTimesheetDetailsWeek } from "src/modules/timesheets/types/timesheet.defaults";
|
||||
import type { TimesheetDetailsWeek } from "src/modules/timesheets/types/timesheet.interfaces";
|
||||
|
||||
|
||||
export interface PayPeriodEmployeeDetails {
|
||||
week1: TimesheetDetailsWeek;
|
||||
week2: TimesheetDetailsWeek;
|
||||
employee_full_name: string;
|
||||
};
|
||||
|
||||
export const default_pay_period_employee_details = {
|
||||
week1: defaultTimesheetDetailsWeek(),
|
||||
week2: defaultTimesheetDetailsWeek(),
|
||||
employee_full_name: "",
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import type { PayPeriodEmployeeOverview } from "./pay-period-employee-overview";
|
||||
|
||||
export interface PayPeriodOverview {
|
||||
pay_period_no: number;
|
||||
pay_year: number;
|
||||
payday: string;
|
||||
period_start: string;
|
||||
period_end: string;
|
||||
label: string;
|
||||
employees_overview: PayPeriodEmployeeOverview[];
|
||||
};
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
// export interface PayPeriodReport {
|
||||
|
||||
// }
|
||||
|
||||
export interface PayPeriodReportFilters {
|
||||
company: {
|
||||
targo: boolean;
|
||||
solucom: boolean;
|
||||
};
|
||||
types: {
|
||||
shifts: boolean;
|
||||
expenses: boolean;
|
||||
holiday: boolean;
|
||||
vacation: boolean;
|
||||
};
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import { useI18n } from 'vue-i18n';
|
|||
import { SHIFT_KEY, type ShiftKey, type ShiftPayload, type ShiftSelectOption } from '../../types/shift.types';
|
||||
import type { UpsertShiftsBody } from '../../types/shift.interfaces';
|
||||
import { upsertShiftsByDate } from '../../composables/api/use-shift-api';
|
||||
/* eslint-disable */
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
|
|
|||
78
src/modules/timesheets/models/expense.models.ts
Normal file
78
src/modules/timesheets/models/expense.models.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// export const EXPENSE_TYPE = [
|
||||
// 'PER_DIEM',
|
||||
// 'MILEAGE',
|
||||
// 'EXPENSES',
|
||||
// 'PRIME_GARDE',
|
||||
// ] as const;
|
||||
|
||||
// export type ExpenseType = (typeof EXPENSE_TYPE)[number];
|
||||
|
||||
// export const TYPES_WITH_MILEAGE_ONLY: Readonly<ExpenseType[]> = ['MILEAGE'];
|
||||
|
||||
// export const TYPES_WITH_AMOUNT_ONLY: Readonly<ExpenseType[]> = [
|
||||
// 'PER_DIEM',
|
||||
// 'EXPENSES',
|
||||
// 'PRIME_GARDE',
|
||||
// ];
|
||||
|
||||
export type ExpenseType = 'PER_DIEM' | 'MILEAGE' | 'EXPENSES' | 'PRIME_GARDE';
|
||||
|
||||
export type ExpenseTotals = {
|
||||
amount: number;
|
||||
mileage: number;
|
||||
};
|
||||
|
||||
// export type ExpenseSavePayload = {
|
||||
// pay_period_no: number;
|
||||
// pay_year: number;
|
||||
// email: string;
|
||||
// expenses: TimesheetExpense[];
|
||||
// };
|
||||
|
||||
export interface Expense {
|
||||
// is_approved: boolean;
|
||||
// comment: string;
|
||||
// amount: number;
|
||||
// supervisor_comment: string;
|
||||
// }
|
||||
|
||||
// export interface TimesheetExpense {
|
||||
date: string;
|
||||
type: string;
|
||||
amount?: number;
|
||||
mileage?: number;
|
||||
comment?: string;
|
||||
supervisor_comment?: string;
|
||||
is_approved?: boolean;
|
||||
}
|
||||
|
||||
// export interface PayPeriodExpenses {
|
||||
export interface TimesheetExpenses {
|
||||
pay_period_no: number;
|
||||
pay_year: number;
|
||||
employee_email: string;
|
||||
is_approved: boolean;
|
||||
// expenses: TimesheetExpense[];
|
||||
expenses: Expense[];
|
||||
totals?: {
|
||||
amount: number;
|
||||
mileage: number;
|
||||
reimbursable_total?: number;
|
||||
}
|
||||
}
|
||||
|
||||
// export interface ExpensePayload{
|
||||
// date: string;
|
||||
// type: ExpenseType;
|
||||
// amount?: number;
|
||||
// mileage?: number;
|
||||
// comment: string;
|
||||
// }
|
||||
|
||||
// export interface UpsertExpensesBody {
|
||||
// expenses: ExpensePayload[];
|
||||
// }
|
||||
|
||||
// export interface UpsertExpensesResponse {
|
||||
// data: PayPeriodExpenses;
|
||||
// }
|
||||
83
src/modules/timesheets/models/shift.models.ts
Normal file
83
src/modules/timesheets/models/shift.models.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// export const SHIFT_KEY = [
|
||||
// 'REGULAR',
|
||||
// 'EVENING',
|
||||
// 'EMERGENCY',
|
||||
// 'HOLIDAY',
|
||||
// 'VACATION',
|
||||
// 'SICK'
|
||||
// ] as const;
|
||||
|
||||
// export type ShiftKey = typeof SHIFT_KEY[number];
|
||||
|
||||
// export type ShiftSelectOption = { value: ShiftKey; label: string };
|
||||
|
||||
// export type ShiftPayload = {
|
||||
// start_time: string;
|
||||
// end_time: string;
|
||||
// type: ShiftKey;
|
||||
// is_remote: boolean;
|
||||
// comment?: string;
|
||||
// }
|
||||
|
||||
export type ShiftKey = 'REGULAR' | 'EVENING' | 'EMERGENCY' | 'HOLIDAY' | 'VACATION' | 'SICK';
|
||||
|
||||
export type UpsertAction = 'created' | 'updated' | 'deleted';
|
||||
|
||||
export type ShiftLegendItem = {
|
||||
type: ShiftKey;
|
||||
color: string;
|
||||
label_key: string;
|
||||
text_color?: string;
|
||||
};
|
||||
|
||||
export interface Shift {
|
||||
date: string;
|
||||
type: ShiftKey;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
comment: string;
|
||||
is_approved: boolean;
|
||||
is_remote: boolean;
|
||||
}
|
||||
|
||||
export interface UpsertShiftsResponse {
|
||||
action: UpsertAction;
|
||||
// day: DayShift[];
|
||||
day: Shift[];
|
||||
}
|
||||
|
||||
// export interface CreateShiftPayload {
|
||||
// date: string;
|
||||
// type: ShiftKey;
|
||||
// start_time: string;
|
||||
// end_time: string;
|
||||
// comment?: string;
|
||||
// is_remote?: boolean;
|
||||
// }
|
||||
|
||||
// export interface CreateWeekShiftPayload {
|
||||
// shifts: CreateShiftPayload[];
|
||||
// }
|
||||
|
||||
// export interface UpsertShiftsBody {
|
||||
// old_shift?: ShiftPayload;
|
||||
// new_shift?: ShiftPayload;
|
||||
// }
|
||||
|
||||
// export interface DayShift {
|
||||
// start_time: string;
|
||||
// end_time: string;
|
||||
// type: string;
|
||||
// is_remote: boolean;
|
||||
// comment?: string | null;
|
||||
// }
|
||||
|
||||
export const default_shift: Readonly<Shift> = {
|
||||
date: '',
|
||||
start_time: '--:--',
|
||||
end_time: '--:--',
|
||||
type:'REGULAR',
|
||||
comment: '',
|
||||
is_approved: false,
|
||||
is_remote: false,
|
||||
};
|
||||
125
src/modules/timesheets/models/timesheet.models.ts
Normal file
125
src/modules/timesheets/models/timesheet.models.ts
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import type { Shift } from "./shift.models";
|
||||
import type { Expense } from "src/modules/timesheets/models/expense.models";
|
||||
// import type {
|
||||
// TimesheetExpenseEntry,
|
||||
// TimesheetShiftEntry,
|
||||
// Week
|
||||
// } from "./timesheet.types";
|
||||
|
||||
// export interface Timesheet {
|
||||
// is_approved: boolean;
|
||||
// start_day: string;
|
||||
// end_day: string;
|
||||
// label: string;
|
||||
// shifts: TimesheetShiftEntry[];
|
||||
// expenses: TimesheetExpenseEntry[];
|
||||
// }
|
||||
|
||||
// export type TimesheetShiftEntry = {
|
||||
// bank_type: string;
|
||||
// date: string;
|
||||
// start_time: string;
|
||||
// end_time: string;
|
||||
// comment: string;
|
||||
// is_approved: boolean;
|
||||
// is_remote: boolean;
|
||||
// };
|
||||
|
||||
// export type TimesheetExpenseEntry = {
|
||||
// bank_type: string;
|
||||
// date: string;
|
||||
// amount: number;
|
||||
// km: number;
|
||||
// comment: string;
|
||||
// is_approved: boolean;
|
||||
// supervisor_comment: string;
|
||||
// };
|
||||
|
||||
export type Week<T> = {
|
||||
sun: T;
|
||||
mon: T;
|
||||
tue: T;
|
||||
wed: T;
|
||||
thu: T;
|
||||
fri: T;
|
||||
sat: T;
|
||||
};
|
||||
|
||||
export interface TimesheetDetails {
|
||||
week1: TimesheetDetailsWeek;
|
||||
week2: TimesheetDetailsWeek;
|
||||
employee_full_name: string;
|
||||
}
|
||||
|
||||
export interface TimesheetDetailsWeek {
|
||||
is_approved: boolean;
|
||||
shifts: Week<TimesheetDetailsWeekDayShifts>
|
||||
expenses: Week<TimesheetDetailsWeekDayExpenses>;
|
||||
}
|
||||
|
||||
export interface TimesheetDetailsWeekDayShifts {
|
||||
shifts: Shift[];
|
||||
regular_hours: number;
|
||||
evening_hours: number;
|
||||
emergency_hours: number;
|
||||
overtime_hours: number;
|
||||
total_hours: number;
|
||||
short_date: string;
|
||||
break_duration?: number;
|
||||
}
|
||||
|
||||
export interface TimesheetDetailsWeekDayExpenses {
|
||||
cash: Expense[];
|
||||
km: Expense[];
|
||||
[otherType: string]: Expense[];
|
||||
}
|
||||
|
||||
// export interface DailyExpense {
|
||||
// is_approved: boolean;
|
||||
// comment: string;
|
||||
// amount: number;
|
||||
// supervisor_comment: string;
|
||||
// }
|
||||
|
||||
// export interface TimesheetPayPeriodDetailsOverview {
|
||||
// week1: TimesheetDetailsWeek;
|
||||
// week2: TimesheetDetailsWeek;
|
||||
// }
|
||||
|
||||
const makeWeek = <T>(factory: ()=> T): Week<T> => ({
|
||||
sun: factory(),
|
||||
mon: factory(),
|
||||
tue: factory(),
|
||||
wed: factory(),
|
||||
thu: factory(),
|
||||
fri: factory(),
|
||||
sat: factory(),
|
||||
});
|
||||
|
||||
const emptyDailySchedule = (): TimesheetDetailsWeekDayShifts => ({
|
||||
shifts: [],
|
||||
regular_hours: 0,
|
||||
evening_hours: 0,
|
||||
emergency_hours: 0,
|
||||
overtime_hours: 0,
|
||||
total_hours: 0,
|
||||
short_date: "",
|
||||
break_duration: 0,
|
||||
});
|
||||
|
||||
const emptyDailyExpenses = (): TimesheetDetailsWeekDayExpenses => ({
|
||||
cash: [],
|
||||
km: [],
|
||||
});
|
||||
|
||||
export const defaultTimesheetDetailsWeek = (): TimesheetDetailsWeek => ({
|
||||
is_approved: false,
|
||||
shifts: makeWeek(emptyDailySchedule),
|
||||
expenses: makeWeek(emptyDailyExpenses),
|
||||
});
|
||||
|
||||
export const default_timesheet_details: TimesheetDetails = {
|
||||
week1: defaultTimesheetDetailsWeek(),
|
||||
week2: defaultTimesheetDetailsWeek(),
|
||||
employee_full_name: "",
|
||||
}
|
||||
|
|
@ -13,9 +13,9 @@ import TimesheetNavigation from '../components/timesheet/timesheet-naviga
|
|||
import ShiftsLegend from '../components/shift/shifts-legend.vue';
|
||||
import ShiftCrudDialog from '../components/shift/shift-crud-dialog.vue';
|
||||
import TimesheetDetailsExpenses from '../components/expenses/timesheet-details-expenses.vue';
|
||||
import { SHIFT_KEY } from '../types/shift.types';
|
||||
import DetailedShiftList from '../components/shift/detailed-shift-list.vue';
|
||||
import type { ShiftKey } from '../models/shift.models';
|
||||
import type { TimesheetExpense } from '../types/expense.interfaces';
|
||||
import DetailedShiftList from '../components/shift/detailed-shift-list.vue';
|
||||
/* eslint-disable */
|
||||
|
||||
//------------------- stores -------------------
|
||||
|
|
@ -29,14 +29,13 @@ const timesheet_api = useTimesheetApi();
|
|||
//------------------- expenses -------------------
|
||||
const openExpensesDialog = () => expenses_store.openDialog({
|
||||
email: auth_store.user.email,
|
||||
pay_year: timesheet_store.current_pay_period.pay_year,
|
||||
pay_period_no: timesheet_store.current_pay_period.pay_period_no,
|
||||
pay_year: timesheet_store.pay_period.pay_year,
|
||||
pay_period_no: timesheet_store.pay_period.pay_period_no,
|
||||
t,
|
||||
});
|
||||
|
||||
const onSaveExpenses = async ( payload: { email: string; pay_year: number; pay_period_no: number; expenses: TimesheetExpense[] }) => {
|
||||
await expenses_store.saveExpenses({...payload, t});
|
||||
await timesheet_store.refreshCurrentPeriodForUser(auth_store.user.email);
|
||||
};
|
||||
|
||||
const onCloseExpenses = () => expenses_store.closeDialog();
|
||||
|
|
@ -45,7 +44,7 @@ const onCloseExpenses = () => expenses_store.closeDialog();
|
|||
const date_options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'long', year: 'numeric' };
|
||||
|
||||
const pay_period_label = computed(() => formatPayPeriodLabel(
|
||||
timesheet_store.current_pay_period?.label,
|
||||
timesheet_store.pay_period.label,
|
||||
locale.value,
|
||||
date.extractDate,
|
||||
date_options
|
||||
|
|
@ -55,11 +54,6 @@ const pay_period_label = computed(() => formatPayPeriodLabel(
|
|||
//------------------- q-select Shift options -------------------
|
||||
const shift_options = computed(() => buildShiftOptions(SHIFT_KEY, t));
|
||||
|
||||
//------------------- navigation by date -------------------
|
||||
const onDateSelected = async (date_string: string) => {
|
||||
await timesheet_store.loadByIsoDate(date_string, auth_store.user.email);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await timesheet_store.loadToday(auth_store.user.email);
|
||||
});
|
||||
|
|
@ -6,7 +6,7 @@ import type { PayPeriodReportFilters } from "src/modules/timesheet-approval/type
|
|||
import type { Timesheet } from "../types/timesheet.interfaces";
|
||||
import type { CreateShiftPayload, CreateWeekShiftPayload } from "../types/shift.interfaces";
|
||||
|
||||
export const timesheetTempService = {
|
||||
export const timesheetService = {
|
||||
//GET
|
||||
getTimesheetsByEmail: async ( email: string, offset = 0): Promise<Timesheet> => {
|
||||
const response = await api.get(`/timesheets/${encodeURIComponent(email)}`, {params: offset ? { offset } : undefined});
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import type { ExpenseType } from "./expense.types";
|
||||
|
||||
export interface Expense {
|
||||
is_approved: boolean;
|
||||
comment: string;
|
||||
amount: number;
|
||||
supervisor_comment: string;
|
||||
}
|
||||
|
||||
export interface TimesheetExpense {
|
||||
date: string;
|
||||
type: string;
|
||||
amount?: number;
|
||||
mileage?: number;
|
||||
comment?: string;
|
||||
supervisor_comment?: string;
|
||||
is_approved?: boolean;
|
||||
}
|
||||
|
||||
export interface PayPeriodExpenses {
|
||||
pay_period_no: number;
|
||||
pay_year: number;
|
||||
employee_email: string;
|
||||
is_approved: boolean;
|
||||
expenses: TimesheetExpense[];
|
||||
totals: {
|
||||
amount: number;
|
||||
mileage: number;
|
||||
reimbursable_total?: number;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ExpensePayload{
|
||||
date: string;
|
||||
type: ExpenseType;
|
||||
amount?: number;
|
||||
mileage?: number;
|
||||
comment: string;
|
||||
}
|
||||
|
||||
export interface UpsertExpensesBody {
|
||||
expenses: ExpensePayload[];
|
||||
}
|
||||
|
||||
export interface UpsertExpensesResponse {
|
||||
data: PayPeriodExpenses;
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import type { TimesheetExpense } from "./expense.interfaces";
|
||||
|
||||
export const EXPENSE_TYPE = [
|
||||
'PER_DIEM',
|
||||
'MILEAGE',
|
||||
'EXPENSES',
|
||||
'PRIME_GARDE',
|
||||
] as const;
|
||||
|
||||
export type ExpenseType = (typeof EXPENSE_TYPE)[number];
|
||||
|
||||
export const TYPES_WITH_MILEAGE_ONLY: Readonly<ExpenseType[]> = ['MILEAGE'];
|
||||
export const TYPES_WITH_AMOUNT_ONLY: Readonly<ExpenseType[]> = [
|
||||
'PER_DIEM',
|
||||
'EXPENSES',
|
||||
'PRIME_GARDE',
|
||||
];
|
||||
|
||||
export type ExpenseTotals = {
|
||||
amount: number;
|
||||
mileage: number;
|
||||
};
|
||||
|
||||
export type ExpenseSavePayload = {
|
||||
pay_period_no: number;
|
||||
pay_year: number;
|
||||
email: string;
|
||||
expenses: TimesheetExpense[];
|
||||
};
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import type { Shift } from "./shift.interfaces";
|
||||
|
||||
export const default_shift: Readonly<Shift> = {
|
||||
date: '',
|
||||
start_time: '--:--',
|
||||
end_time: '--:--',
|
||||
type:'REGULAR',
|
||||
comment: '',
|
||||
is_approved: false,
|
||||
is_remote: false,
|
||||
};
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import type { ShiftKey, ShiftPayload, UpsertAction } from "./shift.types";
|
||||
|
||||
export interface Shift {
|
||||
date: string;
|
||||
type: ShiftKey;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
comment: string;
|
||||
is_approved: boolean;
|
||||
is_remote: boolean;
|
||||
}
|
||||
|
||||
export interface CreateShiftPayload {
|
||||
date: string;
|
||||
type: ShiftKey;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
comment?: string;
|
||||
is_remote?: boolean;
|
||||
}
|
||||
|
||||
export interface CreateWeekShiftPayload {
|
||||
shifts: CreateShiftPayload[];
|
||||
}
|
||||
|
||||
export interface UpsertShiftsBody {
|
||||
old_shift?: ShiftPayload;
|
||||
new_shift?: ShiftPayload;
|
||||
}
|
||||
|
||||
export interface DayShift {
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
type: string;
|
||||
is_remote: boolean;
|
||||
comment?: string | null;
|
||||
}
|
||||
|
||||
export interface UpsertShiftsResponse {
|
||||
action: UpsertAction;
|
||||
day: DayShift[];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
export const SHIFT_KEY = [
|
||||
'REGULAR',
|
||||
'EVENING',
|
||||
'EMERGENCY',
|
||||
'HOLIDAY',
|
||||
'VACATION',
|
||||
'SICK'
|
||||
] as const;
|
||||
|
||||
export type ShiftKey = typeof SHIFT_KEY[number];
|
||||
|
||||
export type ShiftSelectOption = { value: ShiftKey; label: string };
|
||||
|
||||
export type ShiftPayload = {
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
type: ShiftKey;
|
||||
is_remote: boolean;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export type ShiftLegendItem = {
|
||||
type: 'REGULAR'|'EVENING'|'EMERGENCY'|'OVERTIME'|'VACATION'|'HOLIDAY'|'SICK';
|
||||
color: string;
|
||||
label_key: string;
|
||||
text_color?: string;
|
||||
};
|
||||
|
||||
export type UpsertAction = 'created' | 'updated' | 'deleted';
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
import type { WeekDay } from "./timesheet.types";
|
||||
import type {
|
||||
TimesheetDetailsDailyExpenses,
|
||||
TimesheetDetailsDailySchedule,
|
||||
TimesheetDetailsWeek
|
||||
} from "./timesheet.interfaces";
|
||||
|
||||
const makeWeek = <T>(factory: ()=> T): WeekDay<T> => ({
|
||||
sun: factory(),
|
||||
mon: factory(),
|
||||
tue: factory(),
|
||||
wed: factory(),
|
||||
thu: factory(),
|
||||
fri: factory(),
|
||||
sat: factory(),
|
||||
});
|
||||
|
||||
const emptyDailySchedule = (): TimesheetDetailsDailySchedule => ({
|
||||
shifts: [],
|
||||
regular_hours: 0,
|
||||
evening_hours: 0,
|
||||
emergency_hours: 0,
|
||||
overtime_hours: 0,
|
||||
total_hours: 0,
|
||||
comment: "",
|
||||
short_date: "",
|
||||
break_duration: 0,
|
||||
});
|
||||
|
||||
const emptyDailyExpenses = (): TimesheetDetailsDailyExpenses => ({
|
||||
cash: [],
|
||||
km: [],
|
||||
});
|
||||
|
||||
export const defaultTimesheetDetailsWeek = (): TimesheetDetailsWeek => ({
|
||||
is_approved: false,
|
||||
shifts: makeWeek(emptyDailySchedule),
|
||||
expenses: makeWeek(emptyDailyExpenses),
|
||||
});
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
import type { Shift } from "./shift.interfaces";
|
||||
import type {
|
||||
TimesheetExpenseEntry,
|
||||
TimesheetShiftEntry,
|
||||
WeekDay
|
||||
} from "./timesheet.types";
|
||||
|
||||
|
||||
export interface Timesheet {
|
||||
is_approved: boolean;
|
||||
start_day: string;
|
||||
end_day: string;
|
||||
label: string;
|
||||
shifts: TimesheetShiftEntry[];
|
||||
expenses: TimesheetExpenseEntry[];
|
||||
}
|
||||
|
||||
export interface TimesheetDetailsWeek {
|
||||
is_approved: boolean;
|
||||
shifts: WeekDay<TimesheetDetailsDailySchedule>
|
||||
expenses: WeekDay<TimesheetDetailsDailyExpenses>;
|
||||
}
|
||||
|
||||
export interface TimesheetDetailsDailySchedule {
|
||||
shifts: Shift[];
|
||||
regular_hours: number;
|
||||
evening_hours: number;
|
||||
emergency_hours: number;
|
||||
overtime_hours: number;
|
||||
total_hours: number;
|
||||
comment: string;
|
||||
short_date: string;
|
||||
break_duration?: number;
|
||||
}
|
||||
|
||||
export interface DailyExpense {
|
||||
is_approved: boolean;
|
||||
comment: string;
|
||||
amount: number;
|
||||
supervisor_comment: string;
|
||||
}
|
||||
|
||||
export interface TimesheetDetailsDailyExpenses {
|
||||
cash: DailyExpense[];
|
||||
km: DailyExpense[];
|
||||
[otherType: string]: DailyExpense[];
|
||||
}
|
||||
|
||||
|
||||
export interface TimesheetPayPeriodDetailsOverview {
|
||||
week1: TimesheetDetailsWeek;
|
||||
week2: TimesheetDetailsWeek;
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
export type TimesheetShiftEntry = {
|
||||
bank_type: string;
|
||||
date: string;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
comment: string;
|
||||
is_approved: boolean;
|
||||
is_remote: boolean;
|
||||
};
|
||||
|
||||
export type TimesheetExpenseEntry = {
|
||||
bank_type: string;
|
||||
date: string;
|
||||
amount: number;
|
||||
km: number;
|
||||
comment: string;
|
||||
is_approved: boolean;
|
||||
supervisor_comment: string;
|
||||
};
|
||||
|
||||
export type WeekDay<T> = {
|
||||
sun: T;
|
||||
mon: T;
|
||||
tue: T;
|
||||
wed: T;
|
||||
thu: T;
|
||||
fri: T;
|
||||
sat: T;
|
||||
};
|
||||
|
|
@ -1,42 +1,23 @@
|
|||
import { date } from 'quasar';
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, ref } from 'vue';
|
||||
import { withLoading } from 'src/utils/store-helpers';
|
||||
import { timesheetApprovalService } from 'src/modules/timesheet-approval/services/timesheet-approval-service';
|
||||
import { timesheetTempService } from 'src/modules/timesheets/services/timesheet-services';
|
||||
import { default_pay_period_employee_details, type PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/pay-period-employee-details';
|
||||
import { default_pay_period_employee_overview, type PayPeriodEmployeeOverview } from "src/modules/timesheet-approval/types/pay-period-employee-overview";
|
||||
import type { Timesheet } from 'src/modules/timesheets/types/timesheet.interfaces';
|
||||
import type { PayPeriod } from 'src/modules/shared/types/pay-period-interface';
|
||||
import { timesheetService } from 'src/modules/timesheets/services/timesheet-service';
|
||||
import { default_timesheet_approval_overview_crew, type TimesheetApprovalOverviewCrew } from "src/modules/timesheet-approval/models/timesheet-approval-overview.models";
|
||||
// import type { Timesheet } from 'src/modules/timesheets/types/timesheet.interfaces';
|
||||
import type { TimesheetDetails } from 'src/modules/timesheets/models/timesheet.models';
|
||||
import { default_timesheet_details } from 'src/modules/timesheets/types/timesheet.defaults';
|
||||
import { default_pay_period, type PayPeriod } from 'src/modules/shared/types/pay-period-interface';
|
||||
import type { PayPeriodReportFilters } from 'src/modules/timesheet-approval/types/pay-period-report';
|
||||
|
||||
const default_pay_period: PayPeriod = {
|
||||
pay_period_no: -1,
|
||||
period_start: '',
|
||||
period_end: '',
|
||||
payday: '',
|
||||
pay_year: -1,
|
||||
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<boolean>(false);
|
||||
const pay_period = ref<PayPeriod>(default_pay_period);
|
||||
const pay_period_employee_overview_list = ref<PayPeriodEmployeeOverview[]>([]);
|
||||
const pay_period_employee_overview = ref<PayPeriodEmployeeOverview>(default_pay_period_employee_overview);
|
||||
const pay_period_employee_details = ref<PayPeriodEmployeeDetails>(default_pay_period_employee_details);
|
||||
const timesheet_approval_overview_list = ref<TimesheetApprovalOverview[]>([]);
|
||||
const timesheet_aproval_overview = ref<TimesheetApprovalOverview>(default_pay_period_employee_overview);
|
||||
const pay_period_employee_details = ref<TimesheetDetails>(default_timesheet_details);
|
||||
const pay_period_report = ref();
|
||||
const timesheet = ref<Timesheet>(default_timesheet);
|
||||
// const timesheet = ref<Timesheet>(default_timesheet);
|
||||
const is_calendar_limit = computed( ()=>
|
||||
pay_period.value.pay_year === 2024 &&
|
||||
pay_period.value.pay_period_no <= 1
|
||||
|
|
@ -97,21 +78,21 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
|||
return pay_period_employee_overview.value;
|
||||
};
|
||||
|
||||
const getTimesheetByEmail = async (employee_email: string) => {
|
||||
return withLoading( is_loading, async () => {
|
||||
try{
|
||||
const response = await timesheetTempService.getTimesheetsByEmail(employee_email);
|
||||
timesheet.value = response;
|
||||
// const getTimesheetByEmail = async (employee_email: string) => {
|
||||
// return withLoading( is_loading, async () => {
|
||||
// try{
|
||||
// const response = await timesheetTempService.getTimesheetsByEmail(employee_email);
|
||||
// timesheet.value = response;
|
||||
|
||||
return true;
|
||||
}catch (error) {
|
||||
console.error('There was an error retrieving timesheet details for this employee: ', error);
|
||||
timesheet.value = { ...default_timesheet }
|
||||
}
|
||||
// return true;
|
||||
// }catch (error) {
|
||||
// console.error('There was an error retrieving timesheet details for this employee: ', error);
|
||||
// timesheet.value = { ...default_timesheet }
|
||||
// }
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
// return false;
|
||||
// });
|
||||
// };
|
||||
|
||||
const getPayPeriodEmployeeDetailsByEmployeeEmail = async (employee_email: string) => {
|
||||
return withLoading( is_loading, async () => {
|
||||
|
|
@ -163,7 +144,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
|||
is_loading,
|
||||
is_calendar_limit,
|
||||
getPayPeriodByDateOrYearAndNumber,
|
||||
getTimesheetByEmail,
|
||||
// getTimesheetByEmail,
|
||||
getPayPeriodEmployeeOverviewListBySupervisorEmail,
|
||||
getPayPeriodOverviewByEmployeeEmail,
|
||||
getPayPeriodEmployeeDetailsByEmployeeEmail,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user