mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
219 lines
6.2 KiB
Vue
219 lines
6.2 KiB
Vue
<template>
|
|
<div class="contribution-form">
|
|
<BForm
|
|
ref="form"
|
|
class="form-style p-3 bg-white app-box-shadow gradido-border-radius"
|
|
@submit.prevent="submit"
|
|
>
|
|
<ValidatedInput
|
|
id="contribution-date"
|
|
:model-value="formValues.date"
|
|
name="date"
|
|
:label="$t('contribution.selectDate')"
|
|
:no-flip="true"
|
|
class="mb-4 bg-248"
|
|
type="date"
|
|
:rules="validationSchema"
|
|
@update:model-value="updateField"
|
|
/>
|
|
<div v-if="showMessage" class="p-3" data-test="contribtion-message">
|
|
{{ noOpenCreation }}
|
|
</div>
|
|
<div v-else>
|
|
<input-textarea
|
|
id="contribution-memo"
|
|
:model-value="formValues.memo"
|
|
name="memo"
|
|
:label="$t('contribution.activity')"
|
|
:placeholder="$t('contribution.yourActivity')"
|
|
:rules="validationSchema"
|
|
@update:model-value="updateField"
|
|
/>
|
|
<ValidatedInput
|
|
name="hours"
|
|
:model-value="formValues.hours"
|
|
:label="$t('form.hours')"
|
|
placeholder="0.01"
|
|
step="0.01"
|
|
type="number"
|
|
:rules="validationSchema"
|
|
@update:model-value="updateField"
|
|
/>
|
|
<LabeledInput
|
|
id="contribution-amount"
|
|
class="mt-3"
|
|
name="amount"
|
|
:label="$t('form.amount')"
|
|
placeholder="20"
|
|
readonly
|
|
type="text"
|
|
trim
|
|
/>
|
|
<BRow class="mt-5">
|
|
<BCol>
|
|
<BButton
|
|
block
|
|
type="reset"
|
|
variant="secondary"
|
|
data-test="button-cancel"
|
|
@click="fullFormReset"
|
|
>
|
|
{{ $t('form.cancel') }}
|
|
</BButton>
|
|
</BCol>
|
|
<BCol class="text-end mt-lg-0">
|
|
<BButton
|
|
block
|
|
type="submit"
|
|
variant="gradido"
|
|
:disabled="disabled"
|
|
data-test="button-submit"
|
|
>
|
|
{{ form.id ? $t('form.change') : $t('contribution.submit') }}
|
|
</BButton>
|
|
</BCol>
|
|
</BRow>
|
|
</div>
|
|
</BForm>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed } from 'vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
import InputTextarea from '@/components/Inputs/InputTextarea'
|
|
import ValidatedInput from '@/components/Inputs/ValidatedInput'
|
|
import LabeledInput from '@/components/Inputs/LabeledInput'
|
|
import { memo } from '@/validationSchemas'
|
|
import { useForm } from 'vee-validate'
|
|
import { object, date, number } from 'yup'
|
|
|
|
const props = defineProps({
|
|
modelValue: { type: Object, required: true },
|
|
isThisMonth: { type: Boolean, required: true },
|
|
minimalDate: { type: Date, required: true },
|
|
maxGddLastMonth: { type: Number, required: true },
|
|
maxGddThisMonth: { type: Number, required: true },
|
|
})
|
|
|
|
const emit = defineEmits(['update-contribution', 'set-contribution'])
|
|
|
|
const { t } = useI18n()
|
|
|
|
const form = ref({ ...props.modelValue })
|
|
|
|
const maxHours = computed(() => Number(props.isThisMonth ? props.maxGddThisMonth : props.maxGddLastMonth / 20))
|
|
|
|
const validationSchema = computed(() => {
|
|
// const maxGDD = Number(props.isThisMonth ? props.maxGddThisMonth : props.maxGddLastMonth)
|
|
// const maxHours = Number(maxGDD / 20)
|
|
console.log('compute validationSchema', { maxHours })
|
|
return object({
|
|
// The date field is required and needs to be a valid date
|
|
// contribution date
|
|
date: date()
|
|
.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
|
|
.max(new Date().toISOString().slice(0, 10))
|
|
.default(''), // date cannot be in the future
|
|
memo,
|
|
hours: number().required('contribution.noHours')
|
|
.min(0.01, ({min}) => ({ key: 'form.validation.gddCreationTime.min', values: { min } }))
|
|
.max(maxHours.value, ({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())
|
|
}
|
|
),
|
|
})
|
|
})
|
|
const {
|
|
values: formValues,
|
|
meta: formMeta,
|
|
resetForm,
|
|
setFieldValue,
|
|
} = useForm({
|
|
initialValues: {
|
|
date: props.modelValue.date,
|
|
memo: props.modelValue.memo,
|
|
hours: props.modelValue.hours,
|
|
amount: props.modelValue.amount,
|
|
},
|
|
validationSchema: validationSchema.value,
|
|
})
|
|
|
|
const updateField = (newValue, name) => {
|
|
if (typeof name === 'string' && name.length) {
|
|
setFieldValue(name, newValue)
|
|
}
|
|
if (name === 'hours') {
|
|
setFieldValue('amount', (newValue * 20).toFixed(2).toString())
|
|
}
|
|
}
|
|
|
|
const showMessage = computed(() => {
|
|
if (props.maxGddThisMonth <= 0 && props.maxGddLastMonth <= 0) return true
|
|
if (props.modelValue.date)
|
|
return (
|
|
(props.isThisMonth && props.maxGddThisMonth <= 0) ||
|
|
(!props.isThisMonth && props.maxGddLastMonth <= 0)
|
|
)
|
|
return false
|
|
})
|
|
|
|
const disabled = computed(() => {
|
|
return (
|
|
!formMeta.value.valid ||
|
|
(props.isThisMonth && parseFloat(form.value.amount) > parseFloat(props.maxGddThisMonth)) ||
|
|
(!props.isThisMonth && parseFloat(form.value.amount) > parseFloat(props.maxGddLastMonth))
|
|
)
|
|
})
|
|
|
|
const noOpenCreation = computed(() => {
|
|
if (props.maxGddThisMonth <= 0 && props.maxGddLastMonth <= 0) {
|
|
return t('contribution.noOpenCreation.allMonth')
|
|
}
|
|
if (props.isThisMonth && props.maxGddThisMonth <= 0) {
|
|
return t('contribution.noOpenCreation.thisMonth')
|
|
}
|
|
if (!props.isThisMonth && props.maxGddLastMonth <= 0) {
|
|
return t('contribution.noOpenCreation.lastMonth')
|
|
}
|
|
return ''
|
|
})
|
|
|
|
function submit() {
|
|
const dataToSave = { ...formValues }
|
|
let emitOption = 'set-contribution'
|
|
if (props.modelValue.id) {
|
|
dataToSave.id = props.modelValue.id
|
|
emitOption = 'update-contribution'
|
|
}
|
|
emit(emitOption, dataToSave)
|
|
fullFormReset()
|
|
}
|
|
|
|
function fullFormReset() {
|
|
resetForm({
|
|
values: {
|
|
date: '',
|
|
memo: '',
|
|
hours: 0.0,
|
|
amount: '',
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
<style>
|
|
.form-style {
|
|
min-height: 410px;
|
|
}
|
|
|
|
span.errors {
|
|
color: red;
|
|
}
|
|
</style>
|