fix(approvals): reimplement charts with new structures, clean UI/UX, refine list view
This commit is contained in:
parent
75ca572040
commit
a47222a7b8
|
|
@ -5,7 +5,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.text-fb-blue {
|
.text-fb-blue {
|
||||||
color: #4267B2 !important;
|
color: #4267B2 !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
$primary : #30303A;
|
$primary : #30303A;
|
||||||
$secondary : #DAE0E7;
|
$secondary : #DAE0E7;
|
||||||
$accent : #0c9a3b;
|
$accent : #0c9a3b;
|
||||||
$accent2 : #0a7d32;
|
$accent2 : #0a7d32;
|
||||||
|
|
||||||
$dark-shadow-color : #173625;
|
$dark-shadow-color : #000000;
|
||||||
|
|
||||||
$elevation-dark-umbra : rgba($dark-shadow-color, 1);
|
$elevation-dark-umbra : rgba($dark-shadow-color, 1);
|
||||||
$elevation-dark-penumbra : rgba($dark-shadow-color, 0.75);
|
$elevation-dark-penumbra : rgba($dark-shadow-color, 0.75);
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,8 @@ export default {
|
||||||
nav_button: {
|
nav_button: {
|
||||||
calendar_date_picker: "Calendar",
|
calendar_date_picker: "Calendar",
|
||||||
current_week: "This week",
|
current_week: "This week",
|
||||||
next_week: "Next week",
|
next_week: "Next period",
|
||||||
previous_week: "Previous week",
|
previous_week: "Previous period",
|
||||||
},
|
},
|
||||||
save_button: "Save",
|
save_button: "Save",
|
||||||
cancel_button: "Cancel",
|
cancel_button: "Cancel",
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,8 @@ export default {
|
||||||
nav_button: {
|
nav_button: {
|
||||||
calendar_date_picker: "Calendrier",
|
calendar_date_picker: "Calendrier",
|
||||||
current_week: "Semaine actuelle",
|
current_week: "Semaine actuelle",
|
||||||
next_week: "Prochaine semaine",
|
next_week: "Prochaine période",
|
||||||
previous_week: "Semaine précédente",
|
previous_week: "Période précédente",
|
||||||
},
|
},
|
||||||
save_button: "Enregistrer",
|
save_button: "Enregistrer",
|
||||||
cancel_button: "Annuler",
|
cancel_button: "Annuler",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
import { ref } from 'vue';
|
import { 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 } from 'quasar';
|
import { useQuasar, colors } from 'quasar';
|
||||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
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 { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, TimeScale, type ChartData, type ChartDataset } from 'chart.js';
|
||||||
|
|
||||||
|
|
@ -25,28 +25,26 @@
|
||||||
const expenses_labels = ref<string[]>([]);
|
const expenses_labels = ref<string[]>([]);
|
||||||
|
|
||||||
const getExpensesData = (): ChartData<'bar'> => {
|
const getExpensesData = (): ChartData<'bar'> => {
|
||||||
// const all_days = timesheet_store.pay_period_details.weeks.flatMap(week => Object.values(week.expenses));
|
const all_days = timesheet_store.timesheets.flatMap(week => week.days.flatMap(day => day.daily_expenses));
|
||||||
// const all_days_dates = timesheet_store.pay_period_details.weeks.flatMap(week => Object.values(week.shifts))
|
|
||||||
|
|
||||||
// const all_costs = all_days.map(day => day.total_expenses);
|
const all_costs = all_days.map(day => (day.expenses + day.on_call + day.per_diem));
|
||||||
// console.log('costs, ', all_costs);
|
const all_mileage = all_days.map(day => day.mileage);
|
||||||
// const all_mileage = all_days.map(day => day.total_mileage);
|
|
||||||
|
|
||||||
|
|
||||||
// expenses_dataset.value = [
|
expenses_dataset.value = [
|
||||||
// {
|
{
|
||||||
// label: t('timesheet_approvals.table.expenses'),
|
label: t('timesheet_approvals.table.expenses'),
|
||||||
// data: all_costs,
|
data: all_costs,
|
||||||
// backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-primary').trim(),
|
backgroundColor: colors.getPaletteColor('primary'),
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// label: t('timesheet_approvals.table.mileage'),
|
label: t('timesheet_approvals.table.mileage'),
|
||||||
// data: all_mileage,
|
data: all_mileage,
|
||||||
// backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-info').trim(),
|
backgroundColor: colors.getPaletteColor('info'),
|
||||||
// }
|
}
|
||||||
// ]
|
]
|
||||||
|
|
||||||
// expenses_labels.value = all_days_dates.map(day => day.short_date);
|
expenses_labels.value = timesheet_store.timesheets.flatMap(week => week.days.map(day => day.date.slice(-5, )));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
datasets: expenses_dataset.value,
|
datasets: expenses_dataset.value,
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,79 @@
|
||||||
<script setup lang="ts">
|
<script
|
||||||
/* eslint-disable */
|
setup
|
||||||
import { ref } from 'vue';
|
lang="ts"
|
||||||
import { colors } from 'quasar';
|
>
|
||||||
import { Bar } from 'vue-chartjs';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { colors, useQuasar } from 'quasar';
|
||||||
|
import { Bar } from 'vue-chartjs';
|
||||||
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, type ChartData, type ChartDataset } from 'chart.js';
|
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, type ChartData, type ChartDataset } from 'chart.js';
|
||||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||||
|
import type { TotalHours } from 'src/modules/timesheets/models/timesheet.models';
|
||||||
|
|
||||||
|
interface ChartConfigHoursWorked {
|
||||||
|
key: keyof Pick<TotalHours, 'regular' | 'evening' | 'emergency' | 'overtime'>;
|
||||||
|
label: string;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
||||||
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale);
|
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale);
|
||||||
ChartJS.defaults.font.family = '"Roboto", sans-serif';
|
ChartJS.defaults.font.family = '"Roboto", sans-serif';
|
||||||
ChartJS.defaults.maintainAspectRatio = false;
|
// ChartJS.defaults.maintainAspectRatio = false;
|
||||||
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
|
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
|
||||||
|
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
|
|
||||||
const hours_worked_labels = ref<string[]>([]);
|
const hours_worked_labels = ref<string[]>([]);
|
||||||
const hours_worked_dataset = ref<ChartDataset<'bar'>[]>([]);
|
const hours_worked_dataset = ref<ChartDataset<'bar'>[]>([]);
|
||||||
|
|
||||||
const getHoursWorkedData = (): ChartData<'bar'> => {
|
const getHoursWorkedData = (): ChartData<'bar'> => {
|
||||||
|
|
||||||
// const all_days = timesheet_store.pay_period_details.weeks.flatMap( week => Object.values(week.shifts));
|
|
||||||
// const datasetConfig = [
|
|
||||||
// {
|
|
||||||
// key: 'regular_hours',
|
|
||||||
// label: t('shared.shift_type.regular'),
|
|
||||||
// color: colors.getPaletteColor('green-5'),
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: 'evening_hours',
|
|
||||||
// label: t('shared.shift_type.evening'),
|
|
||||||
// color: colors.getPaletteColor('green-9'),
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: 'emergency_hours',
|
|
||||||
// label: t('shared.shift_type.emergency'),
|
|
||||||
// color: getComputedStyle(document.body).getPropertyValue('--q-warning').trim(),
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: 'overtime_hours',
|
|
||||||
// label: t('shared.shift_type.overtime'),
|
|
||||||
// color: getComputedStyle(document.body).getPropertyValue('--q-negative').trim(),
|
|
||||||
// },
|
|
||||||
// ] as const;
|
|
||||||
|
|
||||||
// hours_worked_dataset.value = datasetConfig.map(cfg => ({
|
const all_days = computed(() => timesheet_store.timesheets.flatMap(week => week.days));
|
||||||
// label: cfg.label,
|
const datasetConfig: ChartConfigHoursWorked[] = [
|
||||||
// data: all_days.map(day => day[ cfg.key ]),
|
{
|
||||||
// backgroundColor: cfg.color,
|
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_labels.value = all_days.map(day => day.short_date);
|
hours_worked_dataset.value = datasetConfig.map(cfg => ({
|
||||||
|
label: cfg.label,
|
||||||
|
data: all_days.value.map(day => day.daily_hours[cfg.key]),
|
||||||
|
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 {
|
return {
|
||||||
labels: hours_worked_labels.value,
|
labels: hours_worked_labels.value,
|
||||||
datasets: hours_worked_dataset.value,
|
datasets: hours_worked_dataset.value,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -69,7 +81,7 @@
|
||||||
<Bar
|
<Bar
|
||||||
:data="getHoursWorkedData()"
|
:data="getHoursWorkedData()"
|
||||||
:options="({
|
:options="({
|
||||||
indexAxis: $q.screen.lt.md? 'y' : 'x',
|
indexAxis: $q.screen.lt.md ? 'y' : 'x',
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
labels: {
|
labels: {
|
||||||
|
|
@ -89,10 +101,10 @@
|
||||||
stacked: true,
|
stacked: true,
|
||||||
suggestedMin: 0,
|
suggestedMin: 0,
|
||||||
suggestedMax: 10,
|
suggestedMax: 10,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"
|
})"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -17,33 +17,33 @@
|
||||||
ChartJS.defaults.maintainAspectRatio = false;
|
ChartJS.defaults.maintainAspectRatio = false;
|
||||||
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
|
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
|
||||||
|
|
||||||
const { current_pay_period_overview } = 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], }]);
|
const shift_type_totals = ref<ChartDataset<'doughnut'>[]>([{ data: [40, 0, 2, 5], }]);
|
||||||
|
|
||||||
|
|
||||||
// shift_type_totals.value = [{
|
shift_type_totals.value = [{
|
||||||
// data: [
|
data: [
|
||||||
// current_pay_period_overview.regular_hours,
|
timesheet_store.current_pay_period_overview!.regular_hours,
|
||||||
// current_pay_period_overview.other_hours.evening_hours,
|
timesheet_store.current_pay_period_overview!.other_hours.evening_hours,
|
||||||
// current_pay_period_overview.other_hours.emergency_hours,
|
timesheet_store.current_pay_period_overview!.other_hours.emergency_hours,
|
||||||
// current_pay_period_overview.other_hours.overtime_hours,
|
timesheet_store.current_pay_period_overview!.other_hours.overtime_hours,
|
||||||
// ],
|
],
|
||||||
// backgroundColor: [
|
backgroundColor: [
|
||||||
// colors.getPaletteColor('green-5'), // Regular
|
colors.getPaletteColor('primary'), // Regular
|
||||||
// colors.getPaletteColor('green-9'), // Evening
|
colors.getPaletteColor('accent'), // Evening
|
||||||
// getComputedStyle(document.body).getPropertyValue('--q-warning').trim(), // Emergency
|
colors.getPaletteColor('warning'), // Emergency
|
||||||
// getComputedStyle(document.body).getPropertyValue('--q-negative').trim(), // Overtime
|
colors.getPaletteColor('negative'), // Overtime
|
||||||
// ]
|
]
|
||||||
// }];
|
}];
|
||||||
|
|
||||||
// shift_type_labels.value = [
|
shift_type_labels.value = [
|
||||||
// current_pay_period_overview.regular_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.regular_hours.toString() + 'h',
|
||||||
// current_pay_period_overview.other_hours.evening_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.other_hours.evening_hours.toString() + 'h',
|
||||||
// current_pay_period_overview.other_hours.emergency_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.other_hours.emergency_hours.toString() + 'h',
|
||||||
// current_pay_period_overview.other_hours.overtime_hours.toString() + 'h',
|
timesheet_store.current_pay_period_overview!.other_hours.overtime_hours.toString() + 'h',
|
||||||
// ]
|
]
|
||||||
|
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
const dialog_model = defineModel<boolean>('dialog', { default: false });
|
const dialog_model = defineModel<boolean>('dialog', { default: false });
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const render_key = ref(1);
|
const is_dialog_open = ref(false);
|
||||||
|
|
||||||
provide('employeeEmail', employeeEmail);
|
provide('employeeEmail', employeeEmail);
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -29,45 +29,37 @@
|
||||||
full-height
|
full-height
|
||||||
transition-show="jump-down"
|
transition-show="jump-down"
|
||||||
transition-hide="jump-down"
|
transition-hide="jump-down"
|
||||||
@show="render_key += 1"
|
@show="is_dialog_open = true"
|
||||||
|
@hide="is_dialog_open = false"
|
||||||
>
|
>
|
||||||
<q-card
|
<q-card
|
||||||
class="q-pa-sm shadow-12 rounded-15 column no-wrap relative"
|
class="shadow-12 rounded-15 column no-wrap relative bg-secondary"
|
||||||
:style="$q.screen.lt.md ? '' : 'width: 60vw !important;'"
|
:style="($q.screen.lt.md ? '' : 'width: 60vw !important;') + ($q.dark.isActive ? ' border: 2px solid var(--q-accent)' : '')"
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- employee name -->
|
<!-- employee name -->
|
||||||
<q-card-section
|
<q-card-section
|
||||||
class="text-h5 text-weight-bolder text-center bg-primary q-pa-none text-uppercase text-white col-auto"
|
class="col-auto text-h5 text-weight-bolder text-center text-uppercase text-white q-px-none q-py-xs bg-primary"
|
||||||
>
|
>
|
||||||
<span>TODO: Name goes here</span>
|
<span>{{ timesheet_store.selected_employee_name }}</span>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<!-- employee pay period details using chart -->
|
<!-- employee pay period details using chart -->
|
||||||
<q-card-section
|
<q-card-section
|
||||||
|
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-sm no-wrap"
|
||||||
>
|
>
|
||||||
<DetailsDialogChartHoursWorked
|
<DetailsDialogChartHoursWorked class="col" />
|
||||||
:key="render_key"
|
|
||||||
class="col"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DetailsDialogChartShiftTypes
|
<DetailsDialogChartShiftTypes class="col q-ma-lg" />
|
||||||
:key="render_key + 1"
|
|
||||||
class="col-2 q-ma-lg"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DetailsDialogChartExpenses
|
<DetailsDialogChartExpenses class="col" />
|
||||||
:key="render_key + 2"
|
|
||||||
class="col"
|
|
||||||
/>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-card-section class="col-auto">
|
<q-card-section class="col-auto">
|
||||||
<q-separator />
|
<q-separator />
|
||||||
<ExpenseDialogList
|
<ExpenseDialogList
|
||||||
horizontal
|
|
||||||
:employee-email="employeeEmail"
|
:employee-email="employeeEmail"
|
||||||
/>
|
/>
|
||||||
<q-separator />
|
<q-separator />
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,13 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="q-px-sm q-pb-sm q-mt-sm col-xs-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 grid-style-transition">
|
<div class="q-px-sm q-pb-md col-xs-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 grid-style-transition">
|
||||||
<transition
|
<transition
|
||||||
appear
|
appear
|
||||||
enter-active-class="animated fadeInUp"
|
enter-active-class="animated fadeInUp"
|
||||||
>
|
>
|
||||||
<q-card
|
<q-card
|
||||||
class="rounded-10 shadow-15"
|
class="rounded-10 shadow-5"
|
||||||
:style="`animation-delay: ${index / 15}s;`"
|
:style="`animation-delay: ${index / 15}s;`"
|
||||||
>
|
>
|
||||||
<!-- Card header with employee name and details button-->
|
<!-- Card header with employee name and details button-->
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
import { useExpensesStore } from 'src/stores/expense-store';
|
import { useExpensesStore } from 'src/stores/expense-store';
|
||||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||||
import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api';
|
import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api';
|
||||||
import { pay_period_overview_columns, type TimesheetOverview } from 'src/modules/timesheet-approval/models/timesheet-overview.models';
|
import { overview_column_names, pay_period_overview_columns, type TimesheetOverview } from 'src/modules/timesheet-approval/models/timesheet-overview.models';
|
||||||
|
|
||||||
const expenses_store = useExpensesStore();
|
const expenses_store = useExpensesStore();
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
|
|
@ -17,7 +17,16 @@
|
||||||
|
|
||||||
const employeeEmail = defineModel();
|
const employeeEmail = defineModel();
|
||||||
|
|
||||||
const visible_columns = ref<string[]>(['employee_name', 'REGULAR', 'email', 'is_approved']);
|
const visible_columns = ref<string[]>([
|
||||||
|
overview_column_names.REGULAR,
|
||||||
|
overview_column_names.EVENING,
|
||||||
|
overview_column_names.EMERGENCY,
|
||||||
|
overview_column_names.SICK,
|
||||||
|
overview_column_names.VACATION,
|
||||||
|
overview_column_names.HOLIDAY,
|
||||||
|
overview_column_names.OVERTIME,
|
||||||
|
overview_column_names.IS_APPROVED,
|
||||||
|
]);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'clickedDetailsButton': [email: string];
|
'clickedDetailsButton': [email: string];
|
||||||
|
|
@ -34,12 +43,11 @@
|
||||||
emit('clickedDetailsButton', employee_email);
|
emit('clickedDetailsButton', employee_email);
|
||||||
|
|
||||||
await timesheet_store.getTimesheetsByEmployeeEmail(employee_email);
|
await timesheet_store.getTimesheetsByEmployeeEmail(employee_email);
|
||||||
// await expenses_store.getPayPeriodExpensesByTimesheetId(employee_email);
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="q-pa-md">
|
<div class="q-px-md full-height">
|
||||||
<LoadingOverlay v-model="timesheet_store.is_loading" />
|
<LoadingOverlay v-model="timesheet_store.is_loading" />
|
||||||
<transition
|
<transition
|
||||||
appear
|
appear
|
||||||
|
|
@ -55,18 +63,18 @@
|
||||||
row-key="email"
|
row-key="email"
|
||||||
:filter="timesheet_store.search_filter"
|
:filter="timesheet_store.search_filter"
|
||||||
:grid="timesheet_store.is_approval_grid_mode"
|
:grid="timesheet_store.is_approval_grid_mode"
|
||||||
dense
|
:dense="timesheet_store.is_approval_grid_mode"
|
||||||
hide-pagination
|
hide-pagination
|
||||||
color="accent"
|
color="accent"
|
||||||
:rows-per-page-options="[0]"
|
:rows-per-page-options="[0]"
|
||||||
card-container-class="justify-center"
|
card-container-class="justify-center"
|
||||||
class="q-py-md bg-transparent"
|
class="bg-transparent"
|
||||||
:class="timesheet_store.is_approval_grid_mode ? '' : 'sticky-header-table no-shadow'"
|
:class="timesheet_store.is_approval_grid_mode ? '' : 'sticky-header-table no-shadow'"
|
||||||
table-class="q-pa-none q-py-none q-mx-md rounded-10 bg-dark shadow-15"
|
table-class="q-pa-none q-mx-md rounded-10 bg-dark shadow-15"
|
||||||
:no-data-label="$t('shared.error.no_data_found')"
|
:no-data-label="$t('shared.error.no_data_found')"
|
||||||
:no-results-label="$t('shared.error.no_search_results')"
|
:no-results-label="$t('shared.error.no_search_results')"
|
||||||
:loading-label="$t('shared.label.loading')"
|
:loading-label="$t('shared.label.loading')"
|
||||||
>
|
>
|
||||||
<template #header="props">
|
<template #header="props">
|
||||||
<q-tr
|
<q-tr
|
||||||
:props="props"
|
:props="props"
|
||||||
|
|
@ -83,28 +91,54 @@
|
||||||
</q-th>
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #body-cell="props">
|
<template #body-cell="props">
|
||||||
<q-td
|
<q-td
|
||||||
:props="props"
|
:props="props"
|
||||||
class="text-weight-medium"
|
class="text-weight-medium"
|
||||||
>
|
>
|
||||||
<q-icon
|
<transition
|
||||||
v-if="props.col.name === 'is_approved'"
|
appear
|
||||||
:name="props.value ? 'verified' : 'remove_circle_outline'"
|
enter-active-class="animated fadeInUp"
|
||||||
:color="props.value ? 'accent' : 'grey-5'"
|
leave-active-class="animated fadeOutDown"
|
||||||
:class="props.value ? 'bg-white rounded-20' : ''"
|
mode="out-in"
|
||||||
size="sm"
|
>
|
||||||
/>
|
<div
|
||||||
|
:key="props.rowIndex + (timesheet_store.pay_period?.pay_period_no ?? 0)"
|
||||||
<div v-else-if="props.col.name === 'employee_name'">
|
class="rounded-5"
|
||||||
<span class="text-h5 text-uppercase text-accent q-mr-xs">{{ props.value.split(' ')[0]}}</span>
|
style="font-size: 1.2em;"
|
||||||
<span class="text-uppercase text-weight-light">{{ props.value.split(' ')[1] }}</span>
|
:style="`animation-delay: ${props.rowIndex / 30}s;`"
|
||||||
</div>
|
>
|
||||||
<span v-else>{{ props.value }}</span>
|
<transition
|
||||||
|
v-if="props.col.name === 'is_approved'"
|
||||||
|
enter-active-class="animated swing"
|
||||||
|
mode="out-in"
|
||||||
|
>
|
||||||
|
<q-btn
|
||||||
|
:key="props.row.is_approved"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
:icon="props.value ? 'lock' : 'lock_open'"
|
||||||
|
:color="props.value ? 'white' : 'grey-5'"
|
||||||
|
class="rounded-5 z-top"
|
||||||
|
:class="props.value ? 'bg-accent' : ''"
|
||||||
|
@click.stop="props.row.is_approved = !props.row.is_approved"
|
||||||
|
/>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<div v-else-if="props.col.name === 'employee_name'">
|
||||||
|
<span class="text-h5 text-uppercase text-accent q-mr-xs">
|
||||||
|
{{ props.value.split(' ')[0] }}
|
||||||
|
</span>
|
||||||
|
<span class="text-uppercase text-weight-light">{{ props.value.split(' ')[1]
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<span v-else>{{ props.value }}</span>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Template for individual employee cards -->
|
<!-- Template for individual employee cards -->
|
||||||
<template #item="props: { row: TimesheetOverview, rowIndex: number }">
|
<template #item="props: { row: TimesheetOverview, rowIndex: number }">
|
||||||
<OverviewListItem
|
<OverviewListItem
|
||||||
|
|
@ -115,7 +149,7 @@
|
||||||
@click-details="overview => onClickedDetails(props.row.email, overview)"
|
@click-details="overview => onClickedDetails(props.row.email, overview)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Template for custome failed-to-load state -->
|
<!-- Template for custome failed-to-load state -->
|
||||||
<template #no-data="{ message, filter }">
|
<template #no-data="{ message, filter }">
|
||||||
<div class="full-width column items-center text-accent q-gutter-sm">
|
<div class="full-width column items-center text-accent q-gutter-sm">
|
||||||
|
|
@ -123,7 +157,7 @@
|
||||||
size="4em"
|
size="4em"
|
||||||
:name="filter ? 'filter_alt_off' : 'error_outline'"
|
:name="filter ? 'filter_alt_off' : 'error_outline'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span class="text-h6">
|
<span class="text-h6">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { ref } from "vue";
|
|
||||||
import { useTimesheetStore } from "src/stores/timesheet-store";
|
import { useTimesheetStore } from "src/stores/timesheet-store";
|
||||||
import type { TimesheetApprovalCSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
|
import type { TimesheetApprovalCSVReportFilters } from "src/modules/timesheet-approval/models/timesheet-approval-csv-report.models";
|
||||||
|
|
||||||
|
|
@ -6,44 +5,41 @@ export const useTimesheetApprovalApi = () => {
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const DATE_REGEX = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
|
const DATE_REGEX = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
|
||||||
|
|
||||||
const getTimesheetOverviews = async (date?: string) => {
|
const getTimesheetOverviews = async () => {
|
||||||
timesheet_store.is_loading = true;
|
timesheet_store.is_loading = true;
|
||||||
const success = ref(false);
|
|
||||||
|
|
||||||
if (date !== undefined) {
|
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber();
|
||||||
success.value = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date);
|
if (success) await timesheet_store.getTimesheetOverviews();
|
||||||
} else {
|
|
||||||
success.value = await timesheet_store.getPayPeriodByDateOrYearAndNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success.value === true) {
|
timesheet_store.is_loading = false;
|
||||||
await timesheet_store.getTimesheetOverviews();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTimesheetOverviewsByDate = async (date: string) => {
|
const getTimesheetOverviewsByDate = async (date: string) => {
|
||||||
const valid_date = DATE_REGEX.test(date);
|
const valid_date = DATE_REGEX.test(date);
|
||||||
|
timesheet_store.is_loading = true;
|
||||||
|
|
||||||
if (valid_date) {
|
if (valid_date) {
|
||||||
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date);
|
const success = await timesheet_store.getPayPeriodByDateOrYearAndNumber(date);
|
||||||
if (success) await timesheet_store.getTimesheetOverviews();
|
if (success) await timesheet_store.getTimesheetOverviews();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timesheet_store.is_loading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTimesheetApprovalCSVReport = async ( report_filter_company: boolean[], report_filter_type: boolean[], year?: number, period_number?: number ) => {
|
const getTimesheetApprovalCSVReport = async (report_filter_company: boolean[], report_filter_type: boolean[], year?: number, period_number?: number) => {
|
||||||
if (timesheet_store.pay_period === undefined) return;
|
if (timesheet_store.pay_period === undefined) return;
|
||||||
|
|
||||||
const [ targo, solucom ] = report_filter_company;
|
const [targo, solucom] = report_filter_company;
|
||||||
const [ shifts, expenses, holiday, vacation ] = report_filter_type;
|
const [shifts, expenses, holiday, vacation] = report_filter_type;
|
||||||
const options = {
|
const options = {
|
||||||
types: { shifts, expenses, holiday, vacation },
|
types: { shifts, expenses, holiday, vacation },
|
||||||
companies: { targo, solucom },
|
companies: { targo, solucom },
|
||||||
} as TimesheetApprovalCSVReportFilters;
|
} as TimesheetApprovalCSVReportFilters;
|
||||||
|
|
||||||
await timesheet_store.getPayPeriodReportByYearAndPeriodNumber(
|
await timesheet_store.getPayPeriodReportByYearAndPeriodNumber(
|
||||||
year ?? timesheet_store.pay_period.pay_year,
|
year ?? timesheet_store.pay_period.pay_year,
|
||||||
period_number ?? timesheet_store.pay_period.pay_period_no,
|
period_number ?? timesheet_store.pay_period.pay_period_no,
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,76 +52,102 @@ export const default_pay_period_overview: TimesheetOverview = {
|
||||||
is_approved: false
|
is_approved: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const overview_column_names = {
|
||||||
|
EMPLOYEE_NAME: 'employee_name',
|
||||||
|
EMAIL: 'email',
|
||||||
|
REGULAR: 'REGULAR',
|
||||||
|
EVENING: 'EVENING',
|
||||||
|
EMERGENCY: 'EMERGENCY',
|
||||||
|
SICK: 'SICK',
|
||||||
|
HOLIDAY: 'HOLIDAY',
|
||||||
|
VACATION: 'VACATION',
|
||||||
|
OVERTIME: 'OVERTIME',
|
||||||
|
EXPENSES: 'expenses',
|
||||||
|
MILEAGE: 'mileage',
|
||||||
|
IS_APPROVED: 'is_approved',
|
||||||
|
}
|
||||||
|
|
||||||
export const pay_period_overview_columns: QTableColumn[] = [
|
export const pay_period_overview_columns: QTableColumn[] = [
|
||||||
{
|
{
|
||||||
name: 'employee_name',
|
name: overview_column_names.EMPLOYEE_NAME,
|
||||||
label: 'timesheet_approvals.table.full_name',
|
label: 'timesheet_approvals.table.full_name',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'employee_name',
|
field: 'employee_name',
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'email',
|
name: overview_column_names.EMAIL,
|
||||||
label: 'timesheet_approvals.table.email',
|
label: 'timesheet_approvals.table.email',
|
||||||
|
align: 'left',
|
||||||
field: 'email',
|
field: 'email',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'REGULAR',
|
name: overview_column_names.REGULAR,
|
||||||
label: 'shared.shift_type.regular',
|
label: 'shared.shift_type.regular',
|
||||||
|
align: 'left',
|
||||||
field: 'regular_hours',
|
field: 'regular_hours',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'EVENING',
|
name: overview_column_names.EVENING,
|
||||||
label: 'shared.shift_type.evening',
|
label: 'shared.shift_type.evening',
|
||||||
|
align: 'left',
|
||||||
field: row => row.other_hours.evening_hours,
|
field: row => row.other_hours.evening_hours,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'EMERGENCY',
|
name: overview_column_names.EMERGENCY,
|
||||||
label: 'shared.shift_type.emergency',
|
label: 'shared.shift_type.emergency',
|
||||||
|
align: 'left',
|
||||||
field: row => row.other_hours.emergency_hours,
|
field: row => row.other_hours.emergency_hours,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'SICK',
|
name: overview_column_names.SICK,
|
||||||
label: 'shared.shift_type.sick',
|
label: 'shared.shift_type.sick',
|
||||||
|
align: 'left',
|
||||||
field: row => row.other_hours.sick_hours,
|
field: row => row.other_hours.sick_hours,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'HOLIDAY',
|
name: overview_column_names.HOLIDAY,
|
||||||
label: 'shared.shift_type.holiday',
|
label: 'shared.shift_type.holiday',
|
||||||
|
align: 'left',
|
||||||
field: row => row.other_hours.holiday_hours,
|
field: row => row.other_hours.holiday_hours,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'VACATION',
|
name: overview_column_names.VACATION,
|
||||||
label: 'shared.shift_type.vacation',
|
label: 'shared.shift_type.vacation',
|
||||||
|
align: 'left',
|
||||||
field: row => row.other_hours.vacation_hours,
|
field: row => row.other_hours.vacation_hours,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'OVERTIME',
|
name: overview_column_names.OVERTIME,
|
||||||
label: 'shared.shift_type.overtime',
|
label: 'shared.shift_type.overtime',
|
||||||
|
align: 'left',
|
||||||
field: row => row.other_hours.overtime_hours,
|
field: row => row.other_hours.overtime_hours,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'expenses',
|
name: overview_column_names.EXPENSES,
|
||||||
label: 'timesheet_approvals.table.expenses',
|
label: 'timesheet_approvals.table.expenses',
|
||||||
|
align: 'left',
|
||||||
field: 'expenses',
|
field: 'expenses',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'mileage',
|
name: overview_column_names.MILEAGE,
|
||||||
label: 'timesheet_approvals.table.mileage',
|
label: 'timesheet_approvals.table.mileage',
|
||||||
|
align: 'left',
|
||||||
field: 'mileage',
|
field: 'mileage',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'is_approved',
|
name: overview_column_names.IS_APPROVED,
|
||||||
label: 'timesheet_approvals.table.is_approved',
|
label: 'timesheet_approvals.table.is_approved',
|
||||||
field: 'is_approved',
|
field: 'is_approved',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
const day = timesheet_store.timesheets[timesheet_index]!.days[day_index]!;
|
const day = timesheet_store.timesheets[timesheet_index]!.days[day_index]!;
|
||||||
const shifts_without_deleted_shift = day.shifts.filter(shift => shift.id !== 0);
|
const shifts_without_deleted_shift = day.shifts.filter(shift => shift.id !== 0);
|
||||||
day.shifts = shifts_without_deleted_shift;
|
day.shifts = shifts_without_deleted_shift;
|
||||||
console.log("day's shifts after cleanup: ", day.shifts);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ export const TIME_FORMAT_PATTERN = /^(\d{2}:\d{2})?$/;
|
||||||
export const DATE_FORMAT_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
export const DATE_FORMAT_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
||||||
|
|
||||||
export interface TimesheetResponse {
|
export interface TimesheetResponse {
|
||||||
employee_full_name: string;
|
employee_fullname: string;
|
||||||
timesheets: Timesheet[];
|
timesheets: Timesheet[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,6 +38,8 @@ export interface TotalHours {
|
||||||
|
|
||||||
export interface TotalExpenses {
|
export interface TotalExpenses {
|
||||||
expenses: number;
|
expenses: number;
|
||||||
|
per_diem: number;
|
||||||
|
on_call: number;
|
||||||
mileage: number;
|
mileage: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ export const timesheetService = {
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
getTimesheetsByPayPeriod: async (year: number, period_number: number): Promise<TimesheetResponse> => {
|
getTimesheetsByPayPeriodAndOptionalEmail: async (year: number, period_number: number, employee_email?: string): Promise<TimesheetResponse> => {
|
||||||
const response = await api.get(`timesheets/${year}/${period_number}`);
|
const response = await api.get<{success: boolean, data: TimesheetResponse, error? : string}>(`timesheets/${year}/${period_number}/${employee_email}`);
|
||||||
return response.data.data;
|
return response.data.data;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -31,12 +31,13 @@
|
||||||
<template>
|
<template>
|
||||||
<q-page
|
<q-page
|
||||||
padding
|
padding
|
||||||
class="q-pa-md bg-secondary "
|
class="column q-pa-md bg-secondary"
|
||||||
>
|
>
|
||||||
<PageHeaderTemplate
|
<PageHeaderTemplate
|
||||||
title="timesheet_approvals.page_title"
|
title="timesheet_approvals.page_title"
|
||||||
:start-date="timesheet_store.pay_period?.period_start ?? ''"
|
:start-date="timesheet_store.pay_period?.period_start ?? ''"
|
||||||
:end-date="timesheet_store.pay_period?.period_end ?? ''"
|
:end-date="timesheet_store.pay_period?.period_end ?? ''"
|
||||||
|
class="col-auto"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DetailsDialog
|
<DetailsDialog
|
||||||
|
|
@ -48,8 +49,8 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="full-width q-mb-sm"
|
class="col-auto full-width q-px-lg"
|
||||||
:class="$q.screen.lt.md ? 'text-center' : 'row'"
|
:class="($q.screen.lt.md ? 'text-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"
|
||||||
|
|
@ -85,6 +86,6 @@
|
||||||
<QTableFilters v-model:search="timesheet_store.search_filter" />
|
<QTableFilters v-model:search="timesheet_store.search_filter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OverviewList @clickedDetailsButton="onDetailsClicked" />
|
<OverviewList class="col" @clickedDetailsButton="onDetailsClicked" />
|
||||||
</q-page>
|
</q-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -15,6 +15,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
const pay_period_overviews = ref<TimesheetOverview[]>([]);
|
const pay_period_overviews = ref<TimesheetOverview[]>([]);
|
||||||
const current_pay_period_overview = 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 is_approval_grid_mode = ref<boolean>(true);
|
||||||
const search_filter = ref<string | number | null>('');
|
const search_filter = ref<string | number | null>('');
|
||||||
|
|
@ -22,7 +23,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
|
|
||||||
const getPayPeriodByDateOrYearAndNumber = async (date?: string): Promise<boolean> => {
|
const getPayPeriodByDateOrYearAndNumber = async (date?: string): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
if (date!== undefined) {
|
if (date !== undefined) {
|
||||||
pay_period.value = await timesheetService.getPayPeriodByDate(date);
|
pay_period.value = await timesheetService.getPayPeriodByDate(date);
|
||||||
} else if (pay_period.value !== undefined) {
|
} else if (pay_period.value !== undefined) {
|
||||||
pay_period.value = await timesheetService.getPayPeriodByYearAndPeriodNumber(pay_period.value.pay_year, pay_period.value.pay_period_no);
|
pay_period.value = await timesheetService.getPayPeriodByYearAndPeriodNumber(pay_period.value.pay_year, pay_period.value.pay_period_no);
|
||||||
|
|
@ -47,7 +48,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
is_loading.value = false;
|
is_loading.value = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await timesheetApprovalService.getPayPeriodOverviews(pay_period.value.pay_year, pay_period.value.pay_period_no);
|
const response = await timesheetApprovalService.getPayPeriodOverviews(pay_period.value.pay_year, pay_period.value.pay_period_no);
|
||||||
pay_period_overviews.value = response.employees_overview;
|
pay_period_overviews.value = response.employees_overview;
|
||||||
is_loading.value = false;
|
is_loading.value = false;
|
||||||
|
|
@ -65,13 +66,17 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
|
|
||||||
const getTimesheetsByEmployeeEmail = async (employee_email?: string) => {
|
const getTimesheetsByEmployeeEmail = async (employee_email?: string) => {
|
||||||
is_loading.value = true;
|
is_loading.value = true;
|
||||||
|
let response;
|
||||||
|
|
||||||
if (pay_period.value === undefined) return;
|
if (pay_period.value === undefined) return;
|
||||||
try {
|
try {
|
||||||
if (employee_email) {
|
if (employee_email) {
|
||||||
console.log('email: ', employee_email);
|
response = await timesheetService.getTimesheetsByPayPeriodAndOptionalEmail(pay_period.value.pay_year, pay_period.value.pay_period_no, employee_email);
|
||||||
|
} else {
|
||||||
|
response = await timesheetService.getTimesheetsByPayPeriodAndOptionalEmail(pay_period.value.pay_year, pay_period.value.pay_period_no);
|
||||||
}
|
}
|
||||||
const response = await timesheetService.getTimesheetsByPayPeriod(pay_period.value.pay_year, pay_period.value.pay_period_no);
|
|
||||||
|
selected_employee_name.value = response.employee_fullname;
|
||||||
timesheets.value = response.timesheets;
|
timesheets.value = response.timesheets;
|
||||||
initial_timesheets.value = unwrapAndClone(timesheets.value);
|
initial_timesheets.value = unwrapAndClone(timesheets.value);
|
||||||
is_loading.value = false;
|
is_loading.value = false;
|
||||||
|
|
@ -107,6 +112,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
||||||
pay_period,
|
pay_period,
|
||||||
pay_period_overviews,
|
pay_period_overviews,
|
||||||
current_pay_period_overview,
|
current_pay_period_overview,
|
||||||
|
selected_employee_name,
|
||||||
timesheets,
|
timesheets,
|
||||||
initial_timesheets,
|
initial_timesheets,
|
||||||
getPayPeriodByDateOrYearAndNumber,
|
getPayPeriodByDateOrYearAndNumber,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user