Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenalex836 authored Nov 15, 2024
2 parents 9828abf + 5074ab6 commit 9fe844b
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 47 deletions.
70 changes: 54 additions & 16 deletions src/landings/components/CategoryLanding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,72 @@ import cx from 'classnames'
import { CookBookArticleCard } from './CookBookArticleCard'
import { CookBookFilter } from './CookBookFilter'

//import { useTranslation } from 'src/languages/components/useTranslation'
import { DefaultLayout } from 'src/frame/components/DefaultLayout'
import { ArticleTitle } from 'src/frame/components/article/ArticleTitle'
import { Lead } from 'src/frame/components/ui/Lead'
import { useCategoryLandingContext } from 'src/frame/components/context/CategoryLandingContext'
import { ClientSideRedirects } from 'src/rest/components/ClientSideRedirects'
import { RestRedirect } from 'src/rest/components/RestRedirect'
import { Breadcrumbs } from 'src/frame/components/page-header/Breadcrumbs'
import { ArticleCardItems } from '../types'
import { ArticleCardItems } from 'src/landings/types'

export const CategoryLanding = () => {
const router = useRouter()
//const { t } = useTranslation('toc')
const { title, intro, tocItems } = useCategoryLandingContext()

// tocItems contains directories and its children, we only want the child articles
const onlyFlatItems: ArticleCardItems = tocItems.flatMap((item) => item.childTocItems || [])

const [searchResults, setSearchResults] = useState<ArticleCardItems>(onlyFlatItems)
const [searchQuery, setSearchQuery] = useState('')
const [selectedCategory, setSelectedCategory] = useState('All')
const [selectedComplexity, setSelectedComplexity] = useState('All')

const handleSearch = (query: string) => {
const results = onlyFlatItems.filter((token) => {
return Object.values(token).some((value) => {
if (typeof value === 'string') {
return value.toLowerCase().includes(query.toLowerCase())
} else if (Array.isArray(value)) {
return value.some((item) => item.toLowerCase().includes(query.toLowerCase()))
}
return false
const applyFilters = () => {
let results = onlyFlatItems

if (searchQuery) {
results = results.filter((token) => {
return Object.values(token).some((value) => {
if (typeof value === 'string') {
return value.toLowerCase().includes(searchQuery.toLowerCase())
} else if (Array.isArray(value)) {
return value.some((item) => item.toLowerCase().includes(searchQuery.toLowerCase()))
}
return false
})
})
})
setSearchResults(results)
}

if (selectedCategory !== 'All') {
results = results.filter((item) => item.category?.includes(selectedCategory))
}

if (selectedComplexity !== 'All') {
results = results.filter((item) => item.complexity?.includes(selectedComplexity))
}

return results
}

const searchResults = applyFilters()

const handleSearch = (query: string) => {
setSearchQuery(query)
}

const handleFilter = (option: string, type: 'category' | 'complexity') => {
if (type === 'category') {
setSelectedCategory(option)
} else if (type === 'complexity') {
setSelectedComplexity(option)
}
}

const handleResetFilter = () => {
setSearchQuery('')
setSelectedCategory('All')
setSelectedComplexity('All')
}
return (
<DefaultLayout>
{router.route === '/[versionId]/rest/[category]' && <RestRedirect />}
Expand Down Expand Up @@ -65,7 +97,12 @@ export const CategoryLanding = () => {
<h2>Explore {searchResults.length} prompt articles</h2>
</div>
<div>
<CookBookFilter tokens={onlyFlatItems} onSearch={handleSearch} />
<CookBookFilter
tokens={onlyFlatItems}
onSearch={handleSearch}
handleFilter={handleFilter}
handleResetFilter={handleResetFilter}
/>
</div>
</div>
<ul className="clearfix gutter-md-spacious">
Expand All @@ -80,6 +117,7 @@ export const CategoryLanding = () => {
...(item.category || []),
...(item.complexity || []),
]}
url={item.fullPath}
/>
</li>
))}
Expand Down
7 changes: 5 additions & 2 deletions src/landings/components/CookBookArticleCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Label, LabelGroup } from '@primer/react'
import { Label, LabelGroup, Link } from '@primer/react'
import { BugIcon } from '@primer/octicons-react'

type Props = {
Expand Down Expand Up @@ -55,6 +55,7 @@ export const CookBookArticleCard = ({
tags = defaultProps.tags,
description = defaultProps.description,
image = '',
url,
spotlight = false,
}: Props) => {
return (
Expand All @@ -66,7 +67,9 @@ export const CookBookArticleCard = ({
{spotlight ? setImage(image) : null}
{spotlight ? setIcon('none') : setIcon(icon)}
<div>
<h3 className="h4">{title}</h3>
<Link href={url}>
<h3 className="h4">{title}</h3>
</Link>
<div className="fgColor-muted mb-3 mt-2">{description}</div>
<LabelGroup>
{tags.map((tag, index) => (
Expand Down
114 changes: 85 additions & 29 deletions src/landings/components/CookBookFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
import { TextInput, ActionMenu, ActionList, Button } from '@primer/react'
import { TextInput, ActionMenu, ActionList, Button, Box } from '@primer/react'
import { SearchIcon } from '@primer/octicons-react'
import { useRef, useEffect } from 'react'
import { useRef, useEffect, useState } from 'react'
import { ArticleCardItems } from '#src/landings/types.ts'

type Props = {
tokens: ArticleCardItems
onSearch: (query: string) => void
isSearchOpen?: boolean
handleFilter: (option: string, type: 'category' | 'complexity') => void
handleResetFilter: () => void
}

export const CookBookFilter = ({ onSearch, isSearchOpen }: Props) => {
export const CookBookFilter = ({
onSearch,
isSearchOpen,
tokens,
handleFilter,
handleResetFilter,
}: Props) => {
const categories: string[] = ['All', ...new Set(tokens.flatMap((item) => item.category || []))]
const complexities: string[] = [
'All',
...new Set(tokens.flatMap((item) => item.complexity || [])),
]

const [selectedCategory, setSelectedCategory] = useState(0)
const [selectedComplexity, setSelectedComplexity] = useState(0)

const inputRef = useRef<HTMLInputElement>(null)

const onFilter = (option: string, type: 'category' | 'complexity', index: number) => {
if (type === 'category') {
setSelectedCategory(index)
} else if (type === 'complexity') {
setSelectedComplexity(index)
}
handleFilter(option, type)
}

const onResetFilter = () => {
setSelectedCategory(0)
setSelectedComplexity(0)
handleResetFilter()
if (inputRef.current) {
inputRef.current.value = ''
}
}

useEffect(() => {
if (isSearchOpen) {
inputRef.current?.focus()
Expand Down Expand Up @@ -38,43 +74,63 @@ export const CookBookFilter = ({ onSearch, isSearchOpen }: Props) => {
<div className="d-flex">
<ActionMenu>
<ActionMenu.Button className="col-md-1 col-sm-2 float-md-left m-1">
Category
<Box
sx={{
color: 'fg.muted',
display: 'inline-block',
}}
>
Category:
</Box>{' '}
{categories[selectedCategory]}
</ActionMenu.Button>
<ActionMenu.Overlay width="small">
<ActionList>
<ActionList.Item>Item 1</ActionList.Item>
<ActionList.Item>Item 2</ActionList.Item>
<ActionList.Item>Item 3</ActionList.Item>
<ActionMenu.Overlay width="auto">
<ActionList selectionVariant="single">
{categories.map((category, index) => (
<ActionList.Item
key={index}
selected={index === selectedCategory}
onSelect={() => onFilter(category, 'category', index)}
>
{category}
</ActionList.Item>
))}
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>

<ActionMenu>
<ActionMenu.Button className="col-md-1 col-sm-2 float-left m-1">
Complexity
<ActionMenu.Button className="col-md-1 col-sm-2 float-md-left m-1">
<Box
sx={{
color: 'fg.muted',
display: 'inline-block',
}}
>
Complexity:
</Box>{' '}
{complexities[selectedComplexity]}
</ActionMenu.Button>
<ActionMenu.Overlay width="small">
<ActionList>
<ActionList.Item>Item 1</ActionList.Item>
<ActionList.Item>Item 2</ActionList.Item>
<ActionList.Item>Item 3</ActionList.Item>
<ActionMenu.Overlay width="auto">
<ActionList selectionVariant="single">
{complexities.map((complexity, index) => (
<ActionList.Item
key={index}
selected={index === selectedComplexity}
onSelect={() => onFilter(complexity, 'complexity', index)}
>
{complexity}
</ActionList.Item>
))}
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>

<ActionMenu>
<ActionMenu.Button className="col-md-1 col-sm-2 float-left m-1">
Industry
</ActionMenu.Button>
<ActionMenu.Overlay width="small">
<ActionList>
<ActionList.Item>Item 1</ActionList.Item>
<ActionList.Item>Item 2</ActionList.Item>
<ActionList.Item>Item 3</ActionList.Item>
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>
<Button variant="invisible" className="col-md-1 col-sm-2 float-left mt-1">
<Button
variant="invisible"
className="col-md-1 col-sm-2 float-left mt-1"
onClick={onResetFilter}
>
Reset filters
</Button>
</div>
Expand Down

0 comments on commit 9fe844b

Please sign in to comment.