diff --git a/src/components/base/TwoColumnListItemSelectionBase.ts b/src/components/base/TwoColumnListItemSelectionBase.ts index 919a8de4..8caa39d0 100644 --- a/src/components/base/TwoColumnListItemSelectionBase.ts +++ b/src/components/base/TwoColumnListItemSelectionBase.ts @@ -1,4 +1,6 @@ -import { type Ref } from 'vue'; +import { type Ref, ref, computed } from 'vue'; + +import { useI18n } from '@/locales/helpers.ts'; import { getItemByKeyValue, getPrimaryValueBySecondaryValue } from '@/lib/common.ts'; @@ -29,12 +31,94 @@ export interface CommonTwoColumnListItemSelectionProps { secondaryIconType?: string; secondaryColorField?: string; secondaryHiddenField?: string; - items: unknown[]; + enableFilter?: boolean; + filterPlaceholder?: string; + filterNoItemsText?: string; + items: Record[]; } export function useTwoColumnListItemSelectionBase(props: CommonTwoColumnListItemSelectionProps) { + const { ti } = useI18n(); + + const filterContent = ref(''); + + const filteredItems = computed[]>(() => { + const finalItems: Record[] = []; + const items = props.items; + + for (const item of items) { + if (props.primaryHiddenField && item[props.primaryHiddenField]) { + continue; + } + + if (!props.enableFilter || !filterContent.value) { + finalItems.push(item); + continue; + } + + if (props.primaryTitleField) { + const title = ti(item[props.primaryTitleField] as string, !!props.primaryTitleI18n); + + if (title.toLowerCase().indexOf(filterContent.value.toLowerCase()) >= 0) { + finalItems.push(item); + continue; + } + } + + if (props.primarySubItemsField) { + if (getFilteredSubItems(item).length > 0) { + finalItems.push(item); + } + } + } + + return finalItems; + }); + + function getFilteredSubItems(selectedPrimaryItem: unknown): Record[] { + const finalItems: Record[] = []; + + if (!selectedPrimaryItem || !props.primarySubItemsField) { + return finalItems; + } + + const subItems = (selectedPrimaryItem as Record)[props.primarySubItemsField] as Record[]; + let primaryTitleHasFilterContent = false; + + if (props.primaryTitleField) { + const title = ti((selectedPrimaryItem as Record)[props.primaryTitleField] as string, !!props.primaryTitleI18n); + primaryTitleHasFilterContent = title.toLowerCase().indexOf(filterContent.value.toLowerCase()) >= 0; + } + + for (const subItem of subItems) { + if (props.secondaryHiddenField && subItem[props.secondaryHiddenField]) { + continue; + } + + if (!props.enableFilter || !filterContent.value) { + finalItems.push(subItem); + continue; + } + + if (primaryTitleHasFilterContent) { + finalItems.push(subItem); + continue; + } + + if (props.secondaryTitleField && filterContent.value) { + const title = ti(subItem[props.secondaryTitleField] as string, !!props.secondaryTitleI18n); + + if (title.toLowerCase().indexOf(filterContent.value.toLowerCase()) >= 0) { + finalItems.push(subItem); + } + } + } + + return finalItems; + } + function getCurrentPrimaryValueBySecondaryValue(secondaryValue: unknown): unknown { - return getPrimaryValueBySecondaryValue(props.items as Record[]>[] | Record[]>>, props.primarySubItemsField, props.primaryValueField, props.primaryHiddenField, props.secondaryValueField, props.secondaryHiddenField, secondaryValue); + return getPrimaryValueBySecondaryValue(props.items as Record[]>[], props.primarySubItemsField, props.primaryValueField, props.primaryHiddenField, props.secondaryValueField, props.secondaryHiddenField, secondaryValue); } function isSecondaryValueSelected(currentSecondaryValue: unknown, subItem: unknown): boolean { @@ -45,17 +129,17 @@ export function useTwoColumnListItemSelectionBase(props: CommonTwoColumnListItem } } - function getSelectedPrimaryItem(currentPrimaryValue: unknown) { + function getSelectedPrimaryItem(currentPrimaryValue: unknown): unknown { if (props.primaryValueField) { - return getItemByKeyValue(props.items as Record[] | Record>, currentPrimaryValue, props.primaryValueField); + return getItemByKeyValue(props.items, currentPrimaryValue, props.primaryValueField); } else { return currentPrimaryValue; } } - function getSelectedSecondaryItem(currentSecondaryValue: unknown, selectedPrimaryItem: unknown) { + function getSelectedSecondaryItem(currentSecondaryValue: unknown, selectedPrimaryItem: unknown): unknown { if (currentSecondaryValue && selectedPrimaryItem && (selectedPrimaryItem as Record)[props.primarySubItemsField]) { - return getItemByKeyValue((selectedPrimaryItem as Record)[props.primarySubItemsField] as Record[] | Record>, currentSecondaryValue, props.secondaryValueField as string); + return getItemByKeyValue((selectedPrimaryItem as Record)[props.primarySubItemsField] as Record[], currentSecondaryValue, props.secondaryValueField as string); } else { return null; } @@ -78,7 +162,12 @@ export function useTwoColumnListItemSelectionBase(props: CommonTwoColumnListItem } return { + // states + filterContent, + // computed states + filteredItems, // functions + getFilteredSubItems, getCurrentPrimaryValueBySecondaryValue, isSecondaryValueSelected, getSelectedPrimaryItem, diff --git a/src/components/desktop/TwoColumnSelect.vue b/src/components/desktop/TwoColumnSelect.vue index 2e41c981..75e5b41e 100644 --- a/src/components/desktop/TwoColumnSelect.vue +++ b/src/components/desktop/TwoColumnSelect.vue @@ -14,11 +14,11 @@