183 lines
7.2 KiB
Vue
183 lines
7.2 KiB
Vue
<script
|
|
setup
|
|
lang="ts"
|
|
>
|
|
/* eslint-disable */
|
|
import { date, useQuasar } from 'quasar';
|
|
import { computed, ref } from 'vue';
|
|
import { unwrapAndClone } from 'src/utils/unwrap-and-clone';
|
|
import { useExpensesApi } from 'src/modules/timesheets/composables/use-expense-api';
|
|
import { useExpensesStore } from 'src/stores/expense-store';
|
|
import { getExpenseIcon } from 'src/modules/timesheets/utils/expense.util';
|
|
import type { Expense } from 'src/modules/timesheets/models/expense.models';
|
|
import ExpenseDialogFormMobile from 'src/modules/timesheets/components/mobile/expense-dialog-form-mobile.vue';
|
|
|
|
// =========== state =====================================
|
|
|
|
const expense = defineModel<Expense>({ required: true })
|
|
|
|
const q = useQuasar();
|
|
const expenses_store = useExpensesStore();
|
|
const expenses_api = useExpensesApi();
|
|
|
|
const is_showing_update_form = ref(false);
|
|
const is_showing_delete_confirm = ref(false);
|
|
|
|
// =========== computed ==================================
|
|
|
|
const approved_class = computed(() => expense.value.is_approved ? ' bg-accent text-white' : '')
|
|
const primaryColor = computed(() => q.dark.isActive ? 'blue-grey-3' : 'primary')
|
|
|
|
// =========== methods ===================================
|
|
|
|
const requestExpenseDeletion = async () => {
|
|
showDeleteConfirmation(false);
|
|
await expenses_api.deleteExpenseById(expense.value.id);
|
|
}
|
|
|
|
const onUpdateClicked = () => {
|
|
if (expense.value.is_approved) return;
|
|
|
|
expenses_store.mode = 'update';
|
|
expenses_store.current_expense = expense.value;
|
|
expenses_store.initial_expense = unwrapAndClone(expense.value);
|
|
}
|
|
|
|
const showDeleteConfirmation = (state: boolean) => {
|
|
is_showing_delete_confirm.value = state;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="column bg-dark shadow-5 rounded-5 q-my-sm full-width">
|
|
<!-- expense deletion confirmation -->
|
|
<q-dialog
|
|
v-model="is_showing_delete_confirm"
|
|
backdrop-filter="blur(4px)"
|
|
class="z-max"
|
|
>
|
|
<div class="column rounded-5 bg-dark">
|
|
<span class="col text-uppercase text-weight-light text-h6 q-py-sm q-px-md">
|
|
{{ $t('timesheet.expense.actions.delete_confirm') }}
|
|
</span>
|
|
|
|
<div class="row col">
|
|
<q-btn
|
|
flat
|
|
dense
|
|
square
|
|
size="lg"
|
|
color="negative"
|
|
:label="$t('shared.misc.no')"
|
|
class="col"
|
|
@click="showDeleteConfirmation(false)"
|
|
/>
|
|
|
|
<q-btn
|
|
flat
|
|
dense
|
|
square
|
|
size="lg"
|
|
color="accent"
|
|
:label="$t('shared.misc.yes')"
|
|
class="col"
|
|
@click="requestExpenseDeletion"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</q-dialog>
|
|
|
|
<q-expansion-item
|
|
v-model="is_showing_update_form"
|
|
hide-expand-icon
|
|
dense
|
|
group="expenses"
|
|
header-class="q-px-none"
|
|
class="rounded-5"
|
|
:class="expense.is_approved ? ' bg-accent text-white' : ''"
|
|
@before-show="onUpdateClicked()"
|
|
>
|
|
<template #header>
|
|
<div class="row full-width">
|
|
<div class="column col q-px-sm q-py-xs">
|
|
<!-- date label and delete button -->
|
|
<div class="col-auto row items-center q-pl-xs">
|
|
<q-icon
|
|
name="calendar_month"
|
|
size="sm"
|
|
class="col-auto"
|
|
/>
|
|
|
|
<span
|
|
class="col text-uppercase text-weight-light full-width q-pl-sm text-h6"
|
|
:class="approved_class"
|
|
>
|
|
{{ $d(
|
|
date.extractDate(expense.date, 'YYYY-MM-DD'),
|
|
{ month: 'long', day: 'numeric' }
|
|
) }}
|
|
</span>
|
|
|
|
<q-btn
|
|
flat
|
|
dense
|
|
icon="las la-trash"
|
|
:color="primaryColor"
|
|
size="lg"
|
|
class="col-auto bg-dark q-px-xs"
|
|
style="border-radius: 0 2px 2px 0;"
|
|
@click.stop="showDeleteConfirmation(true)"
|
|
/>
|
|
</div>
|
|
|
|
<div class="col row full-width items-center q-px-xs">
|
|
<!-- avatar type icon section -->
|
|
<q-icon
|
|
:name="getExpenseIcon(expense.type)"
|
|
size="lg"
|
|
class="col-auto q-pr-sm"
|
|
/>
|
|
|
|
<!-- amount or mileage section -->
|
|
<div class="col text-weight-bold text-h6">
|
|
<q-item-label v-if="expense.type === 'MILEAGE'">
|
|
{{ expense.mileage?.toFixed(1) }} km
|
|
</q-item-label>
|
|
<q-item-label v-else>
|
|
$ {{ expense.amount.toFixed(2) }}
|
|
</q-item-label>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- attachment file -->
|
|
<div class="col-auto q-pa-xs full-width">
|
|
<q-btn
|
|
:color="expense.is_approved ? 'white' : 'accent'"
|
|
:text-color="expense.is_approved ? 'accent' : 'white'"
|
|
icon="las la-paperclip"
|
|
:label="expense.attachment_name ?? `( ${$t('shared.label.empty')} )`"
|
|
class="full-width text-lowercase q-mx-sm q-px-sm q-pb-sm inset-shadow"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<q-icon
|
|
v-if="expense.is_approved"
|
|
name="verified"
|
|
color="white"
|
|
size="lg"
|
|
class="full-height q-px-none"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="q-px-sm">
|
|
<ExpenseDialogFormMobile
|
|
v-model="expense"
|
|
@on-update-clicked="is_showing_update_form = false"
|
|
/>
|
|
</div>
|
|
</q-expansion-item>
|
|
</div>
|
|
</template> |