188 lines
7.9 KiB
Vue
188 lines
7.9 KiB
Vue
<script setup lang="ts">
|
|
import { date } from 'quasar';
|
|
import { computed, onMounted } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useAuthStore } from 'src/stores/auth-store';
|
|
import { useExpensesStore } from 'src/stores/expense-store';
|
|
import { useShiftStore } from 'src/stores/shift-store';
|
|
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
|
import { useTimesheetApi } from '../composables/api/use-timesheet-api';
|
|
import { buildShiftOptions } from '../utils/shift.util';
|
|
import { formatPayPeriodLabel } from '../utils/timesheet-format.util';
|
|
import TimesheetNavigation from '../components/timesheet/timesheet-navigation.vue';
|
|
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 type { TimesheetExpense } from '../types/expense.interfaces';
|
|
import DetailedShiftList from '../components/shift/detailed-shift-list.vue';
|
|
/* eslint-disable */
|
|
|
|
//------------------- stores -------------------
|
|
const { locale, t } = useI18n();
|
|
const auth_store = useAuthStore();
|
|
const expenses_store = useExpensesStore();
|
|
const shift_store = useShiftStore();
|
|
const timesheet_store = useTimesheetStore();
|
|
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,
|
|
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();
|
|
|
|
//------------------- pay-period format label -------------------
|
|
const date_options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'long', year: 'numeric' };
|
|
|
|
const pay_period_label = computed(() => formatPayPeriodLabel(
|
|
timesheet_store.current_pay_period?.label,
|
|
locale.value,
|
|
date.extractDate,
|
|
date_options
|
|
)
|
|
);
|
|
|
|
//------------------- 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);
|
|
});
|
|
|
|
// ------------------- shifts -------------------
|
|
const onRequestAdd = ({ date }: { date: string }) => shift_store.openCreate(date);
|
|
const onRequestEdit = ({ date, shift }: { date: string; shift: any }) => shift_store.openEdit(date, shift);
|
|
const onRequestDelete = async ({ date, shift }: { date: string; shift: any }) => shift_store.openDelete(date, shift);
|
|
const onShiftSaved = async () => {
|
|
await timesheet_store.refreshCurrentPeriodForUser(auth_store.user.email);
|
|
};
|
|
</script>
|
|
|
|
|
|
<template>
|
|
<q-page padding class="q-pa-md bg-secondary" >
|
|
<!-- title and dates -->
|
|
<div class="text-h4 row justify-center text-center q-mt-lg text-uppercase text-weight-bolder text-grey-8">
|
|
{{ $t('timesheet.title') }}
|
|
</div>
|
|
<div class="row items-center justify-center q-py-none q-my-none">
|
|
<div
|
|
class="text-primary text-uppercase text-weight-bold"
|
|
:class="$q.screen.lt.md ? '' : 'text-h6'"
|
|
>
|
|
{{ pay_period_label.start_date }}
|
|
</div>
|
|
<div
|
|
class="text-grey-8 text-uppercase q-mx-md"
|
|
:class="$q.screen.lt.md ? 'text-weight-medium text-caption' : 'text-weight-bold'"
|
|
>
|
|
{{ $t('timesheet.date_ranges_to') }}
|
|
</div>
|
|
<div
|
|
class="text-primary text-uppercase text-center text-weight-bold"
|
|
:class="$q.screen.lt.md ? '' : 'text-h6'"
|
|
>
|
|
{{ pay_period_label.end_date }}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<q-card flat class=" col q-mt-md bg-secondary">
|
|
<!-- navigation btn -->
|
|
<q-card-section horizontal>
|
|
<q-btn
|
|
color="primary"
|
|
unelevated
|
|
icon="receipt_long"
|
|
:label="$t('timesheet.expense.open_btn')"
|
|
@click="openExpensesDialog"
|
|
/>
|
|
</q-card-section>
|
|
<q-card-section class="row items-center justify-between q-px-md q-pb-none">
|
|
<TimesheetNavigation
|
|
:is-disabled="timesheet_store.is_loading"
|
|
:is-previous-limit="timesheet_store.is_calendar_limit"
|
|
@date-selected="onDateSelected"
|
|
@pressed-previous-button="timesheet_api.getPreviousPeriodForUser(auth_store.user.email)"
|
|
@pressed-next-button="timesheet_api.getNextPeriodForUser(auth_store.user.email)"
|
|
/>
|
|
</q-card-section>
|
|
<!-- shift's colored legend -->
|
|
<ShiftsLegend
|
|
:is-loading="false"
|
|
/>
|
|
<q-card-section horizontal>
|
|
<!-- display of shifts for 2 timesheets -->
|
|
<DetailedShiftList
|
|
:raw-data="timesheet_store.pay_period_employee_details"
|
|
:current-pay-period="timesheet_store.current_pay_period"
|
|
@request-add="onRequestAdd"
|
|
@request-edit="onRequestEdit"
|
|
@request-delete="onRequestDelete"
|
|
/>
|
|
<q-inner-loading :showing="timesheet_store.is_loading" color="primary"/>
|
|
</q-card-section>
|
|
</q-card>
|
|
</div>
|
|
<!-- read/edit/create/delete expense dialog -->
|
|
<q-dialog
|
|
v-model="expenses_store.is_dialog_open"
|
|
persistent
|
|
>
|
|
<q-card
|
|
class="q-pa-md column"
|
|
style=" min-width: 70vw;"
|
|
>
|
|
<q-inner-loading :showing="expenses_store.is_loading">
|
|
<q-spinner size="32px"/>
|
|
</q-inner-loading>
|
|
|
|
<!-- <q-banner
|
|
v-if="expenses_error"
|
|
dense
|
|
class="bg-red-2 col-auto text-negative q-mt-sm"
|
|
>
|
|
{{ expenses_error }}
|
|
</q-banner> -->
|
|
|
|
<TimesheetDetailsExpenses
|
|
v-if="expenses_store.data"
|
|
:pay_period_no="expenses_store.data.pay_period_no"
|
|
:pay_year="expenses_store.data.pay_year"
|
|
:email="expenses_store.data.employee_email"
|
|
:is_approved="expenses_store.data.is_approved"
|
|
:initial_expenses="expenses_store.data.expenses"
|
|
@save="onSaveExpenses"
|
|
@close="onCloseExpenses"
|
|
@error=" "
|
|
/>
|
|
</q-card>
|
|
</q-dialog>
|
|
|
|
<!-- shift crud dialog -->
|
|
<ShiftCrudDialog
|
|
v-model="shift_store.is_open"
|
|
:mode="shift_store.mode"
|
|
:date-iso="shift_store.date_iso"
|
|
:email="auth_store.user.email"
|
|
:initial-shift="shift_store.initial_shift"
|
|
:shift-options="shift_options"
|
|
@close="shift_store.close"
|
|
@saved="onShiftSaved"
|
|
/>
|
|
</q-page>
|
|
</template> |