fix
parent
1fcf3fb8be
commit
586da8367c
|
@ -12,6 +12,7 @@
|
|||
"dependencies": {
|
||||
"embla-carousel-autoplay": "^8.5.2",
|
||||
"embla-carousel-react": "^8.5.2",
|
||||
"fast-average-color": "^9.4.0",
|
||||
"framer-motion": "^12.4.2",
|
||||
"lucide-react": "^0.475.0",
|
||||
"next": "15.1.6",
|
||||
|
|
|
@ -11,6 +11,9 @@ dependencies:
|
|||
embla-carousel-react:
|
||||
specifier: ^8.5.2
|
||||
version: 8.5.2(react@19.0.0)
|
||||
fast-average-color:
|
||||
specifier: ^9.4.0
|
||||
version: 9.4.0
|
||||
framer-motion:
|
||||
specifier: ^12.4.2
|
||||
version: 12.4.3(react-dom@19.0.0)(react@19.0.0)
|
||||
|
@ -1652,6 +1655,11 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/fast-average-color@9.4.0:
|
||||
resolution: {integrity: sha512-bvM8vV6YwK07dPbzFz77zJaBcfF6ABVfgNwaxVgXc2G+o0e/tzLCF9WU8Ryp1r0Nkk6JuJNsWCzbb4cLOMlB+Q==}
|
||||
engines: {node: '>= 12'}
|
||||
dev: false
|
||||
|
||||
/fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
dev: true
|
||||
|
|
|
@ -202,7 +202,7 @@ export default async function ProductPage({ params }) {
|
|||
const t = await getMessages({ locale });
|
||||
console.log(t)
|
||||
return (
|
||||
<div className="max-w-screen-xl mx-auto px-4 py-8">
|
||||
<div className="max-w-screen-xl mx-auto px-4 py-8 bg-red-50">
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
|
||||
export default function ActiveBrandShowcase() {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsVisible(true);
|
||||
}, []);
|
||||
|
||||
const brandData = {
|
||||
title: "Active",
|
||||
documentId: "kljvt7958pfxnxc8iv4tulz9",
|
||||
image: {
|
||||
documentId: "klzro7ugdmmft1706ysh40vd",
|
||||
alternativeText: null,
|
||||
url: "https://storage.adhorizonintl.com/horizon/media/logo_1_200x130_convert_io_1_03100d49db.webp",
|
||||
},
|
||||
description:
|
||||
'<p>Active is a trusted name in the personal care and household products industry, offering a wide range of high-quality <strong data-start="164" data-end="178">detergents</strong>, <strong data-start="180" data-end="192">shampoos</strong>, and <strong data-start="198" data-end="220">hygiene essentials</strong>. Committed to cleanliness, health, and well-being, Active\'s products are designed to meet the diverse needs of families, ensuring they stay fresh and clean every day. Whether it\'s keeping your home spotless or maintaining personal hygiene, Active provides solutions that are not only effective but also gentle on skin and surfaces. Choose Active for a healthier, cleaner lifestyle!</p><p> </p>',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-cyan-50 flex items-center justify-center p-4 sm:p-6 md:p-8">
|
||||
<div
|
||||
className={`max-w-4xl w-full bg-white rounded-2xl shadow-2xl overflow-hidden transition-all duration-1000 transform ${
|
||||
isVisible ? "translate-y-0 opacity-100" : "translate-y-10 opacity-0"
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-col md:flex-row">
|
||||
{/* Left side - Image and title */}
|
||||
<div className="md:w-2/5 bg-gradient-to-br from-cyan-500 to-blue-600 p-8 flex flex-col items-center justify-center text-white">
|
||||
<div className="w-full max-w-[200px] h-[130px] relative mb-6 bg-white rounded-lg p-4 shadow-lg transform transition-transform duration-500 hover:scale-105">
|
||||
<Image
|
||||
src={brandData.image.url || "/placeholder.svg"}
|
||||
alt={brandData.image.alternativeText || brandData.title}
|
||||
fill
|
||||
style={{ objectFit: "contain" }}
|
||||
className="p-2"
|
||||
/>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold tracking-tight mb-4 text-center">
|
||||
{brandData.title}
|
||||
</h1>
|
||||
<div className="flex space-x-2 mt-2">
|
||||
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm font-medium">
|
||||
Detergents
|
||||
</span>
|
||||
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm font-medium">
|
||||
Shampoos
|
||||
</span>
|
||||
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm font-medium">
|
||||
Hygiene
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right side - Description */}
|
||||
<div className="md:w-3/5 p-8 md:p-10">
|
||||
<div className="relative">
|
||||
<div className="absolute -top-6 -left-6 w-12 h-12 rounded-full bg-cyan-100 opacity-70"></div>
|
||||
<div className="absolute -bottom-6 -right-6 w-16 h-16 rounded-full bg-blue-100 opacity-70"></div>
|
||||
|
||||
<h2 className="text-2xl font-semibold text-gray-800 mb-6 relative">
|
||||
About the Brand
|
||||
</h2>
|
||||
|
||||
<div
|
||||
className="prose prose-lg max-w-none text-gray-600 relative z-10"
|
||||
dangerouslySetInnerHTML={{ __html: brandData.description }}
|
||||
/>
|
||||
|
||||
<div className="mt-8 flex flex-wrap gap-4">
|
||||
<button className="px-6 py-3 bg-gradient-to-r from-cyan-500 to-blue-600 text-white font-medium rounded-lg shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1">
|
||||
Explore Products
|
||||
</button>
|
||||
<button className="px-6 py-3 border-2 border-cyan-500 text-cyan-600 font-medium rounded-lg hover:bg-cyan-50 transition-all duration-300">
|
||||
Learn More
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom section - Features */}
|
||||
<div className="bg-gray-50 p-8 grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="bg-white p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300">
|
||||
<div className="w-12 h-12 bg-cyan-100 rounded-full flex items-center justify-center mb-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6 text-cyan-600"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-2">
|
||||
High Quality
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Premium products designed to meet the highest standards of
|
||||
cleanliness and care.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mb-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6 text-blue-600"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-2">
|
||||
Family Friendly
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Gentle formulations that are safe for the whole family, including
|
||||
sensitive skin.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300">
|
||||
<div className="w-12 h-12 bg-cyan-100 rounded-full flex items-center justify-center mb-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6 text-cyan-600"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-2">
|
||||
Eco-Conscious
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Committed to sustainable practices and environmentally friendly
|
||||
formulations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,165 +1,81 @@
|
|||
"use client"
|
||||
import React, { useEffect } from "react";
|
||||
import CardNormal, { ProductCardSkeleton } from "src/components/Cards/CardNormal";
|
||||
import Paginate from "src/components/Paginate";
|
||||
import graphql from "src/utils/graphql";
|
||||
import Filters from "./Filters";
|
||||
import { useParams, useSearchParams } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
const brandAndCategoriesGQL = `
|
||||
query Categories($locale: I18NLocaleCode) {
|
||||
categories(locale: $locale,pagination: { start: 0, limit: 50 }) {
|
||||
documentId
|
||||
slug
|
||||
title
|
||||
}
|
||||
brands(locale: $locale, pagination: { start: 0, limit: 50 }) {
|
||||
title
|
||||
documentId
|
||||
slug
|
||||
}
|
||||
}
|
||||
import Image from 'next/image';
|
||||
|
||||
`
|
||||
|
||||
const productsGQL = `
|
||||
query Products_connection(
|
||||
$locale: I18NLocaleCode
|
||||
$page: Int
|
||||
$pageSize: Int
|
||||
$category: String
|
||||
$brand: String
|
||||
) {
|
||||
products_connection(
|
||||
pagination: { page: $page, pageSize: $pageSize }
|
||||
filters: {
|
||||
or: [
|
||||
{ category: { slug: { eqi: $category } } }
|
||||
{ brand: { slug: { eqi: $brand } } }
|
||||
]
|
||||
}
|
||||
locale: $locale
|
||||
) {
|
||||
nodes {
|
||||
documentId
|
||||
title
|
||||
images {
|
||||
documentId
|
||||
alternativeText
|
||||
url
|
||||
}
|
||||
category {
|
||||
title
|
||||
documentId
|
||||
slug
|
||||
}
|
||||
brand {
|
||||
documentId
|
||||
title
|
||||
slug
|
||||
image {
|
||||
documentId
|
||||
alternativeText
|
||||
url
|
||||
}
|
||||
}
|
||||
slug
|
||||
}
|
||||
pageInfo {
|
||||
total
|
||||
page
|
||||
pageSize
|
||||
pageCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
`
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import ContactModal from 'src/components/ContactUs';
|
||||
|
||||
|
||||
|
||||
|
||||
const Content = () => {
|
||||
const params = useParams()
|
||||
const searchParams = useSearchParams()
|
||||
const { category } = params
|
||||
const [loading, setLoading] = React.useState(true)
|
||||
const [pageInfo, setPageInfo] = React.useState({ page: 1, pageSize: 12, total: 0, pageCount: 0 })
|
||||
const [products, setProducts] = React.useState([])
|
||||
const [brands, setBrands] = React.useState([])
|
||||
const [categories, setCategories] = React.useState([])
|
||||
const getBrandsAndCategories = async () => {
|
||||
const { brands, categories } = await graphql(brandAndCategoriesGQL, { locale: "en" });
|
||||
setBrands(brands)
|
||||
setCategories(categories)
|
||||
|
||||
}
|
||||
const getProducts = async () => {
|
||||
setLoading(true)
|
||||
|
||||
const page = parseInt(searchParams.get("page")) || 1
|
||||
const { products_connection: { nodes, pageInfo } } = await graphql(productsGQL, {
|
||||
locale: "en",
|
||||
page: page,
|
||||
pageSize: 12,
|
||||
brand: category,
|
||||
category: category
|
||||
})
|
||||
setProducts(nodes)
|
||||
setPageInfo(pageInfo)
|
||||
setLoading(false)
|
||||
const Content = ({ content }) => {
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const openModal = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
const closeModal = () => {
|
||||
setOpen(false);
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getBrandsAndCategories()
|
||||
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
getProducts(category)
|
||||
}, [searchParams])
|
||||
|
||||
console.log("products", products)
|
||||
const t = useTranslations("PLP")
|
||||
return (
|
||||
<>
|
||||
{
|
||||
brands && brands.length > 0 && categories && categories.length > 0 &&
|
||||
<Filters brands={brands} categories={categories} />
|
||||
}
|
||||
<div className="flex flex-col w-full items-center justify-center ">
|
||||
<div className="px-2 pb-20 w-full">
|
||||
<div className="flex">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold ">
|
||||
{t("title")}
|
||||
</h1>
|
||||
<p className="mb-0 text-sm text-gray-400 xs:text-center ">
|
||||
{t("subtitle")}
|
||||
</p>
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div
|
||||
className={`container mx-auto max-w-6xl transition-all duration-1000 transform`}
|
||||
>
|
||||
<div className="bg-gradient-to-br rounded-2xl shadow-2xl overflow-hidden">
|
||||
<div className="flex flex-col lg:flex-row">
|
||||
{/* Left side - Image and title */}
|
||||
<div className="lg:w-2/5 p-8 flex flex-col items-center justify-center text-white " >
|
||||
<div className="w-full max-w-[200px] h-[130px] relative mb-6 bg-white rounded-lg p-4 shadow-lg transform transition-transform duration-500 hover:scale-105">
|
||||
<Image
|
||||
|
||||
src={content.image?.url || "/placeholder.svg"}
|
||||
alt={content.image?.alternativeText || content.title}
|
||||
fill
|
||||
style={{ objectFit: "contain" }}
|
||||
className="p-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* <div className="flex flex-wrap justify-center gap-2 mt-2">
|
||||
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm font-medium">
|
||||
Detergents
|
||||
</span>
|
||||
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm font-medium">
|
||||
Shampoos
|
||||
</span>
|
||||
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm font-medium">
|
||||
Hygiene
|
||||
</span>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
{/* Right side - Description */}
|
||||
<div className="lg:w-3/5 bg-white p-8 lg:p-10 relative">
|
||||
<div className="absolute -top-6 -left-6 w-12 h-12 rounded-full bg-cyan-100 opacity-70 hidden lg:block"></div>
|
||||
<div className="absolute -bottom-6 -right-6 w-16 h-16 rounded-full bg-blue-100 opacity-70 hidden lg:block"></div>
|
||||
|
||||
<h1 className="text-4xl font-bold tracking-tight mb-4 ">{content.title}</h1>
|
||||
|
||||
<div
|
||||
className="prose prose-lg max-w-none text-gray-600 relative z-10"
|
||||
dangerouslySetInnerHTML={{ __html: content.description }}
|
||||
/>
|
||||
|
||||
<div className="mt-8 flex flex-wrap gap-4">
|
||||
{/* <button className="px-6 py-3 bg-gradient-to-r from-cyan-500 to-blue-600 text-white font-medium rounded-lg shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1">
|
||||
View All Products
|
||||
</button> */}
|
||||
<button onClick={()=>setOpen(true)} className="px-6 py-3 font-medium rounded-lg bg-primary-100 transition-all duration-300">
|
||||
Contact Us
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-10 w-full">
|
||||
{!loading && products.map((product, index) => (
|
||||
<div key={index} className="relative">
|
||||
<CardNormal product={product} priority />
|
||||
</div>
|
||||
))}
|
||||
{
|
||||
loading && Array.from({ length: 12 }).map((_, index) => (
|
||||
<div key={index} className="relative">
|
||||
<ProductCardSkeleton />
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<Paginate pageInfo={pageInfo} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
<ContactModal close={closeModal} open={open} />
|
||||
</section >
|
||||
)
|
||||
}
|
||||
|
||||
export default Content;
|
||||
export default Content
|
|
@ -0,0 +1,167 @@
|
|||
"use client"
|
||||
import React, { useEffect } from "react";
|
||||
import CardNormal, { ProductCardSkeleton } from "src/components/Cards/CardNormal";
|
||||
import Paginate from "src/components/Paginate";
|
||||
import graphql from "src/utils/graphql";
|
||||
import Filters from "./Filters";
|
||||
import { useParams, useSearchParams } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
const brandAndCategoriesGQL = `
|
||||
query Categories($locale: I18NLocaleCode) {
|
||||
categories(locale: $locale,pagination: { start: 0, limit: 50 }) {
|
||||
documentId
|
||||
slug
|
||||
title
|
||||
}
|
||||
brands(locale: $locale, pagination: { start: 0, limit: 50 }) {
|
||||
title
|
||||
documentId
|
||||
slug
|
||||
}
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const productsGQL = `
|
||||
query Products_connection(
|
||||
$locale: I18NLocaleCode
|
||||
$page: Int
|
||||
$pageSize: Int
|
||||
$category: String
|
||||
$brand: String
|
||||
) {
|
||||
products_connection(
|
||||
pagination: { page: $page, pageSize: $pageSize }
|
||||
filters: {
|
||||
or: [
|
||||
{ category: { slug: { eqi: $category } } }
|
||||
{ brand: { slug: { eqi: $brand } } }
|
||||
]
|
||||
}
|
||||
locale: $locale
|
||||
) {
|
||||
nodes {
|
||||
documentId
|
||||
title
|
||||
images {
|
||||
documentId
|
||||
alternativeText
|
||||
url
|
||||
}
|
||||
category {
|
||||
title
|
||||
documentId
|
||||
slug
|
||||
|
||||
}
|
||||
brand {
|
||||
documentId
|
||||
title
|
||||
slug
|
||||
image {
|
||||
documentId
|
||||
alternativeText
|
||||
url
|
||||
}
|
||||
description
|
||||
}
|
||||
slug
|
||||
}
|
||||
pageInfo {
|
||||
total
|
||||
page
|
||||
pageSize
|
||||
pageCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
`
|
||||
|
||||
|
||||
|
||||
|
||||
const ProductsListingPage = () => {
|
||||
const params = useParams()
|
||||
const searchParams = useSearchParams()
|
||||
const { category } = params
|
||||
const [loading, setLoading] = React.useState(true)
|
||||
const [pageInfo, setPageInfo] = React.useState({ page: 1, pageSize: 12, total: 0, pageCount: 0 })
|
||||
const [products, setProducts] = React.useState([])
|
||||
const [brands, setBrands] = React.useState([])
|
||||
const [categories, setCategories] = React.useState([])
|
||||
const getBrandsAndCategories = async () => {
|
||||
const { brands, categories } = await graphql(brandAndCategoriesGQL, { locale: "en" });
|
||||
setBrands(brands)
|
||||
setCategories(categories)
|
||||
|
||||
}
|
||||
const getProducts = async () => {
|
||||
setLoading(true)
|
||||
|
||||
const page = parseInt(searchParams.get("page")) || 1
|
||||
const { products_connection: { nodes, pageInfo } } = await graphql(productsGQL, {
|
||||
locale: "en",
|
||||
page: page,
|
||||
pageSize: 12,
|
||||
brand: category,
|
||||
category: category
|
||||
})
|
||||
setProducts(nodes)
|
||||
setPageInfo(pageInfo)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getBrandsAndCategories()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
getProducts(category)
|
||||
}, [searchParams])
|
||||
|
||||
console.log("products", products)
|
||||
const t = useTranslations("PLP")
|
||||
return (
|
||||
<>
|
||||
{
|
||||
brands && brands.length > 0 && categories && categories.length > 0 &&
|
||||
<Filters brands={brands} categories={categories} />
|
||||
}
|
||||
<div className="flex flex-col w-full items-center justify-center ">
|
||||
<div className="px-2 pb-20 w-full">
|
||||
<div className="flex">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold ">
|
||||
{ t("title")}
|
||||
</h1>
|
||||
<p className="mb-0 text-sm text-gray-400 xs:text-center ">
|
||||
{t("subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-10 w-full">
|
||||
{!loading && products.map((product, index) => (
|
||||
<div key={index} className="relative">
|
||||
<CardNormal product={product} priority />
|
||||
</div>
|
||||
))}
|
||||
{
|
||||
loading && Array.from({ length: 12 }).map((_, index) => (
|
||||
<div key={index} className="relative">
|
||||
<ProductCardSkeleton />
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<Paginate pageInfo={pageInfo} />
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductsListingPage;
|
|
@ -1,51 +1,63 @@
|
|||
import React from "react";
|
||||
import CardNormal from "src/components/Cards/CardNormal";
|
||||
import Navbar from "src/components/NavBar";
|
||||
import Content from "./components/Content";
|
||||
import Filters from "./components/Filters";
|
||||
import Footer from "../Landing/components/Footer";
|
||||
import graphql from "src/utils/graphql";
|
||||
import { getLocale } from "next-intl/server";
|
||||
|
||||
// query Products($locale:I18NLocaleCode,$page:Int,$pageSize:Int,$title:String,$categoryTitle:String,$brandTitle:String) {
|
||||
// products(
|
||||
// pagination: { page: $page, pageSize: $pageSize }
|
||||
// filters: {
|
||||
// category: { title: { contains: $categoryTitle } }
|
||||
// brand: { title: { eq: $brandTitle } }
|
||||
// title: { eq: $title }
|
||||
// }
|
||||
// locale: $locale
|
||||
// ) {
|
||||
// title
|
||||
// documentId
|
||||
// price
|
||||
// brand {
|
||||
// title
|
||||
// documentId
|
||||
// slug
|
||||
// }
|
||||
// category {
|
||||
// documentId
|
||||
// title
|
||||
// slug
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
import ProductsListingPage from "./components/Products";
|
||||
import Content from "./components/Content";
|
||||
import graphql from "src/utils/graphql";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const gql = `
|
||||
query Brands($locale: I18NLocaleCode, $slug: String) {
|
||||
brands(filters: { or: [{ slug: { eqi: $slug } }] }, locale: $locale) {
|
||||
title
|
||||
documentId
|
||||
image {
|
||||
documentId
|
||||
alternativeText
|
||||
url
|
||||
}
|
||||
description
|
||||
}
|
||||
categories(filters: { or: [{ slug: { eqi: $slug } }] }, locale: $locale) {
|
||||
documentId
|
||||
title
|
||||
image {
|
||||
documentId
|
||||
alternativeText
|
||||
url
|
||||
}
|
||||
description
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const getContent = async (locale, slug) => {
|
||||
const { brands, categories } = await graphql(gql, {
|
||||
locale,
|
||||
slug
|
||||
})
|
||||
return [...(brands ?? []), ...(categories ?? [])]?.[0]
|
||||
}
|
||||
|
||||
const CategoriesData = async ({ category }) => {
|
||||
|
||||
const locale = await getLocale()
|
||||
const content = await getContent(locale, category)
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<div className={`container-none md:container mx-auto p-4 flex flex-col md:flex-row mt-10 ${locale === "en" ? "ltr" : "rtl"}`}>
|
||||
<div className={`container-none md:container mx-auto p-4 flex flex-col md:flex-row mt-10 ${locale === "en" ? "ltr" : "rtl"}`}>
|
||||
|
||||
|
||||
<ProductsListingPage category={category} />
|
||||
|
||||
<Content category={category} />
|
||||
</div>
|
||||
{
|
||||
content.title &&
|
||||
<Content content={content} />
|
||||
}
|
||||
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -33,20 +33,21 @@ const getStats = async () => {
|
|||
|
||||
|
||||
const Landing = async () => {
|
||||
|
||||
|
||||
const stats = await getStats()
|
||||
|
||||
return (
|
||||
<div className=" text-center text-6xl">
|
||||
{" "}
|
||||
|
||||
|
||||
{/* <HeroSection /> */}
|
||||
<AboutUs />
|
||||
<Sides />
|
||||
<CounterDetail stats={stats} />
|
||||
<Products />
|
||||
|
||||
<Products />
|
||||
{/* <WhyHorizon/> */}
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue