From 3ca4027871c04e96866f2901de0665fe86ae732e Mon Sep 17 00:00:00 2001 From: Darko Gjorgjijoski Date: Sun, 14 Jun 2026 23:42:12 +0200 Subject: [PATCH] fix(documents): repair inline add-item modal on invoice/estimate create Render a single shared ItemModal (was one per row, so stacked dialogs closed each other), validate the modal's own local form (vuelidate did not track the shared store object in the persistent modal), surface save errors, and carry the typed item name into the new-item form. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../components/base/BaseItemSelect.vue | 16 +- .../company/items/components/ItemModal.vue | 189 +++++++++++------- .../scripts/features/company/items/store.ts | 7 +- .../document-form/DocumentItemsTable.vue | 5 + 4 files changed, 134 insertions(+), 83 deletions(-) diff --git a/resources/scripts/components/base/BaseItemSelect.vue b/resources/scripts/components/base/BaseItemSelect.vue index cd2f1d3f..6d6c0bac 100644 --- a/resources/scripts/components/base/BaseItemSelect.vue +++ b/resources/scripts/components/base/BaseItemSelect.vue @@ -5,7 +5,6 @@ import { useUserStore } from '@/scripts/stores/user.store' import { useModalStore } from '@/scripts/stores/modal.store' import { useItemStore } from '@/scripts/features/company/items/store' import { ABILITIES } from '@/scripts/config/abilities' -import ItemModal from '@/scripts/features/company/items/components/ItemModal.vue' import type { Item } from '@/scripts/types/domain' import type { Tax } from '@/scripts/types/domain' @@ -58,6 +57,7 @@ const { t } = useI18n() const itemSelect = ref(null) const multiselectRef = ref<{ close?: () => void } | null>(null) const loading = ref(false) +const searchQuery = ref('') const itemData = reactive({ ...props.item }) async function searchItems(search: string): Promise { @@ -65,6 +65,11 @@ async function searchItems(search: string): Promise { return res.data as unknown as Item[] } +function onSearchChange(val: string): void { + searchQuery.value = val + emit('search', val) +} + const description = computed({ get: () => props.item.description, set: (value: string | null) => { @@ -81,10 +86,9 @@ function openItemModal(): void { title: t('items.add_item'), componentName: 'ItemModal', refreshData: (val: Item) => emit('select', val), + // ItemModal owns its own form; hand it the typed search text to pre-fill the name. data: { - taxPerItem: props.taxPerItem, - taxes: props.taxes, - itemIndex: props.index, + name: searchQuery.value, }, }) }) @@ -100,8 +104,6 @@ function deselectItem(index: number): void {