mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
new approach for validation
This commit is contained in:
parent
ff12773188
commit
52414789cd
@ -29,7 +29,7 @@
|
||||
"@types/leaflet": "^1.9.12",
|
||||
"@vee-validate/i18n": "^4.14.7",
|
||||
"@vee-validate/rules": "^4.14.1",
|
||||
"@vee-validate/yup": "^4.14.1",
|
||||
"@vee-validate/yup": "^4.15.0",
|
||||
"@vitejs/plugin-vue": "5.1.4",
|
||||
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
||||
"@vue/apollo-composable": "^4.0.2",
|
||||
@ -68,7 +68,7 @@
|
||||
"vue-timer-hook": "^1.0.84",
|
||||
"vuex": "^4.1.0",
|
||||
"vuex-persistedstate": "^4.1.0",
|
||||
"yup": "^1.4.0"
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/client": "^3.10.8",
|
||||
|
||||
@ -5,26 +5,18 @@
|
||||
class="form-style p-3 bg-white app-box-shadow gradido-border-radius"
|
||||
@submit.prevent="submit"
|
||||
>
|
||||
<label>{{ $t('contribution.selectDate') }}</label>
|
||||
<BFormInput
|
||||
<ValidatedInput
|
||||
id="contribution-date"
|
||||
:model-value="date"
|
||||
:model-value="formValues.date"
|
||||
name="date"
|
||||
:state="dataFieldMeta.valid"
|
||||
:locale="$i18n.locale"
|
||||
:max="getMaximalDate"
|
||||
:min="minimalDate.toISOString().slice(0, 10)"
|
||||
class="mb-4 bg-248"
|
||||
reset-value=""
|
||||
:label-no-date-selected="$t('contribution.noDateSelected')"
|
||||
required
|
||||
:label="$t('contribution.selectDate')"
|
||||
:no-flip="true"
|
||||
class="mb-4 bg-248"
|
||||
type="date"
|
||||
@update:model-value="handleDateChange"
|
||||
>
|
||||
<template #nav-prev-year><span></span></template>
|
||||
<template #nav-next-year><span></span></template>
|
||||
</BFormInput>
|
||||
|
||||
:schema-description="schemaDescription.fields.date"
|
||||
@update:model-value="updateField"
|
||||
/>
|
||||
<div v-if="showMessage" class="p-3" data-test="contribtion-message">
|
||||
{{ noOpenCreation }}
|
||||
</div>
|
||||
@ -39,12 +31,12 @@
|
||||
<input-hour
|
||||
name="hours"
|
||||
:label="$t('form.hours')"
|
||||
placeholder="0.25"
|
||||
placeholder="0.01"
|
||||
:rules="{
|
||||
required: true,
|
||||
min: 0.25,
|
||||
// decimal: 2,
|
||||
min: 0.01,
|
||||
max: validMaxTime,
|
||||
gddCreationTime: { min: 0.25, max: validMaxTime },
|
||||
}"
|
||||
:valid-max-time="validMaxTime"
|
||||
/>
|
||||
@ -88,12 +80,14 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import InputHour from '@/components/Inputs/InputHour'
|
||||
import InputAmount from '@/components/Inputs/InputAmount'
|
||||
import InputTextarea from '@/components/Inputs/InputTextarea'
|
||||
import { useField, useForm } from 'vee-validate'
|
||||
import ValidatedInput from '@/components/Inputs/ValidatedInput.vue'
|
||||
import { createContributionFormValidation } from '@/validationSchemas'
|
||||
import { useForm, useField } from 'vee-validate'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: Object, required: true },
|
||||
@ -109,11 +103,14 @@ const { t } = useI18n()
|
||||
|
||||
const form = ref({ ...props.modelValue })
|
||||
|
||||
const validationSchema = createContributionFormValidation(t)
|
||||
const schemaDescription = validationSchema.describe()
|
||||
// console.log(schemaDescription)
|
||||
|
||||
const {
|
||||
values: formValues,
|
||||
meta: formMeta,
|
||||
resetForm,
|
||||
defineField,
|
||||
setFieldValue,
|
||||
} = useForm({
|
||||
initialValues: {
|
||||
@ -122,15 +119,15 @@ const {
|
||||
hours: props.modelValue.hours,
|
||||
amount: props.modelValue.amount,
|
||||
},
|
||||
validationSchema
|
||||
})
|
||||
|
||||
const [date, dateProps] = defineField('date')
|
||||
const { meta: dataFieldMeta } = useField('date')
|
||||
|
||||
const { meta: dataFieldMeta } = useField('date', 'required')
|
||||
|
||||
const handleDateChange = (newDate) => {
|
||||
date.value = newDate
|
||||
emit('update:model-value', { ...props.modelValue, date: newDate })
|
||||
const updateField = (newValue, name) => {
|
||||
if(typeof name === 'string' && name.length) {
|
||||
setFieldValue(name, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
const showMessage = computed(() => {
|
||||
@ -146,8 +143,8 @@ const showMessage = computed(() => {
|
||||
const disabled = computed(() => {
|
||||
return (
|
||||
!formMeta.value.valid ||
|
||||
(props.isThisMonth && parseInt(form.value.amount) > parseInt(props.maxGddThisMonth)) ||
|
||||
(!props.isThisMonth && parseInt(form.value.amount) > parseInt(props.maxGddLastMonth))
|
||||
(props.isThisMonth && parseFloat(form.value.amount) > parseFloat(props.maxGddThisMonth)) ||
|
||||
(!props.isThisMonth && parseFloat(form.value.amount) > parseFloat(props.maxGddLastMonth))
|
||||
)
|
||||
})
|
||||
|
||||
@ -172,15 +169,11 @@ const noOpenCreation = computed(() => {
|
||||
return ''
|
||||
})
|
||||
|
||||
const getMaximalDate = computed(() => {
|
||||
return new Date().toISOString().slice(0, 10)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => formValues.hours,
|
||||
() => {
|
||||
updateAmount(formValues.hours)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
function updateAmount(hours) {
|
||||
|
||||
@ -3,16 +3,15 @@
|
||||
<BFormGroup :label="label" :label-for="labelFor">
|
||||
<BFormInput
|
||||
:id="labelFor"
|
||||
:model-value="currentValue"
|
||||
v-model="currentValue"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="number"
|
||||
:state="meta.valid"
|
||||
step="0.25"
|
||||
step="0.01"
|
||||
min="0"
|
||||
:max="validMaxTime"
|
||||
class="bg-248"
|
||||
@update:model-value="currentValue = $event"
|
||||
/>
|
||||
<BFormInvalidFeedback v-if="errorMessage">
|
||||
{{ errorMessage }}
|
||||
|
||||
63
frontend/src/components/Inputs/ValidatedInput.vue
Normal file
63
frontend/src/components/Inputs/ValidatedInput.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div :class="wrapperClassName">
|
||||
<BFormGroup :label="label" :label-for="labelFor">
|
||||
<BFormInput
|
||||
v-bind="$attrs"
|
||||
:min="minValue"
|
||||
:max="maxValue"
|
||||
:model-value="modelValue"
|
||||
:reset-value="props.schemaDescription.default"
|
||||
:locale="$i18n.locale"
|
||||
:required="!props.schemaDescription.optional"
|
||||
@input="updateValue($event.target.value)"
|
||||
/>
|
||||
<BFormInvalidFeedback v-if="errorMessage">
|
||||
{{ props.errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
errorMessage: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
schemaDescription: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits()
|
||||
const updateValue = (newValue) => emit('update:modelValue', newValue, props.name)
|
||||
|
||||
// extract additional parameter like min and max from schema
|
||||
const getDateOnly = (rules, name) => rules.find(test => test.name === name)?.params[name]
|
||||
|
||||
const rules = props.schemaDescription.tests
|
||||
const minValue = getDateOnly(rules, 'min')
|
||||
const maxValue = getDateOnly(rules, 'max')
|
||||
|
||||
const wrapperClassName = computed(() => `input-${props.name}`)
|
||||
const labelFor = computed(() => `${props.name}-input-field`)
|
||||
</script>
|
||||
@ -94,7 +94,7 @@ const form = ref({
|
||||
id: null,
|
||||
date: '',
|
||||
memo: '',
|
||||
hours: 0,
|
||||
hours: 0.0,
|
||||
amount: '',
|
||||
})
|
||||
const originalContributionDate = ref('')
|
||||
|
||||
15
frontend/src/validationSchemas.js
Normal file
15
frontend/src/validationSchemas.js
Normal file
@ -0,0 +1,15 @@
|
||||
import {object, string, date } from 'yup'
|
||||
|
||||
export const createContributionFormValidation = (t) => {
|
||||
return object({
|
||||
// The date field is required and needs to be a valid date
|
||||
// contribution date
|
||||
date:
|
||||
date()
|
||||
.required(t('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
|
||||
.max(new Date().toISOString().slice(0,10))
|
||||
.default(''), // date cannot be in the future
|
||||
memo: string().required(t('')).min(5).max(255)
|
||||
})
|
||||
}
|
||||
@ -1657,14 +1657,13 @@
|
||||
dependencies:
|
||||
vee-validate "4.14.7"
|
||||
|
||||
"@vee-validate/yup@^4.14.1":
|
||||
version "4.14.7"
|
||||
resolved "https://registry.yarnpkg.com/@vee-validate/yup/-/yup-4.14.7.tgz#a029151394ae4fbc7a038dbb49acc86f2ba78ddc"
|
||||
integrity sha512-sMLkSXbVWIFK0BE8gEp2Gcdd3aqpTggBjbkrYmcdgyHBeYoPmhBHhUpkXDFhmsckie2xv6lNTicGO5oJt71N1Q==
|
||||
"@vee-validate/yup@^4.15.0":
|
||||
version "4.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@vee-validate/yup/-/yup-4.15.0.tgz#409f9b57414fadd5b86bc6ada18cd51a7ccd121c"
|
||||
integrity sha512-paK2ZdxZJRrUGwqaqf7KMNC+n5C7UGs7DofK7wZCza/zKT/QtFSxVYgopGoYYrbAfd6DpVmNpf/ouBuRdPBthA==
|
||||
dependencies:
|
||||
type-fest "^4.8.3"
|
||||
vee-validate "4.14.7"
|
||||
yup "^1.3.2"
|
||||
vee-validate "4.15.0"
|
||||
|
||||
"@vitejs/plugin-vue@5.1.4":
|
||||
version "5.1.4"
|
||||
@ -7133,6 +7132,14 @@ vee-validate@4.14.7, vee-validate@^4.13.2:
|
||||
"@vue/devtools-api" "^7.5.2"
|
||||
type-fest "^4.8.3"
|
||||
|
||||
vee-validate@4.15.0:
|
||||
version "4.15.0"
|
||||
resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-4.15.0.tgz#eb77a9c867669d34abbc33ca5e16f2a991eb7ad5"
|
||||
integrity sha512-PGJh1QCFwCBjbHu5aN6vB8macYVWrajbDvgo1Y/8fz9n/RVIkLmZCJDpUgu7+mUmCOPMxeyq7vXUOhbwAqdXcA==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^7.5.2"
|
||||
type-fest "^4.8.3"
|
||||
|
||||
vite-node@2.1.8:
|
||||
version "2.1.8"
|
||||
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.8.tgz#9495ca17652f6f7f95ca7c4b568a235e0c8dbac5"
|
||||
@ -7518,7 +7525,7 @@ yocto-queue@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
yup@^1.3.2, yup@^1.4.0:
|
||||
yup@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/yup/-/yup-1.6.1.tgz#8defcff9daaf9feac178029c0e13b616563ada4b"
|
||||
integrity sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user