diff --git a/.env.production b/.env.production index e05e401..a625c83 100644 --- a/.env.production +++ b/.env.production @@ -6,4 +6,4 @@ NEXT_PUBLIC_PUBLIC_URL=https://api.vesmeh.com NEXT_PUBLIC_API_URL=https://api.vesmeh.com/api NEXT_PUBLIC_STORAGE_URL=http://storage.vesmeh.com STORAGE_URL=http://storage.vesmeh.com -NEXT_PUBLIC_PACKAGE_VERSION=0.3.0 \ No newline at end of file +NEXT_PUBLIC_PACKAGE_VERSION=0.3.1 \ No newline at end of file diff --git a/components/AppsComponent/CategoriesData/page.jsx b/components/AppsComponent/CategoriesData/page.jsx index 1805098..f4bb58c 100644 --- a/components/AppsComponent/CategoriesData/page.jsx +++ b/components/AppsComponent/CategoriesData/page.jsx @@ -8,25 +8,80 @@ import PaginationCategoory from "@comp/Category/PaginationCategoory/page"; import Footer from "@comp/Footer/page"; import Navbar from "@comp/Navbar/page"; import AppContext from "@ctx/AppContext"; -import { useContext, useEffect, useState } from "react"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import { useContext, useEffect, useMemo, useState } from "react"; import InfiniteScroll from "react-infinite-scroll-component"; -export default function CategoriesData({ params }) { - console.log("params", params.id[0]); +export default function CategoriesData({ params, products }) { + console.log(", filters,....params", products); const CTX = useContext(AppContext); - const pageGetProducts = CTX.state.pageGetProducts; + const searchParams = useSearchParams(); + + useEffect(() => { + console.log("setStopProducts", CTX.state.stopProducts); + if ( + Number(searchParams.get("page")) === 0 || + !Number(searchParams.get("page")) || + CTX.state.stopProducts + ) { + CTX.setProducts(products.products); + } else { + CTX.setProducts([...CTX.state.products, ...products.products]); + } + CTX.setStopProducts( + CTX.state.stopProducts || products?.products?.length < 20 + ); + CTX.setPager(products.pager); + CTX.setFilter(products.filters); + }, [products]); + + const pageGetProducts = useMemo( + () => (searchParams.get("page") ? Number(searchParams.get("page")) : 0), + [searchParams] + ); const stopProducts = CTX.state.stopProducts; - const pager = CTX.state.pager; - const productsLength = CTX.state.products?.length ?? 0; - console.log("stopProducts-handleInfiniteNextFetchProducts", productsLength); + const pager = products.pager; + const productsLength = CTX.state.products.length; const filter = CTX.state.filter; - const isChecked = CTX.state.isChecked; - const selectedBrands = CTX.state.selectedBrands; - const rangePrice = CTX.state.rangePrice; + const isChecked = useMemo( + () => Boolean(Number(searchParams.get("isActive"))), + [searchParams] + ); + const selectedBrands = useMemo( + () => + searchParams.get("brandIds") + ? searchParams.get("brandIds").split(",") + : [], + [searchParams] + ); + const rangePrice = useMemo( + () => [ + searchParams.get("maxPrice") + ? Number(searchParams.get("maxPrice")) + : filter?.price?.maximumValue, + searchParams.get("minPrice") + ? Number(searchParams.get("minPrice")) + : filter?.price?.minimumValue, + ], + [searchParams] + ); const isRangePrice = CTX.state.isRangePrice; - const sortBy = CTX.state.sortBy; + const sortBy = useMemo( + () => Number(searchParams.get("sortBy")), + [searchParams] + ); + + console.log( + "filters", + filter, + isChecked, + selectedBrands, + rangePrice, + isRangePrice, + sortBy + ); const fetchBarnds = async () => { const res = await fetch( @@ -39,42 +94,43 @@ export default function CategoriesData({ params }) { }; const decodedName = decodeURIComponent(params.id[1]); - + const pathname = usePathname(); + const router = useRouter(); const handleInfiniteNextFetchProducts = () => { // Increment the page number const nextPage = pageGetProducts + 1; console.log("runeed-handleInfiniteNextFetchProducts", nextPage); + const params = new URLSearchParams(searchParams.toString()); + params.set("page", nextPage); + router.push(`${pathname}?${params}`, { scroll: false }); + // Fetch products for the next page - CTX.fetchProducts( - nextPage, - params.id[0] != 0 ? params.id[0] : "", - selectedBrands, - isChecked, - rangePrice, - rangePrice, - sortBy != -1 ? sortBy : "", - isRangePrice - ); + // CTX.fetchProducts( + // nextPage, + // params.id[0] != 0 ? params.id[0] : "", + // selectedBrands, + // isChecked, + // rangePrice, + // rangePrice, + // sortBy != -1 ? sortBy : "", + // isRangePrice + // ); // Update the pageGetProducts state for the next fetch - CTX.setPageGetProducts(nextPage); + // CTX.setPageGetProducts(nextPage); }; const [loading, setLoading] = useState(true); const getData = async () => { setLoading(true); - await CTX.fetchProducts(0, params.id[0] != 0 ? params.id[0] : ""); + // await CTX.fetchProducts(0, params.id[0] != 0 ? params.id[0] : ""); await fetchBarnds(); setLoading(false); }; useEffect(() => { - window.scrollTo({ - top: 0, - behavior: "smooth", // Optional: smooth scrolling behavior - }); - + setLoading(false); getData(); }, []); diff --git a/components/AppsComponent/RootData/page.jsx b/components/AppsComponent/RootData/page.jsx index 60c1774..b11735a 100644 --- a/components/AppsComponent/RootData/page.jsx +++ b/components/AppsComponent/RootData/page.jsx @@ -17,6 +17,7 @@ import Goftino from "plugins/Goftino/page"; import { useRouter } from "next/navigation"; import NextTopLoader from "nextjs-toploader"; import Yektanet from "plugins/Goftino/page"; +import SideBarNavBarMobile from "@comp/Navbar/SideBarNavBarMobile/page"; const RootData = ({ children }) => { const [cart, setCart] = useState([]); @@ -43,6 +44,14 @@ const RootData = ({ children }) => { const [pageGetProducts, setPageGetProducts] = useState(0); const [isMobile, setIsMobile] = useState(false); const [isOpenLightBox, setIsOpenLightBox] = useState(false); + const [ + cooperationSystemProfileContractData, + setCooperationSystemProfileContractData, + ] = useState(""); + const [cooperationSystemProfileData, setCooperationSystemProfileData] = + useState([]); + const [searchResultData, setSearchResultData] = useState([]); + const [isSearched, setIsSearched] = useState(false); const [isChecked, setIsChecked] = useState(false); const [selectedBrands, setSelectedBrands] = useState([]); @@ -367,6 +376,73 @@ const RootData = ({ children }) => { } }; + const fetchCooperationSystemProfile = async () => { + try { + const data = await Chapar.get( + `${process.env.NEXT_PUBLIC_API_URL}/marketer/profile`, + { + headers: { + Authorization: localStorage.getItem("token"), + }, + } + ); + + console.log( + "---------s---------", + `${process.env.NEXT_PUBLIC_API_URL}/marketer/profile` + ); + setCooperationSystemProfileData(data); + } catch ({ error, status }) { + console.log(status); + toast.error(`${error?.response?.data?.message}`, { + position: "bottom-right", + closeOnClick: true, + }); + } + }; + + const fetchCooperationSystemProfileContract = async () => { + try { + const data = await Chapar.get( + `${process.env.NEXT_PUBLIC_API_URL}/marketer/signup/contract`, + { + headers: { + Authorization: localStorage.getItem("token"), + }, + } + ); + + setCooperationSystemProfileContractData(data); + } catch ({ error, status }) { + console.log(status); + toast.error(`${error?.response?.data?.message}`, { + position: "bottom-right", + closeOnClick: true, + }); + } + }; + + const fetchSearchResult = async (searchValue) => { + try { + const data = await Chapar.get( + `${process.env.NEXT_PUBLIC_API_URL}/search/thumb?name=${searchValue}`, + { + headers: { + Authorization: localStorage.getItem("token"), + }, + } + ); + + setSearchResultData(data); + } catch ({ error, status }) { + console.log(status); + toast.error(`${error?.response?.data?.message}`, { + position: "bottom-right", + closeOnClick: true, + }); + } + }; + useEffect(() => { const storedCart = localStorage.getItem("cart"); const token = localStorage.getItem("token"); @@ -379,6 +455,7 @@ const RootData = ({ children }) => { } fetchNavData(); + // fetchCooperationSystemProfile(); }, []); useEffect(() => { @@ -437,6 +514,10 @@ const RootData = ({ children }) => { isChecked, orderUser, bottomSheetSeeOrderOpen, + cooperationSystemProfileContractData, + cooperationSystemProfileData, + searchResultData, + isSearched, }, setCart, setProducts, @@ -464,6 +545,9 @@ const RootData = ({ children }) => { setBottomSheetSeeOrderOpen, setIsChecked, setOrderUser, + setCooperationSystemProfileContractData, + setCooperationSystemProfileData, + setIsSearched, AddItemToCart, RemoveItemFromCart, fetchNavData, @@ -474,6 +558,10 @@ const RootData = ({ children }) => { fetchOrderBagCheck, fetchOrderUser, GoCheckOut, + fetchCooperationSystemProfile, + fetchCooperationSystemProfileContract, + setSearchResultData, + fetchSearchResult, }} > {children} @@ -499,6 +587,7 @@ const RootData = ({ children }) => { + ); }; diff --git a/components/Blog/BlogComponents/Cart.jsx b/components/Blog/BlogComponents/Cart.jsx new file mode 100644 index 0000000..2d6961a --- /dev/null +++ b/components/Blog/BlogComponents/Cart.jsx @@ -0,0 +1,36 @@ +import Image from "next/image"; +import Link from "next/link"; +import PersianNumber from "plugins/PersianNumber"; +import React from "react"; + +const Cart = ({ mainImage, title, categoryName, slug, id, summery }) => { + console.log(process.env.NEXT_PUBLIC_STORAGE_URL + `/Images/Med/` + mainImage); + return ( + +
+
+
+ +
+
+ +
+

