From 86820b36fb7a6320ca0a4f716fb802117b573de2 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 12 Feb 2025 16:03:46 +0100 Subject: [PATCH] fix inaccuracy with using parseFloat instead of parseInt --- .../Contributions/ContributionForm.spec.js | 7 -- .../Contributions/ContributionForm.vue | 65 +++++------ .../Contributions/OpenCreationsAmount.vue | 11 +- .../src/components/Inputs/InputHour.spec.js | 108 ------------------ frontend/src/components/Inputs/InputHour.vue | 53 --------- .../src/components/Inputs/LabeledInput.vue | 14 +-- .../src/components/Inputs/ValidatedInput.vue | 33 +++--- frontend/src/pages/Community.vue | 12 +- frontend/src/validationSchemas.js | 8 +- 9 files changed, 74 insertions(+), 237 deletions(-) delete mode 100644 frontend/src/components/Inputs/InputHour.spec.js delete mode 100644 frontend/src/components/Inputs/InputHour.vue diff --git a/frontend/src/components/Contributions/ContributionForm.spec.js b/frontend/src/components/Contributions/ContributionForm.spec.js index 47ee4a763..36c209f8d 100644 --- a/frontend/src/components/Contributions/ContributionForm.spec.js +++ b/frontend/src/components/Contributions/ContributionForm.spec.js @@ -4,13 +4,6 @@ import ContributionForm from './ContributionForm.vue' import { useForm } from 'vee-validate' // Mock external components and dependencies -vi.mock('@/components/Inputs/InputHour', () => ({ - default: { - name: 'InputHour', - template: '', - }, -})) - vi.mock('@/components/Inputs/InputAmount', () => ({ default: { name: 'InputAmount', diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 204105f1c..fc96b1706 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -27,8 +27,8 @@ :label="$t('contribution.activity')" :placeholder="$t('contribution.yourActivity')" :rules="validationSchema.fields.memo" - @update:model-value="updateField" textarea="true" + @update:model-value="updateField" /> props.modelValue, (newValue) => Object.assign(form, newValue)) +watch( + () => props.modelValue, + (newValue) => Object.assign(form, newValue), +) // use computed to make sure child input update if props from parent from this component change -const amount = computed(() => form.hours ? (form.hours * 20).toFixed(2).toString() : '20') +const amount = computed(() => form.amount) const date = computed(() => form.date) const hours = computed(() => form.hours) const memo = computed(() => form.memo) @@ -114,50 +117,37 @@ const isThisMonth = computed(() => { const formDate = new Date(form.date) const now = new Date() return formDate.getMonth() === now.getMonth() && formDate.getFullYear() === now.getFullYear() -}); +}) +// reactive validation schema, because some boundaries depend on form input and existing data const validationSchema = computed(() => { - const maxHours = Number((isThisMonth.value ? props.maxGddThisMonth : props.maxGddLastMonth) / 20) - const maxAmounts = Number(isThisMonth.value ? parseFloat(props.maxGddThisMonth): parseFloat(props.maxGddLastMonth)) + const maxAmounts = Number( + isThisMonth.value ? parseFloat(props.maxGddThisMonth) : parseFloat(props.maxGddLastMonth), + ) + const maxHours = Number(maxAmounts / 20) return object({ // The date field is required and needs to be a valid date // contribution date date: dateSchema() .required('contribution.noDateSelected') - .min(new Date(new Date().setMonth(new Date().getMonth() - 1, 1)).toISOString().slice(0, 10)) // min date is first day of last month + .min(new Date(new Date().setMonth(new Date().getMonth() - 1, 1)).toISOString().slice(0, 10)) // min date is first day of last month .max(new Date().toISOString().slice(0, 10)) .default(''), // date cannot be in the future memo: memoSchema, - hours: number().transform((value, originalValue) => - originalValue === "" ? undefined : value - ) + hours: number() + .transform((value, originalValue) => (originalValue === '' ? undefined : value)) .required('contribution.noHours') - .min(0.01, ({min}) => ({ key: 'form.validation.gddCreationTime.min', values: { min } })) - .max(maxHours, ({max}) => ({ key: 'form.validation.gddCreationTime.max', values: { max } })) - .test( - 'decimal-places', - 'form.validation.gddCreationTime.decimal-places', - (value) => { - if (value === undefined || value === null) return true - return /^\d+(\.\d{0,2})?$/.test(value.toString()) - } - ), - amount: number().max(maxAmounts) + .min(0.01, ({ min }) => ({ key: 'form.validation.gddCreationTime.min', values: { min } })) + .max(maxHours, ({ max }) => ({ key: 'form.validation.gddCreationTime.max', values: { max } })) + .test('decimal-places', 'form.validation.gddCreationTime.decimal-places', (value) => { + if (value === undefined || value === null) return true + return /^\d+(\.\d{0,2})?$/.test(value.toString()) + }), + amount: number().max(maxAmounts), }) }) -const updateField = (newValue, name, valid) => { - if (typeof name === 'string' && name.length) { - form[name] = newValue - if (name === 'hours') { - form.amount = (newValue * 20).toFixed(2).toString() - } - } - // console.log('update field', { newValue, name, form, amount: amount.value }) - emit('update:modelValue', form) -} - const disabled = computed(() => !validationSchema.value.isValidSync(form)) const noOpenCreation = computed(() => { @@ -175,6 +165,16 @@ const noOpenCreation = computed(() => { return undefined }) +const updateField = (newValue, name) => { + if (typeof name === 'string' && name.length) { + form[name] = newValue + if (name === 'hours') { + form.amount = form.hours ? (form.hours * 20).toFixed(2).toString() : '20' + } + } + emit('update:modelValue', form) +} + function submit() { const dataToSave = { ...form } let emitOption = 'set-contribution' @@ -188,6 +188,7 @@ function submit() { function fullFormReset() { emit('update:modelValue', { + id: undefined, date: null, memo: '', hours: '', diff --git a/frontend/src/components/Contributions/OpenCreationsAmount.vue b/frontend/src/components/Contributions/OpenCreationsAmount.vue index 3a0b6ea5a..e88fb4f46 100644 --- a/frontend/src/components/Contributions/OpenCreationsAmount.vue +++ b/frontend/src/components/Contributions/OpenCreationsAmount.vue @@ -33,6 +33,9 @@ diff --git a/frontend/src/components/Inputs/LabeledInput.vue b/frontend/src/components/Inputs/LabeledInput.vue index 825478d37..920fceacd 100644 --- a/frontend/src/components/Inputs/LabeledInput.vue +++ b/frontend/src/components/Inputs/LabeledInput.vue @@ -1,18 +1,16 @@