Skip to content

Commit 45ce478

Browse files
author
Isaac Solo
authored
Add merged search / explore page (#12016)
1 parent 6fbce9f commit 45ce478

File tree

6 files changed

+312
-4
lines changed

6 files changed

+312
-4
lines changed

packages/common/src/services/remote-config/feature-flags.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export enum FeatureFlags {
2929
RECENT_COMMENTS = 'recent_comments',
3030
DOWNLOAD_ALL_TRACK_FILES = 'download_all_track_files',
3131
REMIX_CONTEST = 'remix_contest',
32-
WALLET_UI_UPDATE = 'wallet_ui_update'
32+
WALLET_UI_UPDATE = 'wallet_ui_update',
33+
SEARCH_EXPLORE = 'search_explore'
3334
}
3435

3536
type FlagDefaults = Record<FeatureFlags, boolean>
@@ -74,5 +75,6 @@ export const flagDefaults: FlagDefaults = {
7475
[FeatureFlags.RECENT_COMMENTS]: false,
7576
[FeatureFlags.DOWNLOAD_ALL_TRACK_FILES]: false,
7677
[FeatureFlags.REMIX_CONTEST]: false,
77-
[FeatureFlags.WALLET_UI_UPDATE]: false
78+
[FeatureFlags.WALLET_UI_UPDATE]: false,
79+
[FeatureFlags.SEARCH_EXPLORE]: false
7880
}
108 KB
Loading
582 KB
Loading

packages/web/src/pages/explore-page/ExplorePage.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import { FeatureFlags } from '@audius/common/services'
2+
13
import { useIsMobile } from 'hooks/useIsMobile'
4+
import { useFlag } from 'hooks/useRemoteConfig'
25
import { createSeoDescription } from 'utils/seo'
36

47
import DesktopExplorePage from './components/desktop/ExplorePage'
8+
import NewDesktopExplorePage from './components/desktop/NewExplorePage'
59
import MobileExplorePage from './components/mobile/ExplorePage'
610

711
const messages = {
@@ -12,12 +16,21 @@ const messages = {
1216

1317
export const ExplorePage = () => {
1418
const isMobile = useIsMobile()
19+
20+
const { isEnabled: isSearchExploreEnabled } = useFlag(
21+
FeatureFlags.SEARCH_EXPLORE
22+
)
23+
1524
const props = {
1625
title: messages.title,
1726
pageTitle: messages.pageTitle,
1827
description: messages.description
1928
}
2029

21-
const Component = isMobile ? MobileExplorePage : DesktopExplorePage
30+
const Component = isMobile
31+
? MobileExplorePage
32+
: isSearchExploreEnabled
33+
? NewDesktopExplorePage
34+
: DesktopExplorePage
2235
return <Component {...props} />
2336
}

packages/web/src/pages/explore-page/collections.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { route } from '@audius/common/utils'
55
import {
66
IconTurntable as IconExploreTopAlbums,
77
IconPlaylists as IconExploreTopPlaylists,
8-
IconCart
8+
IconCart,
9+
IconRemix
910
} from '@audius/harmony'
1011

1112
import IconCassette from 'assets/img/iconCassette.svg'
@@ -51,6 +52,17 @@ export const PREMIUM_TRACKS: ExploreCollection = {
5152
cardSensitivity: WIDE_CARD_SENSITIVTY
5253
}
5354

55+
export const DOWNLOADS_AVAILABLE: ExploreCollection = {
56+
variant: ExploreCollectionsVariant.DIRECT_LINK,
57+
title: 'Downloads Available',
58+
subtitle: 'Popular tracks with downloads you can use in your own tracks.',
59+
gradient: 'linear-gradient(138deg, #FF00F5 -5.01%, #00D1FF 110.47%)',
60+
shadow: 'rgba(9, 175, 233, 0.35)',
61+
icon: IconRemix,
62+
link: EXPLORE_PREMIUM_TRACKS_PAGE, // TODO make a downloads page
63+
cardSensitivity: WIDE_CARD_SENSITIVTY
64+
}
65+
5466
export const LET_THEM_DJ: ExploreCollection = {
5567
variant: ExploreCollectionsVariant.LET_THEM_DJ,
5668
title: 'Let Them DJ',
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import { useCallback } from 'react'
2+
3+
import { useFeaturedPlaylists, useFeaturedProfiles } from '@audius/common/api'
4+
import { User } from '@audius/common/models'
5+
import { TQCollection } from '@audius/common/src/api/tan-query/models'
6+
import { ExploreCollectionsVariant } from '@audius/common/store'
7+
import {
8+
Paper,
9+
Text,
10+
Flex,
11+
IconNote,
12+
IconAlbum,
13+
IconPlaylists,
14+
TextInput,
15+
TextInputSize,
16+
IconSearch,
17+
IconUser,
18+
TextLink
19+
} from '@audius/harmony'
20+
import { useNavigate } from 'react-router-dom-v5-compat'
21+
22+
import BackgroundWaves from 'assets/img/publicSite/imageSearchHeaderBackground@2x.webp'
23+
import { CollectionCard } from 'components/collection'
24+
import PerspectiveCard, {
25+
TextInterior
26+
} from 'components/perspective-card/PerspectiveCard'
27+
import { UserCard } from 'components/user-card'
28+
import { useIsUSDCEnabled } from 'hooks/useIsUSDCEnabled'
29+
import useTabs from 'hooks/useTabs/useTabs'
30+
import {
31+
PREMIUM_TRACKS,
32+
TRENDING_PLAYLISTS,
33+
TRENDING_UNDERGROUND,
34+
DOWNLOADS_AVAILABLE
35+
} from 'pages/explore-page/collections'
36+
// import { categories } from 'pages/search-page/categories'
37+
// import { useSearchCategory } from 'pages/search-page/hooks'
38+
import { BASE_URL, stripBaseUrl } from 'utils/route'
39+
40+
export type ExplorePageProps = {
41+
title: string
42+
pageTitle: string
43+
description: string
44+
}
45+
export enum SavedPageTabs {
46+
ALL = 'All',
47+
PROFILES = 'Profiles',
48+
TRACKS = 'Tracks',
49+
ALBUMS = 'Albums',
50+
PLAYLISTS = 'Playlists'
51+
}
52+
53+
const messages = {
54+
explore: 'Explore',
55+
description: 'Discover the hottest and trendiest tracks on Audius right now',
56+
searchPlaceholder: 'What do you want to listen to?',
57+
featuredPlaylists: 'Featured Playlists',
58+
remixContests: 'Remix Contests',
59+
artistSpotlight: 'Artist Spotlight',
60+
bestOfAudius: 'Best of Audius',
61+
viewAll: 'View All'
62+
}
63+
64+
const tabHeaders = [
65+
{
66+
icon: <IconSearch />,
67+
text: SavedPageTabs.ALL,
68+
label: SavedPageTabs.ALL
69+
},
70+
{
71+
icon: <IconUser />,
72+
text: SavedPageTabs.PROFILES,
73+
label: SavedPageTabs.PROFILES
74+
},
75+
{
76+
icon: <IconNote />,
77+
text: SavedPageTabs.TRACKS,
78+
label: SavedPageTabs.TRACKS
79+
},
80+
{
81+
icon: <IconAlbum />,
82+
text: SavedPageTabs.ALBUMS,
83+
label: SavedPageTabs.ALBUMS
84+
},
85+
{
86+
icon: <IconPlaylists />,
87+
text: SavedPageTabs.PLAYLISTS,
88+
label: SavedPageTabs.PLAYLISTS
89+
}
90+
]
91+
92+
export const justForYou = [
93+
TRENDING_PLAYLISTS,
94+
TRENDING_UNDERGROUND,
95+
DOWNLOADS_AVAILABLE,
96+
PREMIUM_TRACKS
97+
]
98+
99+
const FEATURED_LIMIT = 5
100+
101+
const ExplorePage = ({ title, pageTitle, description }: ExplorePageProps) => {
102+
const { tabs } = useTabs({
103+
isMobile: false,
104+
tabs: tabHeaders,
105+
elements: tabHeaders.map((tab) => <Flex key={tab.label}>{tab.text}</Flex>)
106+
})
107+
const isUSDCPurchasesEnabled = useIsUSDCEnabled()
108+
const navigate = useNavigate()
109+
const { data: featuredPlaylists } = useFeaturedPlaylists(
110+
{ limit: FEATURED_LIMIT },
111+
{ placeholderData: (prev: TQCollection[]) => prev }
112+
)
113+
const { data: featuredProfiles } = useFeaturedProfiles({
114+
limit: FEATURED_LIMIT
115+
})
116+
const onClickCard = useCallback(
117+
(url: string) => {
118+
if (url.startsWith(BASE_URL)) {
119+
navigate(stripBaseUrl(url))
120+
} else if (url.startsWith('http')) {
121+
const win = window.open(url, '_blank')
122+
if (win) win.focus()
123+
} else {
124+
navigate(url)
125+
}
126+
},
127+
[navigate]
128+
)
129+
130+
const justForYouTiles = justForYou.filter((tile) => {
131+
const isPremiumTracksTile =
132+
tile.variant === ExploreCollectionsVariant.DIRECT_LINK &&
133+
tile.title === PREMIUM_TRACKS.title
134+
return !isPremiumTracksTile || isUSDCPurchasesEnabled
135+
})
136+
137+
// const [categoryKey] = useSearchCategory()
138+
139+
// const filterKeys: string[] = categories[categoryKey].filters
140+
141+
return (
142+
<Flex justifyContent='center'>
143+
<Flex
144+
direction='column'
145+
pv='3xl'
146+
ph='unit15'
147+
gap='3xl'
148+
alignItems='stretch'
149+
// justifyContent='stretch'
150+
w={1200}
151+
>
152+
<Paper
153+
alignItems='center'
154+
direction='column'
155+
mb='2xl'
156+
gap='xl'
157+
pv='xl'
158+
ph='unit14'
159+
css={{
160+
backgroundImage: ` url(${BackgroundWaves})`,
161+
backgroundPosition: 'center',
162+
backgroundSize: 'cover',
163+
backgroundRepeat: 'no-repeat',
164+
backgroundColor: 'lightgray'
165+
}}
166+
borderRadius='l'
167+
alignSelf='stretch'
168+
>
169+
<Text variant='display' size='s' color='staticWhite'>
170+
{messages.explore}
171+
</Text>
172+
<Text variant='heading' size='s' color='staticWhite'>
173+
{messages.description}
174+
</Text>
175+
<Flex w={400}>
176+
<TextInput
177+
width={400}
178+
label={messages.searchPlaceholder}
179+
size={TextInputSize.SMALL}
180+
startIcon={IconSearch}
181+
/>
182+
</Flex>
183+
</Paper>
184+
<Flex alignSelf='flex-start'>{tabs}</Flex>
185+
{/* <Flex direction='row' gap='s' mv={filterKeys.length ? 'm' : undefined}>
186+
{filterKeys.map((filterKey) => {
187+
const FilterComponent = filters[filterKey]
188+
return <FilterComponent key={filterKey} />
189+
})}
190+
</Flex> */}
191+
192+
<Flex direction='column' gap='l'>
193+
<Flex
194+
gap='m'
195+
alignItems='center'
196+
alignSelf='stretch'
197+
justifyContent='space-between'
198+
>
199+
<Text variant='heading'>{messages.featuredPlaylists}</Text>
200+
<TextLink textVariant='title' size='m'>
201+
{messages.viewAll}
202+
</TextLink>
203+
</Flex>
204+
<Flex gap='l' justifyContent='space-between'>
205+
{featuredPlaylists?.map((playlist) => {
206+
return (
207+
<CollectionCard
208+
key={playlist.playlist_id}
209+
id={playlist.playlist_id}
210+
size={'s'}
211+
/>
212+
)
213+
})}
214+
</Flex>
215+
</Flex>
216+
<Flex>
217+
<Flex>
218+
<Text variant='heading'>{messages.remixContests}</Text>
219+
</Flex>
220+
</Flex>
221+
<Flex direction='column' gap='l'>
222+
<Flex
223+
gap='m'
224+
alignItems='center'
225+
alignSelf='stretch'
226+
justifyContent='space-between'
227+
>
228+
<Text variant='heading'>{messages.artistSpotlight}</Text>
229+
<TextLink textVariant='title' size='m'>
230+
{messages.viewAll}
231+
</TextLink>
232+
</Flex>
233+
<Flex gap='l' alignSelf='stretch' justifyContent='space-between'>
234+
{featuredProfiles?.map((featuredProfile: User, i: number) => {
235+
return (
236+
<UserCard
237+
key={featuredProfile.user_id}
238+
id={featuredProfile.user_id}
239+
size='s'
240+
/>
241+
)
242+
})}
243+
</Flex>
244+
</Flex>
245+
<Flex direction='column' gap='l'>
246+
<Text variant='heading'>{messages.bestOfAudius}</Text>
247+
<Flex
248+
wrap='wrap'
249+
gap='l'
250+
direction='row'
251+
justifyContent='space-between'
252+
>
253+
{justForYouTiles.map((i) => {
254+
const Icon = i.icon
255+
return (
256+
<PerspectiveCard
257+
key={i.title}
258+
backgroundGradient={i.gradient}
259+
shadowColor={i.shadow}
260+
useOverlayBlendMode={
261+
i.variant !== ExploreCollectionsVariant.DIRECT_LINK
262+
}
263+
backgroundIcon={Icon ? <Icon color='inverse' /> : undefined}
264+
onClick={() => onClickCard(i.link)}
265+
isIncentivized={!!i.incentivized}
266+
sensitivity={i.cardSensitivity}
267+
>
268+
<Flex w={532} h={200}>
269+
<TextInterior title={i.title} subtitle={i.subtitle} />
270+
</Flex>
271+
</PerspectiveCard>
272+
)
273+
})}
274+
</Flex>
275+
</Flex>
276+
</Flex>
277+
</Flex>
278+
)
279+
}
280+
281+
export default ExplorePage

0 commit comments

Comments
 (0)