Compare commits
9 Commits
9d9ce1737a
...
de6459c85a
Author | SHA1 | Date | |
---|---|---|---|
de6459c85a | |||
6fc4988506 | |||
807e78aa70 | |||
fccd846349 | |||
cab69a41e9 | |||
3373b75557 | |||
cb4e89b480 | |||
0bb0fa6ef1 | |||
cd164b6c69 |
@ -3,44 +3,57 @@ import HeroOther from "@/components/HeroOther";
|
|||||||
import Page from "@/components/Pages/Page";
|
import Page from "@/components/Pages/Page";
|
||||||
import { fetchBlogDetail } from "@/services/payload/blog";
|
import { fetchBlogDetail } from "@/services/payload/blog";
|
||||||
import { fetchPageBySlug } from "@/services/payload/page";
|
import { fetchPageBySlug } from "@/services/payload/page";
|
||||||
|
import { getDefaultMetadata } from "@/utils/metadata";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
|
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
|
||||||
const name = "Cochise Oncology";
|
const defaultMetadata = await getDefaultMetadata();
|
||||||
|
const name = defaultMetadata.openGraph?.siteName ?? "";
|
||||||
let title = "Page";
|
let title = "Page";
|
||||||
let description = "Page";
|
let description = "Page";
|
||||||
|
let publishedAt = "";
|
||||||
|
let updatedAt = "";
|
||||||
let imgUrl = "";
|
let imgUrl = "";
|
||||||
|
|
||||||
const slug = (await params).slug;
|
const slug = (await params).slug;
|
||||||
const blog = await fetchBlogDetail(slug);
|
const blog = await fetchBlogDetail(slug);
|
||||||
|
|
||||||
// check for blog data
|
|
||||||
if (!!blog) {
|
if (!!blog) {
|
||||||
|
// check for blog data
|
||||||
title = `${!!blog.data?.meta?.title ? blog.data?.meta?.title : blog.data.title} - ${name}`;
|
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}`;
|
description = `${!!blog.data?.meta?.description ? blog.data?.meta?.description : blog.data.title} - ${name}`;
|
||||||
imgUrl = blog.imgUrl;
|
imgUrl = blog.imgUrl;
|
||||||
}
|
publishedAt = blog.data.createdAt;
|
||||||
|
updatedAt = blog.data.updatedAt;
|
||||||
|
} else {
|
||||||
// check for page data when blog is not found
|
// check for page data when blog is not found
|
||||||
if (!blog) {
|
|
||||||
const page = await fetchPageBySlug({ slug });
|
const page = await fetchPageBySlug({ slug });
|
||||||
if (!!page) {
|
if (!!page) {
|
||||||
title = `${!!page?.meta?.title ? page?.meta?.title : page.title} - ${name}`;
|
title = `${!!page?.meta?.title ? page?.meta?.title : page.title} - ${name}`;
|
||||||
description = `${!!page?.meta?.description ? page?.meta?.description : page.title} - ${name}`;
|
description = `${!!page?.meta?.description ? page?.meta?.description : page.title} - ${name}`;
|
||||||
imgUrl = page.heroImg?.url;
|
imgUrl = page.heroImg?.url;
|
||||||
|
publishedAt = page.createdAt;
|
||||||
|
updatedAt = page.updatedAt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
defaultMetadata.title = title;
|
||||||
title: title,
|
defaultMetadata.description = description;
|
||||||
description: description,
|
if (!!defaultMetadata.openGraph) {
|
||||||
openGraph: {
|
defaultMetadata.openGraph.title = title;
|
||||||
title: title,
|
// @ts-ignore
|
||||||
description: description,
|
defaultMetadata.openGraph.type = "article";
|
||||||
images: !!imgUrl ? { url: imgUrl } : undefined,
|
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 }> }) {
|
export default async function SinglePage({ params }: { params: Promise<{ slug: string }> }) {
|
||||||
|
@ -3,9 +3,11 @@ import Footer from "@/components/Footer";
|
|||||||
import Header from "@/components/Header";
|
import Header from "@/components/Header";
|
||||||
import InitialScript from "@/components/InitialScript";
|
import InitialScript from "@/components/InitialScript";
|
||||||
import { navMenuData } from "@/data/menu";
|
import { navMenuData } from "@/data/menu";
|
||||||
|
import { getDefaultMetadata } from "@/utils/metadata";
|
||||||
|
|
||||||
import "@public/assets/css/styles.css";
|
import "@public/assets/css/styles.css";
|
||||||
import "jarallax/dist/jarallax.min.css";
|
import "jarallax/dist/jarallax.min.css";
|
||||||
|
import { Metadata } from "next";
|
||||||
import { Roboto } from "next/font/google";
|
import { Roboto } from "next/font/google";
|
||||||
import "photoswipe/dist/photoswipe.css";
|
import "photoswipe/dist/photoswipe.css";
|
||||||
import "react-modal-video/css/modal-video.css";
|
import "react-modal-video/css/modal-video.css";
|
||||||
@ -15,6 +17,11 @@ import "tippy.js/dist/tippy.css";
|
|||||||
|
|
||||||
const roboto = Roboto({ subsets: ["latin"] });
|
const roboto = Roboto({ subsets: ["latin"] });
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const metadata = await getDefaultMetadata();
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
export default function MainLayout({
|
export default function MainLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import formatSlug from "@/utils/formatSlug";
|
import formatSlug from "@/utils/payload/formatSlug";
|
||||||
import type { CollectionConfig } from "payload";
|
import type { CollectionConfig } from "payload";
|
||||||
|
|
||||||
export const BlogCategories: CollectionConfig = {
|
export const BlogCategories: CollectionConfig = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import formatSlug from "@/utils/formatSlug";
|
import formatSlug from "@/utils/payload/formatSlug";
|
||||||
import type { CollectionConfig } from "payload";
|
import type { CollectionConfig } from "payload";
|
||||||
|
|
||||||
export const BlogTags: CollectionConfig = {
|
export const BlogTags: CollectionConfig = {
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import type { CollectionConfig } from "payload";
|
import formatSlug from "@/utils/payload/formatSlug";
|
||||||
|
import setAuthor from "@/utils/payload/setAuthor";
|
||||||
import { lexicalEditor } from "@payloadcms/richtext-lexical";
|
import { lexicalEditor } from "@payloadcms/richtext-lexical";
|
||||||
import formatSlug from "@/utils/formatSlug";
|
import type { CollectionConfig } from "payload";
|
||||||
|
|
||||||
export const Blogs: CollectionConfig = {
|
export const Blogs: CollectionConfig = {
|
||||||
slug: "blogs",
|
slug: "blogs",
|
||||||
labels: { plural: "Posts", singular: "Post" },
|
labels: { plural: "Posts", singular: "Post" },
|
||||||
|
versions: {
|
||||||
|
drafts: {
|
||||||
|
validate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "title",
|
name: "title",
|
||||||
@ -59,19 +65,32 @@ export const Blogs: CollectionConfig = {
|
|||||||
type: "textarea",
|
type: "textarea",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "cannonical_url",
|
name: "canonical_url",
|
||||||
label: "Cannonical Url",
|
label: "Canonical Url",
|
||||||
type: "text",
|
type: "text",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "is_published",
|
name: "createdBy",
|
||||||
label: "Published",
|
type: "relationship",
|
||||||
type: "checkbox",
|
relationTo: "users",
|
||||||
defaultValue: true,
|
hooks: {
|
||||||
|
beforeChange: [setAuthor],
|
||||||
|
},
|
||||||
admin: {
|
admin: {
|
||||||
position: "sidebar",
|
hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "updatedBy",
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: "users",
|
||||||
|
hooks: {
|
||||||
|
beforeChange: [setAuthor],
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
hidden: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -7,11 +7,17 @@ import { GoogleReviewBlock } from "@/blocks/GoogleReview";
|
|||||||
import { HorizontalImageContentBlock } from "@/blocks/HorizontalImageContent";
|
import { HorizontalImageContentBlock } from "@/blocks/HorizontalImageContent";
|
||||||
import { ImageSliderBlock } from "@/blocks/ImageSlider";
|
import { ImageSliderBlock } from "@/blocks/ImageSlider";
|
||||||
import { OurTeamBlock } from "@/blocks/OurTeam";
|
import { OurTeamBlock } from "@/blocks/OurTeam";
|
||||||
import formatSlug from "@/utils/formatSlug";
|
import formatSlug from "@/utils/payload/formatSlug";
|
||||||
|
import setAuthor from "@/utils/payload/setAuthor";
|
||||||
import { CollectionConfig } from "payload";
|
import { CollectionConfig } from "payload";
|
||||||
|
|
||||||
export const Pages: CollectionConfig = {
|
export const Pages: CollectionConfig = {
|
||||||
slug: "pages",
|
slug: "pages",
|
||||||
|
versions: {
|
||||||
|
drafts: {
|
||||||
|
validate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "title",
|
name: "title",
|
||||||
@ -29,9 +35,6 @@ export const Pages: CollectionConfig = {
|
|||||||
name: "slug",
|
name: "slug",
|
||||||
label: "Page Slug",
|
label: "Page Slug",
|
||||||
type: "text",
|
type: "text",
|
||||||
admin: {
|
|
||||||
position: "sidebar",
|
|
||||||
},
|
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeValidate: [formatSlug("title")],
|
beforeValidate: [formatSlug("title")],
|
||||||
},
|
},
|
||||||
@ -75,6 +78,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: {
|
admin: {
|
||||||
hideAPIURL: true,
|
hideAPIURL: true,
|
||||||
|
@ -11,5 +11,10 @@ export const Users: CollectionConfig = {
|
|||||||
fields: [
|
fields: [
|
||||||
// Email added by default
|
// Email added by default
|
||||||
// Add more fields as needed
|
// Add more fields as needed
|
||||||
|
{
|
||||||
|
name: "name",
|
||||||
|
label: "Name",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,10 @@ export function middleware(request: NextRequest) {
|
|||||||
const host = request.headers.get("x-forwarded-host") || request.nextUrl.hostname;
|
const host = request.headers.get("x-forwarded-host") || request.nextUrl.hostname;
|
||||||
const path = request.nextUrl.pathname + request.nextUrl.search;
|
const path = request.nextUrl.pathname + request.nextUrl.search;
|
||||||
// Construct the full URL
|
// 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);
|
request.headers.set("x-full-url", fullUrl);
|
||||||
|
|
||||||
return NextResponse.next({
|
return NextResponse.next({
|
||||||
|
@ -83,6 +83,7 @@ export interface UserAuthOperations {
|
|||||||
*/
|
*/
|
||||||
export interface User {
|
export interface User {
|
||||||
id: number;
|
id: number;
|
||||||
|
name?: string | null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
email: string;
|
email: string;
|
||||||
@ -143,11 +144,13 @@ export interface Blog {
|
|||||||
meta?: {
|
meta?: {
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
description?: 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;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
@ -303,8 +306,11 @@ export interface Page {
|
|||||||
description?: string | null;
|
description?: string | null;
|
||||||
cannonical_url?: string | null;
|
cannonical_url?: string | null;
|
||||||
};
|
};
|
||||||
|
createdBy?: (number | null) | User;
|
||||||
|
updatedBy?: (number | null) | User;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
@ -593,6 +599,7 @@ export interface PayloadMigration {
|
|||||||
* via the `definition` "users_select".
|
* via the `definition` "users_select".
|
||||||
*/
|
*/
|
||||||
export interface UsersSelect<T extends boolean = true> {
|
export interface UsersSelect<T extends boolean = true> {
|
||||||
|
name?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
email?: T;
|
email?: T;
|
||||||
@ -638,11 +645,13 @@ export interface BlogsSelect<T extends boolean = true> {
|
|||||||
| {
|
| {
|
||||||
title?: T;
|
title?: T;
|
||||||
description?: T;
|
description?: T;
|
||||||
cannonical_url?: T;
|
canonical_url?: T;
|
||||||
};
|
};
|
||||||
is_published?: T;
|
createdBy?: T;
|
||||||
|
updatedBy?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
|
_status?: T;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
@ -741,8 +750,11 @@ export interface PagesSelect<T extends boolean = true> {
|
|||||||
description?: T;
|
description?: T;
|
||||||
cannonical_url?: T;
|
cannonical_url?: T;
|
||||||
};
|
};
|
||||||
|
createdBy?: T;
|
||||||
|
updatedBy?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
|
_status?: T;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
@ -10,25 +10,12 @@ export async function fetchBlog(page: number | undefined, search: string = "") {
|
|||||||
pagination: true,
|
pagination: true,
|
||||||
limit: 6,
|
limit: 6,
|
||||||
where: !search
|
where: !search
|
||||||
? {
|
? undefined
|
||||||
is_published: {
|
|
||||||
equals: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: {
|
: {
|
||||||
and: [
|
|
||||||
{
|
|
||||||
is_published: {
|
|
||||||
equals: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: {
|
title: {
|
||||||
contains: search,
|
contains: search,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const formattedData = blogDataQuery.docs.map((item) => {
|
const formattedData = blogDataQuery.docs.map((item) => {
|
||||||
@ -51,9 +38,6 @@ export async function fetchBlogDetail(slug: string | undefined) {
|
|||||||
collection: "blogs",
|
collection: "blogs",
|
||||||
where: {
|
where: {
|
||||||
slug: { equals: slug },
|
slug: { equals: slug },
|
||||||
is_published: {
|
|
||||||
equals: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
limit: 1,
|
limit: 1,
|
||||||
pagination: false,
|
pagination: false,
|
||||||
|
21
src/utils/metadata.ts
Normal file
21
src/utils/metadata.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Metadata } from "next";
|
||||||
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
|
export async function getDefaultMetadata(): Promise<Metadata> {
|
||||||
|
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: "./",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
17
src/utils/payload/setAuthor.ts
Normal file
17
src/utils/payload/setAuthor.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { FieldHook } from "payload";
|
||||||
|
|
||||||
|
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 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setAuthor;
|
Loading…
x
Reference in New Issue
Block a user