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 { computed } from 'vue'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import type {
AnyWritableComponents,
FormField,
FormFieldDict,
} from '@/types/form'
export function useStoreGetters() { export function useStoreGetters() {
const store = useStore() const store = useStore()
return Object.fromEntries( 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"> <script setup lang="ts">
import { computed } from 'vue' import { ref } from 'vue'
import { useI18n } from 'vue-i18n' 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 { 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: { locale: {
label: t('tools_webadmin.language'),
component: 'SelectItem', component: 'SelectItem',
props: { id: 'locale', choices: [] }, label: t('tools_webadmin.language'),
props: { id: 'locale', choices: asUnreffed(availableLocales) },
}, },
fallbackLocale: { fallbackLocale: {
component: 'SelectItem',
label: t('tools_webadmin.fallback_language'), label: t('tools_webadmin.fallback_language'),
description: t('tools_webadmin.fallback_language_description'), description: t('tools_webadmin.fallback_language_description'),
component: 'SelectItem', props: { id: 'fallback-locale', choices: asUnreffed(availableLocales) },
props: { id: 'fallback-locale', choices: [] },
}, },
cache: { cache: {
component: 'CheckboxItem',
id: 'cache', id: 'cache',
label: t('tools_webadmin.cache'), label: t('tools_webadmin.cache'),
description: t('tools_webadmin.cache_description'), description: t('tools_webadmin.cache_description'),
component: 'CheckboxItem',
props: { labels: { true: 'enabled', false: 'disabled' } }, props: { labels: { true: 'enabled', false: 'disabled' } },
}, },
transitions: { transitions: {
component: 'CheckboxItem',
id: 'transitions', id: 'transitions',
label: t('tools_webadmin.transitions'), label: t('tools_webadmin.transitions'),
component: 'CheckboxItem',
props: { labels: { true: 'enabled', false: 'disabled' } }, props: { labels: { true: 'enabled', false: 'disabled' } },
}, },
dark: { dark: {
component: 'CheckboxItem',
id: 'theme', id: 'theme',
label: t('tools_webadmin.theme'), label: t('tools_webadmin.theme'),
component: 'CheckboxItem',
props: { labels: { true: '🌙', false: '☀️' } }, props: { labels: { true: '🌙', false: '☀️' } },
}, },
// experimental: added in `created()` experimental: {
} component: 'CheckboxItem',
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 = {
id: 'experimental', id: 'experimental',
label: t('tools_webadmin.experimental'), label: t('tools_webadmin.experimental'),
description: t('tools_webadmin.experimental_description'), description: t('tools_webadmin.experimental_description'),
component: 'CheckboxItem', // Available in dev mode only
visible: import.meta.env.DEV,
props: { labels: { true: 'enabled', false: 'disabled' } }, 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> </script>
<template> <template>
<CardForm :title="$t('tools_webadmin_settings')" icon="cog" no-footer> <CardForm
<template v-for="(field, fname) in fields" :key="fname"> v-model="form"
<FormField v-bind="field" v-model="form[fname]" /> :fields="fields"
<hr /> :title="$t('tools_webadmin_settings')"
</template> icon="cog"
</CardForm> no-footer
hr
/>
</template> </template>