use correct validation error messages for contribution and send memo

This commit is contained in:
einhornimmond 2025-07-25 14:49:18 +02:00
parent 14e596c8a1
commit 1c06a9cff6
7 changed files with 79 additions and 40 deletions

View File

@ -5,6 +5,7 @@ import ContributionForm from './ContributionForm.vue'
vi.mock('vue-i18n', () => ({
useI18n: () => ({
t: (key) => key,
d: (date) => date,
}),
}))

View File

@ -43,7 +43,7 @@
:label="$t('form.hours')"
placeholder="0.01"
step="0.01"
type="number"
type="text"
:rules="validationSchema.fields.hours"
:disable-smart-valid-state="disableSmartValidState"
@update:model-value="updateField"
@ -92,9 +92,8 @@ import { reactive, computed, ref, onMounted, onUnmounted, toRaw } from 'vue'
import { useI18n } from 'vue-i18n'
import ValidatedInput from '@/components/Inputs/ValidatedInput'
import LabeledInput from '@/components/Inputs/LabeledInput'
import { memo as memoSchema } from '@/validationSchemas'
import OpenCreationsAmount from './OpenCreationsAmount.vue'
import { object, date as dateSchema, number } from 'yup'
import { object, date as dateSchema, number, string } from 'yup'
import { GDD_PER_HOUR } from '../../constants'
const amountToHours = (amount) => parseFloat(amount / GDD_PER_HOUR).toFixed(2)
@ -108,7 +107,7 @@ const props = defineProps({
const emit = defineEmits(['upsert-contribution', 'abort'])
const { t } = useI18n()
const { t, d } = useI18n()
const entityDataToForm = computed(() => ({
...props.modelValue,
@ -151,16 +150,26 @@ const validationSchema = computed(() => {
// The date field is required and needs to be a valid date
// contribution date
contributionDate: dateSchema()
.required()
.min(minimalDate.value.toISOString().slice(0, 10)) // min date is first day of last month
.max(now.value.toISOString().slice(0, 10)), // date cannot be in the future
memo: memoSchema,
.required('form.validation.contributionDate.required')
.min(minimalDate.value.toISOString().slice(0, 10), ({ min }) => ({
key: 'form.validation.contributionDate.min',
values: { min: d(min) },
})) // min date is first day of last month
.max(now.value.toISOString().slice(0, 10), ({ max }) => ({
key: 'form.validation.contributionDate.max',
values: { max: d(max) },
})), // date cannot be in the future
memo: string()
.min(5, ({ min }) => ({ key: 'form.validation.contributionMemo.min', values: { min } }))
.max(255, ({ max }) => ({ key: 'form.validation.contributionMemo.max', values: { max } }))
.required('form.validation.contributionMemo.required'),
hours: number()
.typeError({ key: 'form.validation.hours.typeError', values: { min: 0.01, max: maxHours } })
.required()
.transform((value, originalValue) => (originalValue === '' ? undefined : value))
.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) => {
// .transform((value, originalValue) => (originalValue === '' ? undefined : value))
.min(0.01, ({ min }) => ({ key: 'form.validation.hours.min', values: { min } }))
.max(maxHours, ({ max }) => ({ key: 'form.validation.hours.max', values: { max } }))
.test('decimal-places', 'form.validation.hours.decimal-places', (value) => {
if (value === undefined || value === null) return true
return /^\d+(\.\d{0,2})?$/.test(value.toString())
}),

View File

@ -184,9 +184,15 @@ const userName = ref('')
const validationSchema = computed(() => {
return object({
memo: memoSchema,
identifier: !userIdentifier.value ? identifierSchema.required() : identifierSchema,
identifier: !userIdentifier.value
? identifierSchema.required('form.validation.identifier.required')
: identifierSchema,
amount: number()
.required()
.typeError({
key: 'form.validation.amount.typeError',
values: { min: 0.01, max: props.balance },
})
.transform((value, originalValue) => {
if (typeof originalValue === 'string') {
return Number(originalValue.replace(',', '.'))

View File

@ -71,9 +71,6 @@ const smartValidState = computed(() => {
return valid.value ? true : null
})
const errorMessage = computed(() => {
if (model.value === undefined || model.value === '' || model.value === null) {
return undefined
}
try {
props.rules.validateSync(model.value)
return undefined

View File

@ -204,26 +204,39 @@
"username-placeholder": "Wähle deinen Benutzernamen",
"validation": {
"amount": {
"min": "Der Betrag sollte mindestens {min} groß sein",
"max": "Der Betrag sollte höchstens {max} groß sein",
"decimal-places": "Der Betrag sollte maximal zwei Nachkommastellen enthalten"
"min": "Der Betrag sollte mindestens {min} groß sein.",
"max": "Der Betrag sollte höchstens {max} groß sein.",
"decimal-places": "Der Betrag sollte maximal zwei Nachkommastellen enthalten.",
"typeError": "Der Betrag sollte eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein."
},
"gddCreationTime": {
"min": "Die Stunden sollten mindestens {min} groß sein",
"max": "Die Stunden sollten höchstens {max} groß sein",
"decimal-places": "Die Stunden sollten maximal zwei Nachkommastellen enthalten"
"contributionDate": {
"required": "Das Beitragsdatum ist ein Pflichtfeld.",
"min": "Das Frühste Beitragsdatum ist {min}.",
"max": "Das Späteste Beitragsdatum ist heute, der {max}."
},
"gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein",
"is-not": "Du kannst dir selbst keine Gradidos überweisen",
"contributionMemo": {
"min": "Die Tätigkeitsbeschreibung sollte mindestens {min} Zeichen lang sein.",
"max": "Die Tätigkeitsbeschreibung sollte höchstens {max} Zeichen lang sein.",
"required": "Die Tätigkeitsbeschreibung ist ein Pflichtfeld."
},
"hours": {
"min": "Die Stunden sollten mindestens {min} groß sein.",
"max": "Die Stunden sollten höchstens {max} groß sein.",
"decimal-places": "Die Stunden sollten maximal zwei Nachkommastellen enthalten.",
"typeError": "Die Stunden sollten eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein."
},
"gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein.",
"is-not": "Du kannst dir selbst keine Gradidos überweisen!",
"memo": {
"min": "Die Tätigkeitsbeschreibung sollte mindestens {min} Zeichen lang sein",
"max": "Die Tätigkeitsbeschreibung sollte höchstens {max} Zeichen lang sein"
"min": "Die Nachricht sollte mindestens {min} Zeichen lang sein.",
"max": "Die Nachricht sollte höchstens {max} Zeichen lang sein.",
"required": "Die Nachricht ist ein Pflichtfeld."
},
"requiredField": "{fieldName} ist ein Pflichtfeld",
"username-allowed-chars": "Der Nutzername darf nur aus Buchstaben (ohne Umlaute), Zahlen, Binde- oder Unterstrichen bestehen.",
"username-hyphens": "Binde- oder Unterstriche müssen zwischen Buchstaben oder Zahlen stehen.",
"username-unique": "Der Nutzername ist bereits vergeben.",
"valid-identifier": "Muss eine Email, ein Nutzernamen oder eine gradido ID sein."
"valid-identifier": "Muss eine Email, ein Nutzernamen oder eine Gradido ID sein."
},
"your_amount": "Dein Betrag"
},

View File

@ -204,20 +204,33 @@
"username-placeholder": "Choose your username",
"validation": {
"amount": {
"min": "The amount should be at least {min} in size",
"max": "The amount should not be larger than {max}",
"decimal-places": "The amount should contain a maximum of two decimal places"
"min": "The amount should be at least {min} in size.",
"max": "The amount should not be larger than {max}.",
"decimal-places": "The amount should contain a maximum of two decimal places.",
"typeError": "The amount should be a number between {min} and {max} with at most two digits after the decimal point."
},
"gddCreationTime": {
"min": "The hours should be at least {min} in size",
"max": "The hours should not be larger than {max}",
"decimal-places": "The hours should contain a maximum of two decimal places"
"contributionDate": {
"required": "The contribution date is a required field.",
"min": "The earliest contribution date is {min}.",
"max": "The latest contribution date is today, {max}."
},
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point",
"is-not": "You cannot send Gradidos to yourself",
"contributionMemo": {
"min": "The job description should be at least {min} characters long.",
"max": "The job description should not be longer than {max} characters.",
"required": "The job description is required."
},
"hours": {
"min": "The hours should be at least {min} in size.",
"max": "The hours should not be larger than {max}.",
"decimal-places": "The hours should contain a maximum of two decimal places.",
"typeError": "The hours should be a number between {min} and {max} with at most two digits after the decimal point."
},
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point.",
"is-not": "You cannot send Gradidos to yourself!",
"memo": {
"min": "The job description should be at least {min} characters long",
"max": "The job description should not be longer than {max} characters"
"min": "The message should be at least {min} characters long.",
"max": "The message should not be longer than {max} characters.",
"required": "The message is required."
},
"requiredField": "The {fieldName} field is required",
"username-allowed-chars": "The username may only contain letters, numbers, hyphens or underscores.",

View File

@ -22,7 +22,7 @@ export const translateYupErrorString = (error, t) => {
}
export const memo = string()
.required('contribution.yourActivity')
.required('form.validation.memo.required')
.min(5, ({ min }) => ({ key: 'form.validation.memo.min', values: { min } }))
.max(255, ({ max }) => ({ key: 'form.validation.memo.max', values: { max } }))