Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix featured blogs #56

Merged
merged 3 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 31 additions & 37 deletions apps/studio/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3324,47 +3324,41 @@
},
"optional": true
},
"featured": {
"displayFeaturedBlogs": {
"type": "objectAttribute",
"value": {
"type": "array",
"of": {
"type": "object",
"attributes": {
"_ref": {
"type": "objectAttribute",
"value": {
"type": "string"
}
},
"_type": {
"type": "objectAttribute",
"value": {
"type": "string",
"value": "reference"
}
},
"_weak": {
"type": "objectAttribute",
"value": {
"type": "boolean"
},
"optional": true
}
"type": "union",
"of": [
{
"type": "string",
"value": "yes"
},
"dereferencesTo": "blog",
"rest": {
"type": "object",
"attributes": {
"_key": {
"type": "objectAttribute",
"value": {
"type": "string"
}
}
}
{
"type": "string",
"value": "no"
}
}
]
},
"optional": true
},
"featuredBlogsCount": {
"type": "objectAttribute",
"value": {
"type": "union",
"of": [
{
"type": "string",
"value": "1"
},
{
"type": "string",
"value": "2"
},
{
"type": "string",
"value": "3"
}
]
},
"optional": true
},
Expand Down
47 changes: 30 additions & 17 deletions apps/studio/schemaTypes/documents/blog-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,37 @@ export const blogIndex = defineType({
validation: (Rule) => Rule.required(),
}),
defineField({
name: "featured",
title: "Featured Blogs",
name: "displayFeaturedBlogs",
title: "Display Featured Blogs",
description:
"Choose one special blog post to highlight at the top of your blog page. This post will be displayed in a larger size to catch visitors' attention.",
type: "array",
of: [
defineArrayMember({
type: "reference",
to: [
{
type: "blog",
options: { disableNew: true },
},
],
validation: (rule) => [rule.required()],
}),
],
validation: (rule) => [rule.max(1), rule.unique()],
"When enabled, this will take the top blogs from the ordered blog list and display them as featured at the top of the page",
type: "string",
options: {
list: [
{ title: "Yes", value: "yes" },
{ title: "No", value: "no" },
],
layout: "radio",
},
initialValue: "yes",
group: GROUP.MAIN_CONTENT,
}),
defineField({
name: "featuredBlogsCount",
title: "Number of Featured Blogs",
description: "Select the number of blogs to display as featured.",
type: "string",
options: {
list: [
{ title: "1", value: "1" },
{ title: "2", value: "2" },
{ title: "3", value: "3" },
],
layout: "radio",
direction: "horizontal",
},
initialValue: "1",
hidden: ({ parent }) => parent?.displayFeaturedBlogs !== "yes",
group: GROUP.MAIN_CONTENT,
}),
pageBuilderField,
Expand Down
2 changes: 1 addition & 1 deletion apps/studio/scripts/create-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ async function createData() {
console.log("\n");

console.log("📚 Generating blog index page...");
const blogIndexPage = generateBlogIndexPage(blogPages);
const blogIndexPage = generateBlogIndexPage();

transaction.createIfNotExists(blogIndexPage);
console.log("✅ Created blog index page");
Expand Down
19 changes: 3 additions & 16 deletions apps/studio/utils/mock-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,7 @@ export function generateMockBlogPages({
});
}

type Blog = ReturnType<typeof generateMockBlogPages>[number];

export function generateBlogIndexPage(blogs: Blog[]) {
const featuredBlog = faker.helpers.arrayElement(blogs);

export function generateBlogIndexPage() {
return {
_id: "blogIndex" as const,
_type: "blogIndex" as const,
Expand All @@ -439,16 +435,7 @@ export function generateBlogIndexPage(blogs: Blog[]) {
type: "slug",
current: "/blog",
},
...(featuredBlog?._id
? {
featured: [
{
_type: "reference",
_key: faker.string.uuid(),
_ref: featuredBlog._id,
},
],
}
: {}),
displayFeaturedBlogs: "yes",
featuredBlogsCount: "1",
};
}
58 changes: 36 additions & 22 deletions apps/web/src/app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,37 @@ import { PageBuilder } from "@/components/pagebuilder";
import { sanityFetch } from "@/lib/sanity/live";
import { queryBlogIndexPageData } from "@/lib/sanity/query";
import { getMetaData } from "@/lib/seo";
import { handleErrors } from "@/utils";

/**
* Fetches blog posts data from Sanity CMS
*/
async function fetchBlogPosts() {
return await sanityFetch({ query: queryBlogIndexPageData });
return await handleErrors(sanityFetch({ query: queryBlogIndexPageData }));
}

export async function generateMetadata() {
try {
const { data } = await fetchBlogPosts();
return getMetaData(data ?? {});
} catch {
return getMetaData({});
}
const [result, err] = await fetchBlogPosts();
if (err || !result?.data) return getMetaData({});
return getMetaData(result.data);
}

export default async function BlogIndexPage() {
const { data } = await fetchBlogPosts();
if (!data) notFound();
const [res, err] = await fetchBlogPosts();
if (err || !res?.data) notFound();

const {
blogs = [],
title,
description,
pageBuilder = [],
_id,
_type,
displayFeaturedBlogs,
featuredBlogsCount,
} = res.data;

const { blogs = [], title, description, pageBuilder = [], _id, _type } = data;
const validFeaturedBlogsCount = featuredBlogsCount
? Number.parseInt(featuredBlogsCount)
: 0;

// Handle empty blogs case
if (!blogs.length) {
return (
<main className="container my-16 mx-auto px-4 md:px-6">
Expand All @@ -45,24 +52,31 @@ export default async function BlogIndexPage() {
);
}

// Extract featured blog and remaining blogs
const [featuredBlog, ...remainingBlogs] = blogs;
const shouldDisplayFeaturedBlogs =
displayFeaturedBlogs && validFeaturedBlogsCount > 0;

const featuredBlogs = shouldDisplayFeaturedBlogs
? blogs.slice(0, validFeaturedBlogsCount)
: [];
const remainingBlogs = shouldDisplayFeaturedBlogs
? blogs.slice(validFeaturedBlogsCount)
: blogs;

return (
<main className="bg-background">
<div className="container my-16 mx-auto px-4 md:px-6">
<BlogHeader title={title} description={description} />

{/* Featured Blog */}
{featuredBlog && (
<div className="mx-auto mt-8 sm:mt-12 md:mt-16 mb-12 lg:mb-20">
<FeaturedBlogCard blog={featuredBlog} />
{featuredBlogs.length > 0 && (
<div className="mx-auto mt-8 sm:mt-12 md:mt-16 mb-12 lg:mb-20 grid grid-cols-1 gap-8 md:gap-12">
{featuredBlogs.map((blog) => (
<FeaturedBlogCard key={blog._id} blog={blog} />
))}
</div>
)}

{/* Blog Grid */}
{remainingBlogs.length > 0 && (
<div className="grid grid-cols-1 gap-8 md:gap-12 lg:grid-cols-2">
<div className="grid grid-cols-1 gap-8 md:gap-12 lg:grid-cols-2 mt-8">
{remainingBlogs.map((blog) => (
<BlogCard key={blog._id} blog={blog} />
))}
Expand Down
8 changes: 7 additions & 1 deletion apps/web/src/components/blog-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ function BlogMeta({ publishedAt }: { publishedAt: string | null }) {
return (
<div className="flex items-center gap-x-4 text-xs my-4">
<time dateTime={publishedAt ?? ""} className="text-muted-foreground">
{publishedAt}
{publishedAt
? new Date(publishedAt).toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "numeric",
})
: ""}
</time>
</div>
);
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/lib/sanity/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ export const queryBlogIndexPageData = defineQuery(/* groq */ `
_type,
title,
description,
"displayFeaturedBlogs" : displayFeaturedBlogs == "yes",
"featuredBlogsCount" : featuredBlogsCount,
${pageBuilderFragment},
"slug": slug.current,
"blogs": *[_type == "blog" && (seoHideFromLists != true)] | order(orderRank asc){
Expand Down
Loading