From cd164b6c69fabc7e1785ad3a4beb307b3d9446d6 Mon Sep 17 00:00:00 2001 From: iqbal024 Date: Tue, 4 Mar 2025 09:56:46 +0700 Subject: [PATCH 1/5] add section testemonial --- src/components/Homepage.tsx | 46 ++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/components/Homepage.tsx b/src/components/Homepage.tsx index 88ccaf8..0e7778c 100644 --- a/src/components/Homepage.tsx +++ b/src/components/Homepage.tsx @@ -65,7 +65,51 @@ export default function homepage({ dark = false }) { -
+
+
+

+ I was diagnosed with cancer up in Tucson. The doctor was said to be best oncologist in the state. Problem + was I needed radiation for 45 days not counting weekends and holidays. +

+

+ I had to tell her that that was not doable. I couldn't commute daily and I couldn't rent. I told her that I + could get treatment of some sort in Sierra Vista. She told me that normally she would fight me, but only 2 + Clinics in the state had this latest and greatest radiation hardware. Hers and Cochise Oncology in Sierra + Vista. +

+

+ I had to tell her that that was not doable. I couldn't commute daily and I couldn't rent. I told her that I + could get treatment of some sort in Sierra Vista. She told me that normally she would fight me, but only 2 + Clinics in the state had this latest and greatest radiation hardware. Hers and Cochise Oncology in Sierra + Vista. +

+

Do yourself a favor and see Dr. Vedula.

+

- a Cochise Oncology patient

+

*Individual Results May Vary

+
+ {/*
+

Testimonials

+

+ I was diagnosed with cancer up in Tucson. The doctor was said to be the best oncologist in the state. + Problem was I needed radiation for 45 days not counting weekends and holidays. +

+

+ I had to tell her that that was not doable. I couldn't commute daily and I couldn't rent. I told her that I + could get treatment of some sort in Sierra Vista. She told me that normally she would fight me, but only 2 + clinics in the state had this latest and greatest radiation hardware—hers and Cochise Oncology in Sierra + Vista. +

+

+ At Cochise Oncology, I was introduced to Dr. Vedula. What a good man and what a great doctor. Check out his + credentials. I am now cancer-free for 9 months. It was still 45 days of treatment but with no side effects. + Plus, I would go home every day after undergoing treatment. I forget, maybe 15 minutes of treatment. +

+

Do yourself a favor and see Dr. Vedula.

+

- a Cochise Oncology patient

+

*Individual Results May Vary

+
*/} +
+
-- 2.47.2 From cb4e89b48045d93576675f150a8b6c979e27e56f Mon Sep 17 00:00:00 2001 From: iqbal024 Date: Tue, 4 Mar 2025 11:12:23 +0700 Subject: [PATCH 2/5] update home page --- src/components/Homepage.tsx | 46 ++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/components/Homepage.tsx b/src/components/Homepage.tsx index 0e7778c..2e7c9a7 100644 --- a/src/components/Homepage.tsx +++ b/src/components/Homepage.tsx @@ -87,27 +87,31 @@ export default function homepage({ dark = false }) {

- a Cochise Oncology patient

*Individual Results May Vary

- {/*
-

Testimonials

-

- I was diagnosed with cancer up in Tucson. The doctor was said to be the best oncologist in the state. - Problem was I needed radiation for 45 days not counting weekends and holidays. -

-

- I had to tell her that that was not doable. I couldn't commute daily and I couldn't rent. I told her that I - could get treatment of some sort in Sierra Vista. She told me that normally she would fight me, but only 2 - clinics in the state had this latest and greatest radiation hardware—hers and Cochise Oncology in Sierra - Vista. -

-

- At Cochise Oncology, I was introduced to Dr. Vedula. What a good man and what a great doctor. Check out his - credentials. I am now cancer-free for 9 months. It was still 45 days of treatment but with no side effects. - Plus, I would go home every day after undergoing treatment. I forget, maybe 15 minutes of treatment. -

-

Do yourself a favor and see Dr. Vedula.

-

- a Cochise Oncology patient

-

*Individual Results May Vary

-
*/} +
+
+
+

Testimonials

+
+

+ I was diagnosed with cancer up in Tucson. The doctor was said to be the best oncologist in the state. + Problem was I needed radiation for 45 days not counting weekends and holidays. +

+

+ I had to tell her that that was not doable. I couldn't commute daily and I couldn't rent. I told her that + I could get treatment of some sort in Sierra Vista. She told me that normally she would fight me, but only + 2 clinics in the state had this latest and greatest radiation hardware. Hers and Cochise Oncology in + Sierra Vista. +

+

+ At Cochise Oncology I was introduced to Dr. Vedula. What a good man and what a great doctor. Check out his + credentials. I am now cancer free for 9 months. It was still 45 days of treatment but no side effects. + Plus, I would go home every day after undergoing treatment. I forget, maybe 15 minutes of treatment. +

+

Do yourself a favor and see Dr. Vedula.

+

- a Cochise Oncology patient

+
+

*Individual Results May Vary

+
-- 2.47.2 From cab69a41e930d4e09b7281e0c173f5d94f4d360f Mon Sep 17 00:00:00 2001 From: RizqiSyahrendra Date: Tue, 4 Mar 2025 18:30:59 +0700 Subject: [PATCH 3/5] 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; -- 2.47.2 From 807e78aa70689b616c25e419ce634aa6caab3863 Mon Sep 17 00:00:00 2001 From: RizqiSyahrendra Date: Wed, 5 Mar 2025 00:13:49 +0700 Subject: [PATCH 4/5] feat: blogs and pages set author --- src/collections/Blogs.ts | 21 +++++++++++++-------- src/collections/Pages.ts | 26 +++++++++++++++++++++++--- src/payload-types.ts | 4 ++++ src/utils/payload/setAuthor.ts | 19 +++++++++++-------- 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/collections/Blogs.ts b/src/collections/Blogs.ts index 8714a23..cbfe992 100644 --- a/src/collections/Blogs.ts +++ b/src/collections/Blogs.ts @@ -1,4 +1,5 @@ import formatSlug from "@/utils/payload/formatSlug"; +import setAuthor from "@/utils/payload/setAuthor"; import { lexicalEditor } from "@payloadcms/richtext-lexical"; import type { CollectionConfig } from "payload"; @@ -78,19 +79,23 @@ export const Blogs: CollectionConfig = { name: "createdBy", type: "relationship", relationTo: "users", - hidden: true, - // hooks: { - // beforeChange: [setAuthor], - // }, + hooks: { + beforeChange: [setAuthor], + }, + admin: { + hidden: true, + }, }, { name: "updatedBy", type: "relationship", relationTo: "users", - hidden: true, - // hooks: { - // beforeChange: [setAuthor], - // }, + hooks: { + beforeChange: [setAuthor], + }, + admin: { + hidden: true, + }, }, ], admin: { diff --git a/src/collections/Pages.ts b/src/collections/Pages.ts index f7abf7f..869c4e7 100644 --- a/src/collections/Pages.ts +++ b/src/collections/Pages.ts @@ -8,6 +8,7 @@ import { HorizontalImageContentBlock } from "@/blocks/HorizontalImageContent"; import { ImageSliderBlock } from "@/blocks/ImageSlider"; import { OurTeamBlock } from "@/blocks/OurTeam"; import formatSlug from "@/utils/payload/formatSlug"; +import setAuthor from "@/utils/payload/setAuthor"; import { CollectionConfig } from "payload"; export const Pages: CollectionConfig = { @@ -29,9 +30,6 @@ export const Pages: CollectionConfig = { name: "slug", label: "Page Slug", type: "text", - admin: { - position: "sidebar", - }, hooks: { beforeValidate: [formatSlug("title")], }, @@ -75,6 +73,28 @@ export const Pages: CollectionConfig = { }, ], }, + { + name: "createdBy", + type: "relationship", + relationTo: "users", + hooks: { + beforeChange: [setAuthor], + }, + admin: { + hidden: true, + }, + }, + { + name: "updatedBy", + type: "relationship", + relationTo: "users", + hooks: { + beforeChange: [setAuthor], + }, + admin: { + hidden: true, + }, + }, ], admin: { hideAPIURL: true, diff --git a/src/payload-types.ts b/src/payload-types.ts index 703eae5..15d164f 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -306,6 +306,8 @@ export interface Page { description?: string | null; cannonical_url?: string | null; }; + createdBy?: (number | null) | User; + updatedBy?: (number | null) | User; updatedAt: string; createdAt: string; } @@ -747,6 +749,8 @@ export interface PagesSelect { description?: T; cannonical_url?: T; }; + createdBy?: T; + updatedBy?: T; updatedAt?: T; createdAt?: T; } diff --git a/src/utils/payload/setAuthor.ts b/src/utils/payload/setAuthor.ts index 954b436..f14e7e7 100644 --- a/src/utils/payload/setAuthor.ts +++ b/src/utils/payload/setAuthor.ts @@ -1,14 +1,17 @@ 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; - // } +const setAuthor: FieldHook = ({ value, req, data, field, operation }) => { + if (req.user && !!data) { + if (operation === "create") { + return req.user.id; + } else { + if (field.name === "updatedBy") { + return req.user.id; + } + } + } - return data; + return value; }; export default setAuthor; -- 2.47.2 From 6fc4988506d20eae89dc4a72cf1c6f3302ef8910 Mon Sep 17 00:00:00 2001 From: RizqiSyahrendra Date: Wed, 5 Mar 2025 05:38:02 +0700 Subject: [PATCH 5/5] fix: blogs and pages draft/publish --- src/collections/Blogs.ts | 14 +++++--------- src/collections/Pages.ts | 5 +++++ src/payload-types.ts | 6 ++++-- src/services/payload/blog.ts | 24 ++++-------------------- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/collections/Blogs.ts b/src/collections/Blogs.ts index cbfe992..f9bbd96 100644 --- a/src/collections/Blogs.ts +++ b/src/collections/Blogs.ts @@ -6,6 +6,11 @@ import type { CollectionConfig } from "payload"; export const Blogs: CollectionConfig = { slug: "blogs", labels: { plural: "Posts", singular: "Post" }, + versions: { + drafts: { + validate: true, + }, + }, fields: [ { name: "title", @@ -66,15 +71,6 @@ export const Blogs: CollectionConfig = { }, ], }, - { - name: "is_published", - label: "Published", - type: "checkbox", - defaultValue: true, - admin: { - position: "sidebar", - }, - }, { name: "createdBy", type: "relationship", diff --git a/src/collections/Pages.ts b/src/collections/Pages.ts index 869c4e7..fe7c380 100644 --- a/src/collections/Pages.ts +++ b/src/collections/Pages.ts @@ -13,6 +13,11 @@ import { CollectionConfig } from "payload"; export const Pages: CollectionConfig = { slug: "pages", + versions: { + drafts: { + validate: true, + }, + }, fields: [ { name: "title", diff --git a/src/payload-types.ts b/src/payload-types.ts index 15d164f..9987a52 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -146,11 +146,11 @@ export interface Blog { description?: string | null; canonical_url?: string | null; }; - is_published?: boolean | null; createdBy?: (number | null) | User; updatedBy?: (number | null) | User; updatedAt: string; createdAt: string; + _status?: ('draft' | 'published') | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -310,6 +310,7 @@ export interface Page { updatedBy?: (number | null) | User; updatedAt: string; createdAt: string; + _status?: ('draft' | 'published') | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -646,11 +647,11 @@ export interface BlogsSelect { description?: T; canonical_url?: T; }; - is_published?: T; createdBy?: T; updatedBy?: T; updatedAt?: T; createdAt?: T; + _status?: T; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -753,6 +754,7 @@ export interface PagesSelect { updatedBy?: T; updatedAt?: T; createdAt?: T; + _status?: T; } /** * This interface was referenced by `Config`'s JSON-Schema diff --git a/src/services/payload/blog.ts b/src/services/payload/blog.ts index 410c398..9929eed 100644 --- a/src/services/payload/blog.ts +++ b/src/services/payload/blog.ts @@ -10,24 +10,11 @@ export async function fetchBlog(page: number | undefined, search: string = "") { pagination: true, limit: 6, where: !search - ? { - is_published: { - equals: true, - }, - } + ? undefined : { - and: [ - { - is_published: { - equals: true, - }, - }, - { - title: { - contains: search, - }, - }, - ], + title: { + contains: search, + }, }, }); @@ -51,9 +38,6 @@ export async function fetchBlogDetail(slug: string | undefined) { collection: "blogs", where: { slug: { equals: slug }, - is_published: { - equals: true, - }, }, limit: 1, pagination: false, -- 2.47.2