Skip to content

Commit

Permalink
Cleanup search results screen
Browse files Browse the repository at this point in the history
  • Loading branch information
WRadoslaw committed Mar 1, 2024
1 parent 6af5f3a commit 1e30281
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export const SearchControls = styled.div`
`

export const Results = styled.div<{ filtersOpen: boolean }>`
padding-top: ${sizes(30)};
padding-top: ${sizes(20)};
padding-bottom: ${sizes(12)};
${media.sm} {
padding-top: ${({ filtersOpen }) => sizes(filtersOpen ? 48 : 30)};
padding-top: ${({ filtersOpen }) => sizes(filtersOpen ? 36 : 20)};
transition: padding-top ${transitions.timings.routing} ${transitions.easing};
}
`
Expand All @@ -38,6 +38,7 @@ export const FiltersWrapper = styled.div`
display: flex;
margin-left: auto;
align-items: center;
padding: ${sizes(2)} 0;
`

export const StyledSelect = styled(Select)`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,28 @@
import { FC, memo, useEffect, useMemo, useState } from 'react'
import { FC, memo } from 'react'

import { SvgActionFilters } from '@/assets/icons'
import { EmptyFallback } from '@/components/EmptyFallback'
import { FiltersBar, useFiltersBar } from '@/components/FiltersBar'
import { LimitedWidthContainer } from '@/components/LimitedWidthContainer'
import { Tabs } from '@/components/Tabs'
import { Section } from '@/components/Section/Section'
import { ViewErrorFallback } from '@/components/ViewErrorFallback'
import { ViewWrapper } from '@/components/ViewWrapper'
import { Button } from '@/components/_buttons/Button'
import { ChannelGrid } from '@/components/_channel/ChannelGrid'
import { SkeletonLoaderVideoGrid } from '@/components/_loaders/SkeletonLoaderVideoGrid'
import { VideoGrid } from '@/components/_video/VideoGrid'
import { VideoTileViewer } from '@/components/_video/VideoTileViewer'
import { atlasConfig } from '@/config'
import { useMediaMatch } from '@/hooks/useMediaMatch'
import { useSearchResults } from '@/hooks/useSearchResults'
import { useSearchStore } from '@/providers/search'
import { InfiniteLoadingOffsets } from '@/utils/loading.contants'

import {
FiltersWrapper,
PaddingWrapper,
Results,
SearchControls,
StyledPagination,
StyledSelect,
} from './SearchResults.styles'
import { FiltersWrapper, PaddingWrapper, Results, SearchControls, StyledSelect } from './SearchResults.styles'

type SearchResultsProps = {
query: string
}
const tabs = ['Videos', 'Channels']

const INITIAL_NUMBER_OF_RESULTS = 20

export const SearchResults: FC<SearchResultsProps> = memo(({ query }) => {
const smMatch = useMediaMatch('sm')
const [selectedTabIndex, setSelectedTabIndex] = useState(0)
const [numberOfColumns, setNumberOfColumns] = useState(1)
const [page, setPage] = useState(0)
const filtersBarLogic = useFiltersBar()
const {
setVideoWhereInput,
Expand All @@ -45,53 +31,13 @@ export const SearchResults: FC<SearchResultsProps> = memo(({ query }) => {
videoWhereInput,
} = filtersBarLogic

const numberOfFullyFilledRows = numberOfColumns ? Math.ceil(INITIAL_NUMBER_OF_RESULTS / numberOfColumns) : 6
const numberOfResults =
INITIAL_NUMBER_OF_RESULTS % numberOfColumns === 0
? INITIAL_NUMBER_OF_RESULTS
: numberOfColumns * numberOfFullyFilledRows
const { videos, channels, loading, error } = useSearchResults({
searchQuery: query,
videoWhereInput: selectedTabIndex === 0 ? videoWhereInput : undefined,
first: numberOfResults,
videoWhereInput,
first: 5,
})

const refetch = selectedTabIndex === 0 ? videos.refetch : channels.refetch
const { setSearchOpen, setSearchQuery } = useSearchStore((state) => state.actions)

useEffect(() => {
if (selectedTabIndex === 1) {
setIsFiltersOpen(false)
}
}, [selectedTabIndex, setIsFiltersOpen])

const paginationData = useMemo(() => {
return {
pageInfo: selectedTabIndex === 0 ? videos.pageInfo : channels.pageInfo,
totalCount: selectedTabIndex === 0 ? videos.totalCount : channels.totalCount,
type: selectedTabIndex === 0 ? 'videos' : 'channels',
}
}, [channels.pageInfo, channels.totalCount, selectedTabIndex, videos.pageInfo, videos.totalCount])

const handlePageChange = (page: number) => {
const fetchMore = selectedTabIndex === 0 ? videos.fetchMore : channels.fetchMore
const { totalCount, pageInfo } = paginationData
const items = selectedTabIndex === 0 ? videos.items : channels.items
setPage(page)
if (
!!items.length &&
page * numberOfResults + numberOfResults > items?.length &&
items?.length < (totalCount ?? 0)
) {
fetchMore({
variables: {
first: page * numberOfResults + numberOfResults * 2 - items.length,
after: pageInfo?.endCursor,
},
})
}
}

const handleSelectLanguage = (selectedLanguage: unknown) => {
setLanguage(selectedLanguage as string | null | undefined)
setVideoWhereInput((value) => ({
Expand All @@ -104,58 +50,35 @@ export const SearchResults: FC<SearchResultsProps> = memo(({ query }) => {
setIsFiltersOpen((state) => !state)
}

useEffect(() => {
setPage(0)
}, [query])

useEffect(() => {
setPage(0)
refetch()
}, [refetch, selectedTabIndex])

if (error) {
return <ViewErrorFallback />
}

const mappedTabs = tabs.map((tab) => ({ name: tab }))

const showEmptyFallback =
!loading &&
((videos.items.length === 0 && selectedTabIndex === 0) ||
(channels.items.length === 0 && selectedTabIndex === 1)) &&
!!query

const sliceStart = page * numberOfResults
const sliceEnd = page * numberOfResults + numberOfResults
const paginatedVideos = videos.items.slice(sliceStart, sliceEnd)
const paginatedChannels = channels.items.slice(sliceStart, sliceEnd)
const placeHoldersCount = numberOfColumns * numberOfFullyFilledRows
const showEmptyFallback = !loading && videos.items.length === 0 && channels.items.length === 0 && !!query
const { pageInfo, items: videoItems, fetchMore } = videos

return (
<ViewWrapper>
<SearchControls>
<PaddingWrapper filtersOpen={isFiltersOpen}>
<Tabs tabs={mappedTabs} onSelectTab={setSelectedTabIndex} initialIndex={0} />
<FiltersWrapper>
{smMatch && selectedTabIndex === 0 && (
{smMatch && (
<StyledSelect
onChange={handleSelectLanguage}
size="medium"
value={language}
items={[{ name: 'All languages', value: 'undefined' }, ...atlasConfig.derived.languagesSelectValues]}
/>
)}
{selectedTabIndex === 0 && (
<Button
icon={<SvgActionFilters />}
iconPlacement="left"
variant="secondary"
badge={canClearAllFilters}
onClick={toggleFilters}
>
{smMatch && 'Filters'}
</Button>
)}
<Button
icon={<SvgActionFilters />}
iconPlacement="left"
variant="secondary"
badge={canClearAllFilters}
onClick={toggleFilters}
>
{smMatch && 'Filters'}
</Button>
</FiltersWrapper>
</PaddingWrapper>
<FiltersBar {...filtersBarLogic} activeFilters={['categories', 'date', 'length', 'other', 'language']} />
Expand All @@ -164,7 +87,7 @@ export const SearchResults: FC<SearchResultsProps> = memo(({ query }) => {
<LimitedWidthContainer big>
{showEmptyFallback ? (
<EmptyFallback
title={`No ${selectedTabIndex === 0 ? 'videos' : 'channels'} found`}
title="No results found"
subtitle="Please, try using different search terms or change your filtering criteria"
button={
<Button
Expand All @@ -180,38 +103,33 @@ export const SearchResults: FC<SearchResultsProps> = memo(({ query }) => {
}
/>
) : (
<>
{selectedTabIndex === 0 &&
(loading ? (
<SkeletonLoaderVideoGrid
videosCount={placeHoldersCount}
onResize={(sizes) => {
setNumberOfColumns(sizes.length)
}}
/>
) : (
<VideoGrid videos={paginatedVideos} />
))}
{selectedTabIndex === 1 &&
(loading ? (
<SkeletonLoaderVideoGrid
videosCount={placeHoldersCount}
onResize={(sizes) => {
setNumberOfColumns(sizes.length)
}}
/>
) : (
<ChannelGrid channels={paginatedChannels} repeat="fill" />
))}
</>
<Section
contentProps={{
type: 'grid',
grid: {
xxs: {
columns: 1,
},
},
children: videoItems?.map((video, idx) => (
<VideoTileViewer direction="horizontal" detailsVariant="withChannelName" id={video.id} key={idx} />
)),
}}
footerProps={{
reachedEnd: !pageInfo?.hasNextPage,
fetchMore: async () => {
if (pageInfo?.hasNextPage) {
await fetchMore({
variables: { first: 4, after: pageInfo.endCursor },
})
}
return
},
type: 'infinite',
loadingTriggerOffset: InfiniteLoadingOffsets.VideoTile,
}}
/>
)}
<StyledPagination
onChangePage={handlePageChange}
page={page}
totalCount={paginationData.totalCount}
itemsPerPage={numberOfResults}
maxPaginationLinks={7}
/>
</LimitedWidthContainer>
</Results>
</ViewWrapper>
Expand Down

0 comments on commit 1e30281

Please sign in to comment.