From 27f9c83e8e05eb2d7c10441033a79c6c6ba1a854 Mon Sep 17 00:00:00 2001 From: RizqiSyahrendra Date: Wed, 12 Feb 2025 14:22:55 +0700 Subject: [PATCH] feat(blogs): restructure and add CTA section --- src/app/(main)/blog/[slug]/page.tsx | 9 ++-- src/app/(main)/blog/page.tsx | 7 ++- src/collections/BlogCategories.ts | 28 +++++++++++ src/collections/BlogTags.tsx | 32 +++++++++++++ src/collections/Blogs.ts | 43 +++++++++++++++-- src/collections/Pages.ts | 5 -- src/payload-types.ts | 74 ++++++++++++++++++++++++++++- src/payload.config.ts | 4 +- src/services/payload/blog.ts | 8 ++++ 9 files changed, 194 insertions(+), 16 deletions(-) create mode 100644 src/collections/BlogCategories.ts create mode 100644 src/collections/BlogTags.tsx diff --git a/src/app/(main)/blog/[slug]/page.tsx b/src/app/(main)/blog/[slug]/page.tsx index 0003646..5b76ce0 100644 --- a/src/app/(main)/blog/[slug]/page.tsx +++ b/src/app/(main)/blog/[slug]/page.tsx @@ -1,3 +1,4 @@ +import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter"; import BlogDetail, { BlogDetailContentSkeleton } from "@/components/Blogs/BlogDetail"; import { fetchBlogDetail } from "@/services/payload/blog"; 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 { title: title, - description: title, + description: description, openGraph: { title: title, - description: title, + description: description, images: [{ url: blog.imgUrl }], }, }; @@ -40,6 +42,7 @@ export default async function SingleBlogPage({ params }: { params: Promise<{ slu <> }> + ); diff --git a/src/app/(main)/blog/page.tsx b/src/app/(main)/blog/page.tsx index 438d0bc..b413360 100644 --- a/src/app/(main)/blog/page.tsx +++ b/src/app/(main)/blog/page.tsx @@ -1,3 +1,4 @@ +import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter"; import { BlogCardItemSkeleton } from "@/components/Blogs/BlogCardItem"; import Blogs from "@/components/Blogs/Blogs"; import { sanitizePageNumber } from "@/utils/sanitize"; @@ -5,8 +6,8 @@ import Image from "next/image"; import { Suspense } from "react"; export const metadata = { - title: "Blogs | Cochise Oncology", - description: "Blogs | Cochise Oncology", + title: "Blog - Cochise Oncology", + description: "Blog - Cochise Oncology", }; export default async function BlogPage({ searchParams }: { searchParams?: Promise<{ page?: string }> }) { @@ -36,6 +37,8 @@ export default async function BlogPage({ searchParams }: { searchParams?: Promis + + ); } diff --git a/src/collections/BlogCategories.ts b/src/collections/BlogCategories.ts new file mode 100644 index 0000000..98f8431 --- /dev/null +++ b/src/collections/BlogCategories.ts @@ -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", + }, +}; diff --git a/src/collections/BlogTags.tsx b/src/collections/BlogTags.tsx new file mode 100644 index 0000000..c337fd5 --- /dev/null +++ b/src/collections/BlogTags.tsx @@ -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", + }, +}; diff --git a/src/collections/Blogs.ts b/src/collections/Blogs.ts index ab10ab6..f500a1a 100644 --- a/src/collections/Blogs.ts +++ b/src/collections/Blogs.ts @@ -4,6 +4,7 @@ import formatSlug from "@/utils/formatSlug"; export const Blogs: CollectionConfig = { slug: "blogs", + labels: { plural: "Posts", singular: "Post" }, fields: [ { name: "title", @@ -13,9 +14,6 @@ export const Blogs: CollectionConfig = { { name: "slug", type: "text", - admin: { - position: "sidebar", - }, hooks: { beforeValidate: [formatSlug("title")], }, @@ -33,8 +31,47 @@ export const Blogs: CollectionConfig = { required: true, 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: { hideAPIURL: true, + group: "Blogs", }, }; diff --git a/src/collections/Pages.ts b/src/collections/Pages.ts index 766bf8b..9115e90 100644 --- a/src/collections/Pages.ts +++ b/src/collections/Pages.ts @@ -54,11 +54,6 @@ export const Pages: CollectionConfig = { label: "Description", type: "textarea", }, - { - name: "keywords", - label: "Keywords", - type: "text", - }, ], }, ], diff --git a/src/payload-types.ts b/src/payload-types.ts index 19120e2..89b6426 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -70,6 +70,8 @@ export interface Config { blogs: Blog; pages: Page; teams: Team; + blogCategories: BlogCategory; + blogTags: BlogTag; forms: Form; 'form-submissions': FormSubmission; 'payload-locked-documents': PayloadLockedDocument; @@ -83,6 +85,8 @@ export interface Config { blogs: BlogsSelect | BlogsSelect; pages: PagesSelect | PagesSelect; teams: TeamsSelect | TeamsSelect; + blogCategories: BlogCategoriesSelect | BlogCategoriesSelect; + blogTags: BlogTagsSelect | BlogTagsSelect; forms: FormsSelect | FormsSelect; 'form-submissions': FormSubmissionsSelect | FormSubmissionsSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; @@ -182,6 +186,36 @@ export interface Blog { }; [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; createdAt: string; } @@ -267,7 +301,6 @@ export interface Page { meta?: { title?: string | null; description?: string | null; - keywords?: string | null; }; updatedAt: string; createdAt: string; @@ -496,6 +529,14 @@ export interface PayloadLockedDocument { relationTo: 'teams'; value: number | Team; } | null) + | ({ + relationTo: 'blogCategories'; + value: number | BlogCategory; + } | null) + | ({ + relationTo: 'blogTags'; + value: number | BlogTag; + } | null) | ({ relationTo: 'forms'; value: number | Form; @@ -589,6 +630,15 @@ export interface BlogsSelect { slug?: T; img?: T; content?: T; + categories?: T; + tags?: T; + meta?: + | T + | { + title?: T; + description?: T; + }; + is_published?: T; updatedAt?: T; createdAt?: T; } @@ -652,7 +702,6 @@ export interface PagesSelect { | { title?: T; description?: T; - keywords?: T; }; updatedAt?: T; createdAt?: T; @@ -669,6 +718,27 @@ export interface TeamsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "blogCategories_select". + */ +export interface BlogCategoriesSelect { + 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 { + name?: T; + slug?: T; + description?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "forms_select". diff --git a/src/payload.config.ts b/src/payload.config.ts index 776bfdb..e242a8b 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -8,7 +8,9 @@ import { buildConfig } from "payload"; import sharp from "sharp"; import { fileURLToPath } from "url"; +import { BlogCategories } from "@/collections/BlogCategories"; import { Blogs } from "@/collections/Blogs"; +import { BlogTags } from "@/collections/BlogTags"; import { Media } from "@/collections/Media"; import { Pages } from "@/collections/Pages"; import { Teams } from "@/collections/Teams"; @@ -47,7 +49,7 @@ export default buildConfig({ }, theme: "dark", }, - collections: [Users, Media, Blogs, Pages, Teams], + collections: [Users, Media, Blogs, Pages, Teams, BlogCategories, BlogTags], secret: process.env.PAYLOAD_SECRET || "", typescript: { outputFile: path.resolve(dirname, "payload-types.ts"), diff --git a/src/services/payload/blog.ts b/src/services/payload/blog.ts index 59b34f8..c3269e2 100644 --- a/src/services/payload/blog.ts +++ b/src/services/payload/blog.ts @@ -9,6 +9,11 @@ export async function fetchBlog(page: number | undefined) { page, pagination: true, limit: 6, + where: { + is_published: { + equals: true, + }, + }, }); const formattedData = blogDataQuery.docs.map((item) => { @@ -31,6 +36,9 @@ export async function fetchBlogDetail(slug: string) { collection: "blogs", where: { slug: { equals: slug }, + is_published: { + equals: true, + }, }, limit: 1, pagination: false,