targo-frontend/src/modules/timesheet-approval/components/details-dialog.vue
Nic D db6ec4bc90 feat(approvals): add more functionalities to details window, see notes
Add ability to approve whole time from details dialog directly, in a sticky bar at top with employee name

Add possibility of right-clicking on individual shifts to approve or unapprove
2026-02-03 15:31:06 -05:00

116 lines
4.6 KiB
Vue

<script
setup
lang="ts"
>
import { useI18n } from 'vue-i18n';
import { computed, ref } from 'vue';
import { useTimesheetStore } from 'src/stores/timesheet-store';
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 DetailsDialogChartExpenses from 'src/modules/timesheet-approval/components/details-dialog-chart-expenses.vue';
import TimesheetWrapper from 'src/modules/timesheets/components/timesheet-wrapper.vue';
import ExpenseDialogList from 'src/modules/timesheets/components/expense-dialog-list.vue';
import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api';
const { t } = useI18n();
const timesheet_store = useTimesheetStore();
const timesheetApprovalApi = useTimesheetApprovalApi();
const is_dialog_open = ref(false);
const isApproved = computed(() => timesheet_store.timesheets.every(timesheet => timesheet.is_approved));
const approveButtonLabel = computed(() => isApproved.value ?
t('timesheet_approvals.table.verified') :
t('timesheet_approvals.table.unverified')
);
const approveButtonIcon = computed(() => isApproved.value ? 'lock' : 'lock_open');
const onClickApproveAll = async () => {
const employeeEmail = timesheet_store.current_pay_period_overview?.email;
const isApproved = timesheet_store.timesheets.every(timesheet => timesheet.is_approved);
if (employeeEmail !== undefined && isApproved !== undefined) {
await timesheetApprovalApi.toggleTimesheetsApprovalByEmployeeEmail(
employeeEmail,
!isApproved
);
}
}
</script>
<template>
<q-dialog
v-model="timesheet_store.is_details_dialog_open"
full-width
full-height
transition-show="jump-down"
transition-hide="jump-down"
backdrop-filter="blur(6px)"
@show="is_dialog_open = true"
@hide="is_dialog_open = false"
@before-hide="timesheet_store.getTimesheetOverviews"
>
<div
class="column bg-secondary hide-scrollbar shadow-12 rounded-15 q-pb-sm no-wrap"
:style="($q.screen.lt.md ? '' : 'width:80vw !important;') + ($q.dark.isActive ? ' border: 2px solid var(--q-accent)' : '')"
>
<!-- employee name -->
<div class="col-auto row flex-center q-px-none q-py-sm sticky-top bg-secondary full-width shadow-4">
<span class="col text-h4 text-weight-bolder text-uppercase q-px-lg">
{{ timesheet_store.selected_employee_name }}
</span>
<div class="col-auto q-px-lg">
<q-btn
push
dense
size="lg"
color="accent"
:label="approveButtonLabel"
class="q-px-xl"
@click="onClickApproveAll"
>
<transition enter-active-class="animated swing" mode="out-in">
<q-icon
:key="isApproved ? '1' : '2'"
:name="approveButtonIcon"
class="q-pl-md"
/>
</transition>
</q-btn>
</div>
</div>
<!-- employee pay period details using chart -->
<div
v-if="is_dialog_open && !$q.platform.is.mobile"
class="col-auto q-px-md no-wrap"
:class="$q.platform.is.mobile ? 'column' : 'row'"
>
<DetailsDialogChartHoursWorked class="col" />
<DetailsDialogChartShiftTypes class="col" />
<DetailsDialogChartExpenses class="col" />
</div>
<div class="col-auto">
<ExpenseDialogList mode="approval" />
</div>
<!-- list of shifts -->
<div class="col-auto column no-wrap">
<TimesheetWrapper
mode="approval"
:employee-email="timesheet_store.current_pay_period_overview?.email"
class="col-auto"
/>
</div>
</div>
</q-dialog>
</template>
<style scoped>
.sticky-top {
position: sticky;
z-index: 5;
top: 0;
}
</style>