refactor: AdressItem typing

This commit is contained in:
axolotle 2024-07-05 17:02:53 +02:00
parent f9ddae3237
commit 0414f82d53
3 changed files with 79 additions and 39 deletions

View file

@ -1,35 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
type CustomEmail = { import type {
localPart: string | null AdressItemProps,
separator: string AdressModelValue,
domain: string | null BaseItemComputedProps,
} } from '@/types/form'
const props = withDefaults( withDefaults(
defineProps<{ defineProps<AdressItemProps & BaseItemComputedProps<AdressModelValue>>(),
modelValue: CustomEmail
choices: string[]
placeholder?: string
id?: string
state?: false | null
type?: string
}>(),
{ {
placeholder: undefined,
id: undefined, id: undefined,
state: undefined, name: undefined,
placeholder: undefined,
touchKey: undefined,
type: 'email', type: 'email',
modelValue: undefined,
state: undefined,
validation: undefined,
ariaDescribedby: undefined,
}, },
) )
const emit = defineEmits<{ const emit = defineEmits<{
'update:modelValue': [value: CustomEmail] 'update:modelValue': [value: AdressModelValue]
}>() }>()
function onInput(key: 'localPart' | 'domain', modelValue: string | null) { const model = defineModel<AdressModelValue>({ required: true })
function onInput(key: 'localPart' | 'domain', value: string | null) {
emit('update:modelValue', { emit('update:modelValue', {
...props.modelValue, ...model.value,
[key]: modelValue, [key]: value,
}) })
} }
</script> </script>
@ -37,32 +38,38 @@ function onInput(key: 'localPart' | 'domain', modelValue: string | null) {
<template> <template>
<BInputGroup v-bind="$attrs"> <BInputGroup v-bind="$attrs">
<InputItem <InputItem
:id="id" :id="`${id}-local-part`"
:modelValue="modelValue.localPart"
:placeholder="placeholder" :placeholder="placeholder"
:state="state" touch-key="localPart"
:aria-describedby="id + 'local-part-desc'" :model-value="model.localPart"
@update:modelValue="onInput('localPart', $event)" :aria-describedby="`${id}-local-part-desc`"
:state="validation?.localPart?.$error ? false : null"
:validation="validation?.localPart"
@update:model-value="onInput('localPart', $event as string)"
/> />
<BInputGroupText>{{ modelValue.separator }}</BInputGroupText> <BInputGroupText>{{ modelValue.separator }}</BInputGroupText>
<SelectItem <SelectItem
:modelValue="modelValue.domain" :id="`${id}-domain`"
touch-key="domain"
:model-value="modelValue.domain"
:choices="choices" :choices="choices"
:aria-describedby="id + 'domain-desc'" :aria-describedby="`${id}-domain-desc`"
@update:modelValue="onInput('domain', $event)" :state="validation?.domain?.$error ? false : null"
/> :validation="validation?.domain"
@update:model-value="onInput('domain', $event)"
<span
class="visually-hidden"
:id="id + 'local-part-desc'"
v-t="'address.local_part_description.' + type"
/>
<span
class="visually-hidden"
:id="id + 'domain-desc'"
v-t="'address.domain_description.' + type"
/> />
</BInputGroup> </BInputGroup>
<span
:id="`${id}-local-part-desc`"
v-t="'address.local_part_description.' + type"
class="visually-hidden"
/>
<span
:id="`${id}-domain-desc`"
v-t="'address.domain_description.' + type"
class="visually-hidden"
/>
</template> </template>

View file

@ -0,0 +1,5 @@
import type { InjectionKey } from 'vue'
export const ValidationTouchSymbol = Symbol() as InjectionKey<
(key?: string) => void
>

28
app/src/types/form.ts Normal file
View file

@ -0,0 +1,28 @@
import type { BaseValidation } from '@vuelidate/core'
type StateValidation = false | null
// WRITABLE
type BaseWritableItemProps = {
id?: string
name?: string
placeholder?: string
touchKey?: string
}
export type BaseItemComputedProps<MV extends any = any> = {
ariaDescribedby?: string | string[]
modelValue?: MV
state?: StateValidation
validation?: BaseValidation
}
export type AdressItemProps = BaseWritableItemProps & {
choices: string[]
type?: 'domain' | 'email'
}
export type AdressModelValue = {
localPart: string | null
separator: string
domain: string | null
}