refactor(timesheet): complete overhaul of expense UI, fix functionality in approval module.

This commit is contained in:
Nic D. 2026-03-11 12:24:06 -04:00
parent 4ab271e66f
commit 9213a42d6b
5 changed files with 224 additions and 173 deletions

View File

@ -11,7 +11,12 @@
maxLength?: number; maxLength?: number;
noTopPadding?: boolean; noTopPadding?: boolean;
backgroundColor?: 'bg-secondary' | 'bg-dark'; backgroundColor?: 'bg-secondary' | 'bg-dark';
appendContent?: string | number;
}>(); }>();
defineOptions({
inheritAttrs: false
})
</script> </script>
<template> <template>
@ -21,6 +26,7 @@
> >
<q-input <q-input
v-model="model" v-model="model"
v-bind="$attrs"
dense dense
borderless borderless
color="accent" color="accent"
@ -43,7 +49,11 @@
</span> </span>
</template> </template>
<template #append v-if="requiresDatePicker"> <template
#append
v-if="requiresDatePicker || !!appendContent"
>
<div v-if="requiresDatePicker">
<q-btn <q-btn
flat flat
dense dense
@ -64,6 +74,15 @@
/> />
</q-dialog> </q-dialog>
</q-btn> </q-btn>
</div>
<div
v-if="!!appendContent"
class="self-end text-uppercase text-bold text-accent"
style="font-size: 0.8em;"
>
{{ appendContent }}
</div>
</template> </template>
</q-input> </q-input>
</div> </div>

View File

@ -197,6 +197,7 @@
<ExpenseDialogForm <ExpenseDialogForm
:email="timesheetStore.current_pay_period_overview?.email" :email="timesheetStore.current_pay_period_overview?.email"
:key="refreshKey" :key="refreshKey"
mode="approval"
@click-save="onClickSaveNewExpense" @click-save="onClickSaveNewExpense"
/> />
</q-expansion-item> </q-expansion-item>

View File

@ -117,6 +117,7 @@
<template> <template>
<div class="full-width"> <div class="full-width">
<LoadingOverlay v-model="timesheetStore.is_loading" /> <LoadingOverlay v-model="timesheetStore.is_loading" />
<q-table <q-table
dense dense
row-key="email" row-key="email"

View File

@ -21,6 +21,7 @@
const file = defineModel<File>('file'); const file = defineModel<File>('file');
const { email } = defineProps<{ const { email } = defineProps<{
email?: string | undefined; email?: string | undefined;
mode?: 'normal' | 'approval';
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
'clickSave': [void]; 'clickSave': [void];
@ -91,12 +92,10 @@
flat flat
@submit.prevent="requestExpenseCreationOrUpdate" @submit.prevent="requestExpenseCreationOrUpdate"
> >
<div <div class="column rounded-5 q-pb-sm">
class="row justify-between rounded-5 q-pb-sm" <div class="row">
:class="expenseStore.mode === 'create' ? 'q-px-lg' : ''"
>
<!-- date selection input --> <!-- date selection input -->
<div class="row col items-center"> <div class="row col items-center q-pl-sm">
<q-btn <q-btn
push push
dense dense
@ -187,26 +186,34 @@
</div> </div>
<!-- amount input --> <!-- amount input -->
<div class="col q-px-xs"> <div class="col">
<TargoInput <TargoInput
v-if="TYPES_WITH_AMOUNT_ONLY.includes(expenseStore.current_expense?.type ?? 'EXPENSES')" v-if="TYPES_WITH_AMOUNT_ONLY.includes(expenseStore.current_expense?.type ?? 'EXPENSES')"
v-model.number="expenseStore.current_expense.amount" v-model.number="expenseStore.current_expense.amount"
no-top-padding no-top-padding
background-color="bg-dark" background-color="bg-dark"
type="number"
input-class="text-right"
append-content=" $"
:label="$t('timesheet.expense.amount')" :label="$t('timesheet.expense.amount')"
/> />
<TargoInput <TargoInput
v-else v-else
v-model="expenseStore.current_expense.mileage" v-model.number="expenseStore.current_expense.mileage"
no-top-padding no-top-padding
background-color="bg-dark" background-color="bg-dark"
type="number"
input-class="text-right"
append-content=" km"
:label="$t('timesheet.expense.mileage')" :label="$t('timesheet.expense.mileage')"
/> />
</div> </div>
</div>
<div class="row q-pt-md">
<!-- employee comment input --> <!-- employee comment input -->
<div class="col q-px-xs"> <div class="col">
<TargoInput <TargoInput
v-model="expenseStore.current_expense.comment" v-model="expenseStore.current_expense.comment"
no-top-padding no-top-padding
@ -216,18 +223,36 @@
/> />
</div> </div>
<div
v-if="mode === 'approval'"
class="col"
>
<TargoInput
v-model="expenseStore.current_expense.supervisor_comment"
no-top-padding
background-color="bg-dark"
:max-length="COMMENT_MAX_LENGTH"
:label="$t('timesheet.expense.supervisor_comment')"
/>
</div>
<!-- import attach file section --> <!-- import attach file section -->
<div class="col q-px-xs"> <div class="col-3 q-px-sm">
<q-file <q-file
v-model="file" v-model="file"
standout
dense dense
borderless
color="accent"
label-color="white"
stack-label stack-label
label-slot label-slot
type="file" type="file"
accept="image/*" accept="image/*"
class="q-px-md rounded-5 inset-shadow"
:class="$q.dark.isActive ? 'bg-primary' : 'bg-dark'"
:style="`border: 1px solid var(${$q.dark.isActive ? '--q-secondary' : '--q-primary'});`"
> >
<template #prepend> <template #append>
<q-icon <q-icon
name="attach_file" name="attach_file"
size="sm" size="sm"
@ -236,13 +261,17 @@
</template> </template>
<template #label> <template #label>
<span class="text-weight-bold text-accent text-uppercase text-caption"> <span
class="text-weight-medium text-uppercase q-px-sm no-pointer-events"
:class="$q.dark.isActive ? 'bg-secondary' : 'bg-primary'"
>
{{ $t('timesheet.expense.hints.attach_file') }} {{ $t('timesheet.expense.hints.attach_file') }}
</span> </span>
</template> </template>
</q-file> </q-file>
</div> </div>
</div> </div>
</div>
<div class="col row full-width items-center"> <div class="col row full-width items-center">
<q-space /> <q-space />

View File

@ -244,6 +244,7 @@
<ExpenseDialogForm <ExpenseDialogForm
v-model="expense" v-model="expense"
:email="getEmployeeEmail()" :email="getEmployeeEmail()"
:mode="mode"
@click-save="hideUpdateForm" @click-save="hideUpdateForm"
/> />
</q-expansion-item> </q-expansion-item>