to_inventory/front/components/edit.vue

201 lines
8.0 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 { apiBase } from '~/helpers';
import type { ApiTypeList, ApiTypeExternal, ApiElementSave } from '~/helpers';
import type { FormError, 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
element_additional_data?: 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,
element_additional_data: undefined
})
const external_data = reactive<ExternalDataType>({
partner: [],
categories: [],
element: [],
})
const show_error = ref()
const elements = ref(props.elements)
const validate = (state: any): FormError[] => {
const errors = []
const txt = 'Это поле обязательно'
if (!state.partner) errors.push({ path: 'partner', message: txt })
if (!external_data || !external_data.partner || !external_data.partner.find(el => el.Ref_Key == state.partner)) {
errors.push({ path: 'partner', message: txt })
}
if (!state.element_id) errors.push({ path: 'element_id', message: txt })
// if (!state.element_additional_data) errors.push({ path: 'element_additional_data', message: txt })
return errors
}
async function onSubmit(event: FormSubmitEvent<any>) {
show_error.value = undefined
const prepader_data = event.data
if (!external_data || !external_data.partner) {
return false
}
prepader_data.partner_name = external_data.partner.find(el => el.Ref_Key == state.partner)?.Description
const data = await $fetch<ApiElementSave>(`${apiBase}/element/`, {
method: 'POST', body: JSON.stringify(prepader_data), onResponseError: (error) => {
if (error.response.status == 500) {
show_error.value = Object.entries(error.response._data).map(el => `${el[0]}: ${el[1]}`).join('\n')
}
}
})
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
external_data.element = []
external_data.categories = []
state.categories = []
state.element = undefined
state.element_id = undefined
state.element_additional_data = undefined
}
}
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-7">
<UForm :state="state" :validate="validate" class="flex flex-col gap-4" @submit="onSubmit">
<UFormGroup label="Выбрать организацию" name="partner">
<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" :help="!external_data.element?.length ? `Последовательно
выбирайте категорию. Если все выбрали, а элементов нет -
значит в этой категории нет элементов`: ''">
<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>
<div v-if="state.element">
<h4>Данные об элементе «{{ external_data.element?.find(el => el['Ref_Key'] ===
state.element)?.Description }}»</h4>
<UFormGroup label="ID" name="element_id">
<UInput placeholder="ID" v-model="state.element_id" />
</UFormGroup>
<UFormGroup label="Дополнительные сведения" name="element_additional_data">
<UTextarea placeholder="Дополнительные сведения" v-model="state.element_additional_data" />
</UFormGroup>
</div>
<UButton type="submit" :disabled="!state.element_id">
Сохранить
</UButton>
</UForm>
</div>
<div class="col-span-3 flex flex-col gap-4">
<h2>{{ external_data.partner?.find(el => el["Ref_Key"] == state.partner)?.Description }}</h2>
<UAlert v-if="show_error" title="Server error" :description="show_error" color="primary" />
<dl v-if="elements?.length">
<template v-for="item in elements">
<dt>
<Element :id="item.external_id" />
</dt>
<dd>{{ item.element_id }}</dd>
<dd>{{ item.additional_text }}</dd>
</template>
</dl>
</div>
</div>
</template>
<style scoped>
label {
word-wrap: break-word;
}
</style>