dev #16
@ -111,7 +111,7 @@ export default async function Home() {
|
||||
{
|
||||
"@type": "Organization",
|
||||
"@id": `${fullUrl}#organization`,
|
||||
name: "Cochise Oncology",
|
||||
name: siteName,
|
||||
url: fullUrl,
|
||||
logo: {
|
||||
"@type": "ImageObject",
|
||||
|
157
src/app/(main)/tag/[...path]/page.tsx
Normal file
157
src/app/(main)/tag/[...path]/page.tsx
Normal file
@ -0,0 +1,157 @@
|
||||
import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter";
|
||||
import { BlogCardItemSkeleton } from "@/components/Blogs/BlogCardItem";
|
||||
import Blogs from "@/components/Blogs/Blogs";
|
||||
import HeroOther from "@/components/HeroOther";
|
||||
import { fetchBlogTagBySlug } from "@/services/payload/blog";
|
||||
import { getDefaultMetadata } from "@/utils/metadata";
|
||||
import { sanitizePageNumber } from "@/utils/sanitize";
|
||||
import { Metadata } from "next";
|
||||
import { headers } from "next/headers";
|
||||
import { notFound } from "next/navigation";
|
||||
import { Suspense } from "react";
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ path: string[0] }> }): Promise<Metadata> {
|
||||
const path = (await params)?.path;
|
||||
const paramsTag = path?.[0] ?? "";
|
||||
const metadata = await getDefaultMetadata();
|
||||
|
||||
const tag = await fetchBlogTagBySlug(paramsTag);
|
||||
if (!!tag?.data) {
|
||||
metadata.title = `${tag.data.name} Archives - ${metadata.openGraph?.siteName}`;
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
export default async function TagPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: {
|
||||
params?: Promise<{ path: string[] }>;
|
||||
searchParams?: Promise<{ page?: string; s?: string }>;
|
||||
}) {
|
||||
const path = (await params)?.path;
|
||||
const paramsTag = path?.[0] ?? "";
|
||||
const paramsPage = path?.[2] ?? "";
|
||||
const paramsSearch = (await searchParams)?.s;
|
||||
const page = sanitizePageNumber(paramsPage);
|
||||
const headersList = await headers();
|
||||
const mainUrl = headersList.get("x-main-url");
|
||||
const fullUrl = headersList.get("x-full-url");
|
||||
const siteName = headersList.get("x-site-name");
|
||||
|
||||
const tag = await fetchBlogTagBySlug(paramsTag);
|
||||
if (!tag) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "CollectionPage",
|
||||
"@id": fullUrl,
|
||||
url: fullUrl,
|
||||
name: `${tag.data.name} - ${siteName}`,
|
||||
isPartOf: {
|
||||
"@id": `${mainUrl}/#website`,
|
||||
},
|
||||
primaryImageOfPage: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
image: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
inLanguage: "en-US",
|
||||
},
|
||||
{
|
||||
"@type": "WebSite",
|
||||
"@id": `${mainUrl}/#website`,
|
||||
url: `${mainUrl}/`,
|
||||
name: siteName,
|
||||
description: "",
|
||||
publisher: {
|
||||
"@id": `${mainUrl}/#organization`,
|
||||
},
|
||||
potentialAction: [
|
||||
{
|
||||
"@type": "SearchAction",
|
||||
target: {
|
||||
"@type": "EntryPoint",
|
||||
urlTemplate: `${mainUrl}/?s={search_term_string}`,
|
||||
},
|
||||
"query-input": {
|
||||
"@type": "PropertyValueSpecification",
|
||||
valueRequired: true,
|
||||
valueName: "search_term_string",
|
||||
},
|
||||
},
|
||||
],
|
||||
inLanguage: "en-US",
|
||||
},
|
||||
{
|
||||
"@type": "Organization",
|
||||
"@id": `${mainUrl}/#organization`,
|
||||
name: siteName,
|
||||
url: `${mainUrl}/`,
|
||||
logo: {
|
||||
"@type": "ImageObject",
|
||||
inLanguage: "en-US",
|
||||
"@id": `${mainUrl}/#/schema/logo/image/`,
|
||||
url: `${mainUrl}/assets/images/logo-dark.webp`,
|
||||
contentUrl: `${mainUrl}/assets/images/logo-dark.webp`,
|
||||
caption: siteName,
|
||||
},
|
||||
image: {
|
||||
"@id": `${mainUrl}/#/schema/logo/image/`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<HeroOther title={`Tag: ${tag.data.name}`} />
|
||||
|
||||
<section className="page-section" id="blog">
|
||||
<div className="w-full max-w-7xl mx-auto px-4 md:px-8">
|
||||
<form action={`/tag/${paramsTag}`} method="GET">
|
||||
<div className="input-group">
|
||||
<input
|
||||
type="text"
|
||||
name="s"
|
||||
defaultValue={paramsSearch ?? ""}
|
||||
placeholder="Search blog..."
|
||||
className="input-lg input-circle form-control h-12"
|
||||
/>
|
||||
<div className="input-group-append px-2">
|
||||
<button className="btn btn-info text-white h-12 px-5" type="submit">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<Suspense fallback={<Loading />}>
|
||||
<Blogs preset="tags" tagId={tag.data.id} page={page} search={paramsSearch} />
|
||||
</Suspense>
|
||||
</section>
|
||||
|
||||
<BeforeFooterBlock />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Loading() {
|
||||
return (
|
||||
<div className="container position-relative">
|
||||
<div className="row">
|
||||
<BlogCardItemSkeleton />
|
||||
<BlogCardItemSkeleton />
|
||||
<BlogCardItemSkeleton />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -14,6 +14,10 @@ export type BlogsProps = {
|
||||
preset?: "categories";
|
||||
categoryId: number;
|
||||
}
|
||||
| {
|
||||
preset?: "tags";
|
||||
tagId: number;
|
||||
}
|
||||
);
|
||||
|
||||
export default async function Blogs({ page, search, ...params }: BlogsProps) {
|
||||
@ -25,6 +29,9 @@ export default async function Blogs({ page, search, ...params }: BlogsProps) {
|
||||
if (params.preset === "categories") {
|
||||
fetchBlogParams.categoryId = params.categoryId;
|
||||
}
|
||||
if (params.preset === "tags") {
|
||||
fetchBlogParams.tagId = params.tagId;
|
||||
}
|
||||
|
||||
const data = await fetchBlog(fetchBlogParams);
|
||||
|
||||
|
@ -6,9 +6,10 @@ type FetchBlogParams = {
|
||||
page?: number;
|
||||
search?: string;
|
||||
categoryId?: number;
|
||||
tagId?: number;
|
||||
};
|
||||
|
||||
export async function fetchBlog({ page, search = "", categoryId }: FetchBlogParams = {}) {
|
||||
export async function fetchBlog({ page, search = "", categoryId, tagId }: FetchBlogParams = {}) {
|
||||
const payload = await getPayload({ config: payloadConfig });
|
||||
|
||||
const queryCondition: Where = {};
|
||||
@ -22,6 +23,11 @@ export async function fetchBlog({ page, search = "", categoryId }: FetchBlogPara
|
||||
equals: categoryId,
|
||||
};
|
||||
}
|
||||
if (!!tagId) {
|
||||
queryCondition["tags"] = {
|
||||
equals: tagId,
|
||||
};
|
||||
}
|
||||
|
||||
const blogDataQuery = await payload.find({
|
||||
collection: "blogs",
|
||||
@ -86,3 +92,19 @@ export async function fetchBlogCategoryBySlug(slug: string) {
|
||||
data: category.docs[0],
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchBlogTagBySlug(slug: string) {
|
||||
const payload = await getPayload({ config: payloadConfig });
|
||||
const tag = await payload.find({
|
||||
collection: "blogTags",
|
||||
where: {
|
||||
slug: { equals: slug },
|
||||
},
|
||||
});
|
||||
|
||||
if (!tag?.docs?.[0]) return null;
|
||||
|
||||
return {
|
||||
data: tag.docs[0],
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user