diff --git a/ui/src/components/trainingReport/trainingReportForm.vue b/ui/src/components/trainingReport/trainingReportForm.vue index b68aeb0..e35a2c8 100644 --- a/ui/src/components/trainingReport/trainingReportForm.vue +++ b/ui/src/components/trainingReport/trainingReportForm.vue @@ -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(() => { 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) + ) +}) + +