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 medium filtering to saved seaches #9412

Merged
merged 39 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
dd9bbb1
feat: create new artwork filter store
MounirDhahri Oct 5, 2023
8330a12
minor: separate filter data type
MounirDhahri Oct 5, 2023
987325e
feat: add filters screen wrapper
MounirDhahri Oct 5, 2023
a15f610
feat: prepare your filters section
MounirDhahri Oct 5, 2023
bd8ea4c
refactor: move screen to savesearches directory
MounirDhahri Oct 5, 2023
efcd1c2
feat: wrap the screen with the new artwork filters store
MounirDhahri Oct 5, 2023
bf3f410
feat: add rarity filter functionality
MounirDhahri Oct 5, 2023
766b98b
chore: improve UX of selecting pills 👌
MounirDhahri Oct 6, 2023
fb02385
chore: add rarity options tests
MounirDhahri Oct 6, 2023
f948d37
chore: minor integrity test improvement
MounirDhahri Oct 6, 2023
50542ae
fix: useDebounce logic in pill
MounirDhahri Oct 6, 2023
555932f
feat: display the applied filters on your filters
MounirDhahri Oct 6, 2023
80217a9
feat: add remove filter action
MounirDhahri Oct 6, 2023
b958bec
chore: add note to make sure to implement clear all
MounirDhahri Oct 6, 2023
1e657fe
feat: add your filters tests
MounirDhahri Oct 6, 2023
7101256
feat: add clear all button
MounirDhahri Oct 6, 2023
df88d10
chore: add subtle animations: bring the screen to life
MounirDhahri Oct 6, 2023
b7b6c5d
fix: revert disabled logic in clear all button
MounirDhahri Oct 6, 2023
2e664bc
chore: remove commented line
MounirDhahri Oct 6, 2023
4db98f6
chore: remove unused fields from store
MounirDhahri Oct 6, 2023
1f8cb9a
refact: use SavedSearchStore for ClearAllButton
MounirDhahri Oct 12, 2023
f6b898c
refactor: update Applied fitlers to use SavedSearchStore
MounirDhahri Oct 12, 2023
ad7cd74
chore: do not allow artistIDs pills removal
MounirDhahri Oct 12, 2023
c03631d
chore: do not count artistIDs for clear all button counts
MounirDhahri Oct 12, 2023
05c067c
refactor: use SavedSearchStoreProvider for rarity
MounirDhahri Oct 12, 2023
3cce67e
refactor: remove new filters store
MounirDhahri Oct 12, 2023
f53e10f
fix: rarity filter test
MounirDhahri Oct 12, 2023
37e040e
chore: address review comments
MounirDhahri Oct 12, 2023
806b9a4
feat: add saved searches categories filter
MounirDhahri Oct 12, 2023
9753ed9
fix: remove console.log
MounirDhahri Oct 12, 2023
730e11b
chore: update tests
MounirDhahri Oct 12, 2023
a8df6ae
chore: make value less case sensitive
MounirDhahri Oct 12, 2023
5dada65
fix: test
MounirDhahri Oct 12, 2023
75cc6a5
chore: fix broken tests due to mismatching mediums
MounirDhahri Oct 13, 2023
338c007
chore: adjust mediums
MounirDhahri Oct 13, 2023
d07c129
chore: update list of mediums
MounirDhahri Oct 13, 2023
0a0134f
fix: broken tests
MounirDhahri Oct 17, 2023
2606035
refactor: move gravity mediums to the same folder as my collection me…
MounirDhahri Oct 17, 2023
e0d9b42
refactor: update test names
MounirDhahri Oct 17, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export const CATEGORIES_OPTIONS: FilterData[] = [
paramValue: "Sculpture",
},
{
displayText: "Print",
displayText: "Prints",
paramName: FilterParamName.categories,
paramValue: "Print",
paramValue: "Prints",
},
{
displayText: "Photography",
Expand Down
44 changes: 22 additions & 22 deletions src/app/Components/ArtworkFilter/SavedSearch/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,45 @@ import { ScreenOwnerType } from "@artsy/cohesion"
import { ArtworkSizes } from "__generated__/SavedSearchNameInputQuery.graphql"

export enum SearchCriteria {
acquireable = "acquireable",
additionalGeneIDs = "additionalGeneIDs",
artistID = "artistID",
artistIDs = "artistIDs",
locationCities = "locationCities",
colors = "colors",
partnerIDs = "partnerIDs",
additionalGeneIDs = "additionalGeneIDs",
attributionClass = "attributionClass",
majorPeriods = "majorPeriods",
acquireable = "acquireable",
atAuction = "atAuction",
inquireableOnly = "inquireableOnly",
offerable = "offerable",
attributionClass = "attributionClass",
colors = "colors",
Comment on lines +10 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

dimensionRange = "dimensionRange",
sizes = "sizes",
height = "height",
width = "width",
inquireableOnly = "inquireableOnly",
locationCities = "locationCities",
majorPeriods = "majorPeriods",
materialsTerms = "materialsTerms",
offerable = "offerable",
partnerIDs = "partnerIDs",
priceRange = "priceRange",
sizes = "sizes",
width = "width",
}

export interface SearchCriteriaAttributes {
[SearchCriteria.acquireable]?: boolean | null
[SearchCriteria.additionalGeneIDs]?: string[] | null
[SearchCriteria.artistID]?: string | null
[SearchCriteria.artistIDs]?: string[] | null
[SearchCriteria.locationCities]?: string[] | null
[SearchCriteria.colors]?: string[] | null
[SearchCriteria.partnerIDs]?: string[] | null
[SearchCriteria.additionalGeneIDs]?: string[] | null
[SearchCriteria.attributionClass]?: string[] | null
[SearchCriteria.majorPeriods]?: string[] | null
[SearchCriteria.acquireable]?: boolean | null
[SearchCriteria.atAuction]?: boolean | null
[SearchCriteria.inquireableOnly]?: boolean | null
[SearchCriteria.offerable]?: boolean | null
[SearchCriteria.attributionClass]?: string[] | null
[SearchCriteria.colors]?: string[] | null
[SearchCriteria.dimensionRange]?: string | null
[SearchCriteria.sizes]?: ArtworkSizes[] | null
[SearchCriteria.height]?: string | null
[SearchCriteria.width]?: string | null
[SearchCriteria.inquireableOnly]?: boolean | null
[SearchCriteria.locationCities]?: string[] | null
[SearchCriteria.majorPeriods]?: string[] | null
[SearchCriteria.materialsTerms]?: string[] | null
[SearchCriteria.offerable]?: boolean | null
[SearchCriteria.partnerIDs]?: string[] | null
[SearchCriteria.priceRange]?: string | null
[SearchCriteria.sizes]?: ArtworkSizes[] | null
[SearchCriteria.width]?: string | null
}

export interface SavedSearchEntityArtist {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { OwnerType } from "@artsy/cohesion"
import { fireEvent, waitFor } from "@testing-library/react-native"
import { SavedSearchFilterAdditionalGeneIDs } from "app/Scenes/SavedSearchAlert/Components/SavedSearchFilterAdditionalGeneIDs"
import {
SavedSearchModel,
SavedSearchStoreProvider,
savedSearchModel,
} from "app/Scenes/SavedSearchAlert/SavedSearchStore"
import { gravityArtworkMediumCategories } from "app/utils/artworkMediumCategories"
import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"

const black100Hex = "#000000"

describe("SavedSearchFilterAdditionalGeneIDs", () => {
it("shows all available categories unselected", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchFilterAdditionalGeneIDs />
</SavedSearchStoreProvider>
)

gravityArtworkMediumCategories.slice(0, 7).forEach((option) => {
expect(getByText(option.label)).toBeDefined()
expect(getByText(option.label)).toHaveStyle({
color: black100Hex,
})
})
})

it("shows the right selected categories", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider
runtimeModel={{ ...initialData, attributes: { additionalGeneIDs: ["painting"] } }}
>
<SavedSearchFilterAdditionalGeneIDs />
</SavedSearchStoreProvider>
)

gravityArtworkMediumCategories.slice(0, 7).forEach((option) => {
if (option.value === "Painting") {
expect(getByText("Painting")).not.toHaveStyle({ color: black100Hex })
} else {
expect(getByText(option.label)).toBeDefined()
expect(getByText(option.label)).toHaveStyle({
color: black100Hex,
})
}
})
})

