aggiunto ProfessionalExpenses form
This commit is contained in:
@@ -68,6 +68,7 @@ const currentComponent = computed(() => {
|
|||||||
if (id === 'marital') return defineAsyncComponent(() => import('./steps/MaritalStep.vue'))
|
if (id === 'marital') return defineAsyncComponent(() => import('./steps/MaritalStep.vue'))
|
||||||
if (id === 'children') return defineAsyncComponent(() => import('./steps/ChildrenStep.vue'))
|
if (id === 'children') return defineAsyncComponent(() => import('./steps/ChildrenStep.vue'))
|
||||||
if (id === 'income') return defineAsyncComponent(() => import('./steps/IncomeStep.vue'))
|
if (id === 'income') return defineAsyncComponent(() => import('./steps/IncomeStep.vue'))
|
||||||
|
if (id === 'professionalExpenses') return defineAsyncComponent(() => import('./steps/ProfessionalExpensesStep.vue'))
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
198
app/src/components/steps/ProfessionalExpensesStep.vue
Normal file
198
app/src/components/steps/ProfessionalExpensesStep.vue
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<template>
|
||||||
|
<q-card flat class="full-width q-pa-none">
|
||||||
|
<q-card-section class="full-width">
|
||||||
|
<div class="row items-center">
|
||||||
|
<div class="col">
|
||||||
|
<div class="text-h6">{{ t('PRO') }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<q-btn flat :label="t('button.prev')" @click="emitPrev" class="q-mr-sm" />
|
||||||
|
<q-btn color="primary" :label="t('button.next')" @click="saveAndNext" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<q-separator class="q-my-sm" />
|
||||||
|
|
||||||
|
<q-form ref="formRef" class="q-gutter-md q-mt-md">
|
||||||
|
<div class="row items-center">
|
||||||
|
<div class="col">
|
||||||
|
<q-toggle v-model="form.expensesChanged" :label="t('professionalExpenses.expensesChanged')" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="form.expensesChanged" class="q-mt-md">
|
||||||
|
<q-input
|
||||||
|
v-model="form.workplaceDescription"
|
||||||
|
:label="t('professionalExpenses.workplaceDescription')"
|
||||||
|
type="text"
|
||||||
|
outlined
|
||||||
|
/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6 q-pr-md">
|
||||||
|
<q-select
|
||||||
|
v-model="form.commuteMethod"
|
||||||
|
:options="commuteMethodOptions"
|
||||||
|
:label="t('professionalExpenses.commuteMethod')"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
outlined
|
||||||
|
class="q-mt-md"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<q-input
|
||||||
|
v-model.number="form.commuteKm"
|
||||||
|
:label="t('professionalExpenses.commuteKm')"
|
||||||
|
type="number"
|
||||||
|
outlined
|
||||||
|
class="q-mt-md"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<q-toggle
|
||||||
|
v-model="form.lunchAtHome"
|
||||||
|
:label="t('professionalExpenses.lunchAtHome')"
|
||||||
|
class="q-mt-md"
|
||||||
|
/>
|
||||||
|
<q-toggle
|
||||||
|
v-model="form.eatsOut"
|
||||||
|
:label="t('professionalExpenses.eatsOut')"
|
||||||
|
class="q-mt-md"
|
||||||
|
/>
|
||||||
|
<q-toggle
|
||||||
|
v-if="form.eatsOut"
|
||||||
|
v-model="form.hasCanteenOrVouchers"
|
||||||
|
:label="t('professionalExpenses.hasCanteenOrVouchers')"
|
||||||
|
:rules="[requiredWhenEatsOut]"
|
||||||
|
class="q-mt-md"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</q-form>
|
||||||
|
|
||||||
|
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onMounted, ref, nextTick, watch, computed } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import type { StepDescriptor } from '../../types/types'
|
||||||
|
|
||||||
|
type CommuteMethod = 'CAR' | 'BUS' | 'BIKE' | 'WALK'
|
||||||
|
|
||||||
|
type ProfessionalExpensesForm = {
|
||||||
|
expensesChanged: boolean
|
||||||
|
workplaceDescription: string
|
||||||
|
commuteMethod: CommuteMethod | null
|
||||||
|
commuteKm: number | null
|
||||||
|
lunchAtHome: boolean
|
||||||
|
eatsOut: boolean
|
||||||
|
hasCanteenOrVouchers: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const props = defineProps<{ step?: StepDescriptor }>()
|
||||||
|
const emit = defineEmits(['next', 'prev'])
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
// QForm ref
|
||||||
|
const formRef = ref<{ validate?: () => Promise<boolean> | boolean; resetValidation?: () => void } | null>(null)
|
||||||
|
|
||||||
|
/* const required = (msg?: string) => (v: unknown) => {
|
||||||
|
const message = msg || requiredMessage()
|
||||||
|
if (v === null || v === undefined) return message
|
||||||
|
if (typeof v === 'string') return (v.trim() !== '') || message
|
||||||
|
if (Array.isArray(v)) return v.length > 0 || message
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const minLength = (n: number, msg?: string) => (v: unknown) => {
|
||||||
|
const message = msg || `${t('validation.minLength') || `Minimum ${n} chars`}`
|
||||||
|
if (v === null || v === undefined) return true
|
||||||
|
if (typeof v === 'string') return (v.trim().length >= n) || message
|
||||||
|
return true
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const form = reactive<ProfessionalExpensesForm>({
|
||||||
|
expensesChanged: false,
|
||||||
|
workplaceDescription: '',
|
||||||
|
commuteMethod: null,
|
||||||
|
commuteKm: null,
|
||||||
|
lunchAtHome: false,
|
||||||
|
eatsOut: false,
|
||||||
|
hasCanteenOrVouchers: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const commuteMethodOptions = computed<Array<{ label: string; value: CommuteMethod }>>(() => [
|
||||||
|
{ label: t('professionalExpenses.commuteMethodOptions.car'), value: 'CAR' },
|
||||||
|
{ label: t('professionalExpenses.commuteMethodOptions.bus'), value: 'BUS' },
|
||||||
|
{ label: t('professionalExpenses.commuteMethodOptions.bike'), value: 'BIKE' },
|
||||||
|
{ label: t('professionalExpenses.commuteMethodOptions.walk'), value: 'WALK' }
|
||||||
|
])
|
||||||
|
|
||||||
|
const requiredWhenEatsOut = (v: boolean | null) => {
|
||||||
|
if (!form.eatsOut) return true
|
||||||
|
return v !== null || t('validation.required')
|
||||||
|
}
|
||||||
|
|
||||||
|
/* const professionalExpensesSchema = {
|
||||||
|
fields: [
|
||||||
|
{ key: "expensesChanged", type: "boolean", required: true },
|
||||||
|
{ key: "workplaceDescription", type: "string" },
|
||||||
|
{ key: "commuteMethod", type: "enum", values: ["CAR", "BUS", "BIKE", "WALK"] },
|
||||||
|
{ key: "commuteKm", type: "number" },
|
||||||
|
{ key: "lunchAtHome", type: "boolean" },
|
||||||
|
{ key: "eatsOut", type: "boolean" },
|
||||||
|
{ key: "hasCanteenOrVouchers", type: "boolean", requiredIf: { eatsOut: true } },
|
||||||
|
],
|
||||||
|
} as const;
|
||||||
|
*/
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick()
|
||||||
|
formRef.value?.resetValidation?.()
|
||||||
|
})
|
||||||
|
|
||||||
|
// persist when expensesChanged toggles
|
||||||
|
watch(() => form.expensesChanged, () => {
|
||||||
|
//store.setChildren(buildPayload())
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => form.eatsOut, (value) => {
|
||||||
|
if (!value) form.hasCanteenOrVouchers = false
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function saveAndNext() {
|
||||||
|
try {
|
||||||
|
const ok = await (formRef.value?.validate?.() ?? true)
|
||||||
|
if (ok === false) return
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
emit('next', props.step?.next)
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitPrev() {
|
||||||
|
emit('prev', props.step?.prev)
|
||||||
|
}
|
||||||
|
|
||||||
|
//defineExpose({ buildPayload })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.full-width { width: 100%; }
|
||||||
|
.contained-card { min-width: 480px; max-width: 720px; }
|
||||||
|
.contained-card .q-card-section { padding: 16px; }
|
||||||
|
.contained-card .q-card-actions { padding: 12px 16px; }
|
||||||
|
.child-modal { min-width: 480px; }
|
||||||
|
</style>
|
||||||
@@ -96,6 +96,22 @@ export default {
|
|||||||
noAttachments: 'Attach documents'
|
noAttachments: 'Attach documents'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
professionalExpenses: {
|
||||||
|
expensesChanged: 'Have your professional expenses changed?',
|
||||||
|
workplaceDescription: 'Workplace description',
|
||||||
|
commuteMethod: 'Commute method',
|
||||||
|
commuteMethodOptions: {
|
||||||
|
car: 'Car',
|
||||||
|
bus: 'Bus',
|
||||||
|
bike: 'Bike',
|
||||||
|
walk: 'Walk'
|
||||||
|
},
|
||||||
|
commuteKm: 'Commute distance (km)',
|
||||||
|
lunchAtHome: 'Do you have lunch at home?',
|
||||||
|
eatsOut: 'Do you eat out?',
|
||||||
|
hasCanteenOrVouchers: 'Do you have a canteen or meal vouchers?'
|
||||||
|
},
|
||||||
|
|
||||||
informazionesualimenti: 'Alimony information',
|
informazionesualimenti: 'Alimony information',
|
||||||
inserireindirizzocogniuge: 'Enter spouse address',
|
inserireindirizzocogniuge: 'Enter spouse address',
|
||||||
inserireindirizzopartner: 'Enter partner address',
|
inserireindirizzopartner: 'Enter partner address',
|
||||||
|
|||||||
@@ -96,6 +96,22 @@ export default {
|
|||||||
noAttachments: 'Allega documenti'
|
noAttachments: 'Allega documenti'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
professionalExpenses: {
|
||||||
|
expensesChanged: 'Le spese professionali sono cambiate?',
|
||||||
|
workplaceDescription: 'Descrizione del luogo di lavoro',
|
||||||
|
commuteMethod: 'Metodo di trasporto',
|
||||||
|
commuteMethodOptions: {
|
||||||
|
car: 'Auto',
|
||||||
|
bus: 'Bus',
|
||||||
|
bike: 'Bici',
|
||||||
|
walk: 'A piedi'
|
||||||
|
},
|
||||||
|
commuteKm: 'Km di percorrenza',
|
||||||
|
lunchAtHome: 'Pranzi a casa?',
|
||||||
|
eatsOut: 'Mangi fuori?',
|
||||||
|
hasCanteenOrVouchers: 'Hai mensa o buoni pasto?'
|
||||||
|
},
|
||||||
|
|
||||||
informazionesualimenti: 'Informazioni su alimenti',
|
informazionesualimenti: 'Informazioni su alimenti',
|
||||||
inserireindirizzocogniuge: "Inserire l'indirizzo del coniuge",
|
inserireindirizzocogniuge: "Inserire l'indirizzo del coniuge",
|
||||||
inserireindirizzopartner: "Inserire l'indirizzo del partner",
|
inserireindirizzopartner: "Inserire l'indirizzo del partner",
|
||||||
|
|||||||
Reference in New Issue
Block a user