Compare commits
20 Commits
f3d8e30046
...
c7dcb7e7b4
Author | SHA1 | Date | |
---|---|---|---|
c7dcb7e7b4 | |||
76c39f214c | |||
dbf89a93e5 | |||
9bfe2fc700 | |||
ad39804e06 | |||
ba72910f98 | |||
8ef5545f93 | |||
d010f6a965 | |||
![]() |
b5931a5612 | ||
fa11bb928e | |||
e8cb280326 | |||
18e90ecbf2 | |||
879f156f27 | |||
312c891dda | |||
ae877c44a1 | |||
e1e328f79a | |||
86c8e2a929 | |||
b064367fd7 | |||
f0c7dc58e7 | |||
06b682bee6 |
17
env
17
env
@ -1,17 +0,0 @@
|
||||
SERVICE_SUPABASESERVICE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTczODQ3MzA2MCwiZXhwIjo0ODk0MTQ2NjYwLCJyb2xlIjoic2VydmljZV9yb2xlIn0.nRpZfD6Uur9yzCT_BTgLH9DLWsCcCiAgWKenJ_qYu5M\
|
||||
|
||||
SERVICE_SUPABASEANON_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTczODQ3MzA2MCwiZXhwIjo0ODk0MTQ2NjYwLCJyb2xlIjoiYW5vbiJ9.WXJvhzD1gD6Kxlq8PLFAcpaVFmh9h3xbJHh9oow2IFQ
|
||||
|
||||
SUPABASE_URL=https://supabasekong-n00g8kwoos4skc0gw44k8sks.dev3vds1.link
|
||||
|
||||
# payload
|
||||
|
||||
DATABASE_URI=postgresql://postgres.jswmbraeandqttpcdfmj:qDY4C35XaRsmW6dW@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres
|
||||
PAYLOAD_SECRET=1b7204f9ed5f7ab09706fc51
|
||||
S3_BUCKET=cochise-bucket
|
||||
S3_ACCESS_KEY_ID=97394cd503ae9973efa25168ed980e51
|
||||
S3_SECRET_ACCESS_KEY=9b4e412850582aab32ffdadbe23bb7ea972b39aaf79c34da0c19d3fcafe11dd0
|
||||
S3_REGION=ap-southeast-1
|
||||
S3_ENDPOINT=https://jswmbraeandqttpcdfmj.supabase.co/storage/v1/s3
|
||||
NEXT_PUBLIC_PAYLOAD_URL=http://localhost:3000
|
||||
SITE_URL=http://localhost:3000
|
@ -11,7 +11,7 @@
|
||||
--color-gray-1: #697582;
|
||||
--color-gray-2: #747f8c;
|
||||
--color-gray-3: #8a95a2;
|
||||
--color-primary-1: #1872e8;
|
||||
--color-primary-1: #00898b;
|
||||
--color-primary-1-a: #2b87ff;
|
||||
--color-primary-light-1: #e3effe;
|
||||
--color-primary-light-1-a: #bcd1f1;
|
||||
|
@ -191,7 +191,7 @@ Primary use: Multipurpose Template
|
||||
--color-gray-light-6: #bbb;
|
||||
--color-dark-mode-gray-1: rgba(255, 255, 255, 0.7);
|
||||
--color-dark-mode-gray-2: rgba(255, 255, 255, 0.1275);
|
||||
--color-primary-1: #4567ed;
|
||||
--color-primary-1: #00898b;
|
||||
--color-primary-1-a: #375ae3;
|
||||
--color-primary-light-1: #e3effe;
|
||||
--color-primary-light-1-a: #bcd1f1;
|
||||
|
BIN
public/assets/images/logo-dark.webp
Normal file
BIN
public/assets/images/logo-dark.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -16,6 +16,7 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
let updatedAt = "";
|
||||
let imgUrl = "";
|
||||
let createdByName = "";
|
||||
let canonicalUrl = "";
|
||||
|
||||
const slug = (await params).slug;
|
||||
const blog = await fetchBlogDetail(slug);
|
||||
@ -27,6 +28,9 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
imgUrl = blog.imgUrl;
|
||||
publishedAt = blog.data.createdAt;
|
||||
updatedAt = blog.data.updatedAt;
|
||||
if (!!blog.data?.meta?.canonical_url) {
|
||||
canonicalUrl = blog.data.meta.canonical_url;
|
||||
}
|
||||
if (!!blog?.data?.createdBy && typeof blog.data.createdBy !== "number") {
|
||||
createdByName = blog.data.createdBy?.name ?? "";
|
||||
}
|
||||
@ -39,7 +43,9 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
imgUrl = page.heroImg?.url;
|
||||
publishedAt = page.createdAt;
|
||||
updatedAt = page.updatedAt;
|
||||
|
||||
if (!!page.meta?.canonical_url) {
|
||||
canonicalUrl = page.meta.canonical_url;
|
||||
}
|
||||
if (!!page?.createdBy && typeof page.createdBy !== "number") {
|
||||
createdByName = page?.createdBy?.name ?? "";
|
||||
}
|
||||
@ -55,6 +61,9 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
defaultMetadata.openGraph.description = description;
|
||||
defaultMetadata.openGraph.images = !!imgUrl ? [imgUrl] : undefined;
|
||||
}
|
||||
if (!!defaultMetadata.alternates && !!canonicalUrl) {
|
||||
defaultMetadata.alternates.canonical = canonicalUrl;
|
||||
}
|
||||
defaultMetadata.twitter = {
|
||||
card: "summary_large_image",
|
||||
title: title,
|
||||
|
74
src/app/(main)/category/[...path]/page.tsx
Normal file
74
src/app/(main)/category/[...path]/page.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter";
|
||||
import { BlogCardItemSkeleton } from "@/components/Blogs/BlogCardItem";
|
||||
import Blogs from "@/components/Blogs/Blogs";
|
||||
import HeroOther from "@/components/HeroOther";
|
||||
import { getDefaultMetadata } from "@/utils/metadata";
|
||||
import { sanitizePageNumber } from "@/utils/sanitize";
|
||||
import { Metadata } from "next";
|
||||
// import { headers } from "next/headers";
|
||||
import { Suspense } from "react";
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const metadata = await getDefaultMetadata();
|
||||
return metadata;
|
||||
}
|
||||
|
||||
export default async function CategoryPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: {
|
||||
params?: Promise<{ path: string[] }>;
|
||||
searchParams?: Promise<{ page?: string; s?: string }>;
|
||||
}) {
|
||||
const path = (await params)?.path;
|
||||
// const headersList = await headers();
|
||||
// const paramsCategory = path?.[0] ?? "";
|
||||
const paramsPage = path?.[2] ?? "";
|
||||
const paramsSearch = (await searchParams)?.s;
|
||||
const page = sanitizePageNumber(paramsPage);
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeroOther title="Blog" />
|
||||
|
||||
<section className="page-section" id="blog">
|
||||
<div className="w-full max-w-7xl mx-auto px-4 md:px-8">
|
||||
<form action={`category/chemotherapy/page/1`} 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="categories" page={page} search={paramsSearch} />
|
||||
</Suspense>
|
||||
</section>
|
||||
|
||||
<BeforeFooterBlock />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Loading() {
|
||||
return (
|
||||
<div className="container position-relative">
|
||||
<div className="row">
|
||||
<BlogCardItemSkeleton />
|
||||
<BlogCardItemSkeleton />
|
||||
<BlogCardItemSkeleton />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,38 +1,139 @@
|
||||
import Parallax from "./home-bg-video/page";
|
||||
import Homepage from "@/components/Homepage";
|
||||
import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter";
|
||||
import { Metadata, Viewport } from "next";
|
||||
import { getDefaultMetadata } from "@/utils/metadata";
|
||||
import HomeBgVideo from "@/components/HomeBgVideo";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
export const metadata = {
|
||||
title: "HomePage - Cochise Oncology",
|
||||
description: "Cochise Oncology",
|
||||
keywords: "Cochise Oncology, Oncology, Healthcare, Medical Services, Cancer Treatment",
|
||||
author: "Cochise Oncology",
|
||||
robots: "index, follow",
|
||||
og: {
|
||||
title: "HomePage - Cochise Oncology",
|
||||
description: "Cochise Oncology",
|
||||
type: "website",
|
||||
url: "https://www.cochiseoncology.com",
|
||||
image: "https://www.cochiseoncology.com/og-image.jpg",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
site: "@CochiseOncology",
|
||||
title: "HomePage - Cochise Oncology",
|
||||
description: "Cochise Oncology",
|
||||
image: "https://www.cochiseoncology.com/twitter-image.jpg",
|
||||
},
|
||||
};
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const defaultMetadata = await getDefaultMetadata();
|
||||
defaultMetadata.title = `Homepage - ${defaultMetadata.openGraph?.siteName}`;
|
||||
defaultMetadata.keywords = "Cochise Oncology, Oncology, Healthcare, Medical Services, Cancer Treatment";
|
||||
|
||||
export const viewport = {
|
||||
if (!!defaultMetadata?.openGraph) {
|
||||
defaultMetadata.openGraph.images = ["/assets/images/cochise-welcome.png"];
|
||||
}
|
||||
|
||||
return defaultMetadata;
|
||||
}
|
||||
|
||||
export const viewport: Viewport = {
|
||||
width: "device-width",
|
||||
initialScale: 1,
|
||||
};
|
||||
|
||||
export default function Home() {
|
||||
export default async function Home() {
|
||||
const headersList = await headers();
|
||||
const fullUrl = headersList.get("x-full-url");
|
||||
const siteName = headersList.get("x-site-name");
|
||||
const metaDesc = headersList.get("x-meta-desc");
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "WebPage",
|
||||
"@id": fullUrl,
|
||||
url: fullUrl,
|
||||
name: `Homepage - ${siteName}`,
|
||||
isPartOf: {
|
||||
"@id": `${fullUrl}#website`,
|
||||
},
|
||||
about: {
|
||||
"@id": `${fullUrl}#organization`,
|
||||
},
|
||||
primaryImageOfPage: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
image: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
thumbnailUrl: [`${fullUrl}assets/images/cochise-welcome.png`],
|
||||
datePublished: "2024-07-18T16:29:29+00:00",
|
||||
dateModified: "2025-02-24T21:01:50+00:00",
|
||||
description: metaDesc,
|
||||
breadcrumb: {
|
||||
"@id": `${fullUrl}#breadcrumb`,
|
||||
},
|
||||
inLanguage: "en-US",
|
||||
potentialAction: [
|
||||
{
|
||||
"@type": "ReadAction",
|
||||
target: [fullUrl],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"@type": "ImageObject",
|
||||
inLanguage: "en-US",
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
url: `${fullUrl}assets/images/cochise-welcome.png`,
|
||||
contentUrl: `${fullUrl}assets/images/cochise-welcome.png`,
|
||||
width: 940,
|
||||
height: 788,
|
||||
},
|
||||
{
|
||||
"@type": "BreadcrumbList",
|
||||
"@id": `${fullUrl}#breadcrumb`,
|
||||
itemListElement: [
|
||||
{
|
||||
"@type": "ListItem",
|
||||
position: 1,
|
||||
name: "Home",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"@type": "WebSite",
|
||||
"@id": `${fullUrl}#website`,
|
||||
url: fullUrl,
|
||||
name: siteName,
|
||||
description: "",
|
||||
publisher: {
|
||||
"@id": `${fullUrl}#organization`,
|
||||
},
|
||||
potentialAction: [
|
||||
{
|
||||
"@type": "SearchAction",
|
||||
target: {
|
||||
"@type": "EntryPoint",
|
||||
urlTemplate: `${fullUrl}?s={search_term_string}`,
|
||||
},
|
||||
"query-input": {
|
||||
"@type": "PropertyValueSpecification",
|
||||
valueRequired: true,
|
||||
valueName: "search_term_string",
|
||||
},
|
||||
},
|
||||
],
|
||||
inLanguage: "en-US",
|
||||
},
|
||||
{
|
||||
"@type": "Organization",
|
||||
"@id": `${fullUrl}#organization`,
|
||||
name: "Cochise Oncology",
|
||||
url: fullUrl,
|
||||
logo: {
|
||||
"@type": "ImageObject",
|
||||
inLanguage: "en-US",
|
||||
"@id": `${fullUrl}#/schema/logo/image/`,
|
||||
url: `${fullUrl}assets/images/cochise-welcome.png`,
|
||||
contentUrl: `${fullUrl}assets/images/cochise-welcome.png`,
|
||||
width: 500,
|
||||
height: 195,
|
||||
caption: siteName,
|
||||
},
|
||||
image: {
|
||||
"@id": `${fullUrl}#/schema/logo/image/`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Parallax />
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<HomeBgVideo />
|
||||
<Homepage />
|
||||
<BeforeFooterBlock />
|
||||
</>
|
||||
|
@ -3,7 +3,9 @@ import HeroOther from "@/components/HeroOther";
|
||||
import { fetchTeamDetail } from "@/services/payload/team";
|
||||
import { getDefaultMetadata } from "@/utils/metadata";
|
||||
import { RichText } from "@payloadcms/richtext-lexical/react";
|
||||
import { headers } from "next/headers";
|
||||
import Image from "next/image";
|
||||
import { notFound } from "next/navigation";
|
||||
import { Metadata } from "next/types";
|
||||
import { Suspense } from "react";
|
||||
|
||||
@ -45,17 +47,94 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
export default async function BiographySinglePage({ params }: { params: Promise<{ slug: string }> }) {
|
||||
const slug = (await params).slug;
|
||||
const data = await fetchTeamDetail(decodeURIComponent(slug));
|
||||
if (!data?.data)
|
||||
return (
|
||||
<>
|
||||
<BeforeFooterBlock />
|
||||
</>
|
||||
);
|
||||
if (!data?.data) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
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 metaDesc = headersList.get("x-meta-desc");
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "WebPage",
|
||||
"@id": fullUrl,
|
||||
url: fullUrl,
|
||||
name: `${data?.data?.name ?? ""} - ${siteName}`,
|
||||
isPartOf: {
|
||||
"@id": `${mainUrl}/#website`,
|
||||
},
|
||||
datePublished: data?.data?.createdAt,
|
||||
dateModified: data?.data?.updatedAt,
|
||||
description: metaDesc,
|
||||
breadcrumb: {
|
||||
"@id": `${fullUrl}#breadcrumb`,
|
||||
},
|
||||
inLanguage: "en-US",
|
||||
potentialAction: [
|
||||
{
|
||||
"@type": "ReadAction",
|
||||
target: [fullUrl],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"@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",
|
||||
thumbnailUrl: data.imgUrl,
|
||||
inLanguage: "en-US",
|
||||
"@id": `${mainUrl}/#primaryimage`,
|
||||
url: data.imgUrl,
|
||||
contentUrl: data.imgUrl,
|
||||
width: 500,
|
||||
height: 195,
|
||||
caption: siteName,
|
||||
},
|
||||
image: {
|
||||
"@id": `${mainUrl}/#primaryimage`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Suspense fallback={<Loading />}>
|
||||
<>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<HeroOther
|
||||
img={"/assets/images/full-width-images/section-bg-13.jpeg"}
|
||||
title={data.data.name}
|
||||
|
@ -59,6 +59,10 @@ body {
|
||||
.ext-btn-shadow-sm-primary4 {
|
||||
@apply bg-extColorPrimary4 text-white hover:text-white hover:bg-extColorPrimary6 transition-colors;
|
||||
}
|
||||
|
||||
.ext-btn-shadow-sm-primary8 {
|
||||
@apply bg-extColorPrimary8 text-white hover:text-white hover:bg-extColorPrimary6 transition-colors;
|
||||
}
|
||||
}
|
||||
|
||||
.bg-gradient {
|
||||
|
@ -72,8 +72,8 @@ export const Pages: CollectionConfig = {
|
||||
type: "textarea",
|
||||
},
|
||||
{
|
||||
name: "cannonical_url",
|
||||
label: "Cannonical Url",
|
||||
name: "canonical_url",
|
||||
label: "Canonical Url",
|
||||
type: "text",
|
||||
},
|
||||
],
|
||||
|
@ -52,7 +52,7 @@ export function BeforeFooterBlock({ title, description, buttonText, showLinier =
|
||||
<div className="pt-5">
|
||||
<Link
|
||||
href="/contact"
|
||||
className="inline-block bg-extColorPrimary6 hover:bg-extColorPrimary8 text-white py-3 px-6 rounded-full text-lg shadow-lg transition-all duration-500"
|
||||
className="inline-block bg-extColorPrimary6 hover:bg-extColorPrimary8 text-white py-3 px-6 hover:scale-105 rounded-full text-lg shadow-sm transition-all duration-500"
|
||||
>
|
||||
{buttonText ?? placeholderButtonText} →
|
||||
</Link>
|
||||
|
@ -32,9 +32,9 @@ export function GoogleReviews({ data }: GoogleReviewProps) {
|
||||
<div className="flex justify-center items-center space-x-2">
|
||||
<h2 className="text-xl text-center font-bol mt-[15px]">{data.ratingValue}</h2>
|
||||
<div className="mt-1">
|
||||
<StarRating size={20} value={data.ratingValue} />
|
||||
<StarRating size={30} value={data.ratingValue} />
|
||||
</div>
|
||||
<div className="text-xs font-medium">Over {data.totalRating} Reviews</div>
|
||||
<div className="font-medium">Over {data.totalRating} Reviews</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-20 relative">
|
||||
|
@ -5,7 +5,7 @@ import { fetchBlog } from "@/services/payload/blog";
|
||||
import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize";
|
||||
|
||||
export default async function Blog() {
|
||||
const data = await fetchBlog(undefined);
|
||||
const data = await fetchBlog();
|
||||
|
||||
if (!data?.totalDocs) return <></>;
|
||||
return (
|
||||
|
@ -31,7 +31,7 @@ export function BlogCardItem({ data }: BlogCardItemProps) {
|
||||
<a href={`/${data.slug}/`}>{data.title}</a>
|
||||
</h2>
|
||||
<div className="flex justify-center mt-2">
|
||||
<a href={`/${data.slug}/`} className="ext-btn-shadow-sm ext-btn-shadow-sm-primary4">
|
||||
<a href={`/${data.slug}/`} className="ext-btn-shadow-sm ext-btn-shadow-sm-primary8">
|
||||
Continue Reading
|
||||
</a>
|
||||
</div>
|
||||
|
@ -13,6 +13,7 @@ export interface BlogDetailProps {
|
||||
export default async function BlogDetail({ slug }: BlogDetailProps) {
|
||||
const data = await fetchBlogDetail(slug);
|
||||
const headersList = await headers();
|
||||
const mainUrl = headersList.get("x-main-url");
|
||||
const fullUrl = headersList.get("x-full-url");
|
||||
|
||||
const shareUrl = {
|
||||
@ -25,8 +26,73 @@ export default async function BlogDetail({ slug }: BlogDetailProps) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
let author = {};
|
||||
if (!!data?.data?.createdBy && typeof data?.data?.createdBy !== "number") {
|
||||
author = {
|
||||
author: {
|
||||
name: data?.data?.createdBy?.name,
|
||||
"@id": `${mainUrl}/#/schema/person/${data?.data?.createdBy?.id}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "Article",
|
||||
"@id": `${fullUrl}#article`,
|
||||
isPartOf: {
|
||||
"@id": fullUrl,
|
||||
},
|
||||
...author,
|
||||
headline: data?.data?.title ?? "",
|
||||
datePublished: data?.createdAt,
|
||||
dateModified: data?.updatedAt,
|
||||
mainEntityOfPage: {
|
||||
"@id": fullUrl,
|
||||
},
|
||||
publisher: { "@id": `${mainUrl}/#organization` },
|
||||
image: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
thumbnailUrl: data?.imgUrl ?? "",
|
||||
inLanguage: "en-US",
|
||||
},
|
||||
{
|
||||
"@type": "WebPage",
|
||||
"@id": fullUrl,
|
||||
url: fullUrl,
|
||||
name: `${data?.data?.title ?? ""} - Cochise Oncology`,
|
||||
isPartOf: { "@id": `${mainUrl}/#website` },
|
||||
primaryImageOfPage: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
image: {
|
||||
"@id": `${fullUrl}#primaryimage`,
|
||||
},
|
||||
thumbnailUrl: data?.imgUrl ?? "",
|
||||
datePublished: data?.createdAt,
|
||||
dateModified: data?.updatedAt,
|
||||
description: data?.data?.meta?.description,
|
||||
breadcrumb: {
|
||||
"@id": `${fullUrl}#breadcrumb`,
|
||||
},
|
||||
inLanguage: "en-US",
|
||||
potentialAction: [
|
||||
{
|
||||
"@type": "ReadAction",
|
||||
target: [fullUrl],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
|
||||
<HeroOther title={data.data.title} createdAt={data?.createdAt} shareUrl={shareUrl} />
|
||||
|
||||
{/* Section */}
|
||||
|
@ -4,12 +4,13 @@ import { BlogCardItem } from "./BlogCardItem";
|
||||
import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize";
|
||||
|
||||
export interface BlogsProps {
|
||||
preset?: "blogs" | "categories";
|
||||
page: number;
|
||||
search?: string;
|
||||
}
|
||||
|
||||
export default async function Blogs({ page, search }: BlogsProps) {
|
||||
const data = await fetchBlog(page, search);
|
||||
export default async function Blogs({ page, search, preset = "blogs" }: BlogsProps) {
|
||||
const data = await fetchBlog({ page, search });
|
||||
|
||||
if (!data?.totalDocs) return <></>;
|
||||
|
||||
@ -41,6 +42,7 @@ export default async function Blogs({ page, search }: BlogsProps) {
|
||||
hasNextPage={data.hasNextPage}
|
||||
hasPreviousPage={data.hasPrevPage}
|
||||
totalPages={data.totalPages}
|
||||
usePathParams={preset === "blogs" ? false : true}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Image from "next/image";
|
||||
import { FaClock, FaFacebook, FaFax, FaLinkedin, FaMapMarkerAlt, FaPhone } from "react-icons/fa";
|
||||
import { FaClock, FaFacebookF, FaFax, FaLinkedinIn, FaMapMarkerAlt } from "react-icons/fa";
|
||||
import { GiRotaryPhone } from "react-icons/gi";
|
||||
import ScrollToTop from "./ScrollToTop";
|
||||
import { fetchContact } from "@/services/payload/contact";
|
||||
import { Suspense } from "react";
|
||||
@ -25,11 +26,11 @@ async function FooterWithData() {
|
||||
backgroundImage: "linear-gradient(172deg, #798D90 0%, #C48853 100%)",
|
||||
}}
|
||||
>
|
||||
<div className="container mx-auto flex flex-wrap justify-between items-start px-6">
|
||||
<div className="container mx-auto flex flex-wrap justify-around items-start px-6">
|
||||
<div className="w-full md:w-1/4 mb-6 md:mb-0 flex flex-col items-start">
|
||||
<Image src="/assets/images/demo-slick/logo-dark.webp" alt="Cochise Oncology Logo" width={363} height={138} />
|
||||
<p className="text-sm mt-3">© {new Date().getFullYear()} All Rights Reserved</p>
|
||||
<a href="/privacy-policy" className="text-sm text-orange-300 font-semibold">
|
||||
<p className="mt-4 mb-2">© {new Date().getFullYear()} All Rights Reserved</p>
|
||||
<a href="/privacy-policy" className="text text-extColorPrimary8 font-semibold">
|
||||
Privacy Policy
|
||||
</a>
|
||||
</div>
|
||||
@ -37,8 +38,8 @@ async function FooterWithData() {
|
||||
<div className="w-full md:w-1/3 mb-6 md:mb-0">
|
||||
<h3 className="text-lg font-semibold mb-4">Contact Us</h3>
|
||||
<ul className="space-y-4 border-gray-400 pl-0">
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<FaMapMarkerAlt className="text-2xl text-gray-300" />
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<FaMapMarkerAlt className="text-2xl text-white-300" />
|
||||
<div className="leading-tight">
|
||||
<a
|
||||
href={contact?.location?.href ?? ""}
|
||||
@ -49,49 +50,49 @@ async function FooterWithData() {
|
||||
{contact?.location?.street ?? ""}
|
||||
</a>
|
||||
<br />
|
||||
<span className="text-sm text-gray-300">{contact?.fullLocation ?? ""}</span>
|
||||
<span className="text-sm text-white-300">{contact?.fullLocation ?? ""}</span>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<FaPhone className="text-2xl text-gray-300" />
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<GiRotaryPhone className="text-2xl text-white-300" />
|
||||
<a
|
||||
href={`tel:${contact?.phone ?? ""}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-lg text-white"
|
||||
className="text-lg text-white text-[18px]"
|
||||
>
|
||||
{contact?.phone ?? ""}
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<FaFax className="text-2xl text-gray-300" />
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<FaFax className="text-2xl text-white-300" />
|
||||
<a
|
||||
href={`tel:${contact?.fax ?? ""}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-lg text-white"
|
||||
className="text-lg text-white text-[18px]"
|
||||
>
|
||||
Fax: {contact?.fax ?? ""}
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<FaFacebook className="text-2xl text-gray-300" />
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<FaFacebookF className="text-2xl text-white-300" />
|
||||
<a
|
||||
href={contact?.facebook ?? ""}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-lg text-white"
|
||||
className="text-lg text-white text-[18px]"
|
||||
>
|
||||
Facebook
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4">
|
||||
<FaLinkedin className="text-2xl text-gray-300" />
|
||||
<FaLinkedinIn className="text-2xl text-white-300" />
|
||||
<a
|
||||
href={contact?.linkedin ?? ""}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-lg text-white"
|
||||
className="text-lg text-white text-[18px]"
|
||||
>
|
||||
Linkedin
|
||||
</a>
|
||||
@ -126,7 +127,7 @@ function FooterSkeleton() {
|
||||
backgroundImage: "linear-gradient(172deg, #798D90 0%, #C48853 100%)",
|
||||
}}
|
||||
>
|
||||
<div className="container mx-auto flex flex-wrap justify-between items-start px-6">
|
||||
<div className="container mx-auto flex flex-wrap justify-around items-start px-6">
|
||||
<div className="w-full md:w-1/4 mb-6 md:mb-0 flex flex-col items-start">
|
||||
<Image src="/assets/images/demo-slick/logo-dark.webp" alt="Cochise Oncology Logo" width={363} height={138} />
|
||||
<p className="text-sm mt-3">© {new Date().getFullYear()} All Rights Reserved</p>
|
||||
@ -135,28 +136,28 @@ function FooterSkeleton() {
|
||||
<div className="w-full md:w-1/3 mb-6 md:mb-0 animate-pulse">
|
||||
<h3 className="text-lg font-semibold mb-4">Contact Us</h3>
|
||||
<ul className="space-y-4 border-gray-400 pl-0">
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<FaMapMarkerAlt className="text-2xl text-gray-300" />
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<FaPhone className="text-2xl text-gray-300" />
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<GiRotaryPhone className="text-2xl text-gray-300" />
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4 border-b border-gray-500 pb-2">
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89] pb-2">
|
||||
<FaFax className="text-2xl text-gray-300" />
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4">
|
||||
<FaFacebook className="text-2xl text-gray-300" />
|
||||
<li className="flex items-center space-x-4 border-b-[0.8px] border-[#b69a89]">
|
||||
<FaFacebookF className="text-2xl text-gray-300" />
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
</li>
|
||||
<li className="flex items-center space-x-4">
|
||||
<FaLinkedin className="text-2xl text-gray-300" />
|
||||
<FaLinkedinIn className="text-2xl text-gray-300" />
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
</li>
|
||||
@ -167,8 +168,8 @@ function FooterSkeleton() {
|
||||
<h3 className="text-lg font-semibold mb-4">Business Hours</h3>
|
||||
<div className="flex items-center space-x-2">
|
||||
<FaClock className="text-xl" />
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-white-300 rounded flex-1"></div>
|
||||
<div className="h-2 bg-white-300 rounded flex-1"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,27 +11,27 @@ const shareIcons: Record<string, any> = {
|
||||
phone: {
|
||||
link: "tel:+15208036644",
|
||||
dom: (
|
||||
<span className="social-nav flex gap-1 text-2xl lg:text-[#00898b]">
|
||||
<Image src="/assets/icons/phone.png" alt="Image Description" width={25} height={25} />
|
||||
<b className="text-sm">(520) 803-6644</b>
|
||||
<span className="social-nav flex gap-1 text-2xl lg:text-white">
|
||||
<Image src="/assets/icons/phone.png" alt="Image Description" width={25} height={22} />
|
||||
<b className="text-[17px]">(520) 803-6644</b>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
facebook: {
|
||||
link: "https://www.facebook.com/p/Cochise-Oncology-61556262839823",
|
||||
dom: (
|
||||
<span className="social-nav flex gap-3 text-2xl lg:text-[#00898b]">
|
||||
<FaFacebook />
|
||||
<b className="text-sm lg:hidden">Facebook</b>
|
||||
<span className="social-nav flex gap-3 text-2xl lg:text-white">
|
||||
<FaFacebook size={25} />
|
||||
<b className="text-[17px] lg:hidden">Facebook</b>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
linkedin: {
|
||||
link: "https://linkedin.com/company/cochise-oncology",
|
||||
dom: (
|
||||
<span className="social-nav flex gap-3 text-2xl lg:text-[#00898b]">
|
||||
<FaLinkedin />
|
||||
<b className="text-sm lg:hidden">Linkedin</b>
|
||||
<span className="social-nav flex gap-3 text-2xl lg:text-white">
|
||||
<FaLinkedin size={25} />
|
||||
<b className="text-[17px] lg:hidden">Linkedin</b>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
@ -78,7 +78,7 @@ export default function Header({ links }: { links: typeof navMenuData }) {
|
||||
<div className="flex flex-col items-center h-full w-full content-center justify-center gap-2">
|
||||
<a
|
||||
href="/contact"
|
||||
className="bg-[#00898b] px-3 py-2 rounded-full text-white font-bold hover:cursor-pointer hover:bg-[#00abad] scale-[1.02] mt-3 lg:mt-0"
|
||||
className="bg-extColorPrimary8 px-3 py-2 rounded-full text-white font-bold hover:cursor-pointer hover:scale-[1.15] mt-3 lg:mt-0 transition-transform duration-300"
|
||||
>
|
||||
REQUEST CONSULTATION
|
||||
</a>
|
||||
@ -86,7 +86,7 @@ export default function Header({ links }: { links: typeof navMenuData }) {
|
||||
{Object.keys(shareIcons).map((k, idx) => {
|
||||
return (
|
||||
<li key={idx} className="!p-0 !m-0">
|
||||
<a className="cursor-pointer" href={shareIcons[k].link} target="_blank">
|
||||
<a className="cursor-pointer text-white" href={shareIcons[k].link} target="_blank">
|
||||
{shareIcons[k].dom}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -60,7 +60,10 @@ export default function HeaderNav({ links, animateY = false }: { links: typeof n
|
||||
{link.text} <i className="mi-chevron-down" onClick={() => toggleDropdown([link.text])} />
|
||||
</Link>
|
||||
|
||||
<ul className={`mn-sub to-right ${isDropdownOpen.includes(link.text) && "open"}`} ref={dropdownRef}>
|
||||
<ul
|
||||
className={`mn-sub to-right ${isDropdownOpen.includes(link.text) && "open"} !bg-extColorPrimary8`}
|
||||
ref={dropdownRef}
|
||||
>
|
||||
{link.child.map((subLink: any, subLinkIdx: number) => (
|
||||
<li key={subLinkIdx}>
|
||||
{!Array.isArray(subLink?.child) && (
|
||||
@ -75,7 +78,9 @@ export default function HeaderNav({ links, animateY = false }: { links: typeof n
|
||||
<i className="mi-chevron-down" onClick={() => toggleDropdown([link.text, subLink.text])} />
|
||||
</Link>
|
||||
|
||||
<ul className={`mn-sub to-right ${isDropdownOpen.includes(subLink.text) && "open"}`}>
|
||||
<ul
|
||||
className={`mn-sub to-right ${isDropdownOpen.includes(subLink.text) && "open"} !bg-extColorPrimary8`}
|
||||
>
|
||||
{subLink.child.map((subLink2: any, subLinkIdx2: number) => (
|
||||
<li key={subLinkIdx2}>
|
||||
<Link href={subLink2?.href} onClick={() => toggleMobileMenu()}>
|
||||
|
@ -24,7 +24,8 @@ export default function Hero() {
|
||||
<p className="text-xl">Southern Arizona’s Only Complete Cancer Treatment Center in Sierra Vista.</p>
|
||||
<a
|
||||
href="/contact"
|
||||
className="btn btn-mod btn-border-w btn-large btn-round align-middle w-full md:w-1/2 lg:w-1/4 hover:opacity-[0.5]"
|
||||
// className="btn btn-mod btn-border-w btn-large btn-round align-middle w-full md:w-1/2 lg:w-1/4 hover:opacity-[0.5]"
|
||||
className="inline-block bg-extColorPrimary6 hover:bg-extColorPrimary8 text-white py-1 px-6 hover:scale-105 rounded-full text-lg shadow-lg transition-all duration-500"
|
||||
data-btn-animate="y"
|
||||
>
|
||||
Request Consultation
|
||||
|
@ -1,10 +1,6 @@
|
||||
// "use client";
|
||||
"use client";
|
||||
import Hero from "@/components/Hero";
|
||||
|
||||
// const ParallaxContainer = dynamic(() => import("@/components/ParallaxContainer"), {
|
||||
// ssr: false,
|
||||
// });
|
||||
|
||||
export default function HomeBgVideo() {
|
||||
return (
|
||||
<>
|
@ -123,15 +123,15 @@ export default function homepage({ dark = false }) {
|
||||
<div className="row wow fadeInUp">
|
||||
<div className="col-12 col-lg-6 offset-lg-6 col-xl-6 offset-xl-6">
|
||||
<h2 className="section-title mb-40 mb-sm-30">A Cancer Treatment Center of Excellence</h2>
|
||||
<p className="text-sm">
|
||||
<p className="">
|
||||
Get compassionate care and excellent medical services from COCHISE ONCOLOGY in Sierra Vista, Arizona. We
|
||||
are the largest full-service cancer treatment center between Albuquerque, New Mexico and Tucson,
|
||||
Arizona. Our services cover radiation treatments as well as chemotherapy, and we also have an infusion
|
||||
center. We offer support groups as well as free hospitality housing for patients undergoing treatment.
|
||||
Read on to learn more about our establishment, or reach out to us via phone or email to make an inquiry.
|
||||
</p>
|
||||
<h4>The Mission of Cochise Oncology</h4>
|
||||
<p className="text-sm">
|
||||
<h2 className="section-title mb-40 mb-sm-30">The Mission of Cochise Oncology</h2>
|
||||
<p className="">
|
||||
To provide excellence in cancer and patient care in a comprehensive center for the local community.
|
||||
Optimal cancer treatment places the patient first—from the patient’s first greeting with the front
|
||||
office staff to the trust they develop with the physicians and the whole treatment team. We believe our
|
||||
|
@ -3,6 +3,7 @@ import { RenderBlocks } from "@/components/Blocks/RenderBlocks";
|
||||
import BlogDetail from "@/components/Blogs/BlogDetail";
|
||||
import { fetchPageBySlug } from "@/services/payload/page";
|
||||
import HeroOther from "@/components/HeroOther";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
export interface PageProps {
|
||||
slug: string | undefined;
|
||||
@ -11,6 +12,7 @@ export interface PageProps {
|
||||
export default async function Page({ slug }: PageProps) {
|
||||
const page = await fetchPageBySlug({ slug });
|
||||
|
||||
// if page is a blog post
|
||||
if (!page) {
|
||||
return (
|
||||
<>
|
||||
@ -20,8 +22,88 @@ export default async function Page({ slug }: PageProps) {
|
||||
);
|
||||
}
|
||||
|
||||
// if page is not a blog post
|
||||
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 metaDesc = !!page?.meta?.description ? page.meta?.description : headersList.get("x-meta-desc");
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "WebPage",
|
||||
"@id": fullUrl,
|
||||
url: fullUrl,
|
||||
name: `${page.meta?.title ?? ""} - ${siteName}`,
|
||||
isPartOf: {
|
||||
"@id": `${mainUrl}/#website`,
|
||||
},
|
||||
datePublished: page?.createdAt,
|
||||
dateModified: page?.updatedAt,
|
||||
description: metaDesc,
|
||||
breadcrumb: {
|
||||
"@id": `${fullUrl}#breadcrumb`,
|
||||
},
|
||||
inLanguage: "en-US",
|
||||
potentialAction: [
|
||||
{
|
||||
"@type": "ReadAction",
|
||||
target: [fullUrl],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"@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`,
|
||||
width: 500,
|
||||
height: 195,
|
||||
caption: siteName,
|
||||
},
|
||||
image: {
|
||||
"@id": `${mainUrl}/#/schema/logo/image/`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<HeroOther title={page.title} img={page?.heroImg?.url ?? ""} />
|
||||
<RenderBlocks blocks={page.layout} />
|
||||
</>
|
||||
|
@ -7,9 +7,16 @@ interface PaginationProps {
|
||||
hasPreviousPage: boolean;
|
||||
hasNextPage: boolean;
|
||||
totalPages: number;
|
||||
usePathParams?: boolean;
|
||||
}
|
||||
|
||||
export default function Pagination({ page, hasPreviousPage, hasNextPage, totalPages }: PaginationProps) {
|
||||
export default function Pagination({
|
||||
page,
|
||||
hasPreviousPage,
|
||||
hasNextPage,
|
||||
totalPages,
|
||||
usePathParams = false,
|
||||
}: PaginationProps) {
|
||||
const activePage = page;
|
||||
const pathName = usePathname();
|
||||
|
||||
@ -17,11 +24,16 @@ export default function Pagination({ page, hasPreviousPage, hasNextPage, totalPa
|
||||
const handlePageChange = (page: string | number) => {
|
||||
if (typeof page === "string") return;
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const searchParams = new URLSearchParams(url.search);
|
||||
searchParams.set("page", `${page}`);
|
||||
window.location.href = `${pathName}/?${searchParams}`;
|
||||
|
||||
if (usePathParams) {
|
||||
searchParams.set("page", `${page}`);
|
||||
window.location.href = `${pathName}/page/${page}/?${searchParams}`;
|
||||
} else {
|
||||
searchParams.set("page", `${page}`);
|
||||
window.location.href = `${pathName}/?${searchParams}`;
|
||||
}
|
||||
};
|
||||
|
||||
const getPageNumbers = () => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Image from "next/image";
|
||||
import StarRating from "./StarRating";
|
||||
import { limitString } from "@/utils/general";
|
||||
|
||||
export interface CardStarRatingProps {
|
||||
data: {
|
||||
@ -12,10 +13,10 @@ export function CardStarRating({ data }: CardStarRatingProps) {
|
||||
return (
|
||||
<div className="bg-white p-2 rounded-lg shadow-md">
|
||||
<div className="flex justify-between">
|
||||
<StarRating size={20} value={data.star} />
|
||||
<Image src="/assets/images/google-provider.svg" width={20} height={20} alt="" />
|
||||
<StarRating size={30} value={data.star} />
|
||||
<Image src="/assets/images/google-provider.svg" width={30} height={30} alt="" />
|
||||
</div>
|
||||
<p className="text-xs pl-1 mt-4">{data.description}</p>
|
||||
<p className="p-1 mt-4 text-[22px]">{limitString(data.description)}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -7,12 +7,17 @@ export function middleware(request: NextRequest) {
|
||||
const protocol = request.headers.get("x-forwarded-proto") || "http"; // Default to 'http' if not provided
|
||||
const host = request.headers.get("x-forwarded-host") || request.nextUrl.hostname;
|
||||
const path = request.nextUrl.pathname + request.nextUrl.search;
|
||||
const siteName = "Cochise Oncology";
|
||||
const metaDesc =
|
||||
"Get compassionate care and excellent medical services from COCHISE ONCOLOGY in Sierra Vista, Arizona. We are the largest full-service cancer treatment center between Albuquerque, New Mexico and Tucson, Arizona.";
|
||||
|
||||
// Construct the full URL
|
||||
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-site-name", siteName);
|
||||
request.headers.set("x-meta-desc", metaDesc);
|
||||
|
||||
return NextResponse.next({
|
||||
request: {
|
||||
|
@ -304,7 +304,7 @@ export interface Page {
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
cannonical_url?: string | null;
|
||||
canonical_url?: string | null;
|
||||
};
|
||||
createdBy?: (number | null) | User;
|
||||
updatedBy?: (number | null) | User;
|
||||
@ -749,7 +749,7 @@ export interface PagesSelect<T extends boolean = true> {
|
||||
| {
|
||||
title?: T;
|
||||
description?: T;
|
||||
cannonical_url?: T;
|
||||
canonical_url?: T;
|
||||
};
|
||||
createdBy?: T;
|
||||
updatedBy?: T;
|
||||
|
@ -1,21 +1,34 @@
|
||||
import payloadConfig from "@/payload.config";
|
||||
import { formatDate } from "@/utils/datetime";
|
||||
import { getPayload } from "payload";
|
||||
import { getPayload, Where } from "payload";
|
||||
|
||||
export async function fetchBlog(page: number | undefined, search: string = "") {
|
||||
type FetchBlogParams = {
|
||||
page?: number;
|
||||
search?: string;
|
||||
categorySlug?: string;
|
||||
};
|
||||
|
||||
export async function fetchBlog({ page, search = "", categorySlug = "" }: FetchBlogParams = {}) {
|
||||
const payload = await getPayload({ config: payloadConfig });
|
||||
|
||||
const queryCondition: Where = {};
|
||||
if (!!search) {
|
||||
queryCondition["title"] = {
|
||||
contains: search,
|
||||
};
|
||||
}
|
||||
if (!!categorySlug) {
|
||||
queryCondition["categories"] = {
|
||||
equals: 9,
|
||||
};
|
||||
}
|
||||
|
||||
const blogDataQuery = await payload.find({
|
||||
collection: "blogs",
|
||||
page,
|
||||
pagination: true,
|
||||
limit: 6,
|
||||
where: !search
|
||||
? undefined
|
||||
: {
|
||||
title: {
|
||||
contains: search,
|
||||
},
|
||||
},
|
||||
limit: 9,
|
||||
where: queryCondition,
|
||||
});
|
||||
|
||||
const formattedData = blogDataQuery.docs.map((item) => {
|
||||
@ -47,11 +60,13 @@ export async function fetchBlogDetail(slug: string | undefined) {
|
||||
|
||||
const data = blogDataQuery?.docs?.[0];
|
||||
const createdAt = formatDate(data.createdAt);
|
||||
const updatedAt = formatDate(data.updatedAt);
|
||||
const imgUrl = typeof data.img !== "number" ? (data?.img?.url ?? "") : "";
|
||||
|
||||
return {
|
||||
data,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
imgUrl,
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
export function limitString(text: string) {
|
||||
return `${text.length > 100 ? `${text.slice(0, 100)}...` : text}`;
|
||||
}
|
@ -5,14 +5,30 @@ export async function getDefaultMetadata(): Promise<Metadata> {
|
||||
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 metaDesc = headersList.get("x-meta-desc") ?? "";
|
||||
|
||||
return {
|
||||
metadataBase: new URL(mainUrl),
|
||||
title: siteName,
|
||||
description: metaDesc,
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
"max-image-preview": "large",
|
||||
"max-snippet": -1,
|
||||
"max-video-preview": -1,
|
||||
},
|
||||
openGraph: {
|
||||
siteName,
|
||||
title: siteName,
|
||||
description: metaDesc,
|
||||
type: "website",
|
||||
locale: "en_US",
|
||||
url: fullUrl,
|
||||
siteName: "Cochise Oncology",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "./",
|
||||
|
Loading…
x
Reference in New Issue
Block a user