it("Updates selected categories filters on press", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchFilterAdditionalGeneIDs />
</SavedSearchStoreProvider>
)

expect(getByText("Work on Paper")).toHaveStyle({ color: black100Hex })

fireEvent(getByText("Work on Paper"), "onPress")

waitFor(() => {
expect(getByText("Work on Paper")).not.toHaveStyle({ color: black100Hex })
})
})
})

const initialData: SavedSearchModel = {
...savedSearchModel,
attributes: {
atAuction: true,
},
entity: {
artists: [{ id: "artistID", name: "Banksy" }],
owner: {
type: OwnerType.artist,
id: "ownerId",
slug: "ownerSlug",
},
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Flex, Spacer, Text } from "@artsy/palette-mobile"
import { SearchCriteria } from "app/Components/ArtworkFilter/SavedSearch/types"
import { SavedSearchFilterPill } from "app/Scenes/SavedSearchAlert/Components/SavedSearchFilterPill"
import { SavedSearchStore } from "app/Scenes/SavedSearchAlert/SavedSearchStore"
import { isValueSelected, useSearchCriteriaAttributes } from "app/Scenes/SavedSearchAlert/helpers"
import { gravityArtworkMediumCategories } from "app/utils/artworkMediumCategories"
import { useState } from "react"
import { LayoutAnimation, TouchableOpacity } from "react-native"

export const SavedSearchFilterAdditionalGeneIDs = () => {
const [showAll, setShowAll] = useState(false)

const selectedAttributes = useSearchCriteriaAttributes(
SearchCriteria.additionalGeneIDs
) as string[]

const setValueToAttributesByKeyAction = SavedSearchStore.useStoreActions(
(actions) => actions.setValueToAttributesByKeyAction
)
const removeValueFromAttributesByKeyAction = SavedSearchStore.useStoreActions(
(actions) => actions.removeValueFromAttributesByKeyAction
)

const handlePress = (value: string) => {
const isSelected = isValueSelected({
selectedAttributes,
value: value,
})

if (isSelected) {
removeValueFromAttributesByKeyAction({
key: SearchCriteria.additionalGeneIDs,
value: value,
})
} else {
const newValues = (selectedAttributes || []).concat(value)
setValueToAttributesByKeyAction({
key: SearchCriteria.additionalGeneIDs,
value: newValues,
})
}
}

return (
<Flex px={2}>
<Text variant="sm" fontWeight={500}>
Medium
</Text>
<Spacer y={1} />
<Flex flexDirection="row" flexWrap="wrap">
{gravityArtworkMediumCategories.slice(0, 7).map((option) => {
return (
<SavedSearchFilterPill
key={option.value as string}
accessibilityLabel={option.label}
selected={isValueSelected({
selectedAttributes,
value: option.value,
})}
onPress={() => {
handlePress(option.value as string)
}}
>
{option.label}
</SavedSearchFilterPill>
)
})}

{showAll
? gravityArtworkMediumCategories
.slice(7, gravityArtworkMediumCategories.length)
.map((option) => {
return (
<SavedSearchFilterPill
key={option.value as string}
accessibilityLabel={option.label}
selected={isValueSelected({
selectedAttributes,
value: option.value,
})}
onPress={() => {
handlePress(option.value as string)
}}
>
{option.label}
</SavedSearchFilterPill>
)
})
: null}

<TouchableOpacity
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
setShowAll(!showAll)
}}
>
<Flex height={50} justifyContent="center">
<Text variant="xs" color="blue100">
Show {showAll ? "less" : "more"}
</Text>
</Flex>
</TouchableOpacity>
</Flex>
</Flex>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { OwnerType } from "@artsy/cohesion"
import { fireEvent } from "@testing-library/react-native"
import { SavedSearchAppliedFilters } from "app/Scenes/SavedSearchAlert/Components/SavedSearchFilterAppliedFilters"
import { SavedSearchFilterAppliedFilters } from "app/Scenes/SavedSearchAlert/Components/SavedSearchFilterAppliedFilters"

import {
SavedSearchModel,
Expand All @@ -10,11 +10,11 @@ import {

import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"

describe("SavedSearchAppliedFilters", () => {
describe("SavedSearchFilterAppliedFilters", () => {
it("shows all selected filters", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchAppliedFilters />
<SavedSearchFilterAppliedFilters />
</SavedSearchStoreProvider>
)

Expand All @@ -25,7 +25,7 @@ describe("SavedSearchAppliedFilters", () => {
it("removes filter when tapped", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchAppliedFilters />
<SavedSearchFilterAppliedFilters />
</SavedSearchStoreProvider>
)

Expand All @@ -39,7 +39,7 @@ describe("SavedSearchAppliedFilters", () => {
it("can't remove artist pill", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchAppliedFilters />
<SavedSearchFilterAppliedFilters />
</SavedSearchStoreProvider>
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SavedSearchStore } from "app/Scenes/SavedSearchAlert/SavedSearchStore"
import { useSavedSearchPills } from "app/Scenes/SavedSearchAlert/useSavedSearchPills"
import { MotiView } from "moti"

export const SavedSearchAppliedFilters: React.FC<{}> = ({}) => {
export const SavedSearchFilterAppliedFilters: React.FC<{}> = ({}) => {
const removeValueFromAttributesByKeyAction = SavedSearchStore.useStoreActions(
(state) => state.removeValueFromAttributesByKeyAction
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ export const SavedSearchFilterPill: React.FC<PillProps> = (props) => {
}, [props.selected])

return (
<Pill {...props} mt={1} mr={1} selected={selected} onPress={() => setSelected(!selected)} />
<Pill {...props} mt={1} mr={0.5} selected={selected} onPress={() => setSelected(!selected)} />
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OwnerType } from "@artsy/cohesion"
import { fireEvent, waitFor } from "@testing-library/react-native"
import { ATTRIBUTION_CLASS_OPTIONS } from "app/Components/ArtworkFilter/Filters/AttributionClassOptions"
import { SavedSearchRarity } from "app/Scenes/SavedSearchAlert/Components/SavedSearchFilterRarity"
import { SavedSearchFilterRarity } from "app/Scenes/SavedSearchAlert/Components/SavedSearchFilterRarity"
import {
SavedSearchModel,
SavedSearchStoreProvider,
Expand All @@ -11,11 +11,11 @@ import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"

const black100Hex = "#000000"

describe("SavedSearchRarity", () => {
describe("SavedSearchFilterRarity", () => {
it("shows all available rarity options unselected", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchRarity />
<SavedSearchFilterRarity />
</SavedSearchStoreProvider>
)

Expand All @@ -32,7 +32,7 @@ describe("SavedSearchRarity", () => {
<SavedSearchStoreProvider
runtimeModel={{ ...initialData, attributes: { attributionClass: ["unique"] } }}
>
<SavedSearchRarity />
<SavedSearchFilterRarity />
</SavedSearchStoreProvider>
)

Expand All @@ -45,7 +45,7 @@ describe("SavedSearchRarity", () => {
it("Updates selected filters on press", () => {
const { getByText } = renderWithWrappers(
<SavedSearchStoreProvider runtimeModel={initialData}>
<SavedSearchRarity />
<SavedSearchFilterRarity />
</SavedSearchStoreProvider>
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { SavedSearchFilterPill } from "app/Scenes/SavedSearchAlert/Components/Sa
import { SavedSearchStore } from "app/Scenes/SavedSearchAlert/SavedSearchStore"
import { isValueSelected, useSearchCriteriaAttributes } from "app/Scenes/SavedSearchAlert/helpers"

export const SavedSearchRarity = () => {
export const SavedSearchFilterRarity = () => {
const selectedAttributes = useSearchCriteriaAttributes(
SearchCriteria.attributionClass
) as string[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe("SavedSearchAlertForm", () => {
})

describe("Create flow", () => {
it("calls create mutation when `Save Alert` buttin is pressed", async () => {
it("calls create mutation when `Save Alert` button is pressed", async () => {
const { getByTestId } = renderWithWrappers(<TestRenderer />)

fireEvent.changeText(getByTestId("alert-input-name"), "something new")
Expand Down
Loading