feat(metadata): enhance SEO by adding Open Graph and Twitter metadata across various pages
feat(blog): implement loading and error handling components for blog pages feat(clinic): add loading and error handling components for clinic pages feat(doctor): create loading and error handling components for doctor pages feat(clinics): add loading component for clinics page feat(specialties): improve metadata for specialties page with Open Graph and Twitter images feat(layout): add structured data for Organization and WebSite in layout fix(middleware): restrict middleware execution to specific routes to improve performance chore(audit): add comprehensive SEO and performance audit documentation
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import { Skeleton } from "@mui/material";
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="p-4 flex flex-col gap-6" dir="rtl">
|
||||
<Skeleton variant="rounded" height={180} className="!rounded-lg" />
|
||||
<div className="flex flex-col gap-3">
|
||||
<Skeleton variant="rounded" width={200} height={24} />
|
||||
<Skeleton variant="rounded" width={160} height={20} />
|
||||
</div>
|
||||
<Skeleton variant="rounded" height={300} className="!rounded-lg" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +1,32 @@
|
||||
import { cache } from "react";
|
||||
import ClinicPage from "@/components/clinic";
|
||||
import Layout from "@/components/layout/StLayout";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
import { getStateInfo } from "@/lib/getStateInfo";
|
||||
import { imageUrl } from "@/helper";
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
const getClinic = cache(async (slug) => {
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/api/v1/clinic/${slug}`, {
|
||||
next: { revalidate: 3600, tags: [`clinic-${slug}`] },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
const json = await res.json();
|
||||
return json?.data?.data ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
export async function generateMetadata({ params }) {
|
||||
const { slug } = await params;
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
const { matchedCity } = await getStateInfo();
|
||||
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||
|
||||
try {
|
||||
const res = await fetchReq(`${API_URL}/api/v1/clinic/${slug}`);
|
||||
const clinic = res?.data?.data;
|
||||
const clinic = await getClinic(slug);
|
||||
if (!clinic) return {};
|
||||
|
||||
const title = `${clinic.title} | ${siteName}`;
|
||||
@@ -37,16 +51,14 @@ export async function generateMetadata({ params }) {
|
||||
async function Clinic({ params, searchParams }) {
|
||||
const { slug } = await params;
|
||||
const sp = await searchParams;
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
const page = Number(sp?.page) || 1;
|
||||
const limit = 50;
|
||||
|
||||
const reqClinics = await fetchReq(`${API_URL}/api/v1/clinic/${slug}`);
|
||||
const clinic = await getClinic(slug);
|
||||
const reqDoctors = await fetchReq(
|
||||
`${API_URL}/api/v1/clinic/doctor-list/${slug}?page=${page}&limit=${limit}`
|
||||
);
|
||||
|
||||
const clinic = reqClinics?.data?.data || null;
|
||||
const doctors = reqDoctors?.data?.data || [];
|
||||
const meta = reqDoctors?.data?.meta;
|
||||
const pagedoctors = meta
|
||||
@@ -64,6 +76,18 @@ async function Clinic({ params, searchParams }) {
|
||||
}
|
||||
: null;
|
||||
|
||||
const breadcrumbJsonLd = clinic
|
||||
? {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: [
|
||||
{ "@type": "ListItem", position: 1, name: "خانه", item: "https://www.nobat724.com" },
|
||||
{ "@type": "ListItem", position: 2, name: "کلینیکها", item: "https://www.nobat724.com/clinics" },
|
||||
{ "@type": "ListItem", position: 3, name: clinic.title },
|
||||
],
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{jsonLd && (
|
||||
@@ -72,6 +96,12 @@ async function Clinic({ params, searchParams }) {
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
)}
|
||||
{breadcrumbJsonLd && (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
|
||||
/>
|
||||
)}
|
||||
<Layout>
|
||||
<ClinicPage data={clinic} doctors={doctors} slug={slug} pages={pagedoctors} />
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user