fix: stabilize constructeur selector ui

This commit is contained in:
Matthieu
2025-09-17 16:21:42 +02:00
parent 0a95b90553
commit 8a32ef4bbc
4 changed files with 92 additions and 55 deletions

View File

@@ -20,17 +20,21 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16l4-4 4 4m0-8l-4 4-4-4" />
</svg>
</button>
<ul
<div
v-if="openDropdown"
class="menu bg-base-100 border border-base-200 rounded-box shadow-lg mt-1 w-full max-h-48 overflow-y-auto absolute z-20"
class="absolute z-20 mt-1 w-full max-h-48 overflow-y-auto bg-base-100 border border-base-200 rounded-box shadow-lg flex flex-col"
>
<li v-if="options.length === 0" class="px-3 py-2 text-xs text-gray-500">
<div
v-if="options.length === 0"
class="px-3 py-2 text-xs text-gray-500"
>
Aucun constructeur trouvé
</li>
<li
</div>
<button
v-for="option in options"
:key="option.id"
class="px-3 py-2"
type="button"
class="w-full text-left px-3 py-2 hover:bg-base-200 focus:bg-base-200 focus:outline-none"
@click="selectOption(option)"
>
<div class="flex flex-col">
@@ -39,8 +43,8 @@
{{ [option.email, option.phone].filter(Boolean).join(' • ') || '—' }}
</span>
</div>
</li>
</ul>
</button>
</div>
</div>
<button type="button" class="btn btn-outline btn-sm" @click="openCreateModal = true">
Nouveau
@@ -111,6 +115,23 @@ const openCreateModal = ref(false)
const creating = ref(false)
const options = ref([])
let searchTimeout = null
let lastSearchTerm = ''
const applyOptions = (items = []) => {
const selectedId = props.modelValue
const cloned = [...items]
const limited = cloned.slice(0, 10)
if (selectedId && !limited.some(item => item.id === selectedId)) {
const selected = cloned.find(item => item.id === selectedId)
if (selected) {
if (limited.length >= 10) limited.pop()
limited.unshift(selected)
}
}
options.value = limited
}
const createForm = ref({
name: '',
@@ -140,10 +161,16 @@ watch(
)
const ensureOptionsLoaded = async (force = false) => {
if (!force && !searchTerm.value && constructeurs.value.length) {
applyOptions(constructeurs.value)
return
}
if (!force && searchTerm.value === lastSearchTerm && options.value.length) return
if (options.value.length && !force) return
const result = await searchConstructeurs(searchTerm.value)
if (result.success) {
options.value = result.data
applyOptions(result.data || [])
lastSearchTerm = searchTerm.value
}
}
@@ -151,9 +178,16 @@ const onSearch = () => {
openDropdown.value = true
clearTimeout(searchTimeout)
searchTimeout = setTimeout(async () => {
if (!searchTerm.value && constructeurs.value.length) {
applyOptions(constructeurs.value)
lastSearchTerm = ''
return
}
if (searchTerm.value === lastSearchTerm) return
const result = await searchConstructeurs(searchTerm.value)
if (result.success) {
options.value = result.data
applyOptions(result.data || [])
lastSearchTerm = searchTerm.value
}
}, 250)
}
@@ -184,6 +218,17 @@ const handleCreate = async () => {
}
}
watch(
constructeurs,
(list) => {
applyOptions(list || [])
if (!searchTerm.value) {
lastSearchTerm = ''
}
},
{ immediate: true }
)
const clickHandler = (event) => {
const element = event.target
if (element && element.closest) {
@@ -209,10 +254,3 @@ onBeforeUnmount(() => {
clearTimeout(searchTimeout)
})
</script>
watch(
constructeurs,
(list) => {
options.value = [...list]
},
{ immediate: true }
)