add offer blog page
parent
9f165a79fb
commit
167439c97a
|
@ -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.31.3
|
||||
NEXT_PUBLIC_PACKAGE_VERSION=0.32.31
|
|
@ -0,0 +1,18 @@
|
|||
FROM node:20-alpine3.18 AS runner
|
||||
WORKDIR /app
|
||||
ARG NODE_ENV=production
|
||||
COPY public ./public
|
||||
COPY .next ./.next
|
||||
COPY node_modules ./node_modules
|
||||
COPY package.json ./package.json
|
||||
COPY .env.production ./.env.production
|
||||
COPY next.config.js ./next.config.js
|
||||
|
||||
EXPOSE 3000
|
||||
ENV PORT 3000
|
||||
CMD ["node_modules/.bin/next", "start"]
|
||||
|
||||
|
||||
|
||||
|
||||
# docker build -f Dockerfile.x -t registry.vnfco.ir/netinashop/vesmeh:0.32.31 .
|
|
@ -10,6 +10,7 @@ import PersianNumber from "plugins/PersianNumber";
|
|||
import logo from "../../../public/images/logo.png";
|
||||
|
||||
const ProductData = ({ params, data }) => {
|
||||
console.log("data", data);
|
||||
const [product, setProduct] = useState([]);
|
||||
const [specificationsHeader, setSpecificationsHeader] = useState([]);
|
||||
const [productBarDetail, setProductBarDetail] = useState(0);
|
||||
|
@ -128,10 +129,10 @@ const ProductData = ({ params, data }) => {
|
|||
|
||||
{/* xs:sticky lg:relative xs:top-[60px] lg:top-0 ==> sticky for price=================== */}
|
||||
|
||||
<div className=" w-9/12 lg:col-span-2 sticky top-[80px] xs:hidden lg:block ">
|
||||
<div className=" w-11/12 lg:col-span-2 sticky top-[80px] xs:hidden lg:block ">
|
||||
<div className="p-3 h-fit border-[1px] border-gray-300 rounded-xl ">
|
||||
<div className="flex justify-center">
|
||||
<div className="w-[130px]">
|
||||
<div className="w-[110px]">
|
||||
{data?.product?.files?.length > 0 ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${
|
||||
|
@ -157,7 +158,7 @@ const ProductData = ({ params, data }) => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p className="mb-0 text-sm text-gray-500">
|
||||
<p className="mb-0 text-sm text-gray-500 my-2">
|
||||
{data?.product?.persianName}{" "}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -332,13 +333,24 @@ const ProductData = ({ params, data }) => {
|
|||
<h3 className=" text-sm text-gray-400 mt-7 mb-2">
|
||||
نقد و برسی{" "}
|
||||
</h3>
|
||||
<div className="border p-5 rounded-lg">
|
||||
<div className="flex justify-center py-5">
|
||||
<div className="bg-white shadow w-fit rounded-full text-sm p-4">
|
||||
چیزی یافت نشد
|
||||
|
||||
{!!data?.product.expertCheck ? (
|
||||
<div className="border p-5 rounded-lg">
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: data?.product.expertCheck,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="border p-5 rounded-lg">
|
||||
<div className="flex justify-center py-5">
|
||||
<div className="bg-white shadow w-fit rounded-full text-sm p-4">
|
||||
چیزی یافت نشد
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{" "}
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div id="section3">
|
||||
|
|
|
@ -53,6 +53,10 @@ const RootData = ({ children }) => {
|
|||
const [searchResultData, setSearchResultData] = useState([]);
|
||||
const [isSearched, setIsSearched] = useState(false);
|
||||
|
||||
const [specialOfferData, setSpecialOfferData] = useState([]);
|
||||
const [cosmeticData, setCosmeticData] = useState([]);
|
||||
const [HomeCosmeticData, setHomeCosmeticData] = useState([]);
|
||||
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
const [selectedBrands, setSelectedBrands] = useState([]);
|
||||
const [rangePrice, setRangePrice] = useState([1000, 100]);
|
||||
|
@ -431,6 +435,30 @@ const RootData = ({ children }) => {
|
|||
}
|
||||
};
|
||||
|
||||
const fetchSpecialOffer = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?page=0&specialOffer=true`
|
||||
);
|
||||
const specialOffer = await res.json();
|
||||
setSpecialOfferData(specialOffer);
|
||||
};
|
||||
|
||||
const fetchCosmetic = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?page=0&categoryId=553af942-7a14-4757-9a03-a3ebec6c865a`
|
||||
);
|
||||
const Cosmetic = await res.json();
|
||||
setCosmeticData(Cosmetic);
|
||||
};
|
||||
|
||||
const fetchHomeCosmetic = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?page=0&categoryId=effe5d98-d4b7-47e1-9bfb-4d3c77ab3347`
|
||||
);
|
||||
const HomeCosmetic = await res.json();
|
||||
setHomeCosmeticData(HomeCosmetic);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const storedCart = localStorage.getItem("cart");
|
||||
const token = localStorage.getItem("token");
|
||||
|
@ -506,6 +534,9 @@ const RootData = ({ children }) => {
|
|||
cooperationSystemProfileData,
|
||||
searchResultData,
|
||||
isSearched,
|
||||
cosmeticData,
|
||||
HomeCosmeticData,
|
||||
specialOfferData,
|
||||
},
|
||||
setCart,
|
||||
setProducts,
|
||||
|
@ -550,6 +581,12 @@ const RootData = ({ children }) => {
|
|||
fetchCooperationSystemProfileContract,
|
||||
setSearchResultData,
|
||||
fetchSearchResult,
|
||||
setHomeCosmeticData,
|
||||
setCosmeticData,
|
||||
setSpecialOfferData,
|
||||
fetchHomeCosmetic,
|
||||
fetchCosmetic,
|
||||
fetchSpecialOffer,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
import TimerDownBlog from "@comp/TimerDown/TimerDown";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import hyphenateString from "plugins/HyphenateString/page";
|
||||
import PersianNumber from "plugins/PersianNumber";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
const SliderProductsOffer = ({ data }) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// Filter to get the latest 10 products
|
||||
const latestProducts = data?.products?.slice(-10) || [];
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCurrentIndex((prevIndex) => (prevIndex + 1) % latestProducts.length);
|
||||
}, 10000); // 10 seconds
|
||||
|
||||
return () => clearInterval(interval); // Clean up on unmount
|
||||
}, [latestProducts.length]);
|
||||
|
||||
const handleDotClick = (index) => {
|
||||
setCurrentIndex(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="sticky top-20">
|
||||
{" "}
|
||||
{data?.products?.map((e, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`slider-item ${
|
||||
index === currentIndex ? "block" : "hidden"
|
||||
}`}
|
||||
>
|
||||
<Link href={`/products/${e.id}/${hyphenateString(e.persianName)}`}>
|
||||
<div className="bg-contact-us h-[260px] rounded-2xl">
|
||||
<div>
|
||||
<div className="flex p-3">
|
||||
<div className="w-3/12">
|
||||
<div className="bg-white h-20 w-20 rounded-2xl overflow-hidden">
|
||||
{/* Uncomment and adjust the Image component as needed */}
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e?.mainImage}`}
|
||||
width={350}
|
||||
height={350}
|
||||
className="mx-auto !object-cover w-20 h-20"
|
||||
alt={e?.persianName}
|
||||
priority
|
||||
loading="eager"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative w-9/12 px-2 mt-4">
|
||||
<p className="mb-0 text-white h-[50px] overflow-hidden font-medium px-3">
|
||||
{e?.persianName}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="mb-0 text-center">
|
||||
<PersianNumber
|
||||
number={(e?.cost / 10).toLocaleString()}
|
||||
style="text-white !text-[25px] font-medium"
|
||||
/>
|
||||
<small className="mx-1 text-white">تومان</small>
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<div className="bg-white rounded-full py-1 px-2 ml-2">
|
||||
<p className="mb-0 text-[11px] text-green-900 font-medium">
|
||||
تضمین بهترین قیمت
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<div className="relative bottom-[-70px]">
|
||||
<TimerDownBlog />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full">
|
||||
<svg
|
||||
className="absolute h-[20px] block top-0 rotate-90 mr-[-38px] mt-[168px]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 740 155.61"
|
||||
>
|
||||
<path
|
||||
fill="white"
|
||||
d="M532.54 85.81c69.58,-54.09 138.74,-82.63 207.46,-85.62l-740 0c73.71,3.21 147.93,35.81 222.63,97.82 28.75,23.85 45.98,38.3 83.91,49.54 20.26,6.01 41.42,8.74 63.46,8.18 28.55,0.73 55.61,-4.06 81.17,-14.35 36.28,-14.61 51.98,-32.73 81.37,-55.57z"
|
||||
></path>
|
||||
</svg>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end w-full">
|
||||
<svg
|
||||
className="absolute h-[20px] block top-0 -rotate-90 ml-[-38px] mt-[168px]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 740 155.61"
|
||||
>
|
||||
<path
|
||||
fill="white"
|
||||
d="M532.54 85.81c69.58,-54.09 138.74,-82.63 207.46,-85.62l-740 0c73.71,3.21 147.93,35.81 222.63,97.82 28.75,23.85 45.98,38.3 83.91,49.54 20.26,6.01 41.42,8.74 63.46,8.18 28.55,0.73 55.61,-4.06 81.17,-14.35 36.28,-14.61 51.98,-32.73 81.37,-55.57z"
|
||||
></path>
|
||||
</svg>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
<div className="absolute w-full mt-[13px]">
|
||||
<div className="h-3 w-full border-t-[4px] opacity-15 border-white border-dashed"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
<div className="flex justify-center mt-2">
|
||||
{latestProducts.map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
onClick={() => handleDotClick(index)}
|
||||
className={`w-3 h-3 mx-[1px] mt-1 rounded-full cursor-pointer ${
|
||||
index === currentIndex
|
||||
? "bg-contact-us w-7"
|
||||
: "bg-primary-200 opacity-80"
|
||||
}`}
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SliderProductsOffer;
|
|
@ -1,20 +1,39 @@
|
|||
h2 {
|
||||
#blog-content > h2 {
|
||||
color: rgb(0, 49, 155);
|
||||
|
||||
font-weight: 700;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 2px;
|
||||
font-size: 16px;
|
||||
}
|
||||
p {
|
||||
#blog-content > p {
|
||||
color: rgb(54, 54, 54);
|
||||
font-weight: 400;
|
||||
@apply leading-8 text-base;
|
||||
}
|
||||
#blog-content > li {
|
||||
color: rgb(54, 54, 54);
|
||||
font-weight: 400;
|
||||
@apply leading-8 text-base;
|
||||
}
|
||||
#blog-content > a {
|
||||
color: rgb(54, 54, 54);
|
||||
font-weight: 400;
|
||||
@apply leading-8 text-base text-blue-700 hover:text-blue-900;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: rgb(216, 16, 16);
|
||||
|
||||
font-weight: 600;
|
||||
#blog-content > h3 {
|
||||
color: rgb(216, 16, 16) !important;
|
||||
font-weight: 400;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 2px;
|
||||
margin-right: 10px;
|
||||
font-size: 20px;
|
||||
/* margin-right: 10px; */
|
||||
}
|
||||
|
||||
#blog-content > img {
|
||||
@apply rounded-xl mx-auto shadow-lg my-8;
|
||||
}
|
||||
|
||||
#blog-content > iframe {
|
||||
@apply rounded-xl mx-auto shadow-lg my-8;
|
||||
}
|
||||
|
|
|
@ -1,29 +1,52 @@
|
|||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import Footer from "@comp/Footer/page";
|
||||
import Navbar from "@comp/Navbar/page";
|
||||
|
||||
import "../BlogComponents/styleBlog.css";
|
||||
import TimerDown from "@comp/TimerDown/TimerDown";
|
||||
import TimerDownBlog from "@comp/TimerDown/TimerDown";
|
||||
import PersianNumber from "plugins/PersianNumber";
|
||||
import SliderProductsOffer from "../BlogComponents/SliderProductsOffer/page";
|
||||
import AppContext from "@ctx/AppContext";
|
||||
const BlogData = ({ data }) => {
|
||||
const CTX = useContext(AppContext);
|
||||
|
||||
const specialOfferData = CTX.state.specialOfferData;
|
||||
|
||||
useEffect(() => {
|
||||
if (specialOfferData.length <= 0) {
|
||||
CTX.fetchSpecialOffer();
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<div>
|
||||
<Navbar />
|
||||
|
||||
<div className="xs:px-3 md:px-5 md:container md:mx-auto mb-10">
|
||||
<div className="grid grid-cols-1 gap-7 rtl">
|
||||
<div className=" mt-10 ">
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/Images/Med/${data.mainImage}`}
|
||||
width={500}
|
||||
height={500}
|
||||
className="w-[400px]"
|
||||
/>
|
||||
<h1 className=" font-bold text-right xs:text-[20px] lg:text-[40px]">
|
||||
{data.title}
|
||||
</h1>
|
||||
<div></div>
|
||||
<div dangerouslySetInnerHTML={{ __html: data.content }} />
|
||||
<div className="grid xs:grid-cols-1 lg:grid-cols-6 gap-7 rtl">
|
||||
<div className="lg:col-span-4 mt-10 rtl">
|
||||
<div className=" mt-10 ">
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/Images/Med/${data.mainImage}`}
|
||||
width={500}
|
||||
height={500}
|
||||
className="xs:w-full lg:w-6/12 rounded-3xl mb-3"
|
||||
/>
|
||||
<h1 className=" font-bold text-right xs:text-[20px] lg:text-[40px]">
|
||||
{data.title}
|
||||
</h1>
|
||||
<div></div>
|
||||
<div
|
||||
id="blog-content"
|
||||
dangerouslySetInnerHTML={{ __html: data.content }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-2 mt-10 rtl ">
|
||||
<SliderProductsOffer data={specialOfferData} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,6 +9,7 @@ import Cart from "../BlogComponents/Cart";
|
|||
import PaginationBlogs from "../BlogComponents/PaginationBlogs";
|
||||
|
||||
const BlogsData = ({ dataCaetgories, data }) => {
|
||||
console.log("data", data);
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
|
|
|
@ -3,7 +3,7 @@ import Link from "next/link";
|
|||
import PersianNumber from "plugins/PersianNumber";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const TimerDown = () => {
|
||||
const TimerDownBlog = () => {
|
||||
const [timeRemaining, setTimeRemaining] = useState({
|
||||
days: 0,
|
||||
hours: 0,
|
||||
|
@ -54,50 +54,50 @@ const TimerDown = () => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className=" justify-center ltr realtive mr-5 px-2 mt-[-30px] xs:hidden lg:flex ">
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<p className="mb-0 = text-center text-red-900 font-bold pt-3 ">
|
||||
<div className=" justify-center ltr realtive mr-5 px-2 mt-[-30px] flex ">
|
||||
<div className=" rounded-2xl bg-white w-[40px] h-[40px] mx-1">
|
||||
<p className="mb-0 = text-center text-primary-300 font-bold pt-[10px] ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.days}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
style={"!text-[15px] pt-[-5px] text-primary-900 "}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">روز</p>
|
||||
<p className="text-[10px] pt-2 text-center text-white ">روز</p>
|
||||
</div>
|
||||
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<p className="mb-0 text-center text-red-900 font-bold pt-3 ">
|
||||
<div className=" rounded-2xl bg-white w-[40px] h-[40px] mx-1">
|
||||
<p className="mb-0 text-center text-primary-300 font-bold pt-[10px] ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.hours}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
style={"!text-[15px] pt-[-5px] text-primary-900 "}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">ساعت</p>
|
||||
<p className="text-[10px] pt-2 text-center text-white ">ساعت</p>
|
||||
</div>
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<p className="mb-0 text-center text-red-900 font-bold pt-3 ">
|
||||
<div className=" rounded-2xl bg-white w-[40px] h-[40px] mx-1">
|
||||
<p className="mb-0 text-center text-primary-300 font-bold pt-[10px] ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.minutes}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
style={"!text-[15px] pt-[-5px] text-primary-900 "}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">دقیقه</p>
|
||||
<p className="text-[10px] pt-2 text-center text-white ">دقیقه</p>
|
||||
</div>
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<div className=" rounded-2xl bg-white w-[40px] h-[40px] mx-1">
|
||||
<Link href="/login">
|
||||
{" "}
|
||||
<p className="mb-0 text-center text-red-900 font-bold pt-3 ">
|
||||
<p className="mb-0 text-center text-primary-300 font-bold pt-[10px] ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.seconds}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
style={"!text-[15px] pt-[-5px] text-primary-900 "}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">ثانیه</p>
|
||||
<p className="text-[10px] pt-2 text-center text-white ">ثانیه</p>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TimerDown;
|
||||
export default TimerDownBlog;
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
"use client";
|
||||
import Link from "next/link";
|
||||
import PersianNumber from "plugins/PersianNumber";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const TimerDown = () => {
|
||||
const [timeRemaining, setTimeRemaining] = useState({
|
||||
days: 0,
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
seconds: 0,
|
||||
milliseconds: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const calculateTimeRemaining = () => {
|
||||
// Get current date and time
|
||||
const now = new Date();
|
||||
|
||||
// Calculate yesterday's date
|
||||
const yesterday = new Date(now);
|
||||
yesterday.setDate(now.getDate() - 1);
|
||||
yesterday.setHours(23, 59, 0, 0); // Set time to 23:59:00
|
||||
|
||||
// Calculate tomorrow's date
|
||||
const tomorrow = new Date(now);
|
||||
tomorrow.setDate(now.getDate() + 1);
|
||||
tomorrow.setHours(23, 59, 0, 0); // Set time to 23:59:00
|
||||
|
||||
// Calculate time difference
|
||||
const difference = tomorrow - now;
|
||||
|
||||
// Convert time difference to days, hours, minutes, seconds, and milliseconds
|
||||
const days = Math.floor(difference / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor(
|
||||
(difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
|
||||
);
|
||||
const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((difference % (1000 * 60)) / 1000);
|
||||
const milliseconds = difference % 1000;
|
||||
|
||||
// Update state
|
||||
setTimeRemaining({ days, hours, minutes, seconds, milliseconds });
|
||||
};
|
||||
|
||||
// Call calculateTimeRemaining once to set initial state
|
||||
calculateTimeRemaining();
|
||||
|
||||
// Update time remaining every second
|
||||
const intervalId = setInterval(calculateTimeRemaining, 1000);
|
||||
|
||||
// Clean up interval on component unmount
|
||||
return () => clearInterval(intervalId);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className=" justify-center ltr realtive mr-5 px-2 mt-[-30px] xs:hidden lg:flex ">
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<p className="mb-0 = text-center text-red-900 font-bold pt-3 ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.days}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">روز</p>
|
||||
</div>
|
||||
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<p className="mb-0 text-center text-red-900 font-bold pt-3 ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.hours}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">ساعت</p>
|
||||
</div>
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<p className="mb-0 text-center text-red-900 font-bold pt-3 ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.minutes}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">دقیقه</p>
|
||||
</div>
|
||||
<div className=" rounded-full bg-red-100 w-[50px] h-[50px] mx-1">
|
||||
<Link href="/login">
|
||||
{" "}
|
||||
<p className="mb-0 text-center text-red-900 font-bold pt-3 ">
|
||||
<PersianNumber
|
||||
number={timeRemaining.seconds}
|
||||
style={"text-[27px] text-red-900 "}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-[10px] pt-4 text-center text-gray-600 ">ثانیه</p>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TimerDown;
|
|
@ -4649,6 +4649,30 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-spring-bottom-sheet/node_modules/react-dom": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"scheduler": "^0.20.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/react-spring-bottom-sheet/node_modules/scheduler": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-toastify": {
|
||||
"version": "9.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz",
|
||||
|
@ -5547,6 +5571,20 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||
|
|
|
@ -2,7 +2,9 @@ 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 res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/blog/${id}`, {
|
||||
cache: "no-cache",
|
||||
});
|
||||
const post = await res.json();
|
||||
return post;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,18 @@ async function getData(sParams) {
|
|||
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/blog?` +
|
||||
new URLSearchParams({ ...query })
|
||||
new URLSearchParams({ ...query }),
|
||||
{
|
||||
cache: "no-cache",
|
||||
}
|
||||
// ?page=${params.page ?? 0}
|
||||
// { cache: "no-cache" }
|
||||
);
|
||||
const post = await res.json();
|
||||
//
|
||||
|
||||
console.log("post", post);
|
||||
|
||||
return post;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,10 @@ const fetchProducts = async (categoryId, searchParams) => {
|
|||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?` +
|
||||
new URLSearchParams({ ...query }) +
|
||||
brandIdsQuery
|
||||
brandIdsQuery,
|
||||
{
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (!res.ok) return [];
|
||||
const products = await res.json();
|
||||
|
|
|
@ -7,41 +7,21 @@ import HeroSection from "@comp/LandingPage/HeroSection/page";
|
|||
import HomeSection from "@comp/LandingPage/HomeSection/page";
|
||||
import SurpriseSection from "@comp/LandingPage/SurpriseSection/page";
|
||||
import Navbar from "@comp/Navbar/page";
|
||||
import AppContext from "@ctx/AppContext";
|
||||
import Head from "next/head";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
|
||||
export default function Page() {
|
||||
const [specialOfferData, setSpecialOfferData] = useState([]);
|
||||
const [cosmeticData, setCosmeticData] = useState([]);
|
||||
const [HomeCosmeticData, setHomeCosmeticData] = useState([]);
|
||||
const fetchSpecialOffer = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?page=0&specialOffer=true`
|
||||
);
|
||||
const specialOffer = await res.json();
|
||||
setSpecialOfferData(specialOffer);
|
||||
};
|
||||
const CTX = useContext(AppContext);
|
||||
|
||||
const fetchCosmetic = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?page=0&categoryId=553af942-7a14-4757-9a03-a3ebec6c865a`
|
||||
);
|
||||
const Cosmetic = await res.json();
|
||||
setCosmeticData(Cosmetic);
|
||||
};
|
||||
|
||||
const fetchHomeCosmetic = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product?page=0&categoryId=effe5d98-d4b7-47e1-9bfb-4d3c77ab3347`
|
||||
);
|
||||
const HomeCosmetic = await res.json();
|
||||
setHomeCosmeticData(HomeCosmetic);
|
||||
};
|
||||
const specialOfferData = CTX.state.specialOfferData;
|
||||
const cosmeticData = CTX.state.cosmeticData;
|
||||
const HomeCosmeticData = CTX.state.HomeCosmeticData;
|
||||
|
||||
useEffect(() => {
|
||||
fetchSpecialOffer();
|
||||
fetchCosmetic();
|
||||
fetchHomeCosmetic();
|
||||
CTX.fetchSpecialOffer();
|
||||
CTX.fetchCosmetic();
|
||||
CTX.fetchHomeCosmetic();
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import ProductData from "@comp/AppsComponent/ProductData/page";
|
||||
|
||||
async function getData(id) {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/product/${id}`);
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/product/${id}`, {
|
||||
cache: "no-cache",
|
||||
});
|
||||
const post = await res.json();
|
||||
console.log("object11", post);
|
||||
return post;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue