fix(approvals, timesheet): separation of concern, refactor timesheet route to use optional email, fix frontend routes and streamline store, simplify logic in many places.
This commit is contained in:
parent
a47222a7b8
commit
39ce63603e
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 7.4 MiB |
|
|
@ -13,7 +13,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-card class="rounded-15 shadow-10">
|
<q-card class="rounded-15 shadow-10 full-width">
|
||||||
<q-card-section class="text-center bg-primary q-pa-lg">
|
<q-card-section class="text-center bg-primary q-pa-lg">
|
||||||
<q-img
|
<q-img
|
||||||
src="/src/assets/logo-targo-white.svg"
|
src="/src/assets/logo-targo-white.svg"
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
label-color="accent"
|
label-color="accent"
|
||||||
class="rounded-5 inset-shadow bg-white"
|
class="rounded-5 inset-shadow bg-white"
|
||||||
label-slot
|
label-slot
|
||||||
input-class="text-h6 text-dark"
|
input-class="text-h6 text-primary"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span class="text-weight-bolder text-uppercase text-overline"> {{ $t('login.email') }} </span>
|
<span class="text-weight-bolder text-uppercase text-overline"> {{ $t('login.email') }} </span>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { Bar } from 'vue-chartjs';
|
import { Bar } from 'vue-chartjs';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar, colors } from 'quasar';
|
import { useQuasar, colors } from 'quasar';
|
||||||
|
|
@ -21,42 +21,37 @@
|
||||||
|
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
|
|
||||||
|
const all_days = timesheet_store.timesheets.flatMap(week => week.days.flatMap(day => day.daily_expenses));
|
||||||
|
|
||||||
|
const expenses_labels = ref<string[]>(timesheet_store.timesheets.flatMap(week => week.days.map(day => day.date.slice(-5,))));
|
||||||
const expenses_dataset = ref<ChartDataset<'bar'>[]>([]);
|
const expenses_dataset = ref<ChartDataset<'bar'>[]>([]);
|
||||||
const expenses_labels = ref<string[]>([]);
|
|
||||||
|
|
||||||
const getExpensesData = (): ChartData<'bar'> => {
|
|
||||||
const all_days = timesheet_store.timesheets.flatMap(week => week.days.flatMap(day => day.daily_expenses));
|
|
||||||
|
|
||||||
const all_costs = all_days.map(day => (day.expenses + day.on_call + day.per_diem));
|
|
||||||
const all_mileage = all_days.map(day => day.mileage);
|
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
expenses_dataset.value = [
|
expenses_dataset.value = [
|
||||||
{
|
{
|
||||||
label: t('timesheet_approvals.table.expenses'),
|
label: t('timesheet_approvals.table.expenses'),
|
||||||
data: all_costs,
|
data: all_days.map(day => (day.expenses + day.on_call + day.per_diem)),
|
||||||
backgroundColor: colors.getPaletteColor('primary'),
|
backgroundColor: colors.getPaletteColor('accent'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('timesheet_approvals.table.mileage'),
|
label: t('timesheet_approvals.table.mileage'),
|
||||||
data: all_mileage,
|
data: all_days.map(day => day.mileage),
|
||||||
backgroundColor: colors.getPaletteColor('info'),
|
backgroundColor: colors.getPaletteColor('info'),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
});
|
||||||
expenses_labels.value = timesheet_store.timesheets.flatMap(week => week.days.map(day => day.date.slice(-5, )));
|
|
||||||
|
|
||||||
return {
|
|
||||||
datasets: expenses_dataset.value,
|
|
||||||
labels: expenses_labels.value
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div
|
||||||
|
class="bg-dark rounded-10 q-pa-sm"
|
||||||
|
:style="`min-height: ${$q.screen.lt.md ? '350px;' : '200px'}`"
|
||||||
|
>
|
||||||
<Bar
|
<Bar
|
||||||
:data="getExpensesData()"
|
:data="{
|
||||||
|
datasets: expenses_dataset,
|
||||||
|
labels: expenses_labels,
|
||||||
|
}"
|
||||||
:options="({
|
:options="({
|
||||||
indexAxis: $q.screen.lt.md ? 'y' : 'x',
|
indexAxis: $q.screen.lt.md ? 'y' : 'x',
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
setup
|
setup
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { colors, useQuasar } from 'quasar';
|
import { colors, useQuasar } from 'quasar';
|
||||||
import { Bar } from 'vue-chartjs';
|
import { Bar } from 'vue-chartjs';
|
||||||
|
|
@ -26,60 +26,53 @@
|
||||||
|
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
|
|
||||||
const hours_worked_labels = ref<string[]>([]);
|
const all_days = computed(() => timesheet_store.timesheets.flatMap(week => week.days));
|
||||||
|
|
||||||
|
const datasetConfig: ChartConfigHoursWorked[] = [
|
||||||
|
{
|
||||||
|
key: 'regular',
|
||||||
|
label: t('shared.shift_type.regular'),
|
||||||
|
color: colors.getPaletteColor('accent'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'evening',
|
||||||
|
label: t('shared.shift_type.evening'),
|
||||||
|
color: colors.getPaletteColor('green-10'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'emergency',
|
||||||
|
label: t('shared.shift_type.emergency'),
|
||||||
|
color: getComputedStyle(document.body).getPropertyValue('--q-warning').trim(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'overtime',
|
||||||
|
label: t('shared.shift_type.overtime'),
|
||||||
|
color: getComputedStyle(document.body).getPropertyValue('--q-negative').trim(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const hours_worked_labels = ref<string[]>(all_days.value.map(day => day.date.slice(-5,)));
|
||||||
const hours_worked_dataset = ref<ChartDataset<'bar'>[]>([]);
|
const hours_worked_dataset = ref<ChartDataset<'bar'>[]>([]);
|
||||||
|
|
||||||
const getHoursWorkedData = (): ChartData<'bar'> => {
|
onMounted(() => {
|
||||||
|
|
||||||
const all_days = computed(() => timesheet_store.timesheets.flatMap(week => week.days));
|
|
||||||
const datasetConfig: ChartConfigHoursWorked[] = [
|
|
||||||
{
|
|
||||||
key: 'regular',
|
|
||||||
label: t('shared.shift_type.regular'),
|
|
||||||
color: colors.getPaletteColor('primary'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'evening',
|
|
||||||
label: t('shared.shift_type.evening'),
|
|
||||||
color: colors.getPaletteColor('accent'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'emergency',
|
|
||||||
label: t('shared.shift_type.emergency'),
|
|
||||||
color: getComputedStyle(document.body).getPropertyValue('--q-warning').trim(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'overtime',
|
|
||||||
label: t('shared.shift_type.overtime'),
|
|
||||||
color: getComputedStyle(document.body).getPropertyValue('--q-negative').trim(),
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
hours_worked_dataset.value = datasetConfig.map(cfg => ({
|
hours_worked_dataset.value = datasetConfig.map(cfg => ({
|
||||||
label: cfg.label,
|
label: cfg.label,
|
||||||
data: all_days.value.map(day => day.daily_hours[cfg.key]),
|
data: all_days.value.map(day => day.daily_hours[cfg.key]),
|
||||||
backgroundColor: cfg.color,
|
backgroundColor: cfg.color,
|
||||||
}));
|
}));
|
||||||
|
});
|
||||||
hours_worked_labels.value = all_days.value.map(day => day.date.slice(-5, ));
|
|
||||||
|
|
||||||
console.log('all days: ', all_days.value);
|
|
||||||
|
|
||||||
console.log('hours worked labels: ', hours_worked_labels.value);
|
|
||||||
console.log('hours worked dataset: ', hours_worked_dataset.value);
|
|
||||||
|
|
||||||
return {
|
|
||||||
labels: hours_worked_labels.value,
|
|
||||||
datasets: hours_worked_dataset.value,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div
|
||||||
|
class="bg-dark rounded-10 q-pa-sm"
|
||||||
|
:style="`min-height: ${$q.screen.lt.md ? '450px;' : '200px'}`"
|
||||||
|
>
|
||||||
<Bar
|
<Bar
|
||||||
:data="getHoursWorkedData()"
|
:data="{
|
||||||
|
labels: hours_worked_labels,
|
||||||
|
datasets: hours_worked_dataset,
|
||||||
|
}"
|
||||||
:options="({
|
:options="({
|
||||||
indexAxis: $q.screen.lt.md ? 'y' : 'x',
|
indexAxis: $q.screen.lt.md ? 'y' : 'x',
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { colors } from 'quasar';
|
import { colors } from 'quasar';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { Doughnut } from 'vue-chartjs';
|
import { Doughnut } from 'vue-chartjs';
|
||||||
|
|
@ -19,44 +19,43 @@
|
||||||
|
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
|
|
||||||
const shift_type_labels = ref<string[]>([]);
|
const shift_type_labels = ref<string[]>([
|
||||||
const shift_type_totals = ref<ChartDataset<'doughnut'>[]>([{ data: [40, 0, 2, 5], }]);
|
|
||||||
|
|
||||||
|
|
||||||
shift_type_totals.value = [{
|
|
||||||
data: [
|
|
||||||
timesheet_store.current_pay_period_overview!.regular_hours,
|
|
||||||
timesheet_store.current_pay_period_overview!.other_hours.evening_hours,
|
|
||||||
timesheet_store.current_pay_period_overview!.other_hours.emergency_hours,
|
|
||||||
timesheet_store.current_pay_period_overview!.other_hours.overtime_hours,
|
|
||||||
],
|
|
||||||
backgroundColor: [
|
|
||||||
colors.getPaletteColor('primary'), // Regular
|
|
||||||
colors.getPaletteColor('accent'), // Evening
|
|
||||||
colors.getPaletteColor('warning'), // Emergency
|
|
||||||
colors.getPaletteColor('negative'), // Overtime
|
|
||||||
]
|
|
||||||
}];
|
|
||||||
|
|
||||||
shift_type_labels.value = [
|
|
||||||
timesheet_store.current_pay_period_overview!.regular_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.regular_hours.toString() + 'h',
|
||||||
timesheet_store.current_pay_period_overview!.other_hours.evening_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.other_hours.evening_hours.toString() + 'h',
|
||||||
timesheet_store.current_pay_period_overview!.other_hours.emergency_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.other_hours.emergency_hours.toString() + 'h',
|
||||||
timesheet_store.current_pay_period_overview!.other_hours.overtime_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.other_hours.overtime_hours.toString() + 'h',
|
||||||
]
|
]);
|
||||||
|
|
||||||
|
const shift_type_totals = ref<ChartDataset<'doughnut'>[]>([]);
|
||||||
|
|
||||||
const data = {
|
onMounted(() => {
|
||||||
labels: shift_type_labels.value,
|
shift_type_totals.value = [{
|
||||||
datasets: shift_type_totals.value,
|
data: [
|
||||||
}
|
timesheet_store.current_pay_period_overview!.regular_hours,
|
||||||
|
timesheet_store.current_pay_period_overview!.other_hours.evening_hours,
|
||||||
|
timesheet_store.current_pay_period_overview!.other_hours.emergency_hours,
|
||||||
|
timesheet_store.current_pay_period_overview!.other_hours.overtime_hours,
|
||||||
|
],
|
||||||
|
backgroundColor: [
|
||||||
|
colors.getPaletteColor('accent'), // Regular
|
||||||
|
colors.getPaletteColor('green-10'), // Evening
|
||||||
|
colors.getPaletteColor('warning'), // Emergency
|
||||||
|
colors.getPaletteColor('negative'), // Overtime
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div
|
||||||
|
style="min-height: 100px;"
|
||||||
|
:style="$q.screen.lt.md ? 'max-height: 150px;' : ''"
|
||||||
|
>
|
||||||
<Doughnut
|
<Doughnut
|
||||||
:data="data"
|
:data="{
|
||||||
|
labels: shift_type_labels,
|
||||||
|
datasets: shift_type_totals,
|
||||||
|
}"
|
||||||
:options="({
|
:options="({
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import { provide, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||||
import DetailsDialogChartHoursWorked from 'src/modules/timesheet-approval/components/details-dialog-chart-hours-worked.vue';
|
import DetailsDialogChartHoursWorked from 'src/modules/timesheet-approval/components/details-dialog-chart-hours-worked.vue';
|
||||||
import DetailsDialogChartShiftTypes from 'src/modules/timesheet-approval/components/details-dialog-chart-shift-types.vue';
|
import DetailsDialogChartShiftTypes from 'src/modules/timesheet-approval/components/details-dialog-chart-shift-types.vue';
|
||||||
|
|
@ -11,20 +11,13 @@
|
||||||
import TimesheetWrapper from 'src/modules/timesheets/components/timesheet-wrapper.vue';
|
import TimesheetWrapper from 'src/modules/timesheets/components/timesheet-wrapper.vue';
|
||||||
import ExpenseDialogList from 'src/modules/timesheets/components/expense-dialog-list.vue';
|
import ExpenseDialogList from 'src/modules/timesheets/components/expense-dialog-list.vue';
|
||||||
|
|
||||||
const { employeeEmail } = defineProps<{
|
|
||||||
employeeEmail: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const dialog_model = defineModel<boolean>('dialog', { default: false });
|
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const is_dialog_open = ref(false);
|
const is_dialog_open = ref(false);
|
||||||
|
|
||||||
provide('employeeEmail', employeeEmail);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-dialog
|
<q-dialog
|
||||||
v-model="dialog_model"
|
v-model="timesheet_store.is_details_dialog_open"
|
||||||
full-width
|
full-width
|
||||||
full-height
|
full-height
|
||||||
transition-show="jump-down"
|
transition-show="jump-down"
|
||||||
|
|
@ -33,14 +26,12 @@
|
||||||
@hide="is_dialog_open = false"
|
@hide="is_dialog_open = false"
|
||||||
>
|
>
|
||||||
<q-card
|
<q-card
|
||||||
class="shadow-12 rounded-15 column no-wrap relative bg-secondary"
|
class="shadow-12 rounded-15 column no-wrap relative bg-secondary hide-scrollbar"
|
||||||
:style="($q.screen.lt.md ? '' : 'width: 60vw !important;') + ($q.dark.isActive ? ' border: 2px solid var(--q-accent)' : '')"
|
:style="($q.screen.lt.md ? '' : 'width:80vw !important;') + ($q.dark.isActive ? ' border: 2px solid var(--q-accent)' : '')"
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- employee name -->
|
<!-- employee name -->
|
||||||
<q-card-section
|
<q-card-section class="col-auto text-h4 text-weight-bolder text-center text-uppercase q-px-none q-py-sm">
|
||||||
class="col-auto text-h5 text-weight-bolder text-center text-uppercase text-white q-px-none q-py-xs bg-primary"
|
|
||||||
>
|
|
||||||
<span>{{ timesheet_store.selected_employee_name }}</span>
|
<span>{{ timesheet_store.selected_employee_name }}</span>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
|
|
@ -48,21 +39,15 @@
|
||||||
<q-card-section
|
<q-card-section
|
||||||
v-if="is_dialog_open"
|
v-if="is_dialog_open"
|
||||||
:horizontal="!$q.screen.lt.md"
|
:horizontal="!$q.screen.lt.md"
|
||||||
class="col-auto q-px-sm no-wrap"
|
class="col-auto q-px-md rounded-10 no-wrap"
|
||||||
>
|
>
|
||||||
<DetailsDialogChartHoursWorked class="col" />
|
<DetailsDialogChartHoursWorked class="col" />
|
||||||
|
|
||||||
<DetailsDialogChartShiftTypes class="col q-ma-lg" />
|
<DetailsDialogChartShiftTypes class="col q-ma-lg" />
|
||||||
|
|
||||||
<DetailsDialogChartExpenses class="col" />
|
<DetailsDialogChartExpenses class="col" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-card-section class="col-auto">
|
<q-card-section class="col-auto">
|
||||||
<q-separator />
|
<ExpenseDialogList />
|
||||||
<ExpenseDialogList
|
|
||||||
:employee-email="employeeEmail"
|
|
||||||
/>
|
|
||||||
<q-separator />
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<!-- list of shifts -->
|
<!-- list of shifts -->
|
||||||
|
|
@ -70,10 +55,7 @@
|
||||||
:horizontal="$q.screen.gt.sm"
|
:horizontal="$q.screen.gt.sm"
|
||||||
class="col-auto q-px-sm rounded-5 no-wrap"
|
class="col-auto q-px-sm rounded-5 no-wrap"
|
||||||
>
|
>
|
||||||
<TimesheetWrapper
|
<TimesheetWrapper mode="approval" />
|
||||||
dense
|
|
||||||
:employee-email="employeeEmail"
|
|
||||||
/>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const timesheet_approval_api = useTimesheetApprovalApi();
|
const timesheet_approval_api = useTimesheetApprovalApi();
|
||||||
|
|
||||||
const employeeEmail = defineModel();
|
|
||||||
|
|
||||||
const visible_columns = ref<string[]>([
|
const visible_columns = ref<string[]>([
|
||||||
overview_column_names.REGULAR,
|
overview_column_names.REGULAR,
|
||||||
overview_column_names.EVENING,
|
overview_column_names.EVENING,
|
||||||
|
|
@ -28,21 +26,16 @@
|
||||||
overview_column_names.IS_APPROVED,
|
overview_column_names.IS_APPROVED,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
'clickedDetailsButton': [email: string];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const overview_rows = computed(() => timesheet_store.pay_period_overviews[0]?.regular_hours === -1 ?
|
const overview_rows = computed(() => timesheet_store.pay_period_overviews[0]?.regular_hours === -1 ?
|
||||||
[] :
|
[] :
|
||||||
timesheet_store.pay_period_overviews
|
timesheet_store.pay_period_overviews
|
||||||
)
|
)
|
||||||
|
|
||||||
const onClickedDetails = async (employee_email: string, row: TimesheetOverview) => {
|
const onClickedDetails = async (row: TimesheetOverview) => {
|
||||||
employeeEmail.value = employee_email;
|
|
||||||
timesheet_store.current_pay_period_overview = row;
|
timesheet_store.current_pay_period_overview = row;
|
||||||
emit('clickedDetailsButton', employee_email);
|
await timesheet_store.getTimesheetsByOptionalEmployeeEmail(row.email);
|
||||||
|
|
||||||
await timesheet_store.getTimesheetsByEmployeeEmail(employee_email);
|
timesheet_store.is_details_dialog_open = true;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -99,7 +92,7 @@
|
||||||
>
|
>
|
||||||
<transition
|
<transition
|
||||||
appear
|
appear
|
||||||
enter-active-class="animated fadeInUp"
|
enter-active-class="animated fadeInUp slow"
|
||||||
leave-active-class="animated fadeOutDown"
|
leave-active-class="animated fadeOutDown"
|
||||||
mode="out-in"
|
mode="out-in"
|
||||||
>
|
>
|
||||||
|
|
@ -146,7 +139,7 @@
|
||||||
:key="props.row.email + timesheet_store.pay_period?.pay_period_no"
|
:key="props.row.email + timesheet_store.pay_period?.pay_period_no"
|
||||||
:index="props.rowIndex"
|
:index="props.rowIndex"
|
||||||
:row="props.row"
|
:row="props.row"
|
||||||
@click-details="overview => onClickedDetails(props.row.email, overview)"
|
@click-details="overview => onClickedDetails(overview)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,7 @@
|
||||||
|
|
||||||
const expenses_list = computed(() => {
|
const expenses_list = computed(() => {
|
||||||
if (timesheet_store.timesheets !== undefined) {
|
if (timesheet_store.timesheets !== undefined) {
|
||||||
const current_expenses = timesheet_store.timesheets.flatMap(week => week.days).flatMap(day => day.expenses);
|
return timesheet_store.timesheets.flatMap(week => week.days).flatMap(day => day.expenses);
|
||||||
console.log('current expenses: ', current_expenses);
|
|
||||||
return current_expenses;
|
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="$q.screen.lt.md ? 'column full-width' : 'row'"
|
:class="$q.screen.lt.md ? 'column full-width' : 'row'"
|
||||||
:style="$q.screen.lt.md ? 'width: 90vw !important;' : ''"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="timesheet, timesheet_index in timesheet_store.timesheets"
|
v-for="timesheet, timesheet_index in timesheet_store.timesheets"
|
||||||
|
|
@ -72,7 +71,7 @@
|
||||||
|
|
||||||
<q-card-section
|
<q-card-section
|
||||||
class="text-weight-bolder text-uppercase text-h6 q-py-xs"
|
class="text-weight-bolder text-uppercase text-h6 q-py-xs"
|
||||||
:class="(getDayApproval(day) || timesheet.is_approved) ? 'bg-dark text-white' : 'bg-primary text-white'"
|
:class="(getDayApproval(day) || timesheet.is_approved) ? 'bg-accent text-white' : 'bg-primary text-white'"
|
||||||
style="line-height: 1em;"
|
style="line-height: 1em;"
|
||||||
>
|
>
|
||||||
<span> {{ $d(extractDate(day.date, 'YYYY-MM-DD'), {
|
<span> {{ $d(extractDate(day.date, 'YYYY-MM-DD'), {
|
||||||
|
|
|
||||||
|
|
@ -10,65 +10,59 @@
|
||||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||||
import { useTimesheetApi } from 'src/modules/timesheets/composables/use-timesheet-api';
|
import { useTimesheetApi } from 'src/modules/timesheets/composables/use-timesheet-api';
|
||||||
import { useExpensesStore } from 'src/stores/expense-store';
|
import { useExpensesStore } from 'src/stores/expense-store';
|
||||||
import { provide } from 'vue';
|
|
||||||
import { useShiftApi } from 'src/modules/timesheets/composables/use-shift-api';
|
import { useShiftApi } from 'src/modules/timesheets/composables/use-shift-api';
|
||||||
|
|
||||||
const { open } = useExpensesStore();
|
const expenses_store = useExpensesStore();
|
||||||
const shift_api = useShiftApi();
|
|
||||||
|
|
||||||
const { employeeEmail, dense = false } = defineProps<{
|
|
||||||
employeeEmail: string;
|
|
||||||
dense?: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const timesheet_api = useTimesheetApi();
|
const timesheet_api = useTimesheetApi();
|
||||||
|
const shift_api = useShiftApi();
|
||||||
|
|
||||||
provide('employeeEmail', employeeEmail);
|
const { mode = 'normal' } = defineProps<{
|
||||||
|
mode?: 'approval' | 'normal';
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="column flex-center full-width">
|
<div
|
||||||
|
class="column flex-center full-width"
|
||||||
<LoadingOverlay v-model="timesheet_store.is_loading"/>
|
:class="mode === 'approval' ? 'bg-dark q-px-sm q-pb-sm q-mb-md rounded-10 shadow-10' : ''"
|
||||||
|
>
|
||||||
|
<LoadingOverlay v-model="timesheet_store.is_loading" />
|
||||||
|
|
||||||
<q-card
|
<q-card
|
||||||
flat
|
flat
|
||||||
class="transparent full-width"
|
class="transparent full-width"
|
||||||
>
|
>
|
||||||
<q-card-section
|
<q-card-section
|
||||||
v-if="!dense"
|
|
||||||
:horizontal="$q.screen.gt.sm"
|
:horizontal="$q.screen.gt.sm"
|
||||||
class="q-px-md items-center q-mb-md"
|
class="q-px-md items-center q-mb-md"
|
||||||
:class="$q.screen.lt.md ? 'column' : ''"
|
:class="$q.screen.lt.md ? 'column' : ''"
|
||||||
>
|
>
|
||||||
<!-- navigation btn -->
|
<!-- navigation btn -->
|
||||||
<PayPeriodNavigator
|
<PayPeriodNavigator
|
||||||
v-if="!dense"
|
v-if="mode === 'normal'"
|
||||||
@date-selected="date_value => timesheet_api.getTimesheetsByDate(date_value, employeeEmail)"
|
@date-selected="date_value => timesheet_api.getTimesheetsByDate(date_value)"
|
||||||
@pressed-previous-button="timesheet_api.getTimesheetsByCurrentPayPeriod(employeeEmail)"
|
@pressed-previous-button="timesheet_api.getTimesheetsByCurrentPayPeriod"
|
||||||
@pressed-next-button="timesheet_api.getTimesheetsByCurrentPayPeriod(employeeEmail)"
|
@pressed-next-button="timesheet_api.getTimesheetsByCurrentPayPeriod"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- mobile expenses button -->
|
<!-- mobile expenses button -->
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="$q.screen.lt.md"
|
v-if="$q.screen.lt.md && mode === 'normal'"
|
||||||
push
|
push
|
||||||
rounded
|
rounded
|
||||||
color="accent"
|
color="accent"
|
||||||
icon="receipt_long"
|
icon="receipt_long"
|
||||||
:label="$t('timesheet.expense.open_btn')"
|
:label="$t('timesheet.expense.open_btn')"
|
||||||
class="q-mt-sm"
|
class="q-mt-sm"
|
||||||
@click="open"
|
@click="expenses_store.open"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- shift's colored legend -->
|
|
||||||
<!-- <ShiftListLegend :is-loading="false" /> -->
|
|
||||||
|
|
||||||
<q-space />
|
<q-space />
|
||||||
|
|
||||||
<!-- save timesheet changes button -->
|
<!-- save timesheet changes button -->
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="$q.screen.gt.sm"
|
v-if="mode === 'normal'"
|
||||||
push
|
push
|
||||||
rounded
|
rounded
|
||||||
:disable="timesheet_store.is_loading"
|
:disable="timesheet_store.is_loading"
|
||||||
|
|
@ -81,13 +75,13 @@
|
||||||
|
|
||||||
<!-- desktop expenses button -->
|
<!-- desktop expenses button -->
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="$q.screen.gt.sm"
|
v-if="mode === 'normal'"
|
||||||
push
|
push
|
||||||
rounded
|
rounded
|
||||||
color="accent"
|
color="accent"
|
||||||
icon="receipt_long"
|
icon="receipt_long"
|
||||||
:label="$t('timesheet.expense.open_btn')"
|
:label="$t('timesheet.expense.open_btn')"
|
||||||
@click="open"
|
@click="expenses_store.open"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
@ -96,7 +90,25 @@
|
||||||
<TimesheetErrorWidget />
|
<TimesheetErrorWidget />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<ShiftList :dense="dense" />
|
<ShiftList :mode="mode" />
|
||||||
|
|
||||||
|
<q-card-section
|
||||||
|
horizontal
|
||||||
|
class="q-my-md"
|
||||||
|
>
|
||||||
|
<q-space />
|
||||||
|
<q-btn
|
||||||
|
v-if="mode === 'approval'"
|
||||||
|
push
|
||||||
|
rounded
|
||||||
|
:disable="timesheet_store.is_loading"
|
||||||
|
color="accent"
|
||||||
|
icon="upload"
|
||||||
|
:label="$t('shared.label.save')"
|
||||||
|
class="q-mr-md"
|
||||||
|
@click="shift_api.saveShiftChanges"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
<ExpenseDialog />
|
<ExpenseDialog />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,14 @@ export const useExpensesApi = () => {
|
||||||
const upsertExpense = async (expense: Expense): Promise<void> => {
|
const upsertExpense = async (expense: Expense): Promise<void> => {
|
||||||
const success = await expenses_store.upsertExpense(expense);
|
const success = await expenses_store.upsertExpense(expense);
|
||||||
if (success) {
|
if (success) {
|
||||||
timesheet_store.getTimesheetsByEmployeeEmail();
|
timesheet_store.getTimesheetsByOptionalEmployeeEmail();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteExpenseById = async (expense_id: number): Promise<void> => {
|
const deleteExpenseById = async (expense_id: number): Promise<void> => {
|
||||||
const success = await expenses_store.deleteExpenseById(expense_id);
|
const success = await expenses_store.deleteExpenseById(expense_id);
|
||||||
if (success) {
|
if (success) {
|
||||||
timesheet_store.getTimesheetsByEmployeeEmail();
|
timesheet_store.getTimesheetsByOptionalEmployeeEmail();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export const useShiftApi = () => {
|
||||||
const success = await shift_store.deleteShiftById(shift_id);
|
const success = await shift_store.deleteShiftById(shift_id);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
await timesheet_store.getTimesheetsByEmployeeEmail(auth_store.user?.email ?? '');
|
await timesheet_store.getTimesheetsByOptionalEmployeeEmail(auth_store.user?.email ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
timesheet_store.is_loading = false;
|
timesheet_store.is_loading = false;
|
||||||
|
|
@ -25,7 +25,7 @@ export const useShiftApi = () => {
|
||||||
const update_success = await shift_store.updateShifts();
|
const update_success = await shift_store.updateShifts();
|
||||||
|
|
||||||
if (create_success || update_success){
|
if (create_success || update_success){
|
||||||
await timesheet_store.getTimesheetsByEmployeeEmail(auth_store.user?.email ?? '');
|
await timesheet_store.getTimesheetsByOptionalEmployeeEmail(auth_store.user?.email ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
timesheet_store.is_loading = false;
|
timesheet_store.is_loading = false;
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
import { useAuthStore } from "src/stores/auth-store";
|
|
||||||
import { useTimesheetStore } from "src/stores/timesheet-store"
|
import { useTimesheetStore } from "src/stores/timesheet-store"
|
||||||
|
|
||||||
export const useTimesheetApi = () => {
|
export const useTimesheetApi = () => {
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const auth_store = useAuthStore();
|
|
||||||
|
|
||||||
const getTimesheetsByDate = async (date_string: string, employee_email?: string) => {
|
const getTimesheetsByDate = async (date_string: string, employee_email?: string) => {
|
||||||
timesheet_store.is_loading = true;
|
timesheet_store.is_loading = true;
|
||||||
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date_string);
|
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date_string);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
await timesheet_store.getTimesheetsByEmployeeEmail(employee_email ?? auth_store.user?.email ?? '');
|
await timesheet_store.getTimesheetsByOptionalEmployeeEmail(employee_email);
|
||||||
timesheet_store.is_loading = false;
|
timesheet_store.is_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,7 +22,7 @@ export const useTimesheetApi = () => {
|
||||||
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber();
|
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber();
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
await timesheet_store.getTimesheetsByEmployeeEmail(employee_email ?? auth_store.user?.email ?? '');
|
await timesheet_store.getTimesheetsByOptionalEmployeeEmail(employee_email);
|
||||||
timesheet_store.is_loading = false;
|
timesheet_store.is_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,12 @@ export const timesheetService = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getTimesheetsByPayPeriodAndOptionalEmail: async (year: number, period_number: number, employee_email?: string): Promise<TimesheetResponse> => {
|
getTimesheetsByPayPeriodAndOptionalEmail: async (year: number, period_number: number, employee_email?: string): Promise<TimesheetResponse> => {
|
||||||
const response = await api.get<{success: boolean, data: TimesheetResponse, error? : string}>(`timesheets/${year}/${period_number}/${employee_email}`);
|
if (employee_email !== undefined) {
|
||||||
return response.data.data;
|
const response = await api.get<{success: boolean, data: TimesheetResponse, error? : string}>(`timesheets/${year}/${period_number}?employee_email=${employee_email}`);
|
||||||
|
return response.data.data;
|
||||||
|
} else {
|
||||||
|
const response = await api.get<{success: boolean, data: TimesheetResponse, error? : string}>(`timesheets/${year}/${period_number}`);
|
||||||
|
return response.data.data;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -5,10 +5,12 @@
|
||||||
<template>
|
<template>
|
||||||
<q-layout view="hHh lpR fFf">
|
<q-layout view="hHh lpR fFf">
|
||||||
<q-page-container class="bg-secondary">
|
<q-page-container class="bg-secondary">
|
||||||
<q-page class="column">
|
<q-page class="row">
|
||||||
<q-img src="src/assets/village.png" fit="contain" class="col absolute-bottom-right" style="opacity: 50%;" />
|
<q-img src="src/assets/village.png" fit="cover" :class="$q.screen.lt.md ? 'absolute-bottom' : 'absolute-right'" />
|
||||||
<transition appear slow enter-active-class="animated zoomIn" leave-active-class="animated zoomOut" class="col absolute-center">
|
<transition appear slow enter-active-class="animated zoomIn" leave-active-class="animated zoomOut" class="col-xs-10 absolute-center">
|
||||||
<LoginConnectionPanel />
|
<div class="col-sm-10 col-md-auto">
|
||||||
|
<LoginConnectionPanel />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</q-page>
|
</q-page>
|
||||||
</q-page-container>
|
</q-page-container>
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,6 @@
|
||||||
|
|
||||||
const timesheet_approval_api = useTimesheetApprovalApi();
|
const timesheet_approval_api = useTimesheetApprovalApi();
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const is_details_dialog_open = ref(false);
|
|
||||||
const employee_email = ref('');
|
|
||||||
|
|
||||||
const onDetailsClicked = (email: string) => {
|
|
||||||
employee_email.value = email;
|
|
||||||
is_details_dialog_open.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await timesheet_approval_api.getTimesheetOverviewsByDate(date.formatDate(new Date(), 'YYYY-MM-DD'));
|
await timesheet_approval_api.getTimesheetOverviewsByDate(date.formatDate(new Date(), 'YYYY-MM-DD'));
|
||||||
|
|
@ -41,8 +34,6 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DetailsDialog
|
<DetailsDialog
|
||||||
v-model:dialog="is_details_dialog_open"
|
|
||||||
:employee-email="employee_email"
|
|
||||||
:is-loading="timesheet_store.is_loading"
|
:is-loading="timesheet_store.is_loading"
|
||||||
:employee-overview="timesheet_store.current_pay_period_overview"
|
:employee-overview="timesheet_store.current_pay_period_overview"
|
||||||
:timesheets="timesheet_store.timesheets"
|
:timesheets="timesheet_store.timesheets"
|
||||||
|
|
@ -50,12 +41,13 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="col-auto full-width q-px-lg"
|
class="col-auto full-width q-px-lg"
|
||||||
:class="($q.screen.lt.md ? 'text-center' : 'row') + (timesheet_store.is_approval_grid_mode ? ' q-mb-sm' : ' q-mb-md')"
|
:class="($q.screen.lt.md ? 'column flex-center' : 'row') + (timesheet_store.is_approval_grid_mode ? ' q-mb-sm' : ' q-mb-md')"
|
||||||
>
|
>
|
||||||
<PayPeriodNavigator
|
<PayPeriodNavigator
|
||||||
@date-selected="timesheet_approval_api.getTimesheetOverviews"
|
@date-selected="timesheet_approval_api.getTimesheetOverviews"
|
||||||
@pressed-next-button="timesheet_approval_api.getTimesheetOverviews"
|
@pressed-next-button="timesheet_approval_api.getTimesheetOverviews"
|
||||||
@pressed-previous-button="timesheet_approval_api.getTimesheetOverviews"
|
@pressed-previous-button="timesheet_approval_api.getTimesheetOverviews"
|
||||||
|
:class="$q.screen.lt.md ? 'q-mb-sm' : ''"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-space />
|
<q-space />
|
||||||
|
|
@ -67,25 +59,27 @@
|
||||||
color="white"
|
color="white"
|
||||||
text-color="accent"
|
text-color="accent"
|
||||||
toggle-color="accent"
|
toggle-color="accent"
|
||||||
class="q-mr-md"
|
:class="$q.screen.lt.md ? 'q-mb-sm' : 'q-mr-md'"
|
||||||
:options="[
|
:options="[
|
||||||
{ icon: 'grid_view', value: true },
|
{ icon: 'grid_view', value: true },
|
||||||
{ icon: 'view_list', value: false },
|
{ icon: 'view_list', value: false },
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-btn-dropdown
|
<div class="col-auto row no-wrap flex-center" :class="$q.screen.lt.md ? 'q-mb-md' : ''">
|
||||||
push
|
<q-btn-dropdown
|
||||||
rounded
|
push
|
||||||
icon="filter_alt"
|
rounded
|
||||||
color="accent"
|
icon="filter_alt"
|
||||||
:label="$t('shared.label.filter')"
|
color="accent"
|
||||||
class="q-mr-md"
|
:label="$q.screen.lt.md ? '' : $t('shared.label.filter')"
|
||||||
/>
|
class="col-auto q-mr-sm"
|
||||||
|
/>
|
||||||
|
|
||||||
<QTableFilters v-model:search="timesheet_store.search_filter" />
|
<QTableFilters v-model:search="timesheet_store.search_filter" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OverviewList class="col" @clickedDetailsButton="onDetailsClicked" />
|
<OverviewList class="col" />
|
||||||
</q-page>
|
</q-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -45,7 +45,6 @@ export const useExpensesStore = defineStore('expenses', () => {
|
||||||
|
|
||||||
const deleteExpenseById = async (expense_id: number): Promise<boolean> => {
|
const deleteExpenseById = async (expense_id: number): Promise<boolean> => {
|
||||||
const data = await ExpenseService.deleteExpenseById(expense_id);
|
const data = await ExpenseService.deleteExpenseById(expense_id);
|
||||||
console.log('data received from expense deletion: ', data);
|
|
||||||
return data.success;
|
return data.success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,16 @@ import type { TimesheetApprovalCSVReportFilters } from 'src/modules/timesheet-ap
|
||||||
export const useTimesheetStore = defineStore('timesheet', () => {
|
export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
const is_loading = ref<boolean>(false);
|
const is_loading = ref<boolean>(false);
|
||||||
const pay_period = ref<PayPeriod>();
|
const pay_period = ref<PayPeriod>();
|
||||||
const pay_period_overviews = ref<TimesheetOverview[]>([]);
|
|
||||||
const current_pay_period_overview = ref<TimesheetOverview>();
|
|
||||||
const timesheets = ref<Timesheet[]>([]);
|
const timesheets = ref<Timesheet[]>([]);
|
||||||
const selected_employee_name = ref<string>();
|
|
||||||
const initial_timesheets = ref<Timesheet[]>([]);
|
const initial_timesheets = ref<Timesheet[]>([]);
|
||||||
const is_approval_grid_mode = ref<boolean>(true);
|
|
||||||
|
const pay_period_overviews = ref<TimesheetOverview[]>([]);
|
||||||
|
|
||||||
|
const is_details_dialog_open = ref(false);
|
||||||
|
const selected_employee_name = ref<string>();
|
||||||
|
const current_pay_period_overview = ref<TimesheetOverview>();
|
||||||
const search_filter = ref<string | number | null>('');
|
const search_filter = ref<string | number | null>('');
|
||||||
|
const is_approval_grid_mode = ref<boolean>(true);
|
||||||
const pay_period_report = ref();
|
const pay_period_report = ref();
|
||||||
|
|
||||||
const getPayPeriodByDateOrYearAndNumber = async (date?: string): Promise<boolean> => {
|
const getPayPeriodByDateOrYearAndNumber = async (date?: string): Promise<boolean> => {
|
||||||
|
|
@ -64,11 +67,11 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTimesheetsByEmployeeEmail = async (employee_email?: string) => {
|
const getTimesheetsByOptionalEmployeeEmail = async (employee_email?: string) => {
|
||||||
|
if (pay_period.value === undefined) return;
|
||||||
is_loading.value = true;
|
is_loading.value = true;
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
if (pay_period.value === undefined) return;
|
|
||||||
try {
|
try {
|
||||||
if (employee_email) {
|
if (employee_email) {
|
||||||
response = await timesheetService.getTimesheetsByPayPeriodAndOptionalEmail(pay_period.value.pay_year, pay_period.value.pay_period_no, employee_email);
|
response = await timesheetService.getTimesheetsByPayPeriodAndOptionalEmail(pay_period.value.pay_year, pay_period.value.pay_period_no, employee_email);
|
||||||
|
|
@ -108,6 +111,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
return {
|
return {
|
||||||
is_loading,
|
is_loading,
|
||||||
is_approval_grid_mode,
|
is_approval_grid_mode,
|
||||||
|
is_details_dialog_open,
|
||||||
search_filter,
|
search_filter,
|
||||||
pay_period,
|
pay_period,
|
||||||
pay_period_overviews,
|
pay_period_overviews,
|
||||||
|
|
@ -117,7 +121,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
initial_timesheets,
|
initial_timesheets,
|
||||||
getPayPeriodByDateOrYearAndNumber,
|
getPayPeriodByDateOrYearAndNumber,
|
||||||
getTimesheetOverviews,
|
getTimesheetOverviews,
|
||||||
getTimesheetsByEmployeeEmail,
|
getTimesheetsByOptionalEmployeeEmail,
|
||||||
getPayPeriodReportByYearAndPeriodNumber,
|
getPayPeriodReportByYearAndPeriodNumber,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
Loading…
Reference in New Issue
Block a user