diff --git a/web-app/src/api/data.ts b/web-app/src/api/data.ts index a2946e0..2fb6501 100644 --- a/web-app/src/api/data.ts +++ b/web-app/src/api/data.ts @@ -27,3 +27,7 @@ export function formatMoney(amount: number, currency: Currency) { }) return format.format(amount / Math.pow(10, currency.fractionalDigits)) } + +export function floatMoneyToInteger(amount: number, currency: Currency) { + return Math.round(amount * Math.pow(10, currency.fractionalDigits ?? 0)) +} diff --git a/web-app/src/components/LineItemCard.vue b/web-app/src/components/LineItemCard.vue new file mode 100644 index 0000000..d366835 --- /dev/null +++ b/web-app/src/components/LineItemCard.vue @@ -0,0 +1,60 @@ + + + diff --git a/web-app/src/components/LineItemsEditor.vue b/web-app/src/components/LineItemsEditor.vue index 1bc106d..fbd86c3 100644 --- a/web-app/src/components/LineItemsEditor.vue +++ b/web-app/src/components/LineItemsEditor.vue @@ -7,17 +7,28 @@ modal for adding a new one. import { type TransactionCategoryTree, type TransactionDetailLineItem } from '@/api/transaction'; import AppButton from '@/components/common/AppButton.vue'; import FormGroup from '@/components/common/form/FormGroup.vue'; -import { formatMoney, type Currency } from '@/api/data'; +import { floatMoneyToInteger, formatMoney, type Currency } from '@/api/data'; import ModalWrapper from '@/components/common/ModalWrapper.vue'; import FormControl from '@/components/common/form/FormControl.vue'; -import { ref, type Ref, useTemplateRef } from 'vue'; +import { computed, ref, type Ref, useTemplateRef } from 'vue'; import CategorySelect from './CategorySelect.vue'; +import LineItemCard from './LineItemCard.vue'; +import AppBadge from './common/AppBadge.vue'; const model = defineModel({ required: true }) -defineProps<{ - currency: Currency | null +const props = defineProps<{ + transactionAmount: number + currency: Currency }>() +const computedTotal = computed(() => { + let sum = 0 + for (const item of model.value) { + sum += item.quantity * item.valuePerItem + } + return sum +}) + const addLineItemDescription = ref('') const addLineItemValuePerItem = ref(0) const addLineItemQuantity = ref(0) @@ -39,13 +50,14 @@ function showAddLineItemModal() { } async function addLineItem() { - const idxs: number[] = model.value.map(i => i.idx) - const newIdx = Math.max(...idxs) + const newIdx = model.value.length === 0 + ? 0 + : Math.max(...model.value.map(i => i.idx)) + 1 model.value.push({ idx: newIdx, description: addLineItemDescription.value, quantity: addLineItemQuantity.value, - valuePerItem: addLineItemValuePerItem.value, + valuePerItem: floatMoneyToInteger(addLineItemValuePerItem.value, props.currency), category: selectedCategory.value }) addLineItemModal.value?.close() @@ -57,36 +69,40 @@ function removeLineItem(idx: number) { model.value[i].idx = i } } + +function moveItemUp(idx: number) { + if (idx <= 0) return + const item = model.value[idx] + model.value[idx] = model.value[idx - 1] + model.value[idx - 1] = item + for (let i = 0; i < model.value.length; i++) { + model.value[i].idx = i + } +} + +function moveItemDown(idx: number) { + if (idx >= model.value.length - 1) return + const item = model.value[idx] + model.value[idx] = model.value[idx + 1] + model.value[idx + 1] = item + for (let i = 0; i < model.value.length; i++) { + model.value[i].idx = i + } +} - + diff --git a/web-app/src/components/common/AppButton.vue b/web-app/src/components/common/AppButton.vue index 3de1e53..f5628a3 100644 --- a/web-app/src/components/common/AppButton.vue +++ b/web-app/src/components/common/AppButton.vue @@ -29,7 +29,7 @@ const buttonStyle = computed(() => ({ }))