to_inventory/front/components/edit.vue

169 lines
6.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { object, string, type InferType } from 'yup'
import { apiBase } from '~/helpers';
import type { ApiTypeList, ApiTypeExternal } from '~/helpers';
import type { FormSubmitEvent } from '#ui/types'
const props = defineProps(['elements', 'partner'])
const route = useRoute()
const headers = new Headers();
headers.append("Content-Type", "application/json");
type ExternalDataType = {
partner?: ApiTypeExternal[],
categories?: ApiTypeExternal[][],
element?: ApiTypeExternal[],
}
type StateDataType = {
partner?: string
categories?: string[]
inventory?: string
element?: string
element_id?: string
}
const loading = ref(false)
const state = reactive<StateDataType>({
partner: undefined,
categories: [],
inventory: route.params.inv_id as string || undefined,
element: undefined,
element_id: undefined
})
const external_data = reactive<ExternalDataType>({
partner: [],
categories: [],
element: [],
})
const elements = ref(props.elements)
const schema = object({
element: string().required('Required'),
element_id: string().required('Required')
})
type Schema = InferType<typeof schema>
async function onSubmit(event: FormSubmitEvent<Schema>) {
const prepader_data = event.data
prepader_data.partner_name = external_data.partner.find(el => el.Ref_Key == state.partner)?.Description
if(!prepader_data.partner_name) prepader_data.partner_name = prepader_data.partner
const data = await $fetch(`${apiBase}/element/`, { method: 'POST', body: JSON.stringify(prepader_data) })
const inv_id = route.params.inv_id || data.inventory?.id
if (!route.params.inv_id) {
navigateTo(`/organization/p_${data.partner.id}/i_${data.inventory.id}`)
} else {
const newElements = await $fetch<ApiTypeList>(`${apiBase}/element?inventory_id=${inv_id}`, { headers })
elements.value = newElements.results
}
}
const searchInExternal = (q: string) => {
if (!q.length) {
return external_data.partner?.splice(0, 10)
}
return external_data.partner?.filter(el => {
return el.Description.toLowerCase().indexOf(q.toLowerCase()) !== -1
}).slice(0, 10)
}
const loadPartners = async () => {
loading.value = true
const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/partner/external/`)
if (data) {
external_data.partner = data
if (props.partner) {
state.partner = props.partner
}
}
loading.value = false
}
const loadCategories = async () => {
loading.value = true
const lastCat = state.categories?.at(-1) || ''
const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/element/external_categories/${lastCat}`)
if (data.length) {
external_data.categories?.push(data)
} else {
await loadElements()
}
loading.value = false
}
const loadElements = async () => {
loading.value = true
const lastCat = state.categories?.at(-1) || ''
const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/element/external/${lastCat}`)
if (data) {
external_data.element = data
}
loading.value = false
}
const loadDeepCategories = async (i: number) => {
if ((i + 1) <= (state.categories as string[]).length) {
state.categories = state.categories?.slice(0, i + 1)
external_data.categories = external_data.categories?.slice(0, i + 1)
state.element = undefined
external_data.element = []
}
loadCategories()
}
onMounted(async () => {
await loadPartners()
await loadCategories()
})
</script>
<template>
<div class="grid grid-cols-10 gap-4">
<div class="col-span-3">
<UForm :state="state" class="flex flex-col gap-4" @submit="onSubmit">
<UFormGroup label="Выбрать организацию" name="organization">
<USelectMenu v-model="state.partner" :options="external_data.partner" value-attribute="Ref_Key"
option-attribute="Description" :searchable="searchInExternal"
searchable-placeholder="Выберите организацию из списка контрагентов" :loading="loading"
:disabled="!!props.partner" />
</UFormGroup>
<UFormGroup label="Добавить элемент инвентаризации" v-if="state.partner">
<template v-for="(item, i) in external_data.categories">
<USelectMenu v-model="(state.categories as string[])[i]" :options="item"
value-attribute="Ref_Key" option-attribute="Description" :searchable="true"
:loading="loading" :placeholder="`Категории (${item.length})`"
@change="loadDeepCategories(i)" />
</template>
<USelectMenu v-if="external_data.element?.length" v-model="state.element"
:options="external_data.element" value-attribute="Ref_Key" option-attribute="Description"
:searchable="true" :loading="loading"
:placeholder="`Элементы (${external_data.element.length})`" />
</UFormGroup>
<UFormGroup v-if="state.element"
:label="`Данные об элементе «${external_data.element?.find(el => el['Ref_Key'] === state.element)?.Description}»`">
<UInput placeholder="ID" v-model="state.element_id" />
</UFormGroup>
<UButton type="submit" :disabled="!state.element_id">
Сохранить
</UButton>
</UForm>
</div>
<div class="col-span-7">
<h2>{{ external_data.partner?.find(el => el["Ref_Key"] == state.partner)?.Description }}</h2>
<dl v-if="elements?.length">
<template v-for="item in elements">
<dt>
{{ item.external_id }}
</dt>
<dt>
{{ item.element_id }}
</dt>
</template>
</dl>
</div>
</div>
</template>
<style scoped>
label {
word-wrap: break-word;
}
</style>