refactor: use useForm + rework mapStoreGetSet of ToolWebadmin

This commit is contained in:
axolotle 2024-07-11 15:23:39 +02:00
parent 0262aaaefb
commit 317bf7fbb6
2 changed files with 87 additions and 51 deletions

View file

@ -1,6 +1,13 @@
import type { WritableComputedRef } from 'vue'
import { computed } from 'vue'
import { useStore } from 'vuex'
import type {
AnyWritableComponents,
FormField,
FormFieldDict,
} from '@/types/form'
export function useStoreGetters() {
const store = useStore()
return Object.fromEntries(
@ -10,3 +17,41 @@ export function useStoreGetters() {
]),
)
}
/**
* Dynamicly generate computed properties from store with get/set and automatic commit/dispatch
*/
export function useMapStoreGetSet<FFD extends FormFieldDict>({
commit = [],
dispatch = [],
}: {
commit: Extract<keyof FFD, string>[]
dispatch: Extract<keyof FFD, string>[]
}) {
const store = useStore()
type Types = {
[k in keyof FFD]: FFD[k] extends
| FormField<AnyWritableComponents, infer MV>
| undefined
? MV
: any
}
return [...commit, ...dispatch].reduce(
(obj, prop) => {
obj[prop] = computed<Types[typeof prop]>({
get() {
return store.getters[prop]
},
set(value) {
const isCommit = commit.includes(prop)
const key = (isCommit ? 'SET_' : 'UPDATE_') + prop.toUpperCase()
store[isCommit ? 'commit' : 'dispatch'](key, value)
},
})
return obj
},
{} as { [k in keyof FFD]: WritableComputedRef<any> },
) as {
[k in keyof FFD]: WritableComputedRef<Types[k]>
}
}

View file

@ -1,93 +1,84 @@
<script setup lang="ts">
import { computed } from 'vue'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'
import { asUnreffed } from '@/helpers/commons'
import { useMapStoreGetSet, useStoreGetters } from '@/store/utils'
import type { FormField } from '@/types/form'
const { t } = useI18n()
const store = useStore()
const { availableLocales } = useStoreGetters()
const fields = {
const form = ref({
...useMapStoreGetSet<Fields>({
commit: ['cache', 'transitions', 'experimental'],
dispatch: ['locale', 'fallbackLocale', 'dark'],
}),
})
type Fields = {
locale: FormField<'SelectItem', string>
fallbackLocale: FormField<'SelectItem', string>
cache: FormField<'CheckboxItem', boolean>
transitions: FormField<'CheckboxItem', boolean>
dark: FormField<'CheckboxItem', boolean>
experimental: FormField<'CheckboxItem', boolean>
}
const fields: Fields = {
locale: {
label: t('tools_webadmin.language'),
component: 'SelectItem',
props: { id: 'locale', choices: [] },
label: t('tools_webadmin.language'),
props: { id: 'locale', choices: asUnreffed(availableLocales) },
},
fallbackLocale: {
component: 'SelectItem',
label: t('tools_webadmin.fallback_language'),
description: t('tools_webadmin.fallback_language_description'),
component: 'SelectItem',
props: { id: 'fallback-locale', choices: [] },
props: { id: 'fallback-locale', choices: asUnreffed(availableLocales) },
},
cache: {
component: 'CheckboxItem',
id: 'cache',
label: t('tools_webadmin.cache'),
description: t('tools_webadmin.cache_description'),
component: 'CheckboxItem',
props: { labels: { true: 'enabled', false: 'disabled' } },
},
transitions: {
component: 'CheckboxItem',
id: 'transitions',
label: t('tools_webadmin.transitions'),
component: 'CheckboxItem',
props: { labels: { true: 'enabled', false: 'disabled' } },
},
dark: {
component: 'CheckboxItem',
id: 'theme',
label: t('tools_webadmin.theme'),
component: 'CheckboxItem',
props: { labels: { true: '🌙', false: '☀️' } },
},
// experimental: added in `created()`
}
const form = {
...mapStoreGetSet(['locale', 'fallbackLocale', 'dark'], 'dispatch'),
...mapStoreGetSet(['cache', 'transitions', 'experimental']),
}
const availableLocales = store.getters.availableLocales
fields.locale.props.choices = availableLocales
fields.fallbackLocale.props.choices = availableLocales
if (import.meta.env.DEV) {
fields.experimental = {
experimental: {
component: 'CheckboxItem',
id: 'experimental',
label: t('tools_webadmin.experimental'),
description: t('tools_webadmin.experimental_description'),
component: 'CheckboxItem',
// Available in dev mode only
visible: import.meta.env.DEV,
props: { labels: { true: 'enabled', false: 'disabled' } },
}
}
// FIXME move into helpers ?
// Dynamicly generate computed properties from store with get/set and automatic commit/dispatch
function mapStoreGetSet(props = [], action = 'commit') {
return props.reduce((obj, prop) => {
obj[prop] = computed({
get() {
return store.getters[prop]
},
set(value) {
const key =
(action === 'commit' ? 'SET_' : 'UPDATE_') + prop.toUpperCase()
store[action](key, value)
},
})
return obj
}, {})
},
}
</script>
<template>
<CardForm :title="$t('tools_webadmin_settings')" icon="cog" no-footer>
<template v-for="(field, fname) in fields" :key="fname">
<FormField v-bind="field" v-model="form[fname]" />
<hr />
</template>
</CardForm>
<CardForm
v-model="form"
:fields="fields"
:title="$t('tools_webadmin_settings')"
icon="cog"
no-footer
hr
/>
</template>