Compare commits
1 Commits
d8455ccaa3
...
training-r
| Author | SHA1 | Date | |
|---|---|---|---|
| e04cd1a110 |
@@ -80,6 +80,19 @@ function onSubmit(vals) {
|
||||
}
|
||||
}
|
||||
|
||||
function matchesSearch(text: string, search: string) {
|
||||
if (!search) return true
|
||||
|
||||
const tokens = search
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
|
||||
const target = text.toLowerCase()
|
||||
|
||||
return tokens.every(token => target.includes(token))
|
||||
}
|
||||
|
||||
const { remove, push, fields } = useFieldArray('attendees');
|
||||
|
||||
const selectedCourse = computed<Course | undefined>(() => { return trainings.value?.find(c => c.id == values.course_id) })
|
||||
@@ -110,11 +123,24 @@ const memberSearch = ref('')
|
||||
const MAX_RESULTS = 50
|
||||
|
||||
const filteredMembers = computed(() => {
|
||||
const q = memberSearch?.value?.toLowerCase() ?? ""
|
||||
const q = memberSearch.value?.toLowerCase().trim() ?? ""
|
||||
|
||||
if (!q) {
|
||||
return (members.value ?? []).slice(0, MAX_RESULTS)
|
||||
}
|
||||
|
||||
// Split search into words (handles multiple spaces)
|
||||
const tokens = q.split(/\s+/)
|
||||
|
||||
const results: MemberLight[] = []
|
||||
|
||||
for (const m of members.value ?? []) {
|
||||
if (!q || (m.displayName || m.username).toLowerCase().includes(q)) {
|
||||
const name = (m.displayName || m.username).toLowerCase()
|
||||
|
||||
// ALL tokens must be present (order does not matter)
|
||||
const matches = tokens.every(token => name.includes(token))
|
||||
|
||||
if (matches) {
|
||||
results.push(m)
|
||||
if (results.length >= MAX_RESULTS) break
|
||||
}
|
||||
@@ -123,6 +149,17 @@ const filteredMembers = computed(() => {
|
||||
return results
|
||||
})
|
||||
|
||||
const courseSearch = ref('')
|
||||
|
||||
const filteredCourses = computed(() => {
|
||||
if (!trainings.value) return []
|
||||
|
||||
return trainings.value.filter(course =>
|
||||
matchesSearch(course.name, courseSearch.value)
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<form id="trainingForm" @submit.prevent="submitForm" class="flex flex-col gap-5">
|
||||
@@ -139,18 +176,22 @@ const filteredMembers = computed(() => {
|
||||
selectCourse = false
|
||||
}" class="w-full">
|
||||
<ComboboxAnchor class="w-full">
|
||||
<ComboboxInput @focus="selectCourse = true" placeholder="Search courses..."
|
||||
class="w-full pl-3" :display-value="(id) => {
|
||||
<ComboboxInput @focus="selectCourse = true"
|
||||
@input="courseSearch = $event.target.value"
|
||||
placeholder="Search courses..."
|
||||
class="w-full pl-3"
|
||||
:display-value="(id) => {
|
||||
const c = trainings?.find(t => t.id === id)
|
||||
return c ? c.name : '';
|
||||
}" />
|
||||
}"
|
||||
/>
|
||||
</ComboboxAnchor>
|
||||
|
||||
<ComboboxList class="w-full">
|
||||
<ComboboxEmpty class="text-muted-foreground w-full">No results</ComboboxEmpty>
|
||||
<ComboboxGroup>
|
||||
<div class="max-h-80 overflow-y-scroll scrollbar-themed min-w-md">
|
||||
<template v-for="course in trainings" :key="course.id">
|
||||
<template v-for="course in filteredCourses" :key="course.id">
|
||||
<ComboboxItem :value="course.id"
|
||||
class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
|
||||
{{ course.name }}
|
||||
|
||||
Reference in New Issue
Block a user