diff --git a/package.json b/package.json index d63e516..4c468ad 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5342bda..01810aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/src/app/[locale]/product/[slug]/page.jsx b/src/app/[locale]/product/[slug]/page.jsx index 8db6410..b857084 100644 --- a/src/app/[locale]/product/[slug]/page.jsx +++ b/src/app/[locale]/product/[slug]/page.jsx @@ -202,7 +202,7 @@ export default async function ProductPage({ params }) { const t = await getMessages({ locale }); console.log(t) return ( -
+
diff --git a/src/components/Cards/BrandCard/index.jsx b/src/components/Cards/BrandCard/index.jsx new file mode 100644 index 0000000..678ceda --- /dev/null +++ b/src/components/Cards/BrandCard/index.jsx @@ -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: + '

Active is a trusted name in the personal care and household products industry, offering a wide range of high-quality detergents, shampoos, and hygiene essentials. 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!

 

', + }; + + return ( +
+
+
+ {/* Left side - Image and title */} +
+
+ {brandData.image.alternativeText +
+

+ {brandData.title} +

+
+ + Detergents + + + Shampoos + + + Hygiene + +
+
+ + {/* Right side - Description */} +
+
+
+
+ +

+ About the Brand +

+ +
+ +
+ + +
+
+
+
+ + {/* Bottom section - Features */} +
+
+
+ + + +
+

+ High Quality +

+

+ Premium products designed to meet the highest standards of + cleanliness and care. +

+
+ +
+
+ + + +
+

+ Family Friendly +

+

+ Gentle formulations that are safe for the whole family, including + sensitive skin. +

+
+ +
+
+ + + +
+

+ Eco-Conscious +

+

+ Committed to sustainable practices and environmentally friendly + formulations. +

+
+
+
+
+ ); +} diff --git a/src/view/Categories/components/Content.jsx b/src/view/Categories/components/Content.jsx index 9ccfff0..78a98ed 100644 --- a/src/view/Categories/components/Content.jsx +++ b/src/view/Categories/components/Content.jsx @@ -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 && - - } -
-
-
-
-

- {t("title")} -

-

- {t("subtitle")} -

+
+
+
+
+ {/* Left side - Image and title */} +
+
+ {content.image?.alternativeText +
+ + {/*
+ + Detergents + + + Shampoos + + + Hygiene + +
*/} +
+ + {/* Right side - Description */} +
+
+
+ +

{content.title}

+ +
+ +
+ {/* */} + +
-
- {!loading && products.map((product, index) => ( -
- -
- ))} - { - loading && Array.from({ length: 12 }).map((_, index) => ( -
- -
- )) - } -
-
- - ); -}; + +
+ ) +} -export default Content; +export default Content \ No newline at end of file diff --git a/src/view/Categories/components/Products.jsx b/src/view/Categories/components/Products.jsx new file mode 100644 index 0000000..9858150 --- /dev/null +++ b/src/view/Categories/components/Products.jsx @@ -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 && + + } +
+
+
+
+

+ { t("title")} +

+

+ {t("subtitle")} +

+
+
+
+ {!loading && products.map((product, index) => ( +
+ +
+ ))} + { + loading && Array.from({ length: 12 }).map((_, index) => ( +
+ +
+ )) + } +
+
+ + +
+ + ); +}; + +export default ProductsListingPage; diff --git a/src/view/Categories/index.jsx b/src/view/Categories/index.jsx index fbaa3b2..f6970a0 100644 --- a/src/view/Categories/index.jsx +++ b/src/view/Categories/index.jsx @@ -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 ( <> -
+
+ + + -
+ { + content.title && + + } ); diff --git a/src/view/Landing/index.jsx b/src/view/Landing/index.jsx index 7b4c736..7d2d32a 100644 --- a/src/view/Landing/index.jsx +++ b/src/view/Landing/index.jsx @@ -33,20 +33,21 @@ const getStats = async () => { const Landing = async () => { - + const stats = await getStats() return (
{" "} - + {/* */} - + + {/* */} - +
); };