diff --git a/app/src/components/globals/ViewSearch.vue b/app/src/components/globals/ViewSearch.vue
index a52aa1ad..1cebd5a3 100644
--- a/app/src/components/globals/ViewSearch.vue
+++ b/app/src/components/globals/ViewSearch.vue
@@ -1,18 +1,20 @@
-
@@ -45,11 +59,8 @@ const emit = defineEmits<{
@@ -63,22 +74,10 @@ const emit = defineEmits<{
-
+
- {{
- $t(
- items === null ? 'items_verbose_count' : 'search.not_found',
- {
- items: $t('items.' + itemsName, 0),
- },
- 0,
- )
- }}
+ {{ noItemsMessage }}
diff --git a/app/src/composables/useSearch.ts b/app/src/composables/useSearch.ts
new file mode 100644
index 00000000..c701bb36
--- /dev/null
+++ b/app/src/composables/useSearch.ts
@@ -0,0 +1,46 @@
+import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue'
+import { computed, ref, toValue, watch } from 'vue'
+
+import type { AnyTreeNode, TreeRootNode } from '@/helpers/data/tree'
+
+export function useSearch<
+ T extends any[] | TreeRootNode,
+ V extends T extends (infer V)[] ? V : AnyTreeNode,
+>(
+ items: MaybeRefOrGetter | ComputedRef,
+ filterFn: (search: string, item: V, index: number, arr: T) => boolean,
+ {
+ externalSearch,
+ filterIfNoSearch = false,
+ filterAllFn,
+ }: {
+ filterAllFn?: (search: string, items: T) => boolean | undefined
+ filterIfNoSearch?: boolean
+ externalSearch?: MaybeRefOrGetter
+ } = {},
+): [search: Ref, filteredItems: ComputedRef] {
+ const search = ref(toValue(externalSearch) ?? '')
+ watch(
+ () => toValue(externalSearch),
+ (s) => (search.value = s ?? ''),
+ )
+
+ const filteredItems = computed(() => {
+ const items_ = toValue(items)
+ const s = toValue(search.value).toLowerCase()
+ if (!items_) return undefined
+ if (filterAllFn) {
+ const returnAll = filterAllFn(s, items_)
+ if (returnAll !== undefined) {
+ return returnAll ? items_ : undefined
+ }
+ }
+ if (!s && !filterIfNoSearch) return items_
+ const filteredItems_ = items_.filter((...args) =>
+ filterFn(s, ...(args as [V, number, T])),
+ ) as T
+ return filteredItems_.length ? filteredItems_ : null
+ })
+
+ return [search, filteredItems]
+}
diff --git a/app/src/helpers/data/tree.ts b/app/src/helpers/data/tree.ts
index 52e5f4e2..8c503fc0 100644
--- a/app/src/helpers/data/tree.ts
+++ b/app/src/helpers/data/tree.ts
@@ -106,6 +106,10 @@ class TreeNode {
}
})
}
+
+ get length(): number {
+ return this.children.length
+ }
}
export class TreeRootNode extends TreeNode {