diff --git a/apps/web/app/(marketing)/blog/page.tsx b/apps/web/app/(marketing)/blog/page.tsx index 7925a51d4..86df0eb59 100644 --- a/apps/web/app/(marketing)/blog/page.tsx +++ b/apps/web/app/(marketing)/blog/page.tsx @@ -31,6 +31,8 @@ async function BlogPage({ searchParams }: { searchParams: { page: string } }) { limit, offset, language, + sortBy: 'publishedAt', + sortDirection: 'desc', }); return ( diff --git a/packages/cms/core/src/cms-client.ts b/packages/cms/core/src/cms-client.ts index 2dfb8dee2..7d15732b2 100644 --- a/packages/cms/core/src/cms-client.ts +++ b/packages/cms/core/src/cms-client.ts @@ -36,6 +36,8 @@ export namespace Cms { tags?: string[]; parentIds?: string[]; language?: string | undefined; + sortDirection?: 'asc' | 'desc'; + sortBy?: 'publishedAt' | 'order'; } export interface GetCategoriesOptions { diff --git a/packages/cms/keystatic/src/client.ts b/packages/cms/keystatic/src/client.ts index be7c3576a..de44cf4ff 100644 --- a/packages/cms/keystatic/src/client.ts +++ b/packages/cms/keystatic/src/client.ts @@ -22,33 +22,55 @@ export class KeystaticClient implements CmsClient { const startOffset = options?.offset ?? 0; const endOffset = startOffset + (options?.limit ?? 10); - const filtered = docs.filter((item) => { - const categoryMatch = options?.categories?.length - ? options.categories.find((category) => - item.entry.categories.includes(category), - ) - : true; + const filtered = docs + .filter((item) => { + const categoryMatch = options?.categories?.length + ? options.categories.find((category) => + item.entry.categories.includes(category), + ) + : true; - if (!categoryMatch) { - return false; - } - - if (options.language) { - if (item.entry.language && item.entry.language !== options.language) { + if (!categoryMatch) { return false; } - } - const tagMatch = options?.tags?.length - ? options.tags.find((tag) => item.entry.tags.includes(tag)) - : true; + if (options.language) { + if (item.entry.language && item.entry.language !== options.language) { + return false; + } + } - if (!tagMatch) { - return false; - } + const tagMatch = options?.tags?.length + ? options.tags.find((tag) => item.entry.tags.includes(tag)) + : true; - return true; - }); + if (!tagMatch) { + return false; + } + + return true; + }) + .sort((a, b) => { + const direction = options.sortDirection ?? 'asc'; + const sortBy = options.sortBy ?? 'publishedAt'; + + const transform = (value: string | number | undefined | null) => { + if (typeof value === 'string') { + return new Date(value).getTime(); + } + + return value ?? 0; + }; + + const left = transform(a.entry[sortBy]); + const right = transform(b.entry[sortBy]); + + if (direction === 'asc') { + return left - right; + } + + return right - left; + }); const items = await Promise.all( filtered.slice(startOffset, endOffset).map(async (item) => { diff --git a/packages/cms/wordpress/src/wp-client.ts b/packages/cms/wordpress/src/wp-client.ts index 30a9bb014..15d6e794c 100644 --- a/packages/cms/wordpress/src/wp-client.ts +++ b/packages/cms/wordpress/src/wp-client.ts @@ -38,6 +38,14 @@ export class WordpressClient implements CmsClient { queryParams.append('offset', options.offset.toString()); } + if (options.sortBy) { + queryParams.append('orderby', options.sortBy); + } + + if (options.sortDirection) { + queryParams.append('order', options.sortDirection); + } + if (options?.categories) { const ids = await this.getCategories({ slugs: options.categories,