{title}

+

{summery}

+
+
+

{categoryName}

+
+
+
+
+ + ); +}; + +export default Cart; diff --git a/components/Blog/BlogComponents/PaginationBlogs.jsx b/components/Blog/BlogComponents/PaginationBlogs.jsx new file mode 100644 index 0000000..bd95caf --- /dev/null +++ b/components/Blog/BlogComponents/PaginationBlogs.jsx @@ -0,0 +1,123 @@ +"use client"; +import AppContext from "@ctx/AppContext"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import PersianNumber from "plugins/PersianNumber"; +import { useContext, useEffect, useState } from "react"; + +const PaginationBlogs = ({ totalPage }) => { + console.log("totalPage", totalPage); + const CTX = useContext(AppContext); + const searchParams = useSearchParams(); + const pager = totalPage; + const pathname = usePathname(); + const router = useRouter(); + const [currentPageIndex, setCurrentPageIndex] = useState( + Number(searchParams.get("page")) ? Number(searchParams.get("page")) : 0 + ); + useEffect(() => { + console.log("pagesssss", Number(searchParams.get("page"))); + setCurrentPageIndex( + Number(searchParams.get("page")) ? Number(searchParams.get("page")) : 0 + ); + }, [searchParams]); + const renderPaginationButtons = () => { + const buttons = []; + const totalPages = pager?.totalPage; + const maxButtonsToShow = 7; // Maximum buttons to show + + // If total pages are greater than maxButtonsToShow + if (totalPages > maxButtonsToShow) { + // Show buttons for the first page + buttons.push(renderPageButton(0)); + + // If current page is not too close to the start, show ellipsis + if (currentPageIndex > 2) { + buttons.push(renderEllipsis()); + } + + // Calculate the start index for buttons + const start = Math.max(1, currentPageIndex - 2); + + // Calculate the end index for buttons + const end = Math.min(currentPageIndex + 3, totalPages - 1); + + // Show buttons for pages within range + for (let i = start; i <= end; i++) { + buttons.push(renderPageButton(i)); + } + + // If current page is not too close to the end, show ellipsis + if (currentPageIndex < totalPages - 4) { + buttons.push(renderEllipsis()); + } + + // Show button for the last page + buttons.push(renderPageButton(totalPages - 1)); + } else { + // Show buttons for all pages + for (let i = 0; i < totalPages; i++) { + buttons.push(renderPageButton(i)); + } + } + + return buttons; + }; + + const renderPageButton = (pageIndex) => ( +
handlePageClick(pageIndex)} + > +

+ +

+
+ ); + + const renderEllipsis = () => ( +
+ ... +
+ ); + + const handlePageClick = (pageIndex) => { + setCurrentPageIndex(pageIndex); + // console.log("ss", i); + // CTX.fetchProducts( + // pageIndex, + // props.id[0] != 0 ? props.id[0] : "", + // props.selectedBrands, + // props.isChecked, + // props.rangePrice, + // props.rangePrice, + // props.sortBy != -1 ? props.sortBy : "", + // props.isRangePrice, + // true //pagination say or not + // ); + const nextPage = pageIndex; + console.log("runeed-handleInfiniteNextFetchProducts", nextPage); + + const params = new URLSearchParams(searchParams.toString()); + params.set("page", nextPage); + router.push(`${pathname}?${params}`); + // CTX.setStopProducts(true); + // Your fetchProducts function call here + }; + + return ( +
+
+ {/* Previous page button */} +
+ {renderPaginationButtons()} +
+ {/* Next page button */} +
+
+ ); +}; + +export default PaginationBlogs; diff --git a/components/Blog/BlogComponents/styleBlog.css b/components/Blog/BlogComponents/styleBlog.css new file mode 100644 index 0000000..26aac25 --- /dev/null +++ b/components/Blog/BlogComponents/styleBlog.css @@ -0,0 +1,20 @@ +h2 { + color: rgb(0, 49, 155); + + font-weight: 700; + margin-top: 15px; + margin-bottom: 2px; +} +p { + color: rgb(54, 54, 54); + font-weight: 400; +} + +h3 { + color: rgb(216, 16, 16); + + font-weight: 600; + margin-top: 15px; + margin-bottom: 2px; + margin-right: 10px; +} diff --git a/components/Blog/BlogData/page.jsx b/components/Blog/BlogData/page.jsx new file mode 100644 index 0000000..03a0241 --- /dev/null +++ b/components/Blog/BlogData/page.jsx @@ -0,0 +1,36 @@ +"use client"; + +import Image from "next/image"; +import React, { useEffect, useState } from "react"; +import Footer from "@comp/Footer/page"; +import Navbar from "@comp/Navbar/page"; + +const BlogData = ({ data }) => { + return ( +
+ + +
+
+
+ +

+ {data.title} +

+
+
+
+
+
+ +
+
+ ); +}; + +export default BlogData; diff --git a/components/Blog/BlogsData/page.jsx b/components/Blog/BlogsData/page.jsx new file mode 100644 index 0000000..fad4168 --- /dev/null +++ b/components/Blog/BlogsData/page.jsx @@ -0,0 +1,84 @@ +"use client"; + +import Footer from "@comp/Footer/page"; +import Navbar from "@comp/Navbar/page"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import PersianNumber from "plugins/PersianNumber"; +import React from "react"; +import Cart from "../BlogComponents/Cart"; +import PaginationBlogs from "../BlogComponents/PaginationBlogs"; + +const BlogsData = ({ dataCaetgories, data }) => { + console.log(data); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const router = useRouter(); + + const searchParamsCurrentId = searchParams.get("blogCategoryId"); + const handleGoCategories = (id) => { + // CTX.setIsChecked(!isChecked); + const params = new URLSearchParams(searchParams.toString()); + + params.set("blogCategoryId", id); + + params.set("page", "0"); + router.push(`${pathname}?${params}`); + }; + + console.log("dataCaetgories", dataCaetgories); + + return ( +
+ + +
+
+
+
+ {data?.blogs?.map((e) => ( + + ))} +
+ +
+ +
+
+ +
+

دسته بندی ها

+ +
+ {dataCaetgories?.map((e) => ( +
handleGoCategories(e.id)}> +
+
+

{e.name}

+ + ( + + ) + +
+
+ ))} +
+
+
+
+
+
+ ); +}; + +export default BlogsData; diff --git a/components/Category/FilterCategory/page.jsx b/components/Category/FilterCategory/page.jsx index d159e8b..b233122 100644 --- a/components/Category/FilterCategory/page.jsx +++ b/components/Category/FilterCategory/page.jsx @@ -1,6 +1,7 @@ "use client"; import AppContext from "@ctx/AppContext"; import { Switch } from "@headlessui/react"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import PersianNumber from "plugins/PersianNumber"; import RangeSlider from "plugins/RangeSlider/page"; import { useContext, useEffect, useRef } from "react"; @@ -15,36 +16,74 @@ const FilterCategory = ({ theme, filter, }) => { + const pathname = usePathname(); + const searchParams = useSearchParams(); const CTX = useContext(AppContext); const brands = CTX.state.brands; const pageGetProducts = CTX.state.pageGetProducts; const isFirstRender = useRef(true); - console.log(filter); + console.log("filter", filter); + const router = useRouter(); const handleCheckboxChange = () => { - CTX.setIsChecked(!isChecked); + // CTX.setIsChecked(!isChecked); + const params = new URLSearchParams(searchParams.toString()); + if (!isChecked) { + params.set("isActive", Number(!isChecked)); + } else { + params.delete("isActive"); + } + params.set("page", "0"); + router.push(`${pathname}?${params}`); }; const handleRangeChange = (values) => { - CTX.setIsRangePrice(true); + // CTX.setIsRangePrice(true); console.log(values); - CTX.setRangePrice(values); - console.log("rangePrice", rangePrice); + console.log("filters,values", values); + // CTX.setRangePrice(values); + // console.log("rangePrice", rangePrice); + + const params = new URLSearchParams(searchParams.toString()); + params.set("minPrice", values[0]); + params.set("maxPrice", values[1]); + params.set("page", "0"); + router.push(`${pathname}?${params}`, { scroll: false }); }; const handleFilterBrand = (name, id) => { - // Check if the brand is already selected - const isBrandSelected = selectedBrands.some((brand) => brand.id === id); - - if (!isBrandSelected) { - // If the brand is not already selected, add it to the state - CTX.setSelectedBrands((prevBrands) => [...prevBrands, { name, id }]); + const params = new URLSearchParams(searchParams.toString()); + let brandIds = params.get("brandIds") + ? Array.from(params.get("brandIds").split(",") ?? []) + : []; + // console.log("handleFilterBrand", id, brandIds, brandIds.includes(id)); + if (brandIds.includes(id)) { + brandIds = brandIds.filter((brandId) => brandId !== id); + console.log("handleFilterBrand", brandIds); + if (brandIds.length === 0) { + params.delete("brandIds"); + router.push(`${pathname}?${params}`); + return; + } } else { - // If the brand is already selected, remove it from the state - CTX.setSelectedBrands((prevBrands) => - prevBrands.filter((brand) => brand.id !== id) - ); + brandIds.push(id); } + params.set("brandIds", brandIds.join(",")); + params.set("page", "0"); + console.log("handleFilterBrand", id, brandIds); + router.push(`${pathname}?${params}`); + // Check if the brand is already selected + // const isBrandSelected = selectedBrands.some((brand) => brand.id === id); + + // if (!isBrandSelected) { + // // If the brand is not already selected, add it to the state + // CTX.setSelectedBrands((prevBrands) => [...prevBrands, { name, id }]); + // } else { + // // If the brand is already selected, remove it from the state + // CTX.setSelectedBrands((prevBrands) => + // prevBrands.filter((brand) => brand.id !== id) + // ); + // } }; const handleRangePriceFilter = () => { @@ -60,30 +99,30 @@ const FilterCategory = ({ ); }; - useEffect(() => { - if (isFirstRender.current) { - isFirstRender.current = false; - return; - } + // useEffect(() => { + // if (isFirstRender.current) { + // isFirstRender.current = false; + // return; + // } - CTX.fetchProducts( - 0, - id[0] != 0 ? id[0] : "", - selectedBrands, - isChecked, - rangePrice[0], - rangePrice[1], - sortBy != -1 ? sortBy : "", - isRangePrice - ); - }, [CTX.state.selectedBrands, CTX.state.isChecked]); + // CTX.fetchProducts( + // 0, + // id[0] != 0 ? id[0] : "", + // selectedBrands, + // isChecked, + // rangePrice[0], + // rangePrice[1], + // sortBy != -1 ? sortBy : "", + // isRangePrice + // ); + // }, [CTX.state.selectedBrands, CTX.state.isChecked]); - useEffect(() => { - CTX.setRangePrice([ - filter?.price?.minimumValue, - filter?.price?.maximumValue, - ]); - }, [filter]); + // useEffect(() => { + // CTX.setRangePrice([ + // filter?.price?.minimumValue, + // filter?.price?.maximumValue, + // ]); + // }, [filter]); return (
d.id == e.id) + selectedBrands.find((id) => id == e.id) ? "bg-primary-200 p-1" : "" } `} @@ -149,7 +188,7 @@ const FilterCategory = ({ >

فقط محصولات موجود

handleRangeChange(e)} @@ -201,25 +241,25 @@ const FilterCategory = ({

تا قیمت

- +

از قیمت

- +

-
+ {/*
-
+
*/}
diff --git a/components/Category/ListProdocts/page.jsx b/components/Category/ListProdocts/page.jsx index 14ad8e9..ab528ed 100644 --- a/components/Category/ListProdocts/page.jsx +++ b/components/Category/ListProdocts/page.jsx @@ -1,6 +1,7 @@ "use client"; import CardCategories from "@comp/Cards/CardCategories/page"; import AppContext from "@ctx/AppContext"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import PersianNumber from "plugins/PersianNumber"; import { useContext, useEffect } from "react"; @@ -14,31 +15,20 @@ const ListProdocts = ({ }) => { const CTX = useContext(AppContext); const products = CTX.state.products; + console.log("products filters", products); const pager = CTX.state.pager; const stopProducts = CTX.state.stopProducts; const pageGetProducts = CTX.state.pageGetProducts; - console.log( - "soretby--------------------------------------------------------", - sortBy - ); - - console.log(products); - - useEffect(() => { - if (sortBy != -1) { - CTX.fetchProducts( - 0, - id[0], - selectedBrands, - isChecked, - rangePrice, - rangePrice, - sortBy != -1 ? sortBy : "", - isRangePrice - ); - } - }, [sortBy]); + const searchParams = useSearchParams(); + const pathname = usePathname(); + const router = useRouter(); + const sort = (by) => { + const params = new URLSearchParams(searchParams.toString()); + params.set("sortBy", by); + params.set("page", "0"); + router.push(`${pathname}?${params}`); + }; return (
@@ -55,7 +45,7 @@ const ListProdocts = ({ className={`w-fit rounded-full px-2 mx-2 tr03 ${ sortBy == 1 ? "bg-primary-600" : " opacity-60 " }`} - onClick={() => CTX.setSortBy(1)} + onClick={() => sort(1)} >

CTX.setSortBy(2)} + onClick={() => sort(2)} >

CTX.setSortBy(3)} + onClick={() => sort(3)} >

CTX.setSortBy(4)} + onClick={() => sort(4)} >

CTX.setSortBy(5)} + onClick={() => sort(1)} >

{ const CTX = useContext(AppContext); + const [searchValue, setSearchValue] = useState(""); + const isSearched = CTX.state.isSearched; + + const inputRef = useRef(null); + + const handleRemoveSearch = () => { + CTX.setSearchResultData([]); + setSearchValue(""); + CTX.setIsSearched(false); + }; + + useEffect(() => { + if (CTX.state.closeNavbar) { + inputRef.current.focus(); + } + }, [CTX.state.closeNavbar]); + + const handleInputChange = (event) => { + setSearchValue(event.target.value); + }; + + useEffect(() => { + // Define a function to send the request + const sendRequest = async () => { + CTX.fetchSearchResult(searchValue); + console.log("Sending request for:", searchValue); + }; + + // Set a timer to send the request after 2000 milliseconds of inactivity + const timer = setTimeout(() => { + if (searchValue.trim() !== "") { + sendRequest(); + CTX.setIsSearched(true); + } + + if (searchValue == "") { + CTX.setIsSearched(false); + } + }, 1000); + + // Clean up function to clear the timer on component unmount or when searchTerm changes + return () => clearTimeout(timer); + }, [searchValue]); return ( <> @@ -36,32 +79,72 @@ const SearchSideBar = () => {

CTX.setCloseNavbar(true)} + value={searchValue} + onChange={(e) => handleInputChange(e)} /> -
-
- - - + {!isSearched ? ( +
+
+ + + +
-
+ ) : ( +
handleRemoveSearch()} + > +
+ + + +
+
+ )}
- + + {/* {true && ( +
setSearchResultShow(!searchResultShow)} + > + +
+ )} */} ); }; diff --git a/components/Category/Mobile/FilterCategoryMobile/page.jsx b/components/Category/Mobile/FilterCategoryMobile/page.jsx index 5a8fae2..593025c 100644 --- a/components/Category/Mobile/FilterCategoryMobile/page.jsx +++ b/components/Category/Mobile/FilterCategoryMobile/page.jsx @@ -1,5 +1,6 @@ "use client"; import AppContext from "@ctx/AppContext"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import BottomSheetFilter from "plugins/bottomSheet/BottomSheetFilter"; import { useContext, useEffect, useState } from "react"; @@ -9,20 +10,31 @@ const FilterCategoryMobile = (props) => { const [trendFilter, setTrendFilter] = useState(false); - useEffect(() => { - if (props.sortBy != -1) { - CTX.fetchProducts( - 0, - props.id[0] != 0 ? props.id[0] : "", - props.selectedBrands, - props.isChecked, - props.rangePrice, - props.rangePrice, - props.sortBy != -1 ? props.sortBy : "", - props.isRangePrice - ); - } - }, [props.sortBy]); + // useEffect(() => { + // if (props.sortBy != -1) { + // CTX.fetchProducts( + // 0, + // props.id[0] != 0 ? props.id[0] : "", + // props.selectedBrands, + // props.isChecked, + // props.rangePrice, + // props.rangePrice, + // props.sortBy != -1 ? props.sortBy : "", + // props.isRangePrice + // ); + // } + // }, [props.sortBy]); + + const searchParams = useSearchParams(); + const pathname = usePathname(); + const router = useRouter(); + + const sort = (by) => { + const params = new URLSearchParams(searchParams.toString()); + params.set("sortBy", by); + params.set("page", "0"); + router.push(`${pathname}?${params}`); + }; return ( <> @@ -97,7 +109,7 @@ const FilterCategoryMobile = (props) => { className={`w-fit rounded-full px-2 mx-1 tr03 ${ props.sortBy == 1 ? "bg-primary-600" : " opacity-60 " }`} - onClick={() => CTX.setSortBy(1)} + onClick={() => sort(1)} >

{ className={`w-fit rounded-full px-2 mx-1 tr03 ${ props.sortBy == 2 ? "bg-primary-600" : " opacity-60 " }`} - onClick={() => CTX.setSortBy(2)} + onClick={() => sort(2)} >

{ className={`w-fit rounded-full px-2 mx-1 tr03 ${ props.sortBy == 3 ? "bg-primary-600" : " opacity-60 " }`} - onClick={() => CTX.setSortBy(3)} + onClick={() => sort(3)} >

{ className={`w-fit rounded-full px-2 mx-1 tr03 ${ props.sortBy == 4 ? "bg-primary-600" : " opacity-60 " }`} - onClick={() => CTX.setSortBy(4)} + onClick={() => sort(4)} >

{ className={`w-fit rounded-full px-2 mx-1 tr03 ${ props.sortBy == 5 ? "bg-primary-600" : " opacity-60 " }`} - onClick={() => CTX.setSortBy(5)} + onClick={() => sort(5)} >

{ const CTX = useContext(AppContext); - + const searchParams = useSearchParams(); const pager = CTX.state.pager; - const pageGetProducts = CTX.state.pageGetProducts; - console.log("pager ", pager?.currentPage + 1, pageGetProducts); - - const [currentPageIndex, setCurrentPageIndex] = useState(pageGetProducts); + const pathname = usePathname(); + const router = useRouter(); + const [currentPageIndex, setCurrentPageIndex] = useState( + Number(searchParams.get("page")) ? Number(searchParams.get("page")) : 0 + ); useEffect(() => { - setCurrentPageIndex(pageGetProducts); - }, [pageGetProducts]); + console.log("pagesssss", Number(searchParams.get("page"))); + setCurrentPageIndex( + Number(searchParams.get("page")) ? Number(searchParams.get("page")) : 0 + ); + }, [searchParams]); const renderPaginationButtons = () => { const buttons = []; const totalPages = pager?.totalPage; @@ -80,17 +85,24 @@ const PaginationCategoory = (props) => { const handlePageClick = (pageIndex) => { setCurrentPageIndex(pageIndex); // console.log("ss", i); - CTX.fetchProducts( - pageIndex, - props.id[0] != 0 ? props.id[0] : "", - props.selectedBrands, - props.isChecked, - props.rangePrice, - props.rangePrice, - props.sortBy != -1 ? props.sortBy : "", - props.isRangePrice, - true //pagination say or not - ); + // CTX.fetchProducts( + // pageIndex, + // props.id[0] != 0 ? props.id[0] : "", + // props.selectedBrands, + // props.isChecked, + // props.rangePrice, + // props.rangePrice, + // props.sortBy != -1 ? props.sortBy : "", + // props.isRangePrice, + // true //pagination say or not + // ); + const nextPage = pageIndex; + console.log("runeed-handleInfiniteNextFetchProducts", nextPage); + + const params = new URLSearchParams(searchParams.toString()); + params.set("page", nextPage); + router.push(`${pathname}?${params}`); + CTX.setStopProducts(true); // Your fetchProducts function call here }; diff --git a/components/Footer/page.jsx b/components/Footer/page.jsx index 36ee577..c533b9d 100644 --- a/components/Footer/page.jsx +++ b/components/Footer/page.jsx @@ -117,6 +117,12 @@ const Footer = () => { ژل بهداشتی بانوان{" "} + + +

  • + مجله زیبایی وسمه{" "} +
  • + diff --git a/components/Navbar/CartNavbar/page.jsx b/components/Navbar/CartNavbar/page.jsx index 776b625..4aa2fe9 100644 --- a/components/Navbar/CartNavbar/page.jsx +++ b/components/Navbar/CartNavbar/page.jsx @@ -13,7 +13,9 @@ const CartNavbar = ({ isScrolled }) => { return (
    { + return ( + <> +
    +
    +
    +
    + + + +
    + +
    +

    جستجو های پرطرفدار

    +
    +
    + +
    + +
    +

    شامپو بدن

    +
    + + +
    +

    کرم مرطوب کننده دست و پا

    +
    + + + +
    +

    شوینده ظروف

    +
    + +
    +
    + {searchResultCategoryData?.length > 0 && + searchResultProductData?.length > 0 ? ( + <> + {searchResultCategoryData?.map((e, index) => ( + +
    +
    + {" "} +
    +
    +

    {e.name}

    + + دسته بندی + +
    +
    + + ))} + +
    + + {searchResultProductData?.map((e, index) => ( + +
    +
    +
    + {!!e.mainImage ? ( + {`${e.persianName} + ) : ( +
    + وسمه +
    + )} +
    +
    +
    +

    {e.persianName}

    + + محصول{" "} + +
    +
    + + ))} + + ) : ( +
    +
    + چیزی یافت نشد +
    +
    + )} +
    + + ); +}; + +export default ResultSearchBar; diff --git a/components/Navbar/SideBarNavBarMobile/page.jsx b/components/Navbar/SideBarNavBarMobile/page.jsx index f0597c5..7a08359 100644 --- a/components/Navbar/SideBarNavBarMobile/page.jsx +++ b/components/Navbar/SideBarNavBarMobile/page.jsx @@ -4,6 +4,9 @@ import Image from "next/image"; import Link from "next/link"; import { useContext, useState } from "react"; import logo from "../../../public/images/logo.png"; +import Navbar from "../page"; +import SearchSideBar from "@comp/Category/Mobile/Component/SearchSideBar/page"; +import ResultSearchBar from "../ResultSearchBar/page"; const SideBarNavBarMobile = () => { const CTX = useContext(AppContext); @@ -11,6 +14,9 @@ const SideBarNavBarMobile = () => { const [firstChildIndex, setFirstChildIndex] = useState(-1); const dataNav = CTX.state.navData; + const isSearched = CTX.state.isSearched; + const searchResultCategoryData = CTX.state.searchResultData.categories; + const searchResultProductData = CTX.state.searchResultData.products; console.log(firstChild); @@ -68,85 +74,94 @@ const SideBarNavBarMobile = () => { />
    -
    - - -
    +
    -
    -
      - {dataNav?.map((e, index) => ( -
    • { - setFirstChild(dataNav[index].children); - setFirstChildIndex(index); - }} - key={index} - > -
      -

      {e.name}

      -
      - - - + {isSearched ? ( +
      + +
      + ) : ( +
      +
        + {dataNav?.map((e, index) => ( +
      • { + setFirstChild(dataNav[index].children); + setFirstChildIndex(index); + }} + key={index} + > +
        +

        + {e.name} +

        + +
        + + + +
        -
      - {firstChildIndex == index && ( - <> -
        -
      • - CTX.setCloseNavbar(false)} - > -

        - همه موارد -

        - -
      • {" "} - {firstChild.map((e, index) => ( -
      • + {firstChildIndex == index && ( + <> +
          +
        • CTX.setCloseNavbar(false)} > -
          -

          {e.name}

          -
          +

          + همه موارد +

          -
        • - ))} -
        - - )} -
      • - ))} -
      -
      +
    • {" "} + {firstChild.map((e, index) => ( +
    • + + CTX.setCloseNavbar(false) + } + > +
      +

      + {e.name} +

      +
      + +
    • + ))} +
    + + )} + + ))} + +
    + )}
    diff --git a/components/Navbar/page.jsx b/components/Navbar/page.jsx index 89494e1..33f76fd 100644 --- a/components/Navbar/page.jsx +++ b/components/Navbar/page.jsx @@ -12,14 +12,20 @@ import Link from "next/link"; import PersianNumber from "plugins/PersianNumber"; import BottomSheetCart from "plugins/bottomSheet/BottomSheetCart"; import CartNavbar from "./CartNavbar/page"; +import { debounce } from "lodash"; +import { useRouter } from "next/navigation"; +import ResultSearchBar from "./ResultSearchBar/page"; const Navbar = ({ theme }) => { const [open, setOpen] = useState(false); const CTX = useContext(AppContext); + const router = useRouter(); const dataNav = CTX.state.navData; const profile = CTX.state.profile; const cart = CTX.state.cart; + const searchResultCategoryData = CTX.state.searchResultData.categories; + const searchResultProductData = CTX.state.searchResultData.products; console.log("dataNav", dataNav); @@ -28,12 +34,20 @@ const Navbar = ({ theme }) => { const [closeNavbar, setClosNavbar] = useState(false); const [isScrolled, setIsScrolled] = useState(false); const [smallDashboard, setSmallDashboard] = useState(false); + const [searchResultShow, setSearchResultShow] = useState(false); + const [searchValue, setSearchValue] = useState(""); const handleItemNavber = (index) => { setNavItemHover(index); console.log("index", index); }; + const handleRemoveSearch = () => { + CTX.setSearchResultData([]); + setSearchValue(""); + setSearchResultShow(false); + }; + useEffect(() => { const handleResize = () => { setIsDesktop(window.innerWidth > 1000); // You can adjust the width threshold as needed @@ -64,6 +78,29 @@ const Navbar = ({ theme }) => { }; }, []); + useEffect(() => { + // Define a function to send the request + const sendRequest = async () => { + CTX.fetchSearchResult(searchValue); + console.log("Sending request for:", searchValue); + setSearchResultShow(true); + }; + + // Set a timer to send the request after 2000 milliseconds of inactivity + const timer = setTimeout(() => { + if (searchValue.trim() !== "") { + sendRequest(); + } + }, 1000); + + // Clean up function to clear the timer on component unmount or when searchTerm changes + return () => clearTimeout(timer); + }, [searchValue]); + + const handleInputChange = (event) => { + setSearchValue(event.target.value); + }; + return ( <> {isDesktop && ( @@ -83,6 +120,77 @@ const Navbar = ({ theme }) => {
    + <> +
    + handleInputChange(e)} + /> + + {!searchResultShow ? ( +
    +
    + + + +
    +
    + ) : ( +
    handleRemoveSearch()} + > +
    + + + +
    +
    + )} +
    + + {searchResultShow && ( +
    setSearchResultShow(!searchResultShow)} + > +
    + +
    +
    + )} + {profile?.length <= 0 ? (
    @@ -148,6 +256,17 @@ const Navbar = ({ theme }) => { +
  • + +
    +

    + همکاری در فروش{" "} +

    +
    +
    + +
  • +
  • @@ -364,7 +483,7 @@ const Navbar = ({ theme }) => { {!isDesktop && ( <>
    {
  • +
  • + +
    +

    + همکاری در فروش{" "} +

    +
    +
    + +
  • +
  • diff --git a/package-lock.json b/package-lock.json index bc79413..a5c26e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "axios": "^1.6.5", "framer-motion": "^10.16.16", "jalali-moment": "^3.3.11", + "lodash": "^4.17.21", "next": "14.0.4", "nextjs-toploader": "^1.6.6", "rc-slider": "^10.5.0", diff --git a/package.json b/package.json index 764f6ee..9203dc3 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "axios": "^1.6.5", "framer-motion": "^10.16.16", "jalali-moment": "^3.3.11", + "lodash": "^4.17.21", "next": "14.0.4", "nextjs-toploader": "^1.6.6", "rc-slider": "^10.5.0", diff --git a/plugins/RangeSlider/page.jsx b/plugins/RangeSlider/page.jsx index fdff7fa..3b52dd7 100644 --- a/plugins/RangeSlider/page.jsx +++ b/plugins/RangeSlider/page.jsx @@ -1,7 +1,7 @@ import Slider from "rc-slider"; import "rc-slider/assets/index.css"; -const RangeSlider = ({ min, max, onChange }) => { +const RangeSlider = ({ min, max, onChange, values }) => { const handleStyleMin = { borderColor: "#2189A8", height: 25, @@ -11,6 +11,7 @@ const RangeSlider = ({ min, max, onChange }) => { // left: 0, }; + console.log("slider,values", values, min, max); const trackStyle = [{ backgroundColor: "#2189A8", height: 8 }]; const railStyle = { backgroundColor: "#e6e6e6", height: 8 }; @@ -20,8 +21,10 @@ const RangeSlider = ({ min, max, onChange }) => { min={min} max={max} allowCross={false} + value={values ?? [min, max]} // defaultValue={[min, max]} - onChange={onChange} + + onChangeComplete={onChange} handleStyle={[handleStyleMin, handleStyleMin]} trackStyle={trackStyle} railStyle={railStyle} diff --git a/src/app/blogs/[...id]/page.jsx b/src/app/blogs/[...id]/page.jsx new file mode 100644 index 0000000..657187d --- /dev/null +++ b/src/app/blogs/[...id]/page.jsx @@ -0,0 +1,16 @@ +import BlogData from "@comp/Blog/BlogData/page"; +import React from "react"; + +async function getData(id) { + const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/blog/${id}`); + const post = await res.json(); + return post; +} + +const page = async ({ params }) => { + const data = await getData(params.id[0]); + + return ; +}; + +export default page; diff --git a/src/app/blogs/page.jsx b/src/app/blogs/page.jsx new file mode 100644 index 0000000..931ca91 --- /dev/null +++ b/src/app/blogs/page.jsx @@ -0,0 +1,36 @@ +import BlogsData from "@comp/Blog/BlogsData/page"; +import React from "react"; + +async function getData(searchParams) { + // console.log("page , check", params.page); + + const res = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/blog?` + + new URLSearchParams({ ...searchParams }) + // ?page=${params.page ?? 0} + // { cache: "no-cache" } + ); + const post = await res.json(); + // console.log("dddddddd ", post); + + return post; +} + +async function getCaetgories() { + const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/blog/category`); + + const post = await res.json(); + + // console.log("aaaaaaaaaaaaaaaaaaaa", post); + return post; +} + +const page = async ({ searchParams }) => { + const data = await getData(searchParams); + const dataCaetgories = await getCaetgories(); + // console.log("-------------------------------- ", dataCaetgories); + + return ; +}; + +export default page; diff --git a/src/app/categories/[...id]/page.jsx b/src/app/categories/[...id]/page.jsx index 799fb5e..3db46e9 100644 --- a/src/app/categories/[...id]/page.jsx +++ b/src/app/categories/[...id]/page.jsx @@ -32,10 +32,49 @@ export async function generateMetadata({ params }) { }; } -const page = ({ params }) => { +// page +// categoryId +// brandIds +// isActive +// minPrice +// maxPrice +// sortBy +const fetchProducts = async (categoryId, searchParams) => { + const { brandIds: brandIdsString, isActive, ...params } = searchParams; + const query = { + categoryId, + page: 0, + ...(!!isActive ? { isActive: !!isActive } : {}), + ...params, + }; + + + + const brandIds = brandIdsString?.split(",") ?? []; + const brandIdsQuery = + brandIds?.length > 0 ? `&brandIds=${brandIds?.join("&brandIds=")}` : ""; + + try { + const res = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/product?` + + new URLSearchParams({ ...query }) + + brandIdsQuery + ); + if (!res.ok) return []; + const products = await res.json(); + console.log("ppppp", products); + return products; + } catch (error) { + return []; + } +}; + +const page = async ({ params, searchParams }) => { + const products = await fetchProducts(params?.["id"]?.[0], searchParams); + console.log("filters,page", products); return (
    - +
    ); }; diff --git a/src/app/profile/component/SideBarProfile/page.jsx b/src/app/profile/component/SideBarProfile/page.jsx index 613d2c9..d858f38 100644 --- a/src/app/profile/component/SideBarProfile/page.jsx +++ b/src/app/profile/component/SideBarProfile/page.jsx @@ -9,7 +9,7 @@ const SideBarProfile = () => { const profile = CTX.state.profile; return ( -
    +
    @@ -59,6 +59,17 @@ const SideBarProfile = () => {
  • +
  • + +
    +

    + همکاری در فروش{" "} +

    +
    +
    + +
  • +
  • CTX.setBottomSheetLogOutOpen(true)} diff --git a/src/app/profile/saleCooperationSystem/page.jsx b/src/app/profile/saleCooperationSystem/page.jsx new file mode 100644 index 0000000..19bd219 --- /dev/null +++ b/src/app/profile/saleCooperationSystem/page.jsx @@ -0,0 +1,465 @@ +"use client"; +import Navbar from "@comp/Navbar/page"; +import React, { useContext, useEffect, useRef, useState } from "react"; +import SideBarProfile from "../component/SideBarProfile/page"; +import SimpleReactValidator from "simple-react-validator"; +import { toast } from "react-toastify"; +import PersianNumber from "plugins/PersianNumber"; +import AppContext from "@ctx/AppContext"; +import moment from "jalali-moment"; +import Chapar from "plugins/Chapar"; + +const page = () => { + const CTX = useContext(AppContext); + const cooperationSystemProfileContractData = + CTX.state.cooperationSystemProfileContractData; + + const cooperationSystemProfileData = CTX.state.cooperationSystemProfileData; + const profile = CTX.state.profile; + const [stepsaleCooperationSystem, setStepsaleCooperationSystem] = useState(0); + const [rulesAccept, setRulesAccept] = useState(false); + const [nationalCode, setNationalCode] = useState(""); + const [fatherName, setFatherName] = useState(""); + const [shabaNumber, setShabaNumber] = useState(""); + const [year, setYear] = useState(""); + const [month, setMonth] = useState(""); + const [day, setDay] = useState(""); + const [birthDate, setBirthDate] = useState(""); + + const [, forceUpdate] = useState(); + const [submited, setSubmited] = useState(false); + + const validator = useRef( + new SimpleReactValidator({ + messages: { + required: "پر کردن این فیلد الزامی میباشد", + }, + element: (message) => ( + <> +
    + {message} +
    + + ), + }) + ); + + // Generate options for days and months + const daysOptions = Array.from({ length: 31 }, (_, i) => i + 1); + const monthsOptions = Array.from({ length: 12 }, (_, i) => i + 1); + // Generate options for years between 1340 and 1388 + const yearsOptions = Array.from({ length: 49 }, (_, i) => 1388 - i); + + const body = { + fatherName, + nationalId: nationalCode, + shaba: shabaNumber, + birthDate, + }; + + const handleBirthDate = (year, month, day) => { + setDay(day); + setMonth(month); + setYear(year); + const persianDate = `${year}/${month}/${day}`; + // Convert Persian date to timestamp + const timestamp = moment(persianDate, "jYYYY/jM/jD").unix(); + setBirthDate(timestamp); + console.log(timestamp); + }; + + const sendInfoUserCooperationSystem = async () => { + if (validator.current.allValid()) { + try { + const data = await Chapar.post( + `${process.env.NEXT_PUBLIC_API_URL}/marketer/signup`, + JSON.stringify(body), + { + headers: { + Authorization: localStorage.getItem("token"), + }, + } + ); + + CTX.setCooperationSystemProfileData(data); + setStepsaleCooperationSystem(2); + } catch ({ error, status }) { + toast.error("مشکلی در ارسال اطلاعات رخ داده است", { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + } + } else { + toast.error("پرکردن همه ی فیلد ها واجب است", { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + validator.current.showMessages(); + forceUpdate(1); + } + }; + + useEffect(() => { + console.log("profile.isMarketer", profile); + if (profile.isMarketer) { + CTX.fetchCooperationSystemProfile(); + setStepsaleCooperationSystem(2); + } else { + CTX.fetchCooperationSystemProfileContract(); + setStepsaleCooperationSystem(0); + } + }, [profile]); + + return ( + <> + +
    + + +
    +
    +
    +
    +

    + قوانین همکاری +

    +
    +
    +

    + اطلاعات تکمیلی +

    +
    +
    +

    + داشبورد +

    +
    +
    + + {stepsaleCooperationSystem == 0 ? ( +
    +
    + +
    + { + setRulesAccept(e.target.checked); + }} + /> + +
    + + {!rulesAccept ? ( +
    + +
    + ) : ( +
    setStepsaleCooperationSystem(1)} + > + +
    + )} +
    + ) : stepsaleCooperationSystem == 1 ? ( +
    +
    +
    +
    + +
    + { + setNationalCode(e.target.value); + validator.current.showMessageFor("nationalCode"); + }} + /> + {!submited ? ( + <> + {validator.current.message( + "nationalCode", + nationalCode, + "required" + )} + + ) : ( + "" + )} +
    + +
    +
    + +
    + { + setFatherName(e.target.value); + validator.current.showMessageFor("fatherName"); + }} + /> + {!submited ? ( + <> + {validator.current.message( + "fatherName", + fatherName, + "required" + )} + + ) : ( + "" + )} +
    + +
    +
    + +
    +
    + { + setShabaNumber(e.target.value); + validator.current.showMessageFor("shabaNumber"); + }} + /> +
    +

    + IR -{" "} +

    +
    +
    + {!submited ? ( + <> + {validator.current.message( + "shabaNumber", + shabaNumber, + "required" + )} + + ) : ( + "" + )} +
    + +
    +
    + +
    +
    + + + + + +
    + {!submited ? ( +
    + <>{validator.current.message("day", day, "required")} + <> + {validator.current.message("year", year, "required")} + + <> + {validator.current.message( + "month", + month, + "required" + )} + +
    + ) : ( + "" + )} +
    +
    + +
    sendInfoUserCooperationSystem()} + > + +
    +
    + ) : stepsaleCooperationSystem == 2 ? ( +
    +
    +
    +

    + کد معرف شما{" "} +

    + +
    +

    + {cooperationSystemProfileData?.discountCode} +

    +
    +
    +
    + +
    +
    + +

    + فروش شما +

    +
    +
    + +
    +
    +
    + + + + تومان + +
    +

    + سود شما از خرید{" "} +

    +
    +
    +
    + ) : ( + "" + )} +
    +
    +
    + + ); +}; + +export default page;