From cab69a41e930d4e09b7281e0c173f5d94f4d360f Mon Sep 17 00:00:00 2001 From: RizqiSyahrendra Date: Tue, 4 Mar 2025 18:30:59 +0700 Subject: [PATCH] fix: some meta tags --- src/app/(main)/[slug]/page.tsx | 41 ++++++++++++++++++--------- src/app/(main)/layout.tsx | 7 +++++ src/collections/BlogCategories.ts | 2 +- src/collections/BlogTags.ts | 2 +- src/collections/Blogs.ts | 26 ++++++++++++++--- src/collections/Pages.ts | 2 +- src/collections/Users.ts | 5 ++++ src/middleware.ts | 5 +++- src/payload-types.ts | 10 +++++-- src/utils/metadata.ts | 21 ++++++++++++++ src/utils/{ => payload}/formatSlug.ts | 0 src/utils/payload/setAuthor.ts | 14 +++++++++ 12 files changed, 111 insertions(+), 24 deletions(-) create mode 100644 src/utils/metadata.ts rename src/utils/{ => payload}/formatSlug.ts (100%) create mode 100644 src/utils/payload/setAuthor.ts diff --git a/src/app/(main)/[slug]/page.tsx b/src/app/(main)/[slug]/page.tsx index 1e1da44..b6e529d 100644 --- a/src/app/(main)/[slug]/page.tsx +++ b/src/app/(main)/[slug]/page.tsx @@ -3,44 +3,57 @@ import HeroOther from "@/components/HeroOther"; import Page from "@/components/Pages/Page"; import { fetchBlogDetail } from "@/services/payload/blog"; import { fetchPageBySlug } from "@/services/payload/page"; +import { getDefaultMetadata } from "@/utils/metadata"; import { Metadata } from "next"; import { Suspense } from "react"; export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise { - const name = "Cochise Oncology"; + const defaultMetadata = await getDefaultMetadata(); + const name = defaultMetadata.openGraph?.siteName ?? ""; let title = "Page"; let description = "Page"; + let publishedAt = ""; + let updatedAt = ""; let imgUrl = ""; const slug = (await params).slug; const blog = await fetchBlogDetail(slug); - // check for blog data if (!!blog) { + // check for blog data title = `${!!blog.data?.meta?.title ? blog.data?.meta?.title : blog.data.title} - ${name}`; description = `${!!blog.data?.meta?.description ? blog.data?.meta?.description : blog.data.title} - ${name}`; imgUrl = blog.imgUrl; - } - - // check for page data when blog is not found - if (!blog) { + publishedAt = blog.data.createdAt; + updatedAt = blog.data.updatedAt; + } else { + // check for page data when blog is not found const page = await fetchPageBySlug({ slug }); if (!!page) { title = `${!!page?.meta?.title ? page?.meta?.title : page.title} - ${name}`; description = `${!!page?.meta?.description ? page?.meta?.description : page.title} - ${name}`; imgUrl = page.heroImg?.url; + publishedAt = page.createdAt; + updatedAt = page.updatedAt; } } - return { - title: title, - description: description, - openGraph: { - title: title, - description: description, - images: !!imgUrl ? { url: imgUrl } : undefined, - }, + defaultMetadata.title = title; + defaultMetadata.description = description; + if (!!defaultMetadata.openGraph) { + defaultMetadata.openGraph.title = title; + // @ts-ignore + defaultMetadata.openGraph.type = "article"; + defaultMetadata.openGraph.description = description; + defaultMetadata.openGraph.title = title; + defaultMetadata.openGraph.images = !!imgUrl ? { url: imgUrl } : undefined; + } + defaultMetadata.other = { + "article:published_time": publishedAt, + "article:modified_time": updatedAt, }; + + return defaultMetadata; } export default async function SinglePage({ params }: { params: Promise<{ slug: string }> }) { diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index 6521bf7..b0821a8 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -3,9 +3,11 @@ import Footer from "@/components/Footer"; import Header from "@/components/Header"; import InitialScript from "@/components/InitialScript"; import { navMenuData } from "@/data/menu"; +import { getDefaultMetadata } from "@/utils/metadata"; import "@public/assets/css/styles.css"; import "jarallax/dist/jarallax.min.css"; +import { Metadata } from "next"; import { Roboto } from "next/font/google"; import "photoswipe/dist/photoswipe.css"; import "react-modal-video/css/modal-video.css"; @@ -15,6 +17,11 @@ import "tippy.js/dist/tippy.css"; const roboto = Roboto({ subsets: ["latin"] }); +export async function generateMetadata(): Promise { + const metadata = await getDefaultMetadata(); + return metadata; +} + export default function MainLayout({ children, }: Readonly<{ diff --git a/src/collections/BlogCategories.ts b/src/collections/BlogCategories.ts index 21cabf2..1f31904 100644 --- a/src/collections/BlogCategories.ts +++ b/src/collections/BlogCategories.ts @@ -1,4 +1,4 @@ -import formatSlug from "@/utils/formatSlug"; +import formatSlug from "@/utils/payload/formatSlug"; import type { CollectionConfig } from "payload"; export const BlogCategories: CollectionConfig = { diff --git a/src/collections/BlogTags.ts b/src/collections/BlogTags.ts index 04256cc..a7d623b 100644 --- a/src/collections/BlogTags.ts +++ b/src/collections/BlogTags.ts @@ -1,4 +1,4 @@ -import formatSlug from "@/utils/formatSlug"; +import formatSlug from "@/utils/payload/formatSlug"; import type { CollectionConfig } from "payload"; export const BlogTags: CollectionConfig = { diff --git a/src/collections/Blogs.ts b/src/collections/Blogs.ts index 6168629..8714a23 100644 --- a/src/collections/Blogs.ts +++ b/src/collections/Blogs.ts @@ -1,6 +1,6 @@ -import type { CollectionConfig } from "payload"; +import formatSlug from "@/utils/payload/formatSlug"; import { lexicalEditor } from "@payloadcms/richtext-lexical"; -import formatSlug from "@/utils/formatSlug"; +import type { CollectionConfig } from "payload"; export const Blogs: CollectionConfig = { slug: "blogs", @@ -59,8 +59,8 @@ export const Blogs: CollectionConfig = { type: "textarea", }, { - name: "cannonical_url", - label: "Cannonical Url", + name: "canonical_url", + label: "Canonical Url", type: "text", }, ], @@ -74,6 +74,24 @@ export const Blogs: CollectionConfig = { position: "sidebar", }, }, + { + name: "createdBy", + type: "relationship", + relationTo: "users", + hidden: true, + // hooks: { + // beforeChange: [setAuthor], + // }, + }, + { + name: "updatedBy", + type: "relationship", + relationTo: "users", + hidden: true, + // hooks: { + // beforeChange: [setAuthor], + // }, + }, ], admin: { hideAPIURL: true, diff --git a/src/collections/Pages.ts b/src/collections/Pages.ts index fec04fe..f7abf7f 100644 --- a/src/collections/Pages.ts +++ b/src/collections/Pages.ts @@ -7,7 +7,7 @@ import { GoogleReviewBlock } from "@/blocks/GoogleReview"; import { HorizontalImageContentBlock } from "@/blocks/HorizontalImageContent"; import { ImageSliderBlock } from "@/blocks/ImageSlider"; import { OurTeamBlock } from "@/blocks/OurTeam"; -import formatSlug from "@/utils/formatSlug"; +import formatSlug from "@/utils/payload/formatSlug"; import { CollectionConfig } from "payload"; export const Pages: CollectionConfig = { diff --git a/src/collections/Users.ts b/src/collections/Users.ts index 773550d..bcd1a61 100644 --- a/src/collections/Users.ts +++ b/src/collections/Users.ts @@ -11,5 +11,10 @@ export const Users: CollectionConfig = { fields: [ // Email added by default // Add more fields as needed + { + name: "name", + label: "Name", + type: "text", + }, ], }; diff --git a/src/middleware.ts b/src/middleware.ts index bb27fd2..1d5dc2a 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -8,7 +8,10 @@ export function middleware(request: NextRequest) { const host = request.headers.get("x-forwarded-host") || request.nextUrl.hostname; const path = request.nextUrl.pathname + request.nextUrl.search; // Construct the full URL - const fullUrl = `${protocol}://${host}${path}`; + const mainUrl = `${protocol}://${host}`; + const fullUrl = `${mainUrl}${path}`; + + request.headers.set("x-main-url", mainUrl); request.headers.set("x-full-url", fullUrl); return NextResponse.next({ diff --git a/src/payload-types.ts b/src/payload-types.ts index 203e067..703eae5 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -83,6 +83,7 @@ export interface UserAuthOperations { */ export interface User { id: number; + name?: string | null; updatedAt: string; createdAt: string; email: string; @@ -143,9 +144,11 @@ export interface Blog { meta?: { title?: string | null; description?: string | null; - cannonical_url?: string | null; + canonical_url?: string | null; }; is_published?: boolean | null; + createdBy?: (number | null) | User; + updatedBy?: (number | null) | User; updatedAt: string; createdAt: string; } @@ -593,6 +596,7 @@ export interface PayloadMigration { * via the `definition` "users_select". */ export interface UsersSelect { + name?: T; updatedAt?: T; createdAt?: T; email?: T; @@ -638,9 +642,11 @@ export interface BlogsSelect { | { title?: T; description?: T; - cannonical_url?: T; + canonical_url?: T; }; is_published?: T; + createdBy?: T; + updatedBy?: T; updatedAt?: T; createdAt?: T; } diff --git a/src/utils/metadata.ts b/src/utils/metadata.ts new file mode 100644 index 0000000..e077916 --- /dev/null +++ b/src/utils/metadata.ts @@ -0,0 +1,21 @@ +import { Metadata } from "next"; +import { headers } from "next/headers"; + +export async function getDefaultMetadata(): Promise { + const headersList = await headers(); + const mainUrl = headersList.get("x-main-url") ?? ""; + const fullUrl = headersList.get("x-full-url") ?? ""; + + return { + metadataBase: new URL(mainUrl), + openGraph: { + type: "website", + locale: "en_US", + url: fullUrl, + siteName: "Cochise Oncology", + }, + alternates: { + canonical: "./", + }, + }; +} diff --git a/src/utils/formatSlug.ts b/src/utils/payload/formatSlug.ts similarity index 100% rename from src/utils/formatSlug.ts rename to src/utils/payload/formatSlug.ts diff --git a/src/utils/payload/setAuthor.ts b/src/utils/payload/setAuthor.ts new file mode 100644 index 0000000..954b436 --- /dev/null +++ b/src/utils/payload/setAuthor.ts @@ -0,0 +1,14 @@ +import { FieldHook } from "payload"; + +const setAuthor: FieldHook = ({ req, operation, data, value }) => { + // if (req.user && !!data) { + // if (operation === "create") { + // data.createdBy = req.user.id; + // } + // data.updatedBy = req.user.id; + // } + + return data; +}; + +export default setAuthor;