feat(blogs): restructure and add CTA section

This commit is contained in:
RizqiSyahrendra 2025-02-12 14:22:55 +07:00
parent 3433d3a597
commit 27f9c83e8e
9 changed files with 194 additions and 16 deletions

View File

@ -1,3 +1,4 @@
import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter";
import BlogDetail, { BlogDetailContentSkeleton } from "@/components/Blogs/BlogDetail"; import BlogDetail, { BlogDetailContentSkeleton } from "@/components/Blogs/BlogDetail";
import { fetchBlogDetail } from "@/services/payload/blog"; import { fetchBlogDetail } from "@/services/payload/blog";
import { Metadata } from "next"; import { Metadata } from "next";
@ -20,14 +21,15 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
}; };
} }
const title = `${blog.data.title} - ${name}`; const title = `${!!blog.data?.meta?.title ? blog.data?.meta?.title : blog.data.title} - ${name}`;
const description = `${!!blog.data?.meta?.description ? blog.data?.meta?.description : blog.data.title} - ${name}`;
return { return {
title: title, title: title,
description: title, description: description,
openGraph: { openGraph: {
title: title, title: title,
description: title, description: description,
images: [{ url: blog.imgUrl }], images: [{ url: blog.imgUrl }],
}, },
}; };
@ -40,6 +42,7 @@ export default async function SingleBlogPage({ params }: { params: Promise<{ slu
<> <>
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
<BlogDetail slug={slug} /> <BlogDetail slug={slug} />
<BeforeFooterBlock />
</Suspense> </Suspense>
</> </>
); );

View File

@ -1,3 +1,4 @@
import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter";
import { BlogCardItemSkeleton } from "@/components/Blogs/BlogCardItem"; import { BlogCardItemSkeleton } from "@/components/Blogs/BlogCardItem";
import Blogs from "@/components/Blogs/Blogs"; import Blogs from "@/components/Blogs/Blogs";
import { sanitizePageNumber } from "@/utils/sanitize"; import { sanitizePageNumber } from "@/utils/sanitize";
@ -5,8 +6,8 @@ import Image from "next/image";
import { Suspense } from "react"; import { Suspense } from "react";
export const metadata = { export const metadata = {
title: "Blogs | Cochise Oncology", title: "Blog - Cochise Oncology",
description: "Blogs | Cochise Oncology", description: "Blog - Cochise Oncology",
}; };
export default async function BlogPage({ searchParams }: { searchParams?: Promise<{ page?: string }> }) { export default async function BlogPage({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
@ -36,6 +37,8 @@ export default async function BlogPage({ searchParams }: { searchParams?: Promis
<Blogs page={page} /> <Blogs page={page} />
</Suspense> </Suspense>
</section> </section>
<BeforeFooterBlock />
</> </>
); );
} }

View File

@ -0,0 +1,28 @@
import formatSlug from "@/utils/formatSlug";
import type { CollectionConfig } from "payload";
export const BlogCategories: CollectionConfig = {
slug: "blogCategories",
labels: { plural: "Categories", singular: "Category" },
fields: [
{
name: "name",
type: "text",
required: true,
},
{
name: "slug",
type: "text",
admin: {
position: "sidebar",
},
hooks: {
beforeValidate: [formatSlug("title")],
},
},
],
admin: {
hideAPIURL: true,
group: "Blogs",
},
};

View File

@ -0,0 +1,32 @@
import formatSlug from "@/utils/formatSlug";
import type { CollectionConfig } from "payload";
export const BlogTags: CollectionConfig = {
slug: "blogTags",
labels: { plural: "Tags", singular: "Tag" },
fields: [
{
name: "name",
type: "text",
required: true,
},
{
name: "slug",
type: "text",
admin: {
position: "sidebar",
},
hooks: {
beforeValidate: [formatSlug("title")],
},
},
{
name: "description",
type: "textarea",
},
],
admin: {
hideAPIURL: true,
group: "Blogs",
},
};

View File

@ -4,6 +4,7 @@ import formatSlug from "@/utils/formatSlug";
export const Blogs: CollectionConfig = { export const Blogs: CollectionConfig = {
slug: "blogs", slug: "blogs",
labels: { plural: "Posts", singular: "Post" },
fields: [ fields: [
{ {
name: "title", name: "title",
@ -13,9 +14,6 @@ export const Blogs: CollectionConfig = {
{ {
name: "slug", name: "slug",
type: "text", type: "text",
admin: {
position: "sidebar",
},
hooks: { hooks: {
beforeValidate: [formatSlug("title")], beforeValidate: [formatSlug("title")],
}, },
@ -33,8 +31,47 @@ export const Blogs: CollectionConfig = {
required: true, required: true,
editor: lexicalEditor({}), editor: lexicalEditor({}),
}, },
{
name: "categories",
type: "relationship",
relationTo: "blogCategories",
hasMany: true,
},
{
name: "tags",
type: "relationship",
relationTo: "blogTags",
hasMany: true,
},
{
name: "meta",
label: "Page Meta",
type: "group",
fields: [
{
name: "title",
label: "Title",
type: "text",
},
{
name: "description",
label: "Description",
type: "textarea",
},
],
},
{
name: "is_published",
label: "Published",
type: "checkbox",
defaultValue: true,
admin: {
position: "sidebar",
},
},
], ],
admin: { admin: {
hideAPIURL: true, hideAPIURL: true,
group: "Blogs",
}, },
}; };

View File

@ -54,11 +54,6 @@ export const Pages: CollectionConfig = {
label: "Description", label: "Description",
type: "textarea", type: "textarea",
}, },
{
name: "keywords",
label: "Keywords",
type: "text",
},
], ],
}, },
], ],

