aggiunto lo store ProfessionalExpenses
This commit is contained in:
@@ -63,7 +63,6 @@
|
|||||||
v-if="form.eatsOut"
|
v-if="form.eatsOut"
|
||||||
v-model="form.hasCanteenOrVouchers"
|
v-model="form.hasCanteenOrVouchers"
|
||||||
:label="t('professionalExpenses.hasCanteenOrVouchers')"
|
:label="t('professionalExpenses.hasCanteenOrVouchers')"
|
||||||
:rules="[requiredWhenEatsOut]"
|
|
||||||
class="q-mt-md"
|
class="q-mt-md"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,9 +77,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, onMounted, ref, nextTick, watch, computed } from 'vue'
|
import { onMounted, ref, nextTick, watch, computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import type { StepDescriptor } from '../../types/types'
|
import type { StepDescriptor } from '../../types/types'
|
||||||
|
import { useProfessionalExpensesStore, type ProfessionalExpensesData } from '../../stores/professionalExpenses'
|
||||||
|
|
||||||
type CommuteMethod = 'CAR' | 'BUS' | 'BIKE' | 'WALK'
|
type CommuteMethod = 'CAR' | 'BUS' | 'BIKE' | 'WALK'
|
||||||
|
|
||||||
@@ -94,6 +94,7 @@ type ProfessionalExpensesForm = {
|
|||||||
hasCanteenOrVouchers: boolean
|
hasCanteenOrVouchers: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const store = useProfessionalExpensesStore()
|
||||||
|
|
||||||
const props = defineProps<{ step?: StepDescriptor }>()
|
const props = defineProps<{ step?: StepDescriptor }>()
|
||||||
const emit = defineEmits(['next', 'prev'])
|
const emit = defineEmits(['next', 'prev'])
|
||||||
@@ -120,15 +121,7 @@ const minLength = (n: number, msg?: string) => (v: unknown) => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const form = reactive<ProfessionalExpensesForm>({
|
const form = store.data as ProfessionalExpensesForm
|
||||||
expensesChanged: false,
|
|
||||||
workplaceDescription: '',
|
|
||||||
commuteMethod: null,
|
|
||||||
commuteKm: null,
|
|
||||||
lunchAtHome: false,
|
|
||||||
eatsOut: false,
|
|
||||||
hasCanteenOrVouchers: false
|
|
||||||
})
|
|
||||||
|
|
||||||
const commuteMethodOptions = computed<Array<{ label: string; value: CommuteMethod }>>(() => [
|
const commuteMethodOptions = computed<Array<{ label: string; value: CommuteMethod }>>(() => [
|
||||||
{ label: t('professionalExpenses.commuteMethodOptions.car'), value: 'CAR' },
|
{ label: t('professionalExpenses.commuteMethodOptions.car'), value: 'CAR' },
|
||||||
@@ -137,11 +130,6 @@ const commuteMethodOptions = computed<Array<{ label: string; value: CommuteMetho
|
|||||||
{ label: t('professionalExpenses.commuteMethodOptions.walk'), value: 'WALK' }
|
{ 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 = {
|
/* const professionalExpensesSchema = {
|
||||||
fields: [
|
fields: [
|
||||||
{ key: "expensesChanged", type: "boolean", required: true },
|
{ key: "expensesChanged", type: "boolean", required: true },
|
||||||
@@ -160,10 +148,13 @@ onMounted(async () => {
|
|||||||
formRef.value?.resetValidation?.()
|
formRef.value?.resetValidation?.()
|
||||||
})
|
})
|
||||||
|
|
||||||
// persist when expensesChanged toggles
|
watch(
|
||||||
watch(() => form.expensesChanged, () => {
|
() => form,
|
||||||
//store.setChildren(buildPayload())
|
() => {
|
||||||
})
|
store.persist()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
watch(() => form.eatsOut, (value) => {
|
watch(() => form.eatsOut, (value) => {
|
||||||
if (!value) form.hasCanteenOrVouchers = false
|
if (!value) form.hasCanteenOrVouchers = false
|
||||||
@@ -179,10 +170,12 @@ async function saveAndNext() {
|
|||||||
} catch {
|
} catch {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
store.setProfessionalExpenses(form as ProfessionalExpensesData)
|
||||||
emit('next', props.step?.next)
|
emit('next', props.step?.next)
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitPrev() {
|
function emitPrev() {
|
||||||
|
store.setProfessionalExpenses(form as ProfessionalExpensesData)
|
||||||
emit('prev', props.step?.prev)
|
emit('prev', props.step?.prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
81
app/src/stores/professionalExpenses.ts
Normal file
81
app/src/stores/professionalExpenses.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { LocalStorage } from 'quasar'
|
||||||
|
|
||||||
|
export type CommuteMethod = 'CAR' | 'BUS' | 'BIKE' | 'WALK'
|
||||||
|
|
||||||
|
export interface ProfessionalExpensesData {
|
||||||
|
expensesChanged: boolean
|
||||||
|
workplaceDescription: string
|
||||||
|
commuteMethod: CommuteMethod | null
|
||||||
|
commuteKm: number | null
|
||||||
|
lunchAtHome: boolean
|
||||||
|
eatsOut: boolean
|
||||||
|
hasCanteenOrVouchers: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'professionalExpenses:v1'
|
||||||
|
|
||||||
|
const DEFAULT: ProfessionalExpensesData = {
|
||||||
|
expensesChanged: false,
|
||||||
|
workplaceDescription: '',
|
||||||
|
commuteMethod: null,
|
||||||
|
commuteKm: null,
|
||||||
|
lunchAtHome: false,
|
||||||
|
eatsOut: false,
|
||||||
|
hasCanteenOrVouchers: false
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRecord(v: unknown): v is Record<string, unknown> {
|
||||||
|
return !!v && typeof v === 'object' && !Array.isArray(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useProfessionalExpensesStore = defineStore('professionalexpensesstore', {
|
||||||
|
state: () => {
|
||||||
|
try {
|
||||||
|
let saved: unknown = LocalStorage.getItem(STORAGE_KEY)
|
||||||
|
if (typeof saved === 'string') {
|
||||||
|
try {
|
||||||
|
saved = JSON.parse(saved)
|
||||||
|
} catch {
|
||||||
|
saved = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isRecord(saved)) {
|
||||||
|
const merged = { ...DEFAULT, ...(saved as Partial<ProfessionalExpensesData>) } as ProfessionalExpensesData
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
...merged,
|
||||||
|
hasCanteenOrVouchers: merged.hasCanteenOrVouchers === true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore and fall back to default
|
||||||
|
}
|
||||||
|
return { data: { ...DEFAULT } as ProfessionalExpensesData }
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
persist() {
|
||||||
|
try {
|
||||||
|
LocalStorage.set(STORAGE_KEY, this.data)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('professionalExpenses.store: persist error', err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getProfessionalExpenses() {
|
||||||
|
return this.data
|
||||||
|
},
|
||||||
|
setProfessionalExpenses(partial: Partial<ProfessionalExpensesData>) {
|
||||||
|
this.data = { ...this.data, ...partial }
|
||||||
|
this.persist()
|
||||||
|
},
|
||||||
|
replaceProfessionalExpenses(payload: ProfessionalExpensesData) {
|
||||||
|
this.data = payload
|
||||||
|
this.persist()
|
||||||
|
},
|
||||||
|
resetProfessionalExpenses() {
|
||||||
|
this.data = { ...DEFAULT }
|
||||||
|
this.persist()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user