270 lines
8.1 KiB
JavaScript
270 lines
8.1 KiB
JavaScript
import { Home } from "lucide-react";
|
|
import { ChevronRight } from "lucide-react";
|
|
import { ShoppingCart } from "lucide-react";
|
|
import { getLocale, getMessages } from "next-intl/server";
|
|
import Link from "next/link";
|
|
import { notFound } from "next/navigation";
|
|
import BrandInfo from "src/components/Product/BrandInfo";
|
|
import ProductDescription from "src/components/Product/ProductDescription";
|
|
import ProductGallery from "src/components/Product/ProductGallery";
|
|
import ProductInfo from "src/components/Product/ProductInfo";
|
|
import ProductProperties from "src/components/Product/ProductProperties";
|
|
import ProductRelated from "src/components/Product/ProductRelated";
|
|
import graphql from "src/utils/graphql";
|
|
|
|
const gql = `
|
|
query Products($locale: I18NLocaleCode, $slug: String!) {
|
|
products(filters: { slug: { eqi: $slug } }, locale: $locale) {
|
|
documentId
|
|
title
|
|
price
|
|
summery
|
|
qt
|
|
images {
|
|
documentId
|
|
alternativeText
|
|
url
|
|
}
|
|
category {
|
|
documentId
|
|
title
|
|
slug
|
|
}
|
|
description
|
|
brand {
|
|
documentId
|
|
title
|
|
image {
|
|
alternativeText
|
|
documentId
|
|
url
|
|
}
|
|
slug
|
|
}
|
|
slug
|
|
discount
|
|
showPrice
|
|
seo {
|
|
id
|
|
metaTitle
|
|
metaDescription
|
|
keywords
|
|
metaRobots
|
|
metaViewport
|
|
canonicalURL
|
|
structuredData
|
|
metaImage {
|
|
documentId
|
|
alternativeText
|
|
url
|
|
}
|
|
openGraph {
|
|
id
|
|
ogTitle
|
|
ogDescription
|
|
ogUrl
|
|
ogType
|
|
ogImage {
|
|
documentId
|
|
alternativeText
|
|
url
|
|
}
|
|
}
|
|
}
|
|
properties {
|
|
id
|
|
key
|
|
value
|
|
}
|
|
}
|
|
}
|
|
|
|
`;
|
|
const gql_static = `
|
|
query Products($locale:I18NLocaleCode,$start:Int,$limit:Int) {
|
|
products(locale: $locale, pagination: { start: $start, limit: $limit }) {
|
|
slug
|
|
}
|
|
|
|
}
|
|
`
|
|
|
|
const gql_metadata = `
|
|
query Products($locale:I18NLocaleCode,$slug:String!) {
|
|
products(filters: { slug: { eqi: $slug } }, locale: $locale) {
|
|
title
|
|
seo {
|
|
id
|
|
metaTitle
|
|
metaDescription
|
|
metaRobots
|
|
canonicalURL
|
|
metaImage {
|
|
documentId
|
|
alternativeText
|
|
url
|
|
}
|
|
openGraph {
|
|
id
|
|
ogTitle
|
|
ogDescription
|
|
ogUrl
|
|
ogType
|
|
ogImage {
|
|
documentId
|
|
alternativeText
|
|
url
|
|
}
|
|
}
|
|
structuredData
|
|
}
|
|
}
|
|
}
|
|
`
|
|
export async function generateMetadata({ params }) {
|
|
const { locale, slug } = await params;
|
|
|
|
// Fetch product SEO data from Strapi GraphQL API
|
|
const data = await graphql(gql_metadata, {
|
|
locale,
|
|
slug,
|
|
});
|
|
|
|
const productSEO = data?.products?.[0]?.seo;
|
|
if (productSEO) {
|
|
return {
|
|
title: productSEO.metaTitle,
|
|
description: productSEO.metaDescription,
|
|
robots: productSEO.metaRobots || 'index, follow',
|
|
// canonical: productSEO.canonicalURL || `https://adhorizonintl.com/product/${slug}`,
|
|
alternates: {
|
|
canonical: productSEO.canonicalURL || `https://adhorizonintl.com/product/${slug}`,
|
|
languages: {
|
|
'en': `https://adhorizonintl.com/product/${slug}`,
|
|
'ar-OM': `https://adhorizonintl.com/ar-OM/product/${slug}`,
|
|
},
|
|
},
|
|
openGraph: {
|
|
title: productSEO.openGraph.ogTitle || productSEO.metaTitle,
|
|
description: productSEO.openGraph.ogDescription || productSEO.metaDescription,
|
|
url: productSEO.openGraph.ogUrl || `https://adhorizonintl.com/product/${slug}`,
|
|
type: productSEO.openGraph.ogType || 'website',
|
|
images: [
|
|
{
|
|
url: productSEO.openGraph.ogImage.url,
|
|
alt: productSEO.openGraph.ogImage.alternativeText || 'Product Image',
|
|
},
|
|
],
|
|
},
|
|
twitter: {
|
|
card: 'summary_large_image',
|
|
title: productSEO.metaTitle,
|
|
description: productSEO.metaDescription,
|
|
images: [productSEO.metaImage?.url],
|
|
},
|
|
// structuredData: productSEO.structuredData,
|
|
};
|
|
}
|
|
else {
|
|
return {
|
|
title: data?.products?.[0]?.title,
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// export async function generateStaticParams() {
|
|
// const { products } = await graphql(gql_static, {
|
|
// "locale": "en",
|
|
// "start": 0,
|
|
// "limit": 1500
|
|
// })
|
|
|
|
// return products.map((product) =>
|
|
// ({ slug: product.slug })
|
|
// );
|
|
// }
|
|
|
|
|
|
const getProduct = async (slug) => {
|
|
const { products } = await graphql(gql, {
|
|
locale: "en",
|
|
slug,
|
|
});
|
|
return products[0];
|
|
};
|
|
|
|
export default async function ProductPage({ params }) {
|
|
const { slug } = await params
|
|
const product = await getProduct(slug);
|
|
|
|
if (!product) {
|
|
notFound();
|
|
}
|
|
const locale = await getLocale();
|
|
const t = await getMessages({ locale });
|
|
console.log(t)
|
|
return (
|
|
<div className="contain-none md:container mx-auto px-4 py-8">
|
|
|
|
|
|
|
|
<div className="flex flex-col lg:flex-row gap-8">
|
|
<ProductGallery images={product.images} />
|
|
<div className="flex flex-col gap-4 w-full ">
|
|
<div className={`flex items-center gap-2 mb-6 `}>
|
|
<Link href="/" className=" underline inline-flex gap-2">
|
|
<Home />
|
|
</Link>
|
|
|
|
|
|
{
|
|
product?.category?.slug &&
|
|
<>
|
|
<ChevronRight className={`size-4 ${locale !== "en" && "rotate-180"} `} />
|
|
<Link href={`/products/${product.category.slug}`} className=" underline">
|
|
|
|
{product.category.title}
|
|
</Link>
|
|
</>
|
|
}
|
|
{
|
|
product?.brand?.slug &&
|
|
<>
|
|
<ChevronRight className={`size-4 ${locale !== "en" && "rotate-180"} `} />
|
|
<Link href={`/products/${product.brand.slug}`} className=" underline">
|
|
{product.brand.title}
|
|
</Link>
|
|
</>
|
|
}
|
|
<ChevronRight className={`size-4 ${locale !== "en" && "rotate-180"} `} />
|
|
<span>{product.title}</span>
|
|
</div>
|
|
<div className="h-full flex justify-between flex-row w-full items-start">
|
|
|
|
<ProductInfo
|
|
title={product.title}
|
|
price={product.price}
|
|
discount={product.discount}
|
|
showPrice={product.showPrice}
|
|
category={product.category}
|
|
summery={product.summery}
|
|
brand={product.brand}
|
|
/>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="mt-12">
|
|
<ProductProperties properties={product.properties} />
|
|
</div>
|
|
<div className="mt-12">
|
|
<ProductDescription description={product.description} />
|
|
</div>
|
|
<div className="mt-12">
|
|
<ProductRelated brand={product.brand} category={product.category} />
|
|
</div>
|
|
</div>
|
|
);
|
|
} |