refactor(timesheet): working on expense list, optimizing class usage
working to refactor expense list and form to instead be q-expansion-items that are part of the same group, will trim a lot of needless code and q-slide-transition use this way.
This commit is contained in:
parent
c5cf6becda
commit
1b4e59b292
|
|
@ -35,13 +35,15 @@
|
||||||
const period_end_date = computed(() => timesheet_store.pay_period?.period_end.replaceAll('-', '/') ?? '');
|
const period_end_date = computed(() => timesheet_store.pay_period?.period_end.replaceAll('-', '/') ?? '');
|
||||||
|
|
||||||
const expense_options: ExpenseOption[] = [
|
const expense_options: ExpenseOption[] = [
|
||||||
{label: t('timesheet.expense.types.PER_DIEM'), value: 'PER_DIEM', icon: getExpenseIcon('PER_DIEM')},
|
{ label: t('timesheet.expense.types.PER_DIEM'), value: 'PER_DIEM', icon: getExpenseIcon('PER_DIEM') },
|
||||||
{label: t('timesheet.expense.types.EXPENSES'), value: 'EXPENSES', icon: getExpenseIcon('EXPENSES')},
|
{ label: t('timesheet.expense.types.EXPENSES'), value: 'EXPENSES', icon: getExpenseIcon('EXPENSES') },
|
||||||
{label: t('timesheet.expense.types.MILEAGE'), value: 'MILEAGE', icon: getExpenseIcon('MILEAGE')},
|
{ label: t('timesheet.expense.types.MILEAGE'), value: 'MILEAGE', icon: getExpenseIcon('MILEAGE') },
|
||||||
{label: t('timesheet.expense.types.ON_CALL'), value: 'ON_CALL', icon: getExpenseIcon('ON_CALL')},
|
{ label: t('timesheet.expense.types.ON_CALL'), value: 'ON_CALL', icon: getExpenseIcon('ON_CALL') },
|
||||||
]
|
]
|
||||||
const expense_selected = ref(expense_options.find(expense => expense.value == expenses_store.current_expense.type));
|
const expense_selected = ref(expense_options.find(expense => expense.value == expenses_store.current_expense.type));
|
||||||
|
|
||||||
|
const expense_monetary_string = ref(expenses_store.current_expense.amount.toString());
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'onClickUpdateCancel': [void];
|
'onClickUpdateCancel': [void];
|
||||||
'onClickSaveUpdates': [void];
|
'onClickSaveUpdates': [void];
|
||||||
|
|
@ -68,6 +70,12 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const saveAndConvert = () => {
|
||||||
|
expenses_store.current_expense.amount = convertToMonetaryAmount(expense_monetary_string.value);
|
||||||
|
expense_monetary_string.value = expenses_store.current_expense.amount.toString();
|
||||||
|
console.log('current expense amount: ', expenses_store.current_expense.amount);
|
||||||
|
}
|
||||||
|
|
||||||
watch(expenses_store.current_expense, () => {
|
watch(expenses_store.current_expense, () => {
|
||||||
is_initial_expense.value = deepEqual(expenses_store.current_expense, expenses_store.initial_expense);
|
is_initial_expense.value = deepEqual(expenses_store.current_expense, expenses_store.initial_expense);
|
||||||
});
|
});
|
||||||
|
|
@ -92,15 +100,14 @@
|
||||||
:class="expenses_store.mode === 'create' ? 'q-px-lg' : ''"
|
:class="expenses_store.mode === 'create' ? 'q-px-lg' : ''"
|
||||||
>
|
>
|
||||||
<!-- date selection input -->
|
<!-- date selection input -->
|
||||||
|
<div class="col q-px-xs">
|
||||||
<q-input
|
<q-input
|
||||||
v-model="expenses_store.current_expense.date"
|
v-model="expenses_store.current_expense.date"
|
||||||
dense
|
dense
|
||||||
type="date"
|
standout
|
||||||
borderless
|
|
||||||
readonly
|
readonly
|
||||||
stack-label
|
stack-label
|
||||||
color="primary"
|
color="primary"
|
||||||
class="col-auto q-px-xs"
|
|
||||||
input-class="text-weight-medium"
|
input-class="text-weight-medium"
|
||||||
input-style="font-size: 1em;"
|
input-style="font-size: 1em;"
|
||||||
:label="$t('timesheet.expense.date')"
|
:label="$t('timesheet.expense.date')"
|
||||||
|
|
@ -136,17 +143,18 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- expenses type selection -->
|
<!-- expenses type selection -->
|
||||||
|
<div class="col q-px-xs">
|
||||||
<q-select
|
<q-select
|
||||||
v-model="expense_selected"
|
v-model="expense_selected"
|
||||||
standout="bg-blue-grey-9"
|
standout
|
||||||
dense
|
dense
|
||||||
:options="expense_options"
|
:options="expense_options"
|
||||||
hide-dropdown-icon
|
hide-dropdown-icon
|
||||||
stack-label
|
stack-label
|
||||||
label-slot
|
label-slot
|
||||||
class="col q-px-xs"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
:label="$t('timesheet.expense.type')"
|
:label="$t('timesheet.expense.type')"
|
||||||
:menu-offset="[0, 10]"
|
:menu-offset="[0, 10]"
|
||||||
|
|
@ -181,24 +189,24 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- amount input -->
|
<!-- amount input -->
|
||||||
<div v-if="TYPES_WITH_AMOUNT_ONLY.includes(expenses_store.current_expense?.type ?? 'EXPENSES')">
|
<div class="col q-px-xs">
|
||||||
<q-input
|
<q-input
|
||||||
key="amount"
|
v-if="TYPES_WITH_AMOUNT_ONLY.includes(expenses_store.current_expense?.type ?? 'EXPENSES')"
|
||||||
v-model.number="expenses_store.current_expense.amount"
|
v-model="expense_monetary_string"
|
||||||
standout="bg-blue-grey-9"
|
standout
|
||||||
dense
|
dense
|
||||||
label-slot
|
label-slot
|
||||||
stack-label
|
stack-label
|
||||||
suffix="$"
|
suffix="$"
|
||||||
color="primary"
|
color="primary"
|
||||||
class="col-auto q-px-xs"
|
|
||||||
input-class="text-right text-weight-bold"
|
input-class="text-right text-weight-bold"
|
||||||
:input-style="'font-size: 1.2em;'"
|
:input-style="'font-size: 1.2em;'"
|
||||||
lazy-rules="ondemand"
|
lazy-rules="ondemand"
|
||||||
:rules="[rules.amountRequired]"
|
:rules="[rules.amountRequired]"
|
||||||
@blur="expenses_store.current_expense.amount = convertToMonetaryAmount(expenses_store.current_expense.amount)"
|
@blur="saveAndConvert()"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span class="text-weight-bold text-accent text-uppercase text-caption">
|
<span class="text-weight-bold text-accent text-uppercase text-caption">
|
||||||
|
|
@ -206,24 +214,22 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- mileage input -->
|
|
||||||
<div v-else>
|
|
||||||
<q-input
|
<q-input
|
||||||
|
v-else
|
||||||
key="mileage"
|
key="mileage"
|
||||||
v-model.number="expenses_store.current_expense.mileage"
|
v-model="expenses_store.current_expense.mileage"
|
||||||
standout="bg-blue-grey-9"
|
standout
|
||||||
input-class="text-right"
|
|
||||||
dense
|
dense
|
||||||
stack-label
|
stack-label
|
||||||
clearable
|
clearable
|
||||||
color="primary"
|
|
||||||
class="col q-px-xs"
|
|
||||||
label-slot
|
label-slot
|
||||||
|
input-class="text-right"
|
||||||
|
color="primary"
|
||||||
suffix="km"
|
suffix="km"
|
||||||
lazy-rules="ondemand"
|
lazy-rules="ondemand"
|
||||||
:rules="[rules.mileageRequired]"
|
:rules="[rules.mileageRequired]"
|
||||||
|
@blur="expenses_store.current_expense.amount = convertToMonetaryAmount(expense_monetary_string)"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span class="text-weight-bold text-accent text-uppercase text-caption">
|
<span class="text-weight-bold text-accent text-uppercase text-caption">
|
||||||
|
|
@ -234,15 +240,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- employee comment input -->
|
<!-- employee comment input -->
|
||||||
|
<div class="col q-px-xs">
|
||||||
<q-input
|
<q-input
|
||||||
v-model="expenses_store.current_expense.comment"
|
v-model="expenses_store.current_expense.comment"
|
||||||
standout="bg-blue-grey-9"
|
standout
|
||||||
dense
|
dense
|
||||||
stack-label
|
stack-label
|
||||||
label-slot
|
label-slot
|
||||||
color="primary"
|
color="primary"
|
||||||
type="text"
|
type="text"
|
||||||
class="col q-px-sm"
|
|
||||||
:maxlength="COMMENT_MAX_LENGTH"
|
:maxlength="COMMENT_MAX_LENGTH"
|
||||||
lazy-rules="ondemand"
|
lazy-rules="ondemand"
|
||||||
:rules="[rules.commentRequired]"
|
:rules="[rules.commentRequired]"
|
||||||
|
|
@ -253,18 +259,18 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- import attach file section -->
|
<!-- import attach file section -->
|
||||||
|
<div class="col q-px-xs">
|
||||||
<q-file
|
<q-file
|
||||||
v-model="files"
|
v-model="files"
|
||||||
standout="bg-blue-grey-9"
|
standout
|
||||||
dense
|
dense
|
||||||
use-chips
|
use-chips
|
||||||
multiple
|
multiple
|
||||||
stack-label
|
stack-label
|
||||||
:label="$t('timesheet.expense.hints.attach_file')"
|
label-slot
|
||||||
class="col"
|
|
||||||
style="max-width: 300px;"
|
|
||||||
>
|
>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -281,6 +287,8 @@
|
||||||
</template>
|
</template>
|
||||||
</q-file>
|
</q-file>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col row full-width items-center">
|
<div class="col row full-width items-center">
|
||||||
<q-space />
|
<q-space />
|
||||||
|
|
||||||
|
|
@ -308,3 +316,9 @@
|
||||||
</div>
|
</div>
|
||||||
</q-form>
|
</q-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
:deep(.q-field--standout.q-field--readonly .q-field__control::before) {
|
||||||
|
border: transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,60 +2,25 @@
|
||||||
setup
|
setup
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
import { date } from 'quasar';
|
|
||||||
import { computed, ref, toRaw } from 'vue';
|
|
||||||
import { unwrapAndClone } from 'src/utils/unwrap-and-clone';
|
|
||||||
import { deepEqual } from 'src/utils/deep-equal';
|
|
||||||
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 { useAuthStore } from 'src/stores/auth-store';
|
|
||||||
import { CAN_APPROVE_PAY_PERIODS } from 'src/modules/shared/models/user.models';
|
|
||||||
import { Expense } from 'src/modules/timesheets/models/expense.models';
|
|
||||||
import ExpenseDialogForm from 'src/modules/timesheets/components/expense-dialog-form.vue';
|
import ExpenseDialogForm from 'src/modules/timesheets/components/expense-dialog-form.vue';
|
||||||
|
|
||||||
const { expense, horizontal = false } = defineProps<{
|
import { date } from 'quasar';
|
||||||
expense: Expense;
|
import { computed, ref } from 'vue';
|
||||||
index: number;
|
import { useExpensesStore } from 'src/stores/expense-store';
|
||||||
horizontal?: boolean;
|
import { useExpensesApi } from 'src/modules/timesheets/composables/use-expense-api';
|
||||||
}>();
|
import { getExpenseIcon } from 'src/modules/timesheets/utils/expense.util';
|
||||||
const is_approved = defineModel<boolean>({ required: true });
|
import { Expense } from 'src/modules/timesheets/models/expense.models';
|
||||||
|
|
||||||
|
const expense = defineModel<Expense>({ required: true });
|
||||||
|
|
||||||
const expenses_store = useExpensesStore();
|
const expenses_store = useExpensesStore();
|
||||||
const auth_store = useAuthStore();
|
|
||||||
const expenses_api = useExpensesApi();
|
const expenses_api = useExpensesApi();
|
||||||
|
|
||||||
const refresh_key = ref(1);
|
|
||||||
const background_class = computed(() => deepEqual(expense, expenses_store.current_expense) ? '' : '');
|
|
||||||
const approved_class = computed(() => expense.is_approved ? ' bg-accent text-white' : '')
|
|
||||||
const is_authorized_to_approve = computed(() => CAN_APPROVE_PAY_PERIODS.includes(auth_store.user?.role ?? 'GUEST'))
|
|
||||||
const is_showing_update_form = ref(false);
|
const is_showing_update_form = ref(false);
|
||||||
const is_current_expense = computed(() => expense.id === expenses_store.current_expense.id);
|
const is_current_expense = computed(() => expense.value.id === expenses_store.current_expense.id);
|
||||||
|
|
||||||
const requestExpenseDeletion = async () => {
|
const requestExpenseDeletion = async () => {
|
||||||
await expenses_api.deleteExpenseById(expense.id);
|
await expenses_api.deleteExpenseById(expense.value.id);
|
||||||
}
|
|
||||||
|
|
||||||
const onExpenseClicked = () => {
|
|
||||||
if (is_authorized_to_approve.value) {
|
|
||||||
is_approved.value = !is_approved.value;
|
|
||||||
refresh_key.value += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onUpdateClicked = () => {
|
|
||||||
if (deepEqual(expense, expenses_store.current_expense)) {
|
|
||||||
expenses_store.mode = 'create';
|
|
||||||
Object.assign(expense, toRaw(expenses_store.initial_expense))
|
|
||||||
expenses_store.current_expense = new Expense(date.formatDate(new Date(), 'YYYY-MM-DD'));
|
|
||||||
is_showing_update_form.value = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
expenses_store.mode = 'update';
|
|
||||||
expenses_store.current_expense = expense;
|
|
||||||
expenses_store.initial_expense = unwrapAndClone(expense);
|
|
||||||
is_showing_update_form.value = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSaveUpdatesClicked = () => {
|
const onSaveUpdatesClicked = () => {
|
||||||
|
|
@ -66,124 +31,100 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-item
|
<q-expansion-item
|
||||||
:key="refresh_key"
|
v-model="is_showing_update_form"
|
||||||
:clickable="horizontal"
|
hide-expand-icon
|
||||||
class="column col-4 items-center q-my-sm q-py-none shadow-3 rounded-5 bg-dark"
|
dense
|
||||||
:class="background_class + approved_class"
|
group="expenses"
|
||||||
@click="onExpenseClicked"
|
class="shadow-3 rounded-5 bg-dark"
|
||||||
|
:class="expense.is_approved ? ' bg-accent text-white' : ''"
|
||||||
>
|
>
|
||||||
<div class="col row fit items-center">
|
<template #header>
|
||||||
|
<div class="col row items-center full-width">
|
||||||
<!-- avatar type icon section -->
|
<!-- avatar type icon section -->
|
||||||
<q-item-section avatar>
|
<div class="col-auto">
|
||||||
<q-icon
|
<q-icon
|
||||||
:name="getExpenseIcon(expense.type)"
|
:name="getExpenseIcon(expense.type)"
|
||||||
:color="expense.is_approved ? 'white' : ($q.dark.isActive ? 'white' : 'primary')"
|
:color="expense.is_approved ? 'white' : ($q.dark.isActive ? 'white' : 'primary')"
|
||||||
size="lg"
|
size="lg"
|
||||||
|
class="q-px-sm"
|
||||||
/>
|
/>
|
||||||
</q-item-section>
|
</div>
|
||||||
|
|
||||||
<!-- amount or mileage section -->
|
<!-- amount or mileage section -->
|
||||||
<q-item-section class="col col-md-2 text-weight-bold">
|
<div class="col column">
|
||||||
<q-item-label v-if="expense.type === 'MILEAGE'">
|
<span
|
||||||
{{ expense.mileage?.toFixed(1) }} km
|
class="text-weight-bolder"
|
||||||
</q-item-label>
|
:class="expense.is_approved ? ' bg-accent text-white' : ''"
|
||||||
<q-item-label v-else>
|
style="font-size: 1.3em;"
|
||||||
$ {{ expense.amount.toFixed(2) }}
|
>
|
||||||
</q-item-label>
|
{{ expense.type === 'MILEAGE' ? `${expense.mileage?.toFixed(1)} km` : `$
|
||||||
|
${expense.amount.toFixed(2)}` }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<!-- date label -->
|
<!-- date label -->
|
||||||
<q-item-label
|
<span
|
||||||
caption
|
class="text-uppercase text-weight-light text-caption"
|
||||||
lines="1"
|
:class="expense.is_approved ? ' bg-accent text-white' : ''"
|
||||||
class="text-uppercase text-weight-light"
|
|
||||||
:class="approved_class"
|
|
||||||
>
|
>
|
||||||
{{ $d(date.extractDate(expense.date, 'YYYY-MM-DD'), {
|
{{ $d(date.extractDate(expense.date, 'YYYY-MM-DD'), {
|
||||||
month: 'short', day: 'numeric', weekday:
|
month: 'short', day: 'numeric', weekday:
|
||||||
'long'
|
'long'
|
||||||
}) }}
|
}) }}
|
||||||
</q-item-label>
|
</span>
|
||||||
</q-item-section>
|
</div>
|
||||||
|
|
||||||
<q-space v-if="horizontal" />
|
|
||||||
|
|
||||||
<!-- attachment file icon -->
|
<!-- attachment file icon -->
|
||||||
<q-item-section avatar>
|
<div class="col row items-center justify-start">
|
||||||
<q-btn
|
<q-btn
|
||||||
push
|
push
|
||||||
:color="expense.is_approved ? 'white' : 'accent'"
|
:color="expense.is_approved ? 'white' : 'accent'"
|
||||||
:text-color="expense.is_approved ? 'accent' : 'white'"
|
:text-color="expense.is_approved ? 'accent' : 'white'"
|
||||||
class="col-auto q-mx-sm q-px-sm q-pb-sm"
|
class="col-auto q-px-sm q-mr-sm"
|
||||||
icon="attach_file"
|
icon="attach_file"
|
||||||
/>
|
/>
|
||||||
</q-item-section>
|
|
||||||
|
|
||||||
<q-item-label class="col text-weight-light text-caption">
|
<q-item-label class="col">
|
||||||
<span>attachment_goes_here.jpg</span>
|
attachment_name.jpg
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- comment section -->
|
<!-- comment section -->
|
||||||
<q-item-section
|
<div class="col column">
|
||||||
v-if="!horizontal"
|
<span class="col-auto text-weight-bold text-accent text-uppercase text-caption">
|
||||||
top
|
|
||||||
>
|
|
||||||
<q-item-label
|
|
||||||
lines="1"
|
|
||||||
class="text-weight-medium text-uppercase"
|
|
||||||
>
|
|
||||||
{{ $t('timesheet.expense.employee_comment') }}
|
{{ $t('timesheet.expense.employee_comment') }}
|
||||||
</q-item-label>
|
</span>
|
||||||
<q-item-label
|
|
||||||
caption
|
<span
|
||||||
lines="1"
|
class="col"
|
||||||
:class="approved_class"
|
:class="expense.is_approved ? ' bg-accent text-white' : ''"
|
||||||
|
style="font-size: 1.3em;"
|
||||||
>
|
>
|
||||||
{{ expense.comment }}
|
{{ expense.comment }}
|
||||||
</q-item-label>
|
</span>
|
||||||
</q-item-section>
|
</div>
|
||||||
|
|
||||||
<!-- supervisor comment section -->
|
<!-- supervisor comment section -->
|
||||||
<q-item-section
|
<div
|
||||||
v-if="is_authorized_to_approve"
|
|
||||||
top
|
|
||||||
>
|
|
||||||
<q-item-label
|
|
||||||
lines="1"
|
|
||||||
class="text-weight-medium text-uppercase"
|
|
||||||
>
|
|
||||||
{{ $t('timesheet.expense.supervisor_comment') }}
|
|
||||||
</q-item-label>
|
|
||||||
<q-item-label
|
|
||||||
v-if="expense.supervisor_comment"
|
v-if="expense.supervisor_comment"
|
||||||
caption
|
class="col column"
|
||||||
lines="2"
|
>
|
||||||
|
<span class="col-auto text-weight-bold text-accent text-uppercase text-caption">
|
||||||
|
{{ $t('timesheet.expense.supervisor_comment') }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="col"
|
||||||
|
:class="expense.is_approved ? ' bg-accent text-white' : ''"
|
||||||
|
style="font-size: 1.3em;"
|
||||||
>
|
>
|
||||||
{{ expense.supervisor_comment }}
|
{{ expense.supervisor_comment }}
|
||||||
</q-item-label>
|
</span>
|
||||||
</q-item-section>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<q-item-section
|
<div
|
||||||
:key="refresh_key"
|
class="col-auto row"
|
||||||
side
|
|
||||||
:class="is_current_expense ? 'invisible' : ''"
|
|
||||||
>
|
|
||||||
<q-btn
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
size="lg"
|
|
||||||
icon="edit"
|
|
||||||
color="accent"
|
|
||||||
:disable="expense.is_approved"
|
|
||||||
class="q-py-none z-top"
|
|
||||||
:class="expense.is_approved ? 'invisible no-pointer' : ''"
|
|
||||||
@click.stop="onUpdateClicked"
|
|
||||||
/>
|
|
||||||
</q-item-section>
|
|
||||||
|
|
||||||
<q-item-section
|
|
||||||
side
|
|
||||||
:class="is_current_expense ? 'invisible' : ''"
|
:class="is_current_expense ? 'invisible' : ''"
|
||||||
>
|
>
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -203,18 +144,13 @@
|
||||||
class="q-py-none z-top q-my-xs"
|
class="q-py-none z-top q-my-xs"
|
||||||
@click.stop="requestExpenseDeletion"
|
@click.stop="requestExpenseDeletion"
|
||||||
/>
|
/>
|
||||||
</q-item-section>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<q-slide-transition
|
|
||||||
@hide="expenses_store.mode === 'update' ? null : expenses_store.is_hiding_create_form = false"
|
|
||||||
:duration="200"
|
|
||||||
>
|
|
||||||
<ExpenseDialogForm
|
<ExpenseDialogForm
|
||||||
v-if="is_current_expense && expenses_store.is_hiding_create_form"
|
@on-click-update-cancel="is_showing_update_form = false"
|
||||||
@on-click-update-cancel="onUpdateClicked"
|
|
||||||
@on-click-save-updates="onSaveUpdatesClicked"
|
@on-click-save-updates="onSaveUpdatesClicked"
|
||||||
/>
|
/>
|
||||||
</q-slide-transition>
|
</q-expansion-item>
|
||||||
</q-item>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -51,10 +51,8 @@
|
||||||
|
|
||||||
<ExpenseDialogListItem
|
<ExpenseDialogListItem
|
||||||
v-else
|
v-else
|
||||||
v-model="expense.is_approved"
|
v-model="expenses_list[index]!"
|
||||||
:index="index"
|
:index="index"
|
||||||
:expense="expense"
|
|
||||||
:horizontal="horizontal"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-list>
|
</q-list>
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,19 @@ export const convertToMonetaryAmount = (amount: number | string): number => {
|
||||||
|
|
||||||
if (typeof amount === 'string') {
|
if (typeof amount === 'string') {
|
||||||
try {
|
try {
|
||||||
const single_decimal_amount = amount.replace(/\.(?=.*\.)/g, '');
|
let cleaned_amount = amount.replace(/[^\d.]/g, '');
|
||||||
const numbers_only_decimal = single_decimal_amount.replace(/[^0-9.]/g, '');
|
const first_dot = cleaned_amount.indexOf('.');
|
||||||
|
|
||||||
return Number(numbers_only_decimal);
|
if (first_dot !== -1) {
|
||||||
} catch(error) {
|
cleaned_amount =
|
||||||
|
cleaned_amount.slice(0, first_dot + 1) +
|
||||||
|
cleaned_amount
|
||||||
|
.slice(first_dot + 1, first_dot + 3)
|
||||||
|
.replace(/\./g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Number(cleaned_amount);
|
||||||
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user