Compare commits

..

2 Commits

Author SHA1 Message Date
fabio
3a3e1a90c7 selexione del server 2026-02-19 10:37:43 +01:00
fabio
e752807ede aggiunto lo store ProfessionalExpenses 2026-02-19 10:29:31 +01:00
4 changed files with 101 additions and 22 deletions

View File

@@ -53,7 +53,11 @@ export default defineConfig((ctx) => {
// publicPath: '/', // publicPath: '/',
// analyze: true, // analyze: true,
// env: {}, env: {
DEFAULT_API_BASE_URL: ctx.dev
? 'http://localhost:8082/'
: 'http://bruno.fantasticpartner.com/api/',
},
// rawDefine: {} // rawDefine: {}
// ignorePublicFolder: true, // ignorePublicFolder: true,
// minify: false, // minify: false,

View File

@@ -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)
} }

View 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()
}
}
})

View File

@@ -1,6 +1,7 @@
export type ApiBaseUrl = string export type ApiBaseUrl = string
export const DEFAULT_API_BASE_URL: ApiBaseUrl = 'http://bruno.fantasticpartner.com/api/' export const DEFAULT_API_BASE_URL: ApiBaseUrl =
(process.env.DEFAULT_API_BASE_URL) || 'http://bruno.fantasticpartner.com/api/'
export type UploadDocumentParams = { export type UploadDocumentParams = {
user: string user: string