enhance search view & close #41
This commit is contained in:
parent
1f41575d98
commit
bc2da5ebac
|
@ -10,6 +10,7 @@ type Props = {
|
||||||
posts: PostDataProps[]
|
posts: PostDataProps[]
|
||||||
pageSize?: number
|
pageSize?: number
|
||||||
layout?: PostListLayout
|
layout?: PostListLayout
|
||||||
|
loading?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const getGridItemWidth = (index: number) => {
|
const getGridItemWidth = (index: number) => {
|
||||||
|
@ -56,7 +57,7 @@ export const PostsList = (props: Props) => {
|
||||||
key={index}
|
key={index}
|
||||||
>
|
>
|
||||||
<PostLink href={`/article/${post.slug}`}>
|
<PostLink href={`/article/${post.slug}`}>
|
||||||
<PostWrapper>
|
<PostWrapper className={props.loading ? 'loading' : ''}>
|
||||||
<Post data={post} />
|
<Post data={post} />
|
||||||
</PostWrapper>
|
</PostWrapper>
|
||||||
</PostLink>
|
</PostLink>
|
||||||
|
@ -82,6 +83,12 @@ const PostWrapper = styled.div`
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
border-top: 1px solid rgb(var(--lsd-theme-primary));
|
border-top: 1px solid rgb(var(--lsd-theme-primary));
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const PostLink = styled(Link)`
|
const PostLink = styled(Link)`
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { getArticleCover } from '@/utils/data.utils'
|
import { getArticleCover } from '@/utils/data.utils'
|
||||||
import { Typography } from '@acid-info/lsd-react'
|
|
||||||
import styled from '@emotion/styled'
|
import styled from '@emotion/styled'
|
||||||
import { PostsList } from '../PostList/PostList'
|
import { PostsList } from '../PostList/PostList'
|
||||||
import { Section } from '../Section/Section'
|
import { SearchHook } from '@/types/data.types'
|
||||||
import { SearchHook, SearchResultItem } from '@/types/data.types'
|
|
||||||
import { UnbodyGoogleDoc } from '@/lib/unbody/unbody.types'
|
import { UnbodyGoogleDoc } from '@/lib/unbody/unbody.types'
|
||||||
|
import { SearchResultsSection } from '@/components/SearchResultsSection/SearchResultsSection'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data: SearchHook<UnbodyGoogleDoc>
|
data: SearchHook<UnbodyGoogleDoc>
|
||||||
|
@ -12,19 +11,16 @@ type Props = {
|
||||||
|
|
||||||
export default function RelatedArticles({ data }: Props) {
|
export default function RelatedArticles({ data }: Props) {
|
||||||
if (!data.loading && !data.data) return null
|
if (!data.loading && !data.data) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Section
|
<SearchResultsSection
|
||||||
title={data.loading ? 'Loading...' : 'Related Articles'}
|
resultSize={data.data.length}
|
||||||
matches={data.loading ? undefined : data.data.length}
|
loading={data.loading}
|
||||||
|
title={'Related Articles'}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
<PostsList
|
<PostsList
|
||||||
posts={
|
posts={data.data.map((article) => ({
|
||||||
data.loading
|
|
||||||
? []
|
|
||||||
: data.data.map((article) => ({
|
|
||||||
slug: article.doc.slug,
|
slug: article.doc.slug,
|
||||||
date: article.doc.modifiedAt,
|
date: article.doc.modifiedAt,
|
||||||
title: article.doc.title,
|
title: article.doc.title,
|
||||||
|
@ -32,12 +28,12 @@ export default function RelatedArticles({ data }: Props) {
|
||||||
mentions: article.doc.mentions,
|
mentions: article.doc.mentions,
|
||||||
tags: article.doc.tags,
|
tags: article.doc.tags,
|
||||||
coverImage: getArticleCover(article.doc.blocks),
|
coverImage: getArticleCover(article.doc.blocks),
|
||||||
}))
|
}))}
|
||||||
}
|
|
||||||
pageSize={4}
|
pageSize={4}
|
||||||
|
loading={data.loading}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</Section>
|
</SearchResultsSection>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
import styled from '@emotion/styled'
|
import styled from '@emotion/styled'
|
||||||
import { Section } from '../Section/Section'
|
import { SearchHook, SearchResultItem } from '@/types/data.types'
|
||||||
import { SearchResultItem } from '@/types/data.types'
|
|
||||||
import { UnbodyImageBlock, UnbodyTextBlock } from '@/lib/unbody/unbody.types'
|
import { UnbodyImageBlock, UnbodyTextBlock } from '@/lib/unbody/unbody.types'
|
||||||
import { Grid } from '../Grid/Grid'
|
import { Grid } from '../Grid/Grid'
|
||||||
import { ImageBlock, TextBlock } from '../ContentBlock'
|
import { ImageBlock, TextBlock } from '../ContentBlock'
|
||||||
import { UnbodyGraphQl } from '@/lib/unbody/unbody-content.types'
|
import { UnbodyGraphQl } from '@/lib/unbody/unbody-content.types'
|
||||||
|
import { SearchResultsSection } from '@/components/SearchResultsSection/SearchResultsSection'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
blocks: SearchResultItem<UnbodyImageBlock | UnbodyTextBlock>[]
|
data: SearchHook<UnbodyTextBlock | UnbodyImageBlock>
|
||||||
}
|
}
|
||||||
|
export default function RelatedContent({ data }: Props) {
|
||||||
export default function RelatedContent({ blocks }: Props) {
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Section title={'Related Content'} matches={blocks?.length}>
|
<SearchResultsSection
|
||||||
|
resultSize={data.data.length}
|
||||||
|
loading={data.loading}
|
||||||
|
title={'Related Content'}
|
||||||
|
>
|
||||||
<Grid>
|
<Grid>
|
||||||
{blocks.map(
|
{data.data.map(
|
||||||
(block: SearchResultItem<UnbodyImageBlock | UnbodyTextBlock>) => {
|
(block: SearchResultItem<UnbodyImageBlock | UnbodyTextBlock>) => {
|
||||||
if (!block.doc.document || !block.doc.document[0]) return null
|
if (!block.doc.document || !block.doc.document[0]) return null
|
||||||
|
|
||||||
|
@ -23,7 +26,6 @@ export default function RelatedContent({ blocks }: Props) {
|
||||||
if (UnbodyGraphQl.UnbodyDocumentTypeNames.GoogleDoc) {
|
if (UnbodyGraphQl.UnbodyDocumentTypeNames.GoogleDoc) {
|
||||||
refArticle = block.doc.document[0]
|
refArticle = block.doc.document[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (block.doc.__typename) {
|
switch (block.doc.__typename) {
|
||||||
case UnbodyGraphQl.UnbodyDocumentTypeNames.TextBlock:
|
case UnbodyGraphQl.UnbodyDocumentTypeNames.TextBlock:
|
||||||
return <TextBlock doc={block.doc} />
|
return <TextBlock doc={block.doc} />
|
||||||
|
@ -34,7 +36,7 @@ export default function RelatedContent({ blocks }: Props) {
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Section>
|
</SearchResultsSection>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Section } from '@/components/Section/Section'
|
||||||
|
import React, { PropsWithChildren } from 'react'
|
||||||
|
import { Typography } from '@acid-info/lsd-react'
|
||||||
|
|
||||||
|
type Props = PropsWithChildren<{
|
||||||
|
resultSize: number
|
||||||
|
loading: boolean
|
||||||
|
title: string
|
||||||
|
}>
|
||||||
|
|
||||||
|
export const SearchResultsSection = ({
|
||||||
|
resultSize,
|
||||||
|
loading,
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
}: Props) => (
|
||||||
|
<Section
|
||||||
|
title={title}
|
||||||
|
subtitle={
|
||||||
|
loading ? (
|
||||||
|
<Typography genericFontFamily="sans-serif" variant="body2">
|
||||||
|
Loading...
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Typography genericFontFamily="sans-serif" variant="body2">
|
||||||
|
{resultSize} matches
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Section>
|
||||||
|
)
|
|
@ -1,25 +1,29 @@
|
||||||
import { Typography } from '@acid-info/lsd-react'
|
import { Typography } from '@acid-info/lsd-react'
|
||||||
import styled from '@emotion/styled'
|
import styled from '@emotion/styled'
|
||||||
import { PropsWithChildren } from 'react'
|
import React, { PropsWithChildren } from 'react'
|
||||||
|
|
||||||
type Props = PropsWithChildren<{
|
type Props = PropsWithChildren<{
|
||||||
title: string
|
title: string
|
||||||
matches?: number | string
|
subtitle?: string | React.ReactNode
|
||||||
}>
|
}>
|
||||||
|
|
||||||
export const Section = ({ title, matches, children, ...props }: Props) => {
|
export const Section = ({ title, subtitle, children, ...props }: Props) => {
|
||||||
return (
|
return (
|
||||||
<section style={{ width: '100%' }} {...props}>
|
<section style={{ width: '100%' }} {...props}>
|
||||||
<Container>
|
<Container>
|
||||||
<Typography genericFontFamily="sans-serif" variant="body2">
|
<Typography genericFontFamily="sans-serif" variant="body2">
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
{matches && (
|
{subtitle && (
|
||||||
<>
|
<>
|
||||||
<Typography variant="body2">•</Typography>
|
<Typography variant="body2">•</Typography>
|
||||||
|
{typeof subtitle === 'string' ? (
|
||||||
<Typography genericFontFamily="sans-serif" variant="body2">
|
<Typography genericFontFamily="sans-serif" variant="body2">
|
||||||
{matches} matches
|
subtitle
|
||||||
</Typography>
|
</Typography>
|
||||||
|
) : (
|
||||||
|
subtitle
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -54,7 +54,6 @@ export default function SearchPage({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
if (query.length > 0 || topics.length > 0) {
|
|
||||||
const serchArgs = [
|
const serchArgs = [
|
||||||
extractQueryFromQuery(router.query),
|
extractQueryFromQuery(router.query),
|
||||||
extractTopicsFromQuery(router.query),
|
extractTopicsFromQuery(router.query),
|
||||||
|
@ -65,15 +64,12 @@ export default function SearchPage({
|
||||||
articles.reset(initialArticles)
|
articles.reset(initialArticles)
|
||||||
blocks.reset(initialBlocks)
|
blocks.reset(initialBlocks)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
hasUpdated.current = true
|
|
||||||
}
|
|
||||||
}, [mounted, router.query])
|
}, [mounted, router.query])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ minHeight: '80vh' }}>
|
||||||
<RelatedArticles data={articles} />
|
<RelatedArticles data={articles} />
|
||||||
{blocks.data?.length && <RelatedContent blocks={blocks.data} />}
|
<RelatedContent data={blocks} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue