Files
2025-06-18 18:44:42 +05:30

473 lines
20 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { products } from "@/data/products";
import React, { useEffect, useReducer } from "react";
import Image from "next/image";
import FilteringOptions from "./FilteringOptions";
import Link from "next/link";
import { initialState, reducer } from "@/reducer/FilterReducer";
import { useContextElement } from "@/context/Context";
export default function Shop() {
const { addProductToCart, isAddedToCartProducts } = useContextElement();
const [state, dispatch] = useReducer(reducer, initialState);
const {
price,
brands,
filtered,
sortingOption,
sorted,
currentPage,
itemPerPage,
} = state;
const allProps = {
...state,
setPrice: (value) => dispatch({ type: "SET_PRICE", payload: value }),
setBrands: (newBrand) => {
let newBrands = [...brands];
if (newBrands.includes(newBrand)) {
newBrands = newBrands.filter((brand) => brand != newBrand);
} else {
newBrands = [...newBrands, newBrand];
}
console.log(newBrands);
dispatch({ type: "SET_BRANDS", payload: newBrands });
},
setSortingOption: (value) =>
dispatch({ type: "SET_SORTING_OPTION", payload: value }),
setCurrentPage: (value) =>
dispatch({ type: "SET_CURRENT_PAGE", payload: value }),
setItemPerPage: (value) => {
dispatch({ type: "SET_CURRENT_PAGE", payload: 1 }),
dispatch({ type: "SET_ITEM_PER_PAGE", payload: value });
},
clearFilter: () => {
dispatch({ type: "CLEAR_FILTER" });
},
};
useEffect(() => {
let filteredArrays = [];
if (brands.length) {
const filteredByBrands = [...products].filter((elm) =>
brands.every((brand) => elm.filterBrands.includes(brand))
);
filteredArrays = [...filteredArrays, filteredByBrands];
}
const filteredByPrice = [...products].filter(
(elm) => elm.price >= price[0] && elm.price <= price[1]
);
filteredArrays = [...filteredArrays, filteredByPrice];
const commonItems = [...products].filter((item) =>
filteredArrays.every((array) => array.includes(item))
);
dispatch({ type: "SET_FILTERED", payload: commonItems });
}, [price, brands]);
useEffect(() => {
if (sortingOption === "Price Ascending") {
dispatch({
type: "SET_SORTED",
payload: [...filtered].sort((a, b) => a.price - b.price),
});
} else if (sortingOption === "Price Descending") {
dispatch({
type: "SET_SORTED",
payload: [...filtered].sort((a, b) => b.price - a.price),
});
} else if (sortingOption === "Title Ascending") {
dispatch({
type: "SET_SORTED",
payload: [...filtered].sort((a, b) => a.title.localeCompare(b.title)),
});
} else if (sortingOption === "Title Descending") {
dispatch({
type: "SET_SORTED",
payload: [...filtered].sort((a, b) => b.title.localeCompare(a.title)),
});
} else {
dispatch({ type: "SET_SORTED", payload: filtered });
}
dispatch({ type: "SET_CURRENT_PAGE", payload: 1 });
}, [filtered, sortingOption]);
return (
<div className="tf-spacing-41">
<div className="tf-container">
<div className="wrap-shop">
<div className="row">
<div className="col-xl-8">
<div className="left">
<div className="top mb_92">
<div className="text_mono-gray-8 text-body-1 result-count">
Showing 16 of 8 results
</div>
<div className="wrap d-flex">
<div className="wrap-sort">
<div className="text_mono-gray-8 text-body-1">
Sort by
</div>
<div
className="tf-dropdown-sort"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<div className="btn-select">
<span className="text-body-3 text-sort-value">
{sortingOption}
</span>
<span className="icon icon-angle-down-solid" />
</div>
<div className="dropdown-menu">
{[
"Sort by (Default)",
"Title Ascending",
"Title Descending",
"Price Ascending",
"Price Descending",
].map((elm, i) => (
<div
key={i}
className={`select-item ${
sortingOption == elm ? "active" : ""
}`}
onClick={() => allProps.setSortingOption(elm)}
data-sort-value="best-selling"
>
<span className="text-body-3 text-value-item">
{elm}
</span>
</div>
))}
</div>
</div>
</div>
<div className="wrap-layout">
<ul
className="nav-tab-filter group-layout"
role="tablist"
>
<li className="nav-tab-item" role="presentation">
<a
href="#gridLayout"
className="btn-layout grid nav-link-item active"
data-bs-toggle="tab"
>
<svg
width={22}
height={22}
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.611328 7.94444H21.3891M21.3891 14.6667H0.611328"
stroke="black"
/>
<rect
x="0.5"
y="0.5"
width={21}
height={21}
stroke="black"
/>
<path d="M7.33398 0V20.7778" stroke="black" />
<path d="M14.666 0V20.7778" stroke="black" />
</svg>
</a>
</li>
<li className="nav-tab-item" role="presentation">
<a
href="#listLayout"
className="nav-link-item btn-layout list"
data-bs-toggle="tab"
>
<svg
width={22}
height={22}
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.88867 4.8889H21.3887"
stroke="black"
/>
<circle
cx="1.22222"
cy="4.88889"
r="0.722222"
fill="#D9D9D9"
stroke="black"
/>
<path d="M4.88867 11H21.3887" stroke="black" />
<path
d="M1.94444 11C1.94444 11.3989 1.62109 11.7222 1.22222 11.7222C0.82335 11.7222 0.5 11.3989 0.5 11C0.5 10.6011 0.82335 10.2778 1.22222 10.2778C1.62109 10.2778 1.94444 10.6011 1.94444 11Z"
fill="#D9D9D9"
stroke="black"
/>
<path
d="M4.88867 17.1111H21.3887"
stroke="black"
/>
<path
d="M1.94444 17.1111C1.94444 17.51 1.62109 17.8333 1.22222 17.8333C0.82335 17.8333 0.5 17.51 0.5 17.1111C0.5 16.7122 0.82335 16.3889 1.22222 16.3889C1.62109 16.3889 1.94444 16.7122 1.94444 17.1111Z"
fill="#D9D9D9"
stroke="black"
/>
</svg>
</a>
</li>
</ul>
</div>
</div>
</div>
<div className="flat-animate-tab">
<div className="tab-content">
<div
className="tab-pane active show"
id="gridLayout"
role="tabpanel"
>
<div className="tf-grid-layout-2 md-col-3">
{sorted.map((product) => (
<div
className="product-item hover-image"
key={product.id}
>
<Link
href={`/product-details/${product.id}`}
className="img-style"
>
<Image
className="lazyload"
data-src={product.imgSrc}
alt="item"
src={product.imgSrc}
width={product.width}
height={product.height}
/>
</Link>
<div className="content">
<div className="info">
<div className="text-body-1 product-name mb_8">
<Link
href={`/product-details/${product.id}`}
className="link"
>
{product.title}
</Link>
</div>
<div className="h6 price d-flex gap_10">
{product.oldPrice ? (
<>
<span className="new-price">
$
{product.price.toFixed(
product.price % 1 === 0 ? 0 : 2
)}
</span>
<span className="old-price sub-heading">
$
{product.oldPrice.toFixed(
product.oldPrice % 1 === 0 ? 0 : 2
)}
</span>
</>
) : (
`$${product.price.toFixed(
product.price % 1 === 0 ? 0 : 2
)}`
)}
</div>
</div>
<a
href="#"
onClick={(e) => {
e.preventDefault();
addProductToCart(product.id);
}}
className={`add-cart ${
isAddedToCartProducts(product.id)
? "cart-added"
: ""
}`}
>
<i className="icon-shopping-cart-solid" />
</a>
</div>
</div>
))}
</div>
<ul className="wg-pagination d-flex justify-content-center gap_12 mt_58">
<li>
<a href="#">
<i className="icon-angle-left-solid" />
</a>
</li>
<li>
<a href="#" className="active">
1
</a>
</li>
<li>
<a href="#">...</a>
</li>
<li>
<a href="#">4</a>
</li>
<li>
<a href="#">
<i className="icon-angle-right-solid" />
</a>
</li>
</ul>
</div>
<div className="tab-pane" id="listLayout" role="tabpanel">
<div className="wrap-list d-flex gap-16 flex-direction-column">
{sorted.map((product, i) => (
<div
key={i}
className="product-item hover-image style-list"
>
<Link
href={`/product-details/${product.id}`}
className="img-style"
>
<Image
className="lazyload"
alt="item"
src={product.imgSrc}
width={product.width}
height={product.height}
/>
</Link>
<div className="content">
<div className="info">
<div className="text-body-1 product-name mb_8">
<Link
href={`/product-details/${product.id}`}
className="link"
>
{product.title}
</Link>
</div>
<div className="h6 price d-flex gap_10">
{product.oldPrice ? (
<>
<span className="new-price">
$
{product.price.toFixed(
product.price % 1 === 0 ? 0 : 2
)}
</span>
<span className="old-price sub-heading">
$
{product.oldPrice.toFixed(
product.oldPrice % 1 === 0 ? 0 : 2
)}
</span>
</>
) : (
`$${product.price.toFixed(
product.price % 1 === 0 ? 0 : 2
)}`
)}
</div>
</div>
<div className="list-product-btn">
<a
onClick={(e) => {
e.preventDefault();
addProductToCart(product.id);
}}
className="add-cart"
href="#"
>
{isAddedToCartProducts(product.id)
? "Already Added"
: "Add to Cart"}
</a>
<a
href="#"
className="box-icon wishlist btn-icon-action"
>
<span className="icon icon-heart" />
<span className="tooltip">Wishlist</span>
</a>
<a
href="#"
className="box-icon quickview tf-btn-loading"
>
<span className="icon icon-eye" />
<span className="tooltip">Quick View</span>
</a>
</div>
</div>
</div>
))}
</div>
<ul className="wg-pagination d-flex justify-content-center gap_12 mt_58">
<li>
<a href="#">
<i className="icon-angle-left-solid" />
</a>
</li>
<li>
<a href="#" className="active">
1
</a>
</li>
<li>
<a href="#">...</a>
</li>
<li>
<a href="#">4</a>
</li>
<li>
<a href="#">
<i className="icon-angle-right-solid" />
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div className="col-xl-4">
<div className="right">
<div className="sildebar-fiiler canvas-filter">
<div className="canvas-wrapper">
<div className="canvas-header d-flex d-xl-none">
<h5 className="">
<span className="icon icon-filter" />
Filters
</h5>
<div className="close-filter">
<span className="icon-times-solid" />
</div>
</div>
<div className="canvas-body">
<FilteringOptions allProps={allProps} />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}