Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add framed works filter to artwork screens #11435

Merged
merged 1 commit into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 104 additions & 62 deletions data/schema.graphql

Large diffs are not rendered by default.

25 changes: 15 additions & 10 deletions src/app/Components/ArtworkFilter/ArtworkFilterHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import {
} from "lodash"

export enum FilterDisplayName {
// artist = "Artists",
additionalGeneIDs = "Medium",
artistIDs = "Artists",
artistNationalities = "Nationality & Ethnicity",
artistsIFollow = "Artist",
artistSeriesIDs = "Artist Series",
artistsIFollow = "Artist",
attributionClass = "Rarity",
availability = "Availability",
categories = "Medium",
colors = "Color",
estimateRange = "Price/Estimate Range",
framed = "Frame",
locationCities = "Artwork Location",
materialsTerms = "Material",
medium = "Medium",
Expand All @@ -44,14 +44,15 @@ export enum FilterParamName {
allowEmptyCreatedDates = "allowEmptyCreatedDates",
artistIDs = "artistIDs",
artistNationalities = "artistNationalities",
artistsIFollow = "includeArtworksByFollowedArtists",
artistSeriesIDs = "artistSeriesIDs",
artistsIFollow = "includeArtworksByFollowedArtists",
attributionClass = "attributionClass",
categories = "categories",
colors = "colors",
earliestCreatedYear = "earliestCreatedYear",
estimateRange = "estimateRange",
forSale = "forSale",
framed = "framed",
height = "height",
keyword = "keyword",
latestCreatedYear = "latestCreatedYear",
Expand Down Expand Up @@ -80,34 +81,35 @@ export type FilterParams = {
}

export const QueryParamsToFilterValueMapping: Record<string, FilterParamName> = {
acquireable: FilterParamName.waysToBuyPurchase,
additional_gene_ids: FilterParamName.additionalGeneIDs,
artist_ids: FilterParamName.artistIDs,
artist_nationalities: FilterParamName.artistNationalities,
artist_series_ids: FilterParamName.artistSeriesIDs,
include_artworks_by_followed_artists: FilterParamName.artistsIFollow,
at_auction: FilterParamName.waysToBuyBid,
attribution_class: FilterParamName.attributionClass,
colors: FilterParamName.colors,
earliest_created_year: FilterParamName.earliestCreatedYear,
estimate_range: FilterParamName.estimateRange,
for_sale: FilterParamName.forSale,
framed: FilterParamName.framed,
height: FilterParamName.height,
include_artworks_by_followed_artists: FilterParamName.artistsIFollow,
inquireable_only: FilterParamName.waysToBuyContactGallery,
keyword: FilterParamName.keyword,
latest_created_year: FilterParamName.latestCreatedYear,
location_cities: FilterParamName.locationCities,
major_periods: FilterParamName.timePeriod,
materials_terms: FilterParamName.materialsTerms,
medium: FilterParamName.medium,
offerable: FilterParamName.waysToBuyMakeOffer,
organizations: FilterParamName.organizations,
partner_ids: FilterParamName.partnerIDs,
price_range: FilterParamName.priceRange,
show_only_submitted_artworks: FilterParamName.showOnlySubmittedArtworks,
sizes: FilterParamName.sizes,
sort: FilterParamName.sort,
state: FilterParamName.state,
major_periods: FilterParamName.timePeriod,
at_auction: FilterParamName.waysToBuyBid,
inquireable_only: FilterParamName.waysToBuyContactGallery,
offerable: FilterParamName.waysToBuyMakeOffer,
acquireable: FilterParamName.waysToBuyPurchase,
width: FilterParamName.width,
}

Expand Down Expand Up @@ -144,6 +146,7 @@ export const ParamDefaultValues = {
earliestCreatedYear: undefined,
estimateRange: "",
forSale: undefined,
framed: undefined,
height: "*-*",
includeArtworksByFollowedArtists: false,
inquireableOnly: false,
Expand All @@ -159,9 +162,9 @@ export const ParamDefaultValues = {
priceRange: "*-*",
showOnlySubmittedArtworks: false,
sizes: [],
state: "All",
sortArtworks: "-decayed_merch",
sortSaleArtworks: "position",
state: "All",
viewAs: ViewAsValues.Grid,
width: "*-*",
}
Expand All @@ -180,6 +183,7 @@ export const defaultCommonFilterOptions = {
earliestCreatedYear: ParamDefaultValues.earliestCreatedYear,
estimateRange: ParamDefaultValues.estimateRange,
forSale: ParamDefaultValues.forSale,
framed: ParamDefaultValues.framed,
height: ParamDefaultValues.height,
includeArtworksByFollowedArtists: ParamDefaultValues.includeArtworksByFollowedArtists,
inquireableOnly: ParamDefaultValues.inquireableOnly,
Expand Down Expand Up @@ -492,6 +496,7 @@ export const prepareFilterArtworksParamsForInput = (filters: FilterParams) => {
"extraAggregationGeneIDs",
"first",
"forSale",
"framed",
"geneID",
"geneIDs",
"height",
Expand Down
5 changes: 4 additions & 1 deletion src/app/Components/ArtworkFilter/ArtworkFilterNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { AvailabilityOptionsScreen } from "app/Components/ArtworkFilter/Filters/
import { CategoriesOptionsScreen } from "app/Components/ArtworkFilter/Filters/CategoriesOptions"
import { ColorsOptionsScreen } from "app/Components/ArtworkFilter/Filters/ColorsOptions"
import { EstimateRangeOptionsScreen } from "app/Components/ArtworkFilter/Filters/EstimateRangeOptions"
import { FramedOptionsScreen } from "app/Components/ArtworkFilter/Filters/FramedOptions"
import { GalleriesAndInstitutionsOptionsScreen } from "app/Components/ArtworkFilter/Filters/GalleriesAndInstitutionsOptions"
import { MaterialsTermsOptionsScreen } from "app/Components/ArtworkFilter/Filters/MaterialsTermsOptions"
import { MediumOptionsScreen } from "app/Components/ArtworkFilter/Filters/MediumOptions"
Expand Down Expand Up @@ -89,9 +90,10 @@ export type ArtworkFilterNavigationStack = {
ColorsOptionsScreen: undefined
EstimateRangeOptionsScreen: undefined
FilterOptionsScreen: ArtworkFilterOptionsScreenParams
FramedOptionsScreen: undefined
GalleriesAndInstitutionsOptionsScreen: undefined
MaterialsTermsOptionsScreen: undefined
LocationCitiesOptionsScreen: undefined
MaterialsTermsOptionsScreen: undefined
MediumOptionsScreen: undefined
PriceRangeOptionsScreen: undefined
SizesOptionsScreen: undefined
Expand Down Expand Up @@ -342,6 +344,7 @@ export const ArtworkFilterNavigator: React.FC<ArtworkFilterProps> = (props) => {
name="EstimateRangeOptionsScreen"
component={EstimateRangeOptionsScreen}
/>
<Stack.Screen name="FramedOptionsScreen" component={FramedOptionsScreen} />
<Stack.Screen
name="GalleriesAndInstitutionsOptionsScreen"
component={GalleriesAndInstitutionsOptionsScreen}
Expand Down
21 changes: 20 additions & 1 deletion src/app/Components/ArtworkFilter/ArtworkFilterOptionsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export const ArtworkFilterOptionsScreen: React.FC<
> = ({ navigation, route }) => {
const enableArtistSeriesFilter = useFeatureFlag("AREnableArtistSeriesFilter")
const enableAvailabilityFilter = useFeatureFlag("AREnableAvailabilityFilter")
const enableFramedFilter = useFeatureFlag("AREnableFramedFilter")

const tracking = useTracking()
const { closeModal, id, mode, slug, title = "Sort & Filter" } = route.params

Expand Down Expand Up @@ -106,7 +108,8 @@ export const ArtworkFilterOptionsScreen: React.FC<
.filter(
(filterOption) =>
(enableArtistSeriesFilter || filterOption.filterType !== "artistSeriesIDs") &&
(enableAvailabilityFilter || filterOption.filterType !== "availability")
(enableAvailabilityFilter || filterOption.filterType !== "availability") &&
(enableFramedFilter || filterOption.filterType !== "framed")
)

const clearAllFilters = () => {
Expand Down Expand Up @@ -197,6 +200,7 @@ export const getStaticFilterOptionsByMode = (
switch (mode) {
case FilterModalMode.SaleArtworks:
return [
filterOptionToDisplayConfigMap.framed,
filterOptionToDisplayConfigMap.estimateRange,
filterOptionToDisplayConfigMap.sort,
filterOptionToDisplayConfigMap.viewAs,
Expand All @@ -216,6 +220,7 @@ export const getStaticFilterOptionsByMode = (

default:
return [
filterOptionToDisplayConfigMap.framed,
filterOptionToDisplayConfigMap.attributionClass,
filterOptionToDisplayConfigMap.availability,
filterOptionToDisplayConfigMap.sort,
Expand Down Expand Up @@ -414,6 +419,11 @@ export const filterOptionToDisplayConfigMap: Record<string, FilterDisplayConfig>
filterType: "estimateRange",
ScreenComponent: "EstimateRangeOptionsScreen",
},
framed: {
displayText: FilterDisplayName.framed,
filterType: "framed",
ScreenComponent: "FramedOptionsScreen",
},
availability: {
displayText: FilterDisplayName.availability,
filterType: "availability",
Expand Down Expand Up @@ -496,6 +506,7 @@ const CollectionFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"artistNationalities",
Expand All @@ -513,6 +524,7 @@ const ArtistArtworksFiltersSorted: FilterScreen[] = [
"artistSeriesIDs",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"locationCities",
Expand All @@ -528,6 +540,7 @@ const ArtistSeriesFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"locationCities",
Expand All @@ -543,6 +556,7 @@ const ArtworksFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"artistNationalities",
Expand All @@ -559,6 +573,7 @@ const FairFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"artistNationalities",
Expand All @@ -573,6 +588,7 @@ const SaleArtworksFiltersSorted: FilterScreen[] = [
"medium",
"additionalGeneIDs",
"estimateRange",
"framed",
]

const ShowFiltersSorted: FilterScreen[] = [
Expand All @@ -583,6 +599,7 @@ const ShowFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"artistNationalities",
Expand All @@ -598,6 +615,7 @@ const PartnerFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"artistNationalities",
Expand All @@ -613,6 +631,7 @@ const TagAndGeneFiltersSorted: FilterScreen[] = [
"priceRange",
"sizes",
"waysToBuy",
"framed",
"availability",
"materialsTerms",
"artistNationalities",
Expand Down
97 changes: 97 additions & 0 deletions src/app/Components/ArtworkFilter/Filters/FramedOptions.tests.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { fireEvent, screen } from "@testing-library/react-native"
import { FilterParamName } from "app/Components/ArtworkFilter/ArtworkFilterHelpers"
import {
ArtworkFiltersState,
ArtworkFiltersStoreProvider,
getArtworkFiltersModel,
} from "app/Components/ArtworkFilter/ArtworkFilterStore"
import { MockFilterScreen } from "app/Components/ArtworkFilter/FilterTestHelper"
import { FramedOptionsScreen } from "app/Components/ArtworkFilter/Filters/FramedOptions.tsx"
import { __globalStoreTestUtils__ } from "app/store/GlobalStore"
import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"
import { getEssentialProps } from "./helper"

describe(FramedOptionsScreen, () => {
beforeEach(() => {
__globalStoreTestUtils__?.injectFeatureFlags({ AREnableFramedFilter: true })
})

const initialState: ArtworkFiltersState = {
aggregations: [],
appliedFilters: [],
applyFilters: false,
counts: {
total: null,
followedArtists: null,
},
showFilterArtworksModal: false,
sizeMetric: "cm",
filterType: "artwork",
previouslyAppliedFilters: [],
selectedFilters: [],
}

const MockFramedOptionsScreen = ({
initialData = initialState,
}: {
initialData?: ArtworkFiltersState
}) => {
return (
<ArtworkFiltersStoreProvider
runtimeModel={{
...getArtworkFiltersModel(),
...initialData,
}}
>
<FramedOptionsScreen {...getEssentialProps()} />
</ArtworkFiltersStoreProvider>
)
}

describe("no filters are selected", () => {
it("renders all options", () => {
renderWithWrappers(<MockFramedOptionsScreen initialData={initialState} />)

expect(screen.getByText("Show only framed works")).toBeTruthy()
})
})

describe("a filter is selected", () => {
const state: ArtworkFiltersState = {
...initialState,
selectedFilters: [
{
displayText: "Show only framed works",
paramName: FilterParamName.framed,
paramValue: true,
},
],
}

it("displays the number of the selected filters on the filter modal screen", () => {
renderWithWrappers(<MockFilterScreen initialState={state} />)

expect(screen.getByText("Frame • 1")).toBeTruthy()
})

it("toggles selected filters 'ON' and unselected filters 'OFF", async () => {
renderWithWrappers(<MockFramedOptionsScreen initialData={state} />)

const options = screen.getAllByTestId("multi-select-option-button")
const checkboxes = screen.getAllByTestId("multi-select-option-checkbox")

expect(options).toHaveLength(1)
expect(options[0]).toHaveTextContent("Show only framed works")

expect(checkboxes[0]).toHaveProp("selected", true)

fireEvent.press(options[0])

expect(checkboxes[0]).toHaveProp("selected", false)

fireEvent.press(options[0])

expect(checkboxes[0]).toHaveProp("selected", true)
})
})
})
Loading