targo-frontend/src/modules/timesheet-approval/components/timesheet-approval-employee-overview-list.vue

152 lines
5.8 KiB
Vue

<script setup lang="ts">
/* eslint-disable */
import { computed, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api';
import TimesheetApprovalPeriodPicker from '../components/timesheet-approval-period-picker.vue';
import TimesheetApprovalEmployeeOverviewListItem from './timesheet-approval-employee-overview-list-item.vue';
import { date, type QTableColumn } from 'quasar';
import type { PayPeriodEmployeeOverview } from '../types/timesheet-approval-pay-period-employee-overview-interface';
const { t } = useI18n();
const timesheet_store = useTimesheetStore();
const timesheet_approval_api = useTimesheetApprovalApi();
const FORWARD = 1
const BACKWARD = -1
const filter = ref<string | number | null>('');
const original_approvals = ref<Record<string, boolean>>({});
const columns = computed((): QTableColumn<PayPeriodEmployeeOverview>[] => [
{
name: 'employee_name',
label: t('timeSheetValidations.tableColumnLabelFullname'),
field: 'employee_name',
sortable: true
},
{
name: 'regular_hours',
label: t('timeSheetValidations.tableColumnLabelRegularHours'),
field: 'regular_hours',
sortable: true
},
{
name: 'evening_hours',
label: t('timeSheetValidations.tableColumnLabelEveningHours'),
field: 'evening_hours'
},
{
name: 'emergency_hours',
label: t('timeSheetValidations.tableColumnLabelEmergencyHours'),
field: 'emergency_hours'
},
{
name: 'overtime_hours',
label: t('timeSheetValidations.tableColumnLabelOvertime'),
field: 'overtime_hours'
},
{
name: 'expenses',
label: t('timeSheetValidations.tableColumnLabelExpenses'),
field: 'expenses',
sortable: true
},
{
name: 'mileage',
label: t('timeSheetValidations.tableColumnLabelMileage'),
field: 'mileage',
sortable: true
}
]);
const has_changes = computed(() => {
return timesheet_store.pay_period_employee_overviews.some(emp => {
return emp.is_approved !== original_approvals.value[emp.email];
});
});
const is_calendar_limit = computed( () => {
return timesheet_store.current_pay_period.pay_year === 2024 &&
timesheet_store.current_pay_period.pay_period_no <= 1;
});
const onDateSelected = async (date_string: string) => {
await timesheet_approval_api.getPayPeriodOverviewByDate(date_string);
}
onMounted( async () => {
const today = date.formatDate(new Date(), 'YYYY-MM-DD');
await timesheet_approval_api.getPayPeriodOverviewByDate(today);
const approvals = timesheet_store.pay_period_employee_overviews.map(emp => [emp.email, emp.is_approved]);
original_approvals.value = Object.fromEntries(approvals);
})
</script>
<template>
<div class="q-pa-md">
<q-table
:rows="timesheet_store.pay_period_employee_overviews"
:columns="columns"
row-key="email"
:filter="filter"
grid
dense
hide-pagination
color="primary"
:rows-per-page-options="[0]"
card-container-class="justify-center"
:loading="timesheet_store.is_loading"
:no-data-label="$t('shared.failedToLoad')"
:no-results-label="$t('shared.failedToSearch')"
:loading-label="$t('shared.loading')"
>
<!-- Top Bar that contains Search, Title, Filters -->
<template v-slot:top>
<div :class="$q.screen.lt.md ? 'column justify-center items-center' : 'full-width row'">
<!-- Date Picker -->
<TimesheetApprovalPeriodPicker
:is-disabled="timesheet_store.is_loading"
:is-previous-limit="is_calendar_limit"
@date-selected="onDateSelected"
@pressed-previous-button="timesheet_approval_api.getNextPayPeriodOverview(BACKWARD)"
@pressed-next-button="timesheet_approval_api.getNextPayPeriodOverview(FORWARD)"
/>
<q-space />
</div>
</template>
<!-- Template for individual employee cards -->
<template v-slot:item="props: {
cols: (QTableColumn<PayPeriodEmployeeOverview> & { value: unknown })[],
row: PayPeriodEmployeeOverview
}">
<TimesheetApprovalEmployeeOverviewListItem
:cols="props.cols"
:row="props.row"
v-model="props.row.is_approved"/>
</template>
<!-- Template for custome failed-to-load state -->
<template v-slot:no-data="{ message, filter }">
<div class="full-width column items-center text-primary q-gutter-sm">
<span class="text-h6 q-mt-xl">
{{ message }}
</span>
<q-icon
size="4em"
:name="filter ? 'filter_alt_off' : 'error_outline'"
/>
</div>
</template>
</q-table>
</div>
</template>