Merge pull request #2933 from rommapp/none-filter-support

Add NONE support for filter logic operators
This commit is contained in:
Georges-Antoine Assi
2026-01-23 08:35:36 -05:00
committed by GitHub
7 changed files with 148 additions and 97 deletions

View File

@@ -351,55 +351,55 @@ def get_roms(
genres_logic: Annotated[
str,
Query(
description="Logic operator for genres filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for genres filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
franchises_logic: Annotated[
str,
Query(
description="Logic operator for franchises filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for franchises filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
collections_logic: Annotated[
str,
Query(
description="Logic operator for collections filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for collections filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
companies_logic: Annotated[
str,
Query(
description="Logic operator for companies filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for companies filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
age_ratings_logic: Annotated[
str,
Query(
description="Logic operator for age ratings filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for age ratings filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
regions_logic: Annotated[
str,
Query(
description="Logic operator for regions filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for regions filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
languages_logic: Annotated[
str,
Query(
description="Logic operator for languages filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for languages filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
statuses_logic: Annotated[
str,
Query(
description="Logic operator for statuses filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for statuses filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
player_counts_logic: Annotated[
str,
Query(
description="Logic operator for player counts filter: 'any' (OR) or 'all' (AND).",
description="Logic operator for player counts filter: 'any' (OR), 'all' (AND) or 'none' (NOT).",
),
] = "any",
order_by: Annotated[

View File

@@ -372,9 +372,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(RomMetadata.genres, values, session=session))
condition = op(RomMetadata.genres, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_franchises(
self,
@@ -383,9 +385,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(RomMetadata.franchises, values, session=session))
condition = op(RomMetadata.franchises, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_collections(
self,
@@ -394,9 +398,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(RomMetadata.collections, values, session=session))
condition = op(RomMetadata.collections, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_companies(
self,
@@ -405,9 +411,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(RomMetadata.companies, values, session=session))
condition = op(RomMetadata.companies, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_age_ratings(
self,
@@ -416,9 +424,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(RomMetadata.age_ratings, values, session=session))
condition = op(RomMetadata.age_ratings, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_status(self, query: Query, statuses: Sequence[str]):
"""Filter by one or more user statuses using OR logic."""
@@ -449,9 +459,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(Rom.regions, values, session=session))
condition = op(Rom.regions, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_languages(
self,
@@ -460,9 +472,11 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
op = json_array_contains_all if match_all else json_array_contains_any
return query.filter(op(Rom.languages, values, session=session))
condition = op(Rom.languages, values, session=session)
return query.filter(~condition) if match_none else query.filter(condition)
def _filter_by_player_counts(
self,
@@ -471,8 +485,12 @@ class DBRomsHandler(DBBaseHandler):
session: Session,
values: Sequence[str],
match_all: bool = False,
match_none: bool = False,
) -> Query:
return query.filter(RomMetadata.player_count.in_(values))
condition = RomMetadata.player_count.in_(values)
if match_none:
return query.filter(not_(condition))
return query.filter(condition)
@begin_session
def filter_roms(
@@ -695,7 +713,11 @@ class DBRomsHandler(DBBaseHandler):
for values, logic, filter_func in filters_to_apply:
if values:
query = filter_func(
query, session=session, values=values, match_all=(logic == "all")
query,
session=session,
values=values,
match_all=(logic == "all"),
match_none=(logic == "none"),
)
# The RomUser table is already joined if user_id is set

View File

@@ -15,7 +15,9 @@ import FilterPlatformBtn from "@/components/Gallery/AppBar/common/FilterDrawer/F
import FilterPlayablesBtn from "@/components/Gallery/AppBar/common/FilterDrawer/FilterPlayablesBtn.vue";
import FilterRaBtn from "@/components/Gallery/AppBar/common/FilterDrawer/FilterRaBtn.vue";
import FilterVerifiedBtn from "@/components/Gallery/AppBar/common/FilterDrawer/FilterVerifiedBtn.vue";
import storeGalleryFilter from "@/stores/galleryFilter";
import storeGalleryFilter, {
type FilterLogicOperator,
} from "@/stores/galleryFilter";
import storePlatforms from "@/stores/platforms";
import storeRoms from "@/stores/roms";
import type { Events } from "@/types/emitter";
@@ -112,49 +114,49 @@ const onFilterChange = debounce(
: null,
genres:
selectedGenres.value.length > 0 ? selectedGenres.value.join(",") : null,
genresLogic: selectedGenres.value.length > 1 ? genresLogic.value : null,
genresLogic: selectedGenres.value.length > 0 ? genresLogic.value : null,
franchises:
selectedFranchises.value.length > 0
? selectedFranchises.value.join(",")
: null,
franchisesLogic:
selectedFranchises.value.length > 1 ? franchisesLogic.value : null,
selectedFranchises.value.length > 0 ? franchisesLogic.value : null,
collections:
selectedCollections.value.length > 0
? selectedCollections.value.join(",")
: null,
collectionsLogic:
selectedCollections.value.length > 1 ? collectionsLogic.value : null,
selectedCollections.value.length > 0 ? collectionsLogic.value : null,
companies:
selectedCompanies.value.length > 0
? selectedCompanies.value.join(",")
: null,
companiesLogic:
selectedCompanies.value.length > 1 ? companiesLogic.value : null,
selectedCompanies.value.length > 0 ? companiesLogic.value : null,
ageRatings:
selectedAgeRatings.value.length > 0
? selectedAgeRatings.value.join(",")
: null,
ageRatingsLogic:
selectedAgeRatings.value.length > 1 ? ageRatingsLogic.value : null,
selectedAgeRatings.value.length > 0 ? ageRatingsLogic.value : null,
regions:
selectedRegions.value.length > 0
? selectedRegions.value.join(",")
: null,
regionsLogic:
selectedRegions.value.length > 1 ? regionsLogic.value : null,
selectedRegions.value.length > 0 ? regionsLogic.value : null,
languages:
selectedLanguages.value.length > 0
? selectedLanguages.value.join(",")
: null,
languagesLogic:
selectedLanguages.value.length > 1 ? languagesLogic.value : null,
selectedLanguages.value.length > 0 ? languagesLogic.value : null,
statuses:
selectedStatuses.value.length > 0
? selectedStatuses.value.join(",")
: null,
statusesLogic:
selectedStatuses.value.length > 1 ? statusesLogic.value : null,
selectedStatuses.value.length > 0 ? statusesLogic.value : null,
playerCounts:
selectedPlayerCounts.value.length > 0
? selectedPlayerCounts.value.join(",")
@@ -184,7 +186,7 @@ const filters = [
selected: selectedGenres,
items: filterGenres,
logic: genresLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setGenresLogic(logic),
},
{
@@ -192,7 +194,7 @@ const filters = [
selected: selectedFranchises,
items: filterFranchises,
logic: franchisesLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setFranchisesLogic(logic),
},
{
@@ -200,7 +202,7 @@ const filters = [
selected: selectedCollections,
items: filterCollections,
logic: collectionsLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setCollectionsLogic(logic),
},
{
@@ -208,7 +210,7 @@ const filters = [
selected: selectedCompanies,
items: filterCompanies,
logic: companiesLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setCompaniesLogic(logic),
},
{
@@ -216,7 +218,7 @@ const filters = [
selected: selectedAgeRatings,
items: filterAgeRatings,
logic: ageRatingsLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setAgeRatingsLogic(logic),
},
{
@@ -224,7 +226,7 @@ const filters = [
selected: selectedRegions,
items: filterRegions,
logic: regionsLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setRegionsLogic(logic),
},
{
@@ -232,7 +234,7 @@ const filters = [
selected: selectedLanguages,
items: filterLanguages,
logic: languagesLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setLanguagesLogic(logic),
},
{
@@ -240,7 +242,7 @@ const filters = [
selected: selectedPlayerCounts,
items: filterPlayerCounts,
logic: playerCountsLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setPlayerCountsLogic(logic),
},
{
@@ -248,7 +250,7 @@ const filters = [
selected: selectedStatuses,
items: filterStatuses,
logic: statusesLogic,
setLogic: (logic: "any" | "all") =>
setLogic: (logic: FilterLogicOperator) =>
galleryFilterStore.setStatusesLogic(logic),
},
];
@@ -377,7 +379,7 @@ onMounted(async () => {
const genres = (urlGenres as string).split(",").filter((g) => g.trim());
galleryFilterStore.setSelectedFilterGenres(genres);
if (urlGenresLogic !== undefined) {
galleryFilterStore.setGenresLogic(urlGenresLogic as "any" | "all");
galleryFilterStore.setGenresLogic(urlGenresLogic as FilterLogicOperator);
}
}
@@ -388,7 +390,7 @@ onMounted(async () => {
galleryFilterStore.setSelectedFilterFranchises(franchises);
if (urlFranchisesLogic !== undefined) {
galleryFilterStore.setFranchisesLogic(
urlFranchisesLogic as "any" | "all",
urlFranchisesLogic as FilterLogicOperator,
);
}
}
@@ -400,7 +402,7 @@ onMounted(async () => {
galleryFilterStore.setSelectedFilterCollections(collections);
if (urlCollectionsLogic !== undefined) {
galleryFilterStore.setCollectionsLogic(
urlCollectionsLogic as "any" | "all",
urlCollectionsLogic as FilterLogicOperator,
);
}
}
@@ -411,7 +413,9 @@ onMounted(async () => {
.filter((c) => c.trim());
galleryFilterStore.setSelectedFilterCompanies(companies);
if (urlCompaniesLogic !== undefined) {
galleryFilterStore.setCompaniesLogic(urlCompaniesLogic as "any" | "all");
galleryFilterStore.setCompaniesLogic(
urlCompaniesLogic as FilterLogicOperator,
);
}
}
@@ -422,7 +426,7 @@ onMounted(async () => {
galleryFilterStore.setSelectedFilterAgeRatings(ageRatings);
if (urlAgeRatingsLogic !== undefined) {
galleryFilterStore.setAgeRatingsLogic(
urlAgeRatingsLogic as "any" | "all",
urlAgeRatingsLogic as FilterLogicOperator,
);
}
}
@@ -431,7 +435,9 @@ onMounted(async () => {
const regions = (urlRegions as string).split(",").filter((r) => r.trim());
galleryFilterStore.setSelectedFilterRegions(regions);
if (urlRegionsLogic !== undefined) {
galleryFilterStore.setRegionsLogic(urlRegionsLogic as "any" | "all");
galleryFilterStore.setRegionsLogic(
urlRegionsLogic as FilterLogicOperator,
);
}
}
@@ -441,7 +447,9 @@ onMounted(async () => {
.filter((l) => l.trim());
galleryFilterStore.setSelectedFilterLanguages(languages);
if (urlLanguagesLogic !== undefined) {
galleryFilterStore.setLanguagesLogic(urlLanguagesLogic as "any" | "all");
galleryFilterStore.setLanguagesLogic(
urlLanguagesLogic as FilterLogicOperator,
);
}
}
@@ -449,7 +457,9 @@ onMounted(async () => {
const statuses = (urlStatuses as string).split(",").filter((s) => s.trim());
galleryFilterStore.setSelectedFilterStatuses(statuses);
if (urlStatusesLogic !== undefined) {
galleryFilterStore.setStatusesLogic(urlStatusesLogic as "any" | "all");
galleryFilterStore.setStatusesLogic(
urlStatusesLogic as FilterLogicOperator,
);
}
}
@@ -460,7 +470,7 @@ onMounted(async () => {
galleryFilterStore.setSelectedFilterPlayerCounts(playerCounts);
if (urlPlayerCountsLogic !== undefined) {
galleryFilterStore.setPlayerCountsLogic(
urlPlayerCountsLogic as "any" | "all",
urlPlayerCountsLogic as FilterLogicOperator,
);
}
}
@@ -568,7 +578,7 @@ onMounted(async () => {
>
<template #activator="{ props }">
<v-btn value="any" size="small" v-bind="props">
<v-icon size="x-large">mdi-set-none</v-icon>
<v-icon size="x-large">mdi-set-all</v-icon>
</v-btn>
</template>
</v-tooltip>
@@ -579,7 +589,18 @@ onMounted(async () => {
>
<template #activator="{ props }">
<v-btn value="all" size="small" v-bind="props">
<v-icon size="x-large">mdi-set-all</v-icon>
<v-icon size="x-large">mdi-set-center</v-icon>
</v-btn>
</template>
</v-tooltip>
<v-tooltip
:text="t('platform.match-none-logic')"
location="bottom"
open-delay="500"
>
<template #activator="{ props }">
<v-btn value="none" size="small" v-bind="props">
<v-icon size="x-large">mdi-set-none</v-icon>
</v-btn>
</template>
</v-tooltip>

View File

@@ -11,12 +11,14 @@ import { ROUTES } from "@/plugins/router";
import collectionApi from "@/services/api/collection";
import storeCollections from "@/stores/collections";
import storeGalleryFilter from "@/stores/galleryFilter";
import storeRoms from "@/stores/roms";
import type { Events } from "@/types/emitter";
import { getStatusKeyForText } from "@/utils";
const { t } = useI18n();
const galleryFilterStore = storeGalleryFilter();
const collectionsStore = storeCollections();
const romsStore = storeRoms();
const { mdAndUp } = useDisplay();
const router = useRouter();
const show = ref(false);
@@ -24,6 +26,7 @@ const name = ref("");
const description = ref("");
const isPublic = ref(false);
const { currentPlatform } = storeToRefs(romsStore);
const {
searchTerm,
filterMatched,
@@ -70,10 +73,13 @@ const filterSummary = computed(() => {
const filters = [];
if (searchTerm.value) filters.push(`Search: "${searchTerm.value}"`);
if (selectedPlatforms.value && selectedPlatforms.value.length > 0)
if (selectedPlatforms.value && selectedPlatforms.value.length > 0) {
filters.push(
`Platforms: ${selectedPlatforms.value.map((p) => p.name).join(", ")}`,
`Platforms: ${selectedPlatforms.value.map((p) => p.display_name).join(", ")}`,
);
} else if (currentPlatform.value) {
filters.push(`Platform: ${currentPlatform.value.display_name}`);
}
if (filterMatched.value) filters.push("Matched only");
if (filterFavorites.value) filters.push("Favorites");
if (filterDuplicates.value) filters.push("Duplicates");
@@ -125,14 +131,14 @@ async function createSmartCollection() {
emitter?.emit("showLoadingDialog", { loading: true, scrim: true });
try {
const filterCriteria: Record<
string,
number | boolean | string | string[] | number[] | (string | null)[] | null
> = {};
const filterCriteria: Record<string, any> = {};
if (searchTerm.value) filterCriteria.search_term = searchTerm.value;
if (selectedPlatforms.value && selectedPlatforms.value.length > 0)
if (selectedPlatforms.value && selectedPlatforms.value.length > 0) {
filterCriteria.platform_ids = selectedPlatforms.value.map((p) => p.id);
} else if (currentPlatform.value) {
filterCriteria.platform_ids = [currentPlatform.value.id];
}
if (filterMatched.value) filterCriteria.matched = true;
if (filterFavorites.value) filterCriteria.favorite = true;
if (filterDuplicates.value) filterCriteria.duplicate = true;
@@ -142,27 +148,27 @@ async function createSmartCollection() {
if (filterVerified.value) filterCriteria.verified = true;
if (selectedGenres.value && selectedGenres.value.length > 0) {
filterCriteria.genres = selectedGenres.value;
if (selectedGenres.value.length > 1)
if (selectedGenres.value.length > 0)
filterCriteria.genres_logic = genresLogic.value;
}
if (selectedFranchises.value && selectedFranchises.value.length > 0) {
filterCriteria.franchises = selectedFranchises.value;
if (selectedFranchises.value.length > 1)
if (selectedFranchises.value.length > 0)
filterCriteria.franchises_logic = franchisesLogic.value;
}
if (selectedCollections.value && selectedCollections.value.length > 0) {
filterCriteria.collections = selectedCollections.value;
if (selectedCollections.value.length > 1)
if (selectedCollections.value.length > 0)
filterCriteria.collections_logic = collectionsLogic.value;
}
if (selectedCompanies.value && selectedCompanies.value.length > 0) {
filterCriteria.companies = selectedCompanies.value;
if (selectedCompanies.value.length > 1)
if (selectedCompanies.value.length > 0)
filterCriteria.companies_logic = companiesLogic.value;
}
if (selectedAgeRatings.value && selectedAgeRatings.value.length > 0) {
filterCriteria.age_ratings = selectedAgeRatings.value;
if (selectedAgeRatings.value.length > 1)
if (selectedAgeRatings.value.length > 0)
filterCriteria.age_ratings_logic = ageRatingsLogic.value;
}
if (selectedStatuses.value && selectedStatuses.value.length > 0) {
@@ -176,12 +182,12 @@ async function createSmartCollection() {
}
if (selectedRegions.value && selectedRegions.value.length > 0) {
filterCriteria.regions = selectedRegions.value;
if (selectedRegions.value.length > 1)
if (selectedRegions.value.length > 0)
filterCriteria.regions_logic = regionsLogic.value;
}
if (selectedLanguages.value && selectedLanguages.value.length > 0) {
filterCriteria.languages = selectedLanguages.value;
if (selectedLanguages.value.length > 1)
if (selectedLanguages.value.length > 0)
filterCriteria.languages_logic = languagesLogic.value;
}

View File

@@ -188,39 +188,39 @@ async function getRoms({
: undefined,
// Logic operators
genres_logic:
selectedGenres && selectedGenres.length > 1
selectedGenres && selectedGenres.length > 0
? genresLogic || "any"
: undefined,
franchises_logic:
selectedFranchises && selectedFranchises.length > 1
selectedFranchises && selectedFranchises.length > 0
? franchisesLogic || "any"
: undefined,
collections_logic:
selectedCollections && selectedCollections.length > 1
selectedCollections && selectedCollections.length > 0
? collectionsLogic || "any"
: undefined,
companies_logic:
selectedCompanies && selectedCompanies.length > 1
selectedCompanies && selectedCompanies.length > 0
? companiesLogic || "any"
: undefined,
age_ratings_logic:
selectedAgeRatings && selectedAgeRatings.length > 1
selectedAgeRatings && selectedAgeRatings.length > 0
? ageRatingsLogic || "any"
: undefined,
regions_logic:
selectedRegions && selectedRegions.length > 1
selectedRegions && selectedRegions.length > 0
? regionsLogic || "any"
: undefined,
languages_logic:
selectedLanguages && selectedLanguages.length > 1
selectedLanguages && selectedLanguages.length > 0
? languagesLogic || "any"
: undefined,
statuses_logic:
selectedStatuses && selectedStatuses.length > 1
selectedStatuses && selectedStatuses.length > 0
? statusesLogic || "any"
: undefined,
player_counts_logic:
selectedPlayerCounts && selectedPlayerCounts.length > 1
selectedPlayerCounts && selectedPlayerCounts.length > 0
? playerCountsLogic || "any"
: undefined,
...(filterMatched !== null ? { matched: filterMatched } : {}),

View File

@@ -80,39 +80,39 @@ class CachedApiService {
: undefined,
// Logic operators
genres_logic:
params.selectedGenres && params.selectedGenres.length > 1
params.selectedGenres && params.selectedGenres.length > 0
? params.genresLogic || "any"
: undefined,
franchises_logic:
params.selectedFranchises && params.selectedFranchises.length > 1
params.selectedFranchises && params.selectedFranchises.length > 0
? params.franchisesLogic || "any"
: undefined,
collections_logic:
params.selectedCollections && params.selectedCollections.length > 1
params.selectedCollections && params.selectedCollections.length > 0
? params.collectionsLogic || "any"
: undefined,
companies_logic:
params.selectedCompanies && params.selectedCompanies.length > 1
params.selectedCompanies && params.selectedCompanies.length > 0
? params.companiesLogic || "any"
: undefined,
age_ratings_logic:
params.selectedAgeRatings && params.selectedAgeRatings.length > 1
params.selectedAgeRatings && params.selectedAgeRatings.length > 0
? params.ageRatingsLogic || "any"
: undefined,
regions_logic:
params.selectedRegions && params.selectedRegions.length > 1
params.selectedRegions && params.selectedRegions.length > 0
? params.regionsLogic || "any"
: undefined,
languages_logic:
params.selectedLanguages && params.selectedLanguages.length > 1
params.selectedLanguages && params.selectedLanguages.length > 0
? params.languagesLogic || "any"
: undefined,
statuses_logic:
params.selectedStatuses && params.selectedStatuses.length > 1
params.selectedStatuses && params.selectedStatuses.length > 0
? params.statusesLogic || "any"
: undefined,
player_counts_logic:
params.selectedPlayerCounts && params.selectedPlayerCounts.length > 1
params.selectedPlayerCounts && params.selectedPlayerCounts.length > 0
? params.playerCountsLogic || "any"
: undefined,
...(params.filterMatched !== null

View File

@@ -15,6 +15,8 @@ export type FilterType =
| "language"
| "playerCount";
export type FilterLogicOperator = "any" | "all" | "none";
const defaultFilterState = {
activeFilterDrawer: false,
searchTerm: null as string | null,
@@ -47,15 +49,15 @@ const defaultFilterState = {
selectedPlayerCounts: [] as string[],
selectedStatuses: [] as string[],
// Logic operators for multi-select filters
genresLogic: "any" as "any" | "all",
franchisesLogic: "any" as "any" | "all",
collectionsLogic: "any" as "any" | "all",
companiesLogic: "any" as "any" | "all",
ageRatingsLogic: "any" as "any" | "all",
regionsLogic: "any" as "any" | "all",
languagesLogic: "any" as "any" | "all",
statusesLogic: "any" as "any" | "all",
playerCountsLogic: "any" as "any" | "all",
genresLogic: "any" as FilterLogicOperator,
franchisesLogic: "any" as FilterLogicOperator,
collectionsLogic: "any" as FilterLogicOperator,
companiesLogic: "any" as FilterLogicOperator,
ageRatingsLogic: "any" as FilterLogicOperator,
regionsLogic: "any" as FilterLogicOperator,
languagesLogic: "any" as FilterLogicOperator,
statusesLogic: "any" as FilterLogicOperator,
playerCountsLogic: "any" as FilterLogicOperator,
};
export default defineStore("galleryFilter", {
@@ -105,55 +107,55 @@ export default defineStore("galleryFilter", {
setSelectedFilterGenres(genres: string[]) {
this.selectedGenres = genres;
},
setGenresLogic(logic: "any" | "all") {
setGenresLogic(logic: FilterLogicOperator) {
this.genresLogic = logic;
},
setSelectedFilterFranchises(franchises: string[]) {
this.selectedFranchises = franchises;
},
setFranchisesLogic(logic: "any" | "all") {
setFranchisesLogic(logic: FilterLogicOperator) {
this.franchisesLogic = logic;
},
setSelectedFilterCollections(collections: string[]) {
this.selectedCollections = collections;
},
setCollectionsLogic(logic: "any" | "all") {
setCollectionsLogic(logic: FilterLogicOperator) {
this.collectionsLogic = logic;
},
setSelectedFilterCompanies(companies: string[]) {
this.selectedCompanies = companies;
},
setCompaniesLogic(logic: "any" | "all") {
setCompaniesLogic(logic: FilterLogicOperator) {
this.companiesLogic = logic;
},
setSelectedFilterAgeRatings(ageRatings: string[]) {
this.selectedAgeRatings = ageRatings;
},
setAgeRatingsLogic(logic: "any" | "all") {
setAgeRatingsLogic(logic: FilterLogicOperator) {
this.ageRatingsLogic = logic;
},
setSelectedFilterRegions(regions: string[]) {
this.selectedRegions = regions;
},
setRegionsLogic(logic: "any" | "all") {
setRegionsLogic(logic: FilterLogicOperator) {
this.regionsLogic = logic;
},
setSelectedFilterLanguages(languages: string[]) {
this.selectedLanguages = languages;
},
setLanguagesLogic(logic: "any" | "all") {
setLanguagesLogic(logic: FilterLogicOperator) {
this.languagesLogic = logic;
},
setSelectedFilterPlayerCounts(playerCounts: string[]) {
this.selectedPlayerCounts = playerCounts;
},
setPlayerCountsLogic(logic: "any" | "all") {
setPlayerCountsLogic(logic: FilterLogicOperator) {
this.playerCountsLogic = logic;
},
setSelectedFilterStatuses(statuses: string[]) {
this.selectedStatuses = statuses;
},
setStatusesLogic(logic: "any" | "all") {
setStatusesLogic(logic: FilterLogicOperator) {
this.statusesLogic = logic;
},
setFilterMatched(value: boolean | null) {