View File

@ -70,6 +70,8 @@ export interface Config {
blogs: Blog; blogs: Blog;
pages: Page; pages: Page;
teams: Team; teams: Team;
blogCategories: BlogCategory;
blogTags: BlogTag;
forms: Form; forms: Form;
'form-submissions': FormSubmission; 'form-submissions': FormSubmission;
'payload-locked-documents': PayloadLockedDocument; 'payload-locked-documents': PayloadLockedDocument;
@ -83,6 +85,8 @@ export interface Config {
blogs: BlogsSelect<false> | BlogsSelect<true>; blogs: BlogsSelect<false> | BlogsSelect<true>;
pages: PagesSelect<false> | PagesSelect<true>; pages: PagesSelect<false> | PagesSelect<true>;
teams: TeamsSelect<false> | TeamsSelect<true>; teams: TeamsSelect<false> | TeamsSelect<true>;
blogCategories: BlogCategoriesSelect<false> | BlogCategoriesSelect<true>;
blogTags: BlogTagsSelect<false> | BlogTagsSelect<true>;
forms: FormsSelect<false> | FormsSelect<true>; forms: FormsSelect<false> | FormsSelect<true>;
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>; 'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>; 'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
@ -182,6 +186,36 @@ export interface Blog {
}; };
[k: string]: unknown; [k: string]: unknown;
}; };
categories?: (number | BlogCategory)[] | null;
tags?: (number | BlogTag)[] | null;
meta?: {
title?: string | null;
description?: string | null;
};
is_published?: boolean | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blogCategories".
*/
export interface BlogCategory {
id: number;
name: string;
slug?: string | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blogTags".
*/
export interface BlogTag {
id: number;
name: string;
slug?: string | null;
description?: string | null;
updatedAt: string; updatedAt: string;
createdAt: string; createdAt: string;
} }
@ -267,7 +301,6 @@ export interface Page {
meta?: { meta?: {
title?: string | null; title?: string | null;
description?: string | null; description?: string | null;
keywords?: string | null;
}; };
updatedAt: string; updatedAt: string;
createdAt: string; createdAt: string;
@ -496,6 +529,14 @@ export interface PayloadLockedDocument {
relationTo: 'teams'; relationTo: 'teams';
value: number | Team; value: number | Team;
} | null) } | null)
| ({
relationTo: 'blogCategories';
value: number | BlogCategory;
} | null)
| ({
relationTo: 'blogTags';
value: number | BlogTag;
} | null)
| ({ | ({
relationTo: 'forms'; relationTo: 'forms';
value: number | Form; value: number | Form;
@ -589,6 +630,15 @@ export interface BlogsSelect<T extends boolean = true> {
slug?: T; slug?: T;
img?: T; img?: T;
content?: T; content?: T;
categories?: T;
tags?: T;
meta?:
| T
| {
title?: T;
description?: T;
};
is_published?: T;
updatedAt?: T; updatedAt?: T;
createdAt?: T; createdAt?: T;
} }
@ -652,7 +702,6 @@ export interface PagesSelect<T extends boolean = true> {
| { | {
title?: T; title?: T;
description?: T; description?: T;
keywords?: T;
}; };
updatedAt?: T; updatedAt?: T;
createdAt?: T; createdAt?: T;
@ -669,6 +718,27 @@ export interface TeamsSelect<T extends boolean = true> {
updatedAt?: T; updatedAt?: T;
createdAt?: T; createdAt?: T;
} }
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blogCategories_select".
*/
export interface BlogCategoriesSelect<T extends boolean = true> {
name?: T;
slug?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blogTags_select".
*/
export interface BlogTagsSelect<T extends boolean = true> {
name?: T;
slug?: T;
description?: T;
updatedAt?: T;
createdAt?: T;
}
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "forms_select". * via the `definition` "forms_select".

View File

@ -8,7 +8,9 @@ import { buildConfig } from "payload";
import sharp from "sharp"; import sharp from "sharp";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
import { BlogCategories } from "@/collections/BlogCategories";
import { Blogs } from "@/collections/Blogs"; import { Blogs } from "@/collections/Blogs";
import { BlogTags } from "@/collections/BlogTags";
import { Media } from "@/collections/Media"; import { Media } from "@/collections/Media";
import { Pages } from "@/collections/Pages"; import { Pages } from "@/collections/Pages";
import { Teams } from "@/collections/Teams"; import { Teams } from "@/collections/Teams";
@ -47,7 +49,7 @@ export default buildConfig({
}, },
theme: "dark", theme: "dark",
}, },
collections: [Users, Media, Blogs, Pages, Teams], collections: [Users, Media, Blogs, Pages, Teams, BlogCategories, BlogTags],
secret: process.env.PAYLOAD_SECRET || "", secret: process.env.PAYLOAD_SECRET || "",
typescript: { typescript: {
outputFile: path.resolve(dirname, "payload-types.ts"), outputFile: path.resolve(dirname, "payload-types.ts"),

View File

@ -9,6 +9,11 @@ export async function fetchBlog(page: number | undefined) {
page, page,
pagination: true, pagination: true,
limit: 6, limit: 6,
where: {
is_published: {
equals: true,
},
},
}); });
const formattedData = blogDataQuery.docs.map((item) => { const formattedData = blogDataQuery.docs.map((item) => {
@ -31,6 +36,9 @@ export async function fetchBlogDetail(slug: string) {
collection: "blogs", collection: "blogs",
where: { where: {
slug: { equals: slug }, slug: { equals: slug },
is_published: {
equals: true,
},
}, },
limit: 1, limit: 1,
pagination: false, pagination: false,