-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…ured-categories-filtering-on-homepage [DEV-12642] Feature - Display featured categories on homepage and allow filtering by them
- Loading branch information
Showing
12 changed files
with
251 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
modules/InfiniteStories/ui/CategoriesFilters/CategoriesFilters.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
.title { | ||
margin-bottom: $spacing-5; | ||
} | ||
|
||
.filters { | ||
display: flex; | ||
align-items: center; | ||
flex-wrap: wrap; | ||
gap: $spacing-2; | ||
} | ||
|
||
.badge { | ||
display: flex; | ||
align-items: center; | ||
flex-shrink: 0; | ||
padding: $spacing-2 $spacing-3; | ||
text-decoration: none; | ||
color: $color-text; | ||
background: $color-base-white; | ||
border: 1px solid $color-base-200; | ||
border-radius: 100px; | ||
|
||
&.active { | ||
color: var(--prezly-accent-color-button-text); | ||
background-color: var(--prezly-accent-color); | ||
border-color: var(--prezly-accent-color); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
modules/InfiniteStories/ui/CategoriesFilters/CategoriesFilters.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import type { Category } from '@prezly/sdk/dist/types'; | ||
import type { Locale } from '@prezly/theme-kit-nextjs'; | ||
import classNames from 'classnames'; | ||
import Link from 'next/link'; | ||
|
||
import { PageTitle } from '@/components/PageTitle'; | ||
|
||
import styles from './CategoriesFilters.module.scss'; | ||
|
||
interface Props { | ||
activeCategory: Pick<Category, 'id'> | undefined; | ||
categories: Category[]; | ||
className?: string; | ||
locale: Locale.Code; | ||
} | ||
|
||
export function CategoriesFilters({ activeCategory, categories, className, locale }: Props) { | ||
return ( | ||
<div className={className}> | ||
<PageTitle className={styles.title} title="Latest stories" /> | ||
<div className={styles.filters}> | ||
<Filter isActive={activeCategory === undefined}>All stories</Filter> | ||
{categories.map(({ id, display_name, i18n }) => ( | ||
<Filter categoryId={id} isActive={activeCategory?.id === id} key={id}> | ||
{i18n[locale]?.name || display_name} | ||
</Filter> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export function Filter(props: { | ||
categoryId?: Category['id']; | ||
children: string; | ||
isActive: boolean; | ||
}) { | ||
const { categoryId, children, isActive } = props; | ||
|
||
return ( | ||
<Link | ||
href={categoryId ? { query: { category: categoryId } } : { query: { category: null } }} | ||
className={classNames(styles.badge, { | ||
[styles.active]: isActive, | ||
})} | ||
scroll={false} | ||
> | ||
{children} | ||
</Link> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './CategoriesFilters'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './CategoriesFilters'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,91 @@ | ||
import type { Category } from '@prezly/sdk'; | ||
import type { Locale } from '@prezly/theme-kit-nextjs'; | ||
|
||
import { app } from '@/adapters/server'; | ||
|
||
import { InfiniteStories } from '../InfiniteStories'; | ||
|
||
interface Props { | ||
categoryId: Category['id'] | undefined; | ||
localeCode: Locale.Code; | ||
pageSize: number; | ||
} | ||
|
||
export async function Stories({ localeCode, pageSize }: Props) { | ||
export async function Stories({ categoryId, localeCode, pageSize }: Props) { | ||
const newsroom = await app().newsroom(); | ||
const languageSettings = await app().languageOrDefault(localeCode); | ||
const { stories, pagination } = await app().stories({ | ||
limit: pageSize, | ||
locale: { code: localeCode }, | ||
const categories = await app().categories(); | ||
const featuredCategories = categories.filter( | ||
({ is_featured, i18n }) => is_featured && i18n[localeCode]?.public_stories_number > 0, | ||
); | ||
const hasFeaturedCategories = featuredCategories.length > 0; | ||
|
||
const { stories, pagination, excludedStoryUuids } = await getStories({ | ||
categoryId, | ||
hasFeaturedCategories, | ||
localeCode, | ||
pageSize, | ||
}); | ||
|
||
return ( | ||
<InfiniteStories | ||
key={categoryId} | ||
category={categoryId ? { id: categoryId } : undefined} | ||
categories={featuredCategories} | ||
newsroomName={languageSettings.company_information.name || newsroom.name} | ||
pageSize={pageSize} | ||
initialStories={stories} | ||
total={pagination.matched_records_number} | ||
excludedStoryUuids={excludedStoryUuids} | ||
/> | ||
); | ||
} | ||
|
||
async function getStories({ | ||
categoryId, | ||
hasFeaturedCategories, | ||
localeCode, | ||
pageSize, | ||
}: { | ||
categoryId: number | undefined; | ||
hasFeaturedCategories: boolean; | ||
localeCode: Locale.Code; | ||
pageSize: number; | ||
}) { | ||
if (hasFeaturedCategories) { | ||
const { stories: pinnedOrMostRecentStories } = await app().stories({ | ||
limit: 1, | ||
locale: { code: localeCode }, | ||
}); | ||
|
||
const pinnedOrMostRecentStory = pinnedOrMostRecentStories[0]; | ||
|
||
// Exclude the pinned/most recent story from the initial stories list | ||
// so it's not duplicated below the categories filters | ||
const query = pinnedOrMostRecentStory | ||
? { | ||
uuid: { $nin: [pinnedOrMostRecentStory.uuid] }, | ||
} | ||
: undefined; | ||
|
||
const { stories, pagination } = await app().stories({ | ||
category: categoryId ? { id: categoryId } : undefined, | ||
limit: pageSize - 1, | ||
locale: { code: localeCode }, | ||
query, | ||
}); | ||
|
||
return { | ||
stories: [...pinnedOrMostRecentStories, ...stories], | ||
pagination, | ||
excludedStoryUuids: pinnedOrMostRecentStories.map((story) => story.uuid), | ||
}; | ||
} | ||
|
||
const { stories, pagination } = await app().stories({ | ||
limit: pageSize, | ||
locale: { code: localeCode }, | ||
}); | ||
|
||
return { stories, pagination }; | ||
} |
Oops, something went wrong.