199 lines
6.2 KiB
Vue
199 lines
6.2 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import type { QForm } from 'quasar';
|
|
import type { TimesheetExpense } from '../../types/expense.interfaces';
|
|
import type { ExpenseType } from '../../types/expense.types';
|
|
/* eslint-disable */
|
|
|
|
//---------------- v-models ------------------
|
|
const draft = defineModel<Partial<TimesheetExpense>>('draft');
|
|
const files = defineModel<File[] | null>('files');
|
|
const datePickerOpen = defineModel<boolean | null>('datePickerOpen', {default: false });
|
|
|
|
//------------------ Props ------------------
|
|
const {setType} = defineProps<{
|
|
type_options: { label: string; value: ExpenseType }[];
|
|
show_amount: boolean;
|
|
is_readonly: boolean;
|
|
rules: {
|
|
typeRequired: (val: unknown) => true | string;
|
|
amountRequired: (val: unknown) => true | string;
|
|
mileageRequired: (val: unknown) => true | string;
|
|
commentRequired: (val: unknown) => true | string;
|
|
commentTooLong: (val: unknown) => true | string;
|
|
};
|
|
comment_max_length: number;
|
|
setType: (val: ExpenseType) => void;
|
|
}>();
|
|
|
|
//------------------ Emits ------------------
|
|
defineEmits<{
|
|
'submit': [void];
|
|
}>();
|
|
|
|
//------------------ Exposes ------------------
|
|
const inner_form = ref<QForm | null>(null);
|
|
defineExpose({
|
|
validate: async ( force = true ) => (await inner_form.value?.validate(force)) === true,
|
|
});
|
|
|
|
//------------------ Handlers ------------------
|
|
const onTypeChange = (val: ExpenseType) => {
|
|
setType(val);
|
|
};
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<q-form
|
|
ref="inner_form"
|
|
flat
|
|
v-if="!is_readonly"
|
|
@submit.prevent="$emit('submit')"
|
|
>
|
|
<div class="text-subtitle2 q-py-sm">
|
|
{{ $t('timesheet.expense.add_expense')}}
|
|
</div>
|
|
<div class="row justify-between">
|
|
|
|
<!-- date selection input -->
|
|
<q-input
|
|
v-model="draft!.date"
|
|
dense
|
|
filled
|
|
readonly
|
|
stack-label
|
|
class="col q-px-xs"
|
|
color="primary"
|
|
:label="$t('timesheet.expense.date')"
|
|
>
|
|
<template #before>
|
|
<q-btn
|
|
push
|
|
dense
|
|
icon="event"
|
|
color="primary"
|
|
@click="datePickerOpen = true"
|
|
/>
|
|
<q-dialog v-model="datePickerOpen">
|
|
<q-date
|
|
v-model="draft!.date"
|
|
@update:model-value="datePickerOpen = false"
|
|
mask="YYYY-MM-DD"
|
|
/>
|
|
</q-dialog>
|
|
</template>
|
|
</q-input>
|
|
|
|
<!-- expenses type selection -->
|
|
<q-select
|
|
v-model="draft!.type"
|
|
:options="type_options"
|
|
filled
|
|
dense
|
|
class="col q-px-xs"
|
|
color="primary"
|
|
emit-value
|
|
map-options
|
|
:label="$t('timesheet.expense.type')"
|
|
:rules="[ rules.typeRequired ]"
|
|
@update:model-value="val => setType(val as ExpenseType)"
|
|
/>
|
|
|
|
<!-- amount input -->
|
|
<template v-if="show_amount">
|
|
<q-input
|
|
key="amount"
|
|
v-model.number="draft!.amount"
|
|
filled
|
|
input-class="text-right"
|
|
dense
|
|
stack-label
|
|
clearable
|
|
color="primary"
|
|
class="col q-px-xs"
|
|
:label="$t('timesheet.expense.amount')"
|
|
suffix="$"
|
|
lazy-rules="ondemand"
|
|
:rules="[ rules.amountRequired ]"
|
|
/>
|
|
</template>
|
|
|
|
<!-- mileage input -->
|
|
<template v-else>
|
|
<q-input
|
|
key="mileage"
|
|
v-model.number="draft!.mileage"
|
|
filled
|
|
input-class="text-right"
|
|
dense
|
|
stack-label
|
|
clearable
|
|
color="primary"
|
|
class="col q-px-xs"
|
|
:label="$t('timesheet.expense.mileage')"
|
|
suffix="km"
|
|
lazy-rules="ondemand"
|
|
:rules="[ rules.mileageRequired ]"
|
|
/>
|
|
</template>
|
|
|
|
<!-- employee comment input -->
|
|
<q-input
|
|
v-model="draft!.comment"
|
|
filled
|
|
color="primary"
|
|
type="text"
|
|
class="col q-px-sm"
|
|
dense
|
|
stack-label
|
|
clearable
|
|
:counter="true"
|
|
:maxlength="comment_max_length"
|
|
lazy-rules="ondemand"
|
|
:rules="[ rules.commentRequired, rules.commentTooLong ]"
|
|
>
|
|
<template #label>
|
|
<span class="text-weight-bold ">
|
|
{{ $t('timesheet.expense.comment') }}
|
|
</span>
|
|
</template>
|
|
</q-input>
|
|
|
|
<!-- import attach file section -->
|
|
<q-file
|
|
v-model="files"
|
|
:label="$t('timesheet.expense.hints.attach_file')"
|
|
filled
|
|
use-chips
|
|
multiple
|
|
stack-label
|
|
class="col"
|
|
style="max-width: 300px;"
|
|
dense
|
|
>
|
|
<template #prepend>
|
|
<q-icon
|
|
name="attach_file"
|
|
size="sm"
|
|
color="primary"
|
|
|
|
/>
|
|
</template>
|
|
</q-file>
|
|
|
|
<!-- add btn section -->
|
|
<div>
|
|
<q-btn
|
|
push
|
|
dense
|
|
color="primary"
|
|
icon="add"
|
|
size="sm"
|
|
class="q-mt-sm q-ml-sm"
|
|
type="submit"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</q-form>
|
|
</template> |