Compare commits
6 Commits
29149b1f6f
...
123112393d
Author | SHA1 | Date |
---|---|---|
|
123112393d | |
|
6c6c48f5cb | |
|
45bfebf2ca | |
|
230aad7abc | |
|
df1c6a3818 | |
|
03e98063c0 |
|
@ -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=1.0.3.5
|
||||
NEXT_PUBLIC_PACKAGE_VERSION=1.0.5.7
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
import Footer from "@comp/Footer/page";
|
||||
import Navbar from "@comp/Navbar/page";
|
||||
import GalleryBox from "plugins/Gallery/page";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
|
||||
import AddToCart from "@comp/Cards/Components/AddToCart/page";
|
||||
import Image from "next/image";
|
||||
|
@ -12,14 +12,22 @@ import moment from "jalali-moment";
|
|||
import Chapar from "plugins/Chapar";
|
||||
import { toast } from "react-toastify";
|
||||
import { useRouter } from "next/navigation";
|
||||
import InfiniteScroll from "react-infinite-scroll-component";
|
||||
import BottomSheetComment from "plugins/bottomSheet/BottomSheetComment";
|
||||
import AppContext from "@ctx/AppContext";
|
||||
|
||||
const ProductData = ({ params, data }) => {
|
||||
console.log("data", data);
|
||||
|
||||
const CTX = useContext(AppContext);
|
||||
const [product, setProduct] = useState([]);
|
||||
const [review, setReview] = useState([]);
|
||||
const [specificationsHeader, setSpecificationsHeader] = useState([]);
|
||||
const [productBarDetail, setProductBarDetail] = useState(0);
|
||||
const [comment, setComment] = useState("");
|
||||
const [content, setContent] = useState("");
|
||||
const [rate, setRate] = useState(4);
|
||||
const [page, setPage] = useState(0);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -29,26 +37,40 @@ const ProductData = ({ params, data }) => {
|
|||
setProduct(post.product);
|
||||
};
|
||||
|
||||
const fetchReview = async (id) => {
|
||||
const fetchReview = async (id, currentPage, afterCreatReview) => {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product/${id}/review?page=0`
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product/${id}/comment?page=${currentPage}&count=10`
|
||||
);
|
||||
|
||||
// Check if the response is OK and has JSON content
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP error! status: ${res.status}`);
|
||||
}
|
||||
|
||||
const post = await res.json();
|
||||
const data = await res.json();
|
||||
|
||||
console.log("post test comment", post);
|
||||
setReview(post);
|
||||
// Assuming the API returns an array of reviews and a total count or indication if more data is available
|
||||
if (data.length < 10) {
|
||||
setHasMore(false);
|
||||
}
|
||||
|
||||
if (afterCreatReview) {
|
||||
setReview((prevReview) => [...prevReview, ...data]);
|
||||
} else {
|
||||
setReview(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching review:", error);
|
||||
console.error("Error fetching reviews:", error);
|
||||
setHasMore(false); // Stop further fetches on error
|
||||
}
|
||||
};
|
||||
|
||||
const fetchMoreData = () => {
|
||||
const nextPage = page + 1;
|
||||
fetchReview(params.id[0], nextPage);
|
||||
setPage(nextPage);
|
||||
};
|
||||
|
||||
const displaySpecifications = (specs) => {
|
||||
let data = [];
|
||||
if (specs?.length > 3) {
|
||||
|
@ -81,20 +103,21 @@ const ProductData = ({ params, data }) => {
|
|||
|
||||
const createProductReview = async () => {
|
||||
const body = {
|
||||
title: `${data.product?.persianName}نظر کاربر برای محصول`,
|
||||
comment,
|
||||
title: ` نظر کاربر برای محصول {" "}${data.product?.persianName}`,
|
||||
content,
|
||||
rate: 1,
|
||||
productId: params.id[0],
|
||||
rate,
|
||||
};
|
||||
try {
|
||||
const data = await Chapar.post(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/product/review`,
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/comment`,
|
||||
body
|
||||
);
|
||||
|
||||
setComment("");
|
||||
setContent("");
|
||||
|
||||
fetchReview(params.id[0]);
|
||||
fetchReview(params.id[0], 0);
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
|
@ -113,9 +136,13 @@ const ProductData = ({ params, data }) => {
|
|||
}
|
||||
};
|
||||
|
||||
const handleStarClick = (value) => {
|
||||
setRate(value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchPost(params.id[0]);
|
||||
fetchReview(params.id[0]);
|
||||
fetchReview(params.id[0], 0);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -127,8 +154,8 @@ const ProductData = ({ params, data }) => {
|
|||
return (
|
||||
<>
|
||||
<Navbar theme={1} />
|
||||
<div className=" py-10">
|
||||
<div className="grid xs:grid-cols-1 lg:grid-cols-8 rtl gap-6 lg:px-20">
|
||||
<div className="py-10 ">
|
||||
<div className="grid gap-6 xs:grid-cols-1 lg:grid-cols-8 rtl lg:px-20">
|
||||
<div className="lg:col-span-3 ">
|
||||
<GalleryBox file={data?.product?.files} />
|
||||
</div>
|
||||
|
@ -144,18 +171,18 @@ const ProductData = ({ params, data }) => {
|
|||
</div>
|
||||
|
||||
<div className="flex my-4">
|
||||
<div className="bg-primary-400 rounded-full py-1 px-3 ml-2">
|
||||
<div className="px-3 py-1 ml-2 rounded-full bg-primary-400">
|
||||
<p className="mb-0 text-sm text-white ">اصالت کالای </p>
|
||||
</div>
|
||||
|
||||
{data?.product?.hasDiscount && (
|
||||
<div className="bg-danger-100 rounded-full py-1 px-3 ml-2">
|
||||
<div className="px-3 py-1 ml-2 rounded-full bg-danger-100">
|
||||
<p className="mb-0 text-sm text-white ">بمب امروز </p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!data?.product?.warranty == "" && (
|
||||
<div className="bg-secondary-500 rounded-full py-1 px-3 ml-2">
|
||||
<div className="px-3 py-1 ml-2 rounded-full bg-secondary-500">
|
||||
<p className="mb-0 text-sm text-white ">
|
||||
{product?.warranty}
|
||||
</p>
|
||||
|
@ -174,20 +201,18 @@ const ProductData = ({ params, data }) => {
|
|||
</div> */}
|
||||
|
||||
<div>
|
||||
<div className="text-right mt-3 flex justify-between">
|
||||
<h2 className="mb-0 text-gray-400 text-sm">
|
||||
<div className="flex justify-between mt-3 text-right">
|
||||
<h2 className="mb-0 text-sm text-gray-400">
|
||||
{data?.product?.summery}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul className="mt-3 px-3">
|
||||
<ul className="px-3 mt-3">
|
||||
{specificationsHeader.map((e, index) => (
|
||||
<li className=" flex my-2" key={index}>
|
||||
<li className="flex my-2 " key={index}>
|
||||
<div className="w-[10px] h-[10px] relative rounded-full bg-primary-500 mt-1"></div>
|
||||
<p className="mb-0 w-full text-sm text-gray-700 mx-2 ">
|
||||
{e}
|
||||
</p>
|
||||
<p className="w-full mx-2 mb-0 text-sm text-gray-700 ">{e}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
@ -224,7 +249,7 @@ const ProductData = ({ params, data }) => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p className="mb-0 text-sm text-gray-500 my-2">
|
||||
<p className="my-2 mb-0 text-sm text-gray-500">
|
||||
{data?.product?.persianName}{" "}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -262,7 +287,7 @@ const ProductData = ({ params, data }) => {
|
|||
|
||||
<div className="w-6/12 mx-auto h-[1px] bg-gray-200 mt-4"></div>
|
||||
|
||||
<div className=" mt-4 flex justify-between ">
|
||||
<div className="flex justify-between mt-4 ">
|
||||
{true ? (
|
||||
<div className="flex justify-end">
|
||||
<div className="mb-0 font-bold text-sm absolute mt-[-11px] ml-[0px] right-0 mr-[13px] text-red-600 flex rtl">
|
||||
|
@ -288,7 +313,7 @@ const ProductData = ({ params, data }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber
|
||||
number={(data?.cost / 10).toLocaleString()}
|
||||
/>
|
||||
|
@ -303,7 +328,7 @@ const ProductData = ({ params, data }) => {
|
|||
|
||||
<div className="lg:col-span-6">
|
||||
<div className="xs:px-[15px] lg:px-[100px]">
|
||||
<div className="bg-gray-200 rounded-full xs:p-1 lg:p-3 flex w-fit sticky top-0 ">
|
||||
<div className="sticky top-0 flex bg-gray-200 rounded-full xs:p-1 lg:p-3 w-fit ">
|
||||
<div
|
||||
className={` rounded-full xs:p-2 lg:p-3 cursor-pointer tr03 ${
|
||||
productBarDetail == 0 ? "bg-primary-500 text-gray-100" : ""
|
||||
|
@ -349,7 +374,7 @@ const ProductData = ({ params, data }) => {
|
|||
</div>
|
||||
|
||||
<div id="section0">
|
||||
<h3 className=" text-sm text-gray-400 mt-7 mb-2">
|
||||
<h3 className="mb-2 text-sm text-gray-400 mt-7">
|
||||
مشخصات محصول
|
||||
</h3>
|
||||
<div className="min-w-[200px] mt-5 rounded-xl overflow-hidden border rtl ">
|
||||
|
@ -362,7 +387,7 @@ const ProductData = ({ params, data }) => {
|
|||
>
|
||||
<p className="mb-0 text-sm text-gray-600">
|
||||
{e.title}:
|
||||
<small className="text-sm text-gray-800 font-bold ">
|
||||
<small className="text-sm font-bold text-gray-800 ">
|
||||
{" "}
|
||||
{e.value}{" "}
|
||||
</small>
|
||||
|
@ -373,12 +398,10 @@ const ProductData = ({ params, data }) => {
|
|||
</div>
|
||||
|
||||
<div id="section2">
|
||||
<h3 className=" text-sm text-gray-400 mt-7 mb-2">
|
||||
نقد و برسی{" "}
|
||||
</h3>
|
||||
<h3 className="mb-2 text-sm text-gray-400 mt-7">نقد و برسی </h3>
|
||||
|
||||
{!!data?.product?.expertCheck ? (
|
||||
<div className="border p-5 rounded-lg">
|
||||
<div className="p-5 border rounded-lg">
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: data?.product?.expertCheck,
|
||||
|
@ -386,9 +409,9 @@ const ProductData = ({ params, data }) => {
|
|||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="border p-5 rounded-lg">
|
||||
<div className="p-5 border rounded-lg">
|
||||
<div className="flex justify-center py-5">
|
||||
<div className="bg-white shadow w-fit rounded-full text-sm p-4">
|
||||
<div className="p-4 text-sm bg-white rounded-full shadow w-fit">
|
||||
چیزی یافت نشد
|
||||
</div>
|
||||
</div>
|
||||
|
@ -398,161 +421,108 @@ const ProductData = ({ params, data }) => {
|
|||
|
||||
<div id="section3">
|
||||
<div className="flex">
|
||||
<h3 className=" text-sm text-gray-400 mt-7 mb-2">
|
||||
<h3 className="mb-2 text-sm text-gray-400 mt-7">
|
||||
دیدگاه مخاطبان{" "}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="border p-5 rounded-lg">
|
||||
{review?.length > 0 ? (
|
||||
<>
|
||||
{review?.map((e) => (
|
||||
<div className="mt-10">
|
||||
<div className="flex relative">
|
||||
<div className="xs:w-[40px] lg:w-[60px] xs:h-[40px] lg:h-[60px] relative bg-white rounded-2xl text-center">
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 168 183"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="opacity-30 mx-auto"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M83.9994 0.666992C130.024 0.666992 167.333 37.9753 167.333 84.0003C167.361 103.233 160.71 121.878 148.516 136.75L148.683 136.934L147.583 137.867C139.767 147.11 130.028 154.535 119.046 159.624C108.064 164.714 96.1035 167.345 83.9994 167.334C59.4161 167.334 37.3328 156.692 22.0828 139.775L20.4161 137.859L19.3161 136.942L19.4828 136.742C7.2903 121.872 0.63933 103.23 0.666096 84.0003C0.666096 37.9753 37.9744 0.666992 83.9994 0.666992ZM83.9994 125.667C68.4994 125.667 54.4911 130.6 44.0578 137.384C55.5793 146.025 69.5975 150.687 83.9994 150.667C98.4014 150.687 112.42 146.025 123.941 137.384C112.019 129.745 98.1588 125.68 83.9994 125.667ZM83.9994 17.3337C71.4538 17.3333 59.1627 20.8729 48.5388 27.5457C37.9149 34.2185 29.3895 43.7536 23.9424 55.0551C18.4954 66.3565 16.3478 78.9656 17.7465 91.433C19.1452 103.9 24.0335 115.72 31.8494 125.534C45.3578 115.842 63.7911 109 83.9994 109C104.208 109 122.641 115.842 136.149 125.534C143.965 115.72 148.854 103.9 150.252 91.433C151.651 78.9656 149.503 66.3565 144.056 55.0551C138.609 43.7536 130.084 34.2185 119.46 27.5457C108.836 20.8729 96.5451 17.3333 83.9994 17.3337ZM83.9994 34.0003C92.84 34.0003 101.318 37.5122 107.57 43.7634C113.821 50.0146 117.333 58.4931 117.333 67.3337C117.333 76.1742 113.821 84.6527 107.57 90.9039C101.318 97.1551 92.84 100.667 83.9994 100.667C75.1589 100.667 66.6804 97.1551 60.4292 90.9039C54.178 84.6527 50.6661 76.1742 50.6661 67.3337C50.6661 58.4931 54.178 50.0146 60.4292 43.7634C66.6804 37.5122 75.1589 34.0003 83.9994 34.0003ZM83.9994 50.667C79.5791 50.667 75.3399 52.4229 72.2143 55.5485C69.0887 58.6742 67.3328 62.9134 67.3328 67.3337C67.3328 71.7539 69.0887 75.9932 72.2143 79.1188C75.3399 82.2444 79.5791 84.0003 83.9994 84.0003C88.4197 84.0003 92.6589 82.2444 95.7845 79.1188C98.9101 75.9932 100.666 71.7539 100.666 67.3337C100.666 62.9134 98.9101 58.6742 95.7845 55.5485C92.6589 52.4229 88.4197 50.667 83.9994 50.667Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="p-5 border rounded-lg">
|
||||
<InfiniteScroll
|
||||
dataLength={review.length}
|
||||
next={fetchMoreData}
|
||||
hasMore={hasMore}
|
||||
>
|
||||
{review.length > 0 ? (
|
||||
review.map((e) => (
|
||||
<>
|
||||
<div key={e.id} className="mt-10">
|
||||
<div className="relative flex">
|
||||
<div className="xs:w-[40px] lg:w-[60px] xs:h-[40px] lg:h-[60px] relative bg-white rounded-2xl text-center">
|
||||
{/* SVG Icon */}
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 168 183"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mx-auto opacity-30"
|
||||
>
|
||||
{/* SVG Path */}
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M83.9994 0.666992C130.024 0.666992 167.333 37.9753 167.333 84.0003C167.361 103.233 160.71 121.878 148.516 136.75L148.683 136.934L147.583 137.867C139.767 147.11 130.028 154.535 119.046 159.624C108.064 164.714 96.1035 167.345 83.9994 167.334C59.4161 167.334 37.3328 156.692 22.0828 139.775L20.4161 137.859L19.3161 136.942L19.4828 136.742C7.2903 121.872 0.63933 103.23 0.666096 84.0003C0.666096 37.9753 37.9744 0.666992 83.9994 0.666992ZM83.9994 125.667C68.4994 125.667 54.4911 130.6 44.0578 137.384C55.5793 146.025 69.5975 150.687 83.9994 150.667C98.4014 150.687 112.42 146.025 123.941 137.384C112.019 129.745 98.1588 125.68 83.9994 125.667ZM83.9994 17.3337C71.4538 17.3333 59.1627 20.8729 48.5388 27.5457C37.9149 34.2185 29.3895 43.7536 23.9424 55.0551C18.4954 66.3565 16.3478 78.9656 17.7465 91.433C19.1452 103.9 24.0335 115.72 31.8494 125.534C45.3578 115.842 63.7911 109 83.9994 109C104.208 109 122.641 115.842 136.149 125.534C143.965 115.72 148.854 103.9 150.252 91.433C151.651 78.9656 149.503 66.3565 144.056 55.0551C138.609 43.7536 130.084 34.2185 119.46 27.5457C108.836 20.8729 96.5451 17.3333 83.9994 17.3337ZM83.9994 34.0003C92.84 34.0003 101.318 37.5122 107.57 43.7634C113.821 50.0146 117.333 58.4931 117.333 67.3337C117.333 76.1742 113.821 84.6527 107.57 90.9039C101.318 97.1551 92.84 100.667 83.9994 100.667C75.1589 100.667 66.6804 97.1551 60.4292 90.9039C54.178 84.6527 50.6661 76.1742 50.6661 67.3337C50.6661 58.4931 54.178 50.0146 60.4292 43.7634C66.6804 37.5122 75.1589 34.0003 83.9994 34.0003ZM83.9994 50.667C79.5791 50.667 75.3399 52.4229 72.2143 55.5485C69.0887 58.6742 67.3328 62.9134 67.3328 67.3337C67.3328 71.7539 69.0887 75.9932 72.2143 79.1188C75.3399 82.2444 79.5791 84.0003 83.9994 84.0003C88.4197 84.0003 92.6589 82.2444 95.7845 79.1188C98.9101 75.9932 100.666 71.7539 100.666 67.3337C100.666 62.9134 98.9101 58.6742 95.7845 55.5485C92.6589 52.4229 88.4197 50.667 83.9994 50.667Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="mr-2 mt-1 w-full">
|
||||
<h3 className="font-bold">{e?.userFullName} </h3>
|
||||
<p className="mb-0 mt-1 text-gray-400 text-sm">
|
||||
<PersianNumber
|
||||
number={moment(e?.createdAt).format(
|
||||
"jYYYY/jMM/jDD"
|
||||
)}
|
||||
style={"text-sm"}
|
||||
/>
|
||||
</p>
|
||||
<div className="w-full mt-1 mr-2">
|
||||
<h3 className="font-bold">{e?.userFullName}</h3>
|
||||
<p className="mt-1 mb-0 text-sm text-gray-400">
|
||||
<PersianNumber
|
||||
number={moment(e?.createdAt).format(
|
||||
"jYYYY/jMM/jDD"
|
||||
)}
|
||||
style={"text-sm"}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p className="mb-0 text-sm text-gray-600">
|
||||
{e?.comment}{" "}
|
||||
</p>
|
||||
<p className="mb-0 text-sm text-gray-600">
|
||||
{e?.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<hr className="my-10" />
|
||||
</>
|
||||
) : (
|
||||
<div className="flex justify-center py-5">
|
||||
<div className="bg-white shadow w-fit rounded-full text-sm p-4">
|
||||
چیزی یافت نشد
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{e?.children && e.children?.length > 0 && (
|
||||
<div className="mt-5 lg:mr-10">
|
||||
<div className="relative flex">
|
||||
<div className="xs:w-[50px] lg:w-[60px] xs:h-[50px] lg:h-[60px] relative bg-primary-300 rounded-2xl text-center">
|
||||
<div className="w-[35px] mx-auto mt-4 ">
|
||||
<Image src={logo} alt="Logo" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className="">
|
||||
<div className="flex relative">
|
||||
<div className="xs:w-[40px] lg:w-[60px] xs:h-[40px] lg:h-[60px] relative bg-white rounded-2xl text-center">
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 168 183"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="opacity-30 mx-auto"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M83.9994 0.666992C130.024 0.666992 167.333 37.9753 167.333 84.0003C167.361 103.233 160.71 121.878 148.516 136.75L148.683 136.934L147.583 137.867C139.767 147.11 130.028 154.535 119.046 159.624C108.064 164.714 96.1035 167.345 83.9994 167.334C59.4161 167.334 37.3328 156.692 22.0828 139.775L20.4161 137.859L19.3161 136.942L19.4828 136.742C7.2903 121.872 0.63933 103.23 0.666096 84.0003C0.666096 37.9753 37.9744 0.666992 83.9994 0.666992ZM83.9994 125.667C68.4994 125.667 54.4911 130.6 44.0578 137.384C55.5793 146.025 69.5975 150.687 83.9994 150.667C98.4014 150.687 112.42 146.025 123.941 137.384C112.019 129.745 98.1588 125.68 83.9994 125.667ZM83.9994 17.3337C71.4538 17.3333 59.1627 20.8729 48.5388 27.5457C37.9149 34.2185 29.3895 43.7536 23.9424 55.0551C18.4954 66.3565 16.3478 78.9656 17.7465 91.433C19.1452 103.9 24.0335 115.72 31.8494 125.534C45.3578 115.842 63.7911 109 83.9994 109C104.208 109 122.641 115.842 136.149 125.534C143.965 115.72 148.854 103.9 150.252 91.433C151.651 78.9656 149.503 66.3565 144.056 55.0551C138.609 43.7536 130.084 34.2185 119.46 27.5457C108.836 20.8729 96.5451 17.3333 83.9994 17.3337ZM83.9994 34.0003C92.84 34.0003 101.318 37.5122 107.57 43.7634C113.821 50.0146 117.333 58.4931 117.333 67.3337C117.333 76.1742 113.821 84.6527 107.57 90.9039C101.318 97.1551 92.84 100.667 83.9994 100.667C75.1589 100.667 66.6804 97.1551 60.4292 90.9039C54.178 84.6527 50.6661 76.1742 50.6661 67.3337C50.6661 58.4931 54.178 50.0146 60.4292 43.7634C66.6804 37.5122 75.1589 34.0003 83.9994 34.0003ZM83.9994 50.667C79.5791 50.667 75.3399 52.4229 72.2143 55.5485C69.0887 58.6742 67.3328 62.9134 67.3328 67.3337C67.3328 71.7539 69.0887 75.9932 72.2143 79.1188C75.3399 82.2444 79.5791 84.0003 83.9994 84.0003C88.4197 84.0003 92.6589 82.2444 95.7845 79.1188C98.9101 75.9932 100.666 71.7539 100.666 67.3337C100.666 62.9134 98.9101 58.6742 95.7845 55.5485C92.6589 52.4229 88.4197 50.667 83.9994 50.667Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="w-full mt-1 mr-2">
|
||||
<h3 className="font-bold xs:text-sm lg:text-base">
|
||||
پشتیبانی فروشگاه وسمه
|
||||
</h3>
|
||||
<p className="mb-0 text-sm text-gray-400">
|
||||
<PersianNumber
|
||||
number={moment(
|
||||
e?.children[0]?.createdAt
|
||||
).format("jYYYY/jMM/jDD")}
|
||||
style={"!text-[12px]"}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<div className="mr-2 mt-1 w-full">
|
||||
<h3 className="font-bold">محدثه سروری پور </h3>
|
||||
<p className="mb-0 mt-1 text-gray-400 text-sm">
|
||||
<PersianNumber
|
||||
number={moment(Date()).format("jYYYY/jMM/jDD")}
|
||||
style={"text-sm"}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p className="mb-0 text-sm text-gray-600">
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت
|
||||
چاپ و با استفاده از طراحان گرافیک است
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:mr-10 mt-5">
|
||||
<div className="flex relative">
|
||||
<div className="xs:w-[40px] lg:w-[60px] xs:h-[40px] lg:h-[60px] relative bg-primary-300 rounded-2xl text-center">
|
||||
<div className="w-[45px] mx-auto mt-6">
|
||||
<Image src={logo} />
|
||||
<p className="mb-0 text-sm text-gray-600">
|
||||
{e?.children[0]?.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
))
|
||||
) : (
|
||||
<div className="flex justify-center py-5">
|
||||
<div className="p-4 text-sm bg-white rounded-full shadow w-fit">
|
||||
چیزی یافت نشد
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
|
||||
<div className="mr-2 mt-1 w-full">
|
||||
<h3 className="font-bold xs:text-sm lg:text-base">
|
||||
پشتیبانی فروشگاه وسمه - آقای حیدریان
|
||||
</h3>
|
||||
<p className="mb-0 text-gray-400 text-sm">
|
||||
<PersianNumber
|
||||
number={moment(Date()).format("jYYYY/jMM/jDD")}
|
||||
style={"!text-[12px]"}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p className="mb-0 text-sm text-gray-600">
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت
|
||||
چاپ و با استفاده از طراحان گرافیک است چاپگرها و متون
|
||||
بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و
|
||||
برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع
|
||||
با هدف بهبود ابزارهای کاربردی می باشد
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div>
|
||||
<h3 className="font-bold">دیدگاه خود را وارد کنید </h3>{" "}
|
||||
<textarea
|
||||
className="form-control mt-2"
|
||||
name=""
|
||||
id=""
|
||||
cols="30"
|
||||
rows="8"
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
value={comment}
|
||||
/>
|
||||
<div
|
||||
className="flex justify-end"
|
||||
onClick={() => handleCreateReview()}
|
||||
>
|
||||
<button className="btn btn-primary text-sm py-3 rounded-3xl">
|
||||
ارسال دیدگاه ( برای ارسال دیدگاه ابتدا باید ورود کنید){" "}
|
||||
</button>
|
||||
</div>
|
||||
<div onClick={() => CTX.setBottomSheetCommentOpen(true)}>
|
||||
باز شدن
|
||||
</div>
|
||||
{/* <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>
|
||||
|
||||
<div className="xs:block lg:hidden sticky bottom-0 ">
|
||||
<div className="sticky bottom-0 xs:block lg:hidden ">
|
||||
<div className="w-full bg-[white] p-2 border-t-[1px] border-gray-100 mt-[30px]">
|
||||
<div className="py-4 flex ltr justify-between px-4 relative">
|
||||
<div className="relative flex justify-between px-4 py-4 ltr">
|
||||
{product?.hasDiscount ? (
|
||||
<>
|
||||
<p className="mb-0 font-bold text-sm absolute ml-[33px] opacity-30 mt-[-5px] text-red-600">
|
||||
|
@ -578,7 +548,7 @@ const ProductData = ({ params, data }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber
|
||||
number={(data?.product?.cost / 10).toLocaleString()}
|
||||
/>
|
||||
|
@ -594,6 +564,15 @@ const ProductData = ({ params, data }) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<BottomSheetComment
|
||||
handleCreateReview={handleCreateReview}
|
||||
name={data?.product?.persianName}
|
||||
content={content}
|
||||
setContent={setContent}
|
||||
handleStarClick={handleStarClick}
|
||||
rate={rate}
|
||||
/>
|
||||
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -34,6 +34,7 @@ const RootData = ({ children }) => {
|
|||
const [bottomSheetAddressOpen, setBottomSheetAddressOpen] = useState(false);
|
||||
const [bottomSheetLogOutOpen, setBottomSheetLogOutOpen] = useState(false);
|
||||
const [bottomSheetSeeOrderOpen, setBottomSheetSeeOrderOpen] = useState(false);
|
||||
const [bottomSheetCommentOpen, setBottomSheetCommentOpen] = useState(false);
|
||||
const [bottomSheetDeleteAddressOpen, setBottomSheetDeleteAddressOpen] =
|
||||
useState(false);
|
||||
const [checkOutData, setCheckOutData] = useState([]);
|
||||
|
@ -542,6 +543,7 @@ const RootData = ({ children }) => {
|
|||
bottomSheetAddressOpen,
|
||||
bottomSheetDeleteAddressOpen,
|
||||
bottomSheetLogOutOpen,
|
||||
bottomSheetCommentOpen,
|
||||
checkOutData,
|
||||
addressData,
|
||||
profile,
|
||||
|
@ -580,6 +582,7 @@ const RootData = ({ children }) => {
|
|||
setBottomSheetAddressOpen,
|
||||
setBottomSheetDeleteAddressOpen,
|
||||
setBottomSheetLogOutOpen,
|
||||
setBottomSheetCommentOpen,
|
||||
setCheckOutData,
|
||||
setStopProducts,
|
||||
setProfile,
|
||||
|
|
|
@ -24,15 +24,15 @@ const BlogData = ({ data }) => {
|
|||
<div>
|
||||
<Navbar />
|
||||
|
||||
<div className="xs:px-3 md:px-5 md:container md:mx-auto mb-10">
|
||||
<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 ">
|
||||
<div className="mb-10 xs:px-3 md:px-5 md:container md:mx-auto">
|
||||
<div className="grid xs:grid-cols-1 lg:grid-cols-6 gap-7 rtl">
|
||||
<div className="mt-10 lg:col-span-4 rtl">
|
||||
<div className="mt-10 ">
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/Images/Med/${data.mainImage}`}
|
||||
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"
|
||||
className="mb-3 xs:w-full lg:w-6/12 rounded-3xl"
|
||||
/>
|
||||
<h1 className=" font-bold text-right xs:text-[20px] lg:text-[40px]">
|
||||
{data.title}
|
||||
|
@ -45,7 +45,7 @@ const BlogData = ({ data }) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-2 mt-10 rtl ">
|
||||
<div className="mt-10 lg:col-span-2 rtl ">
|
||||
<SliderProductsOffer data={specialOfferData} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -15,10 +15,10 @@ const CardCart = ({ data }) => {
|
|||
return (
|
||||
<div className="group border-t-[1px] border-gray-100 w-full hover:bg-white z-40 tr03 flex rtl pt-2">
|
||||
<Link href={`/products/${data.id}/${hyphenatedName}`}>
|
||||
<div className=" h-fit ">
|
||||
<div className=" h-fit">
|
||||
{!!data.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data?.mainImage}`}
|
||||
width={100}
|
||||
height={100}
|
||||
className="xs:!w-[110px] lg:!w-[130px] mx-auto !object-cover"
|
||||
|
@ -35,19 +35,19 @@ const CardCart = ({ data }) => {
|
|||
)}
|
||||
</div>
|
||||
</Link>
|
||||
<div className="p-3 text-right w-full">
|
||||
<div className="w-full p-3 text-right">
|
||||
<Link href={`/products/${data.id}/${hyphenatedName}`}>
|
||||
<p className="mb-0 xs:text-[12px] lg:text-[11px] xl:text-[15px] max-h-[50px] tr03 ">
|
||||
{data?.persianName}
|
||||
</p>
|
||||
</Link>
|
||||
|
||||
<div className=" rounded-full flex ltr pt-2 mt-2 w-full">
|
||||
<div className="flex w-full pt-2 mt-2 rounded-full ltr">
|
||||
<AddToCart data={data} theme={1} />
|
||||
|
||||
<div className="w-full text-right rounded-full">
|
||||
<div className="w-full text-right rounded-full">
|
||||
{data?.hasDiscount ? (
|
||||
<div className="flex justify-end relative">
|
||||
<div className="relative flex justify-end">
|
||||
<p className="mb-0 font-bold text-sm absolute opacity-40 mt-[-7px] ml-[20px] text-red-600">
|
||||
<del>
|
||||
<PersianNumber
|
||||
|
@ -69,7 +69,7 @@ const CardCart = ({ data }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber number={(data?.cost / 10).toLocaleString()} />
|
||||
</p>
|
||||
<small className="mr-1 mt-[6px]">تومان</small>
|
||||
|
|
|
@ -15,7 +15,7 @@ const CardCategories = ({ data }) => {
|
|||
const hyphenatedName = hyphenateString(data.persianName);
|
||||
|
||||
return (
|
||||
<div className="group border border-gray-50 w-full hover:bg-white z-40 tr03">
|
||||
<div className="z-40 w-full border group border-gray-50 hover:bg-white tr03">
|
||||
<>
|
||||
<div
|
||||
className={` tr03 py-2 overflow-hidden xs:h-[200px] lg:h-[230px] ${
|
||||
|
@ -26,7 +26,7 @@ const CardCategories = ({ data }) => {
|
|||
>
|
||||
{data.hasDiscount && (
|
||||
<div className="absolute m-3 ">
|
||||
<div className="w-fit rounded-lg bg-red-600 overflow-hidden px-1 ">
|
||||
<div className="px-1 overflow-hidden bg-red-600 rounded-lg w-fit ">
|
||||
<p className="mb-0 text-[10px] text-white pt-[3px] ">
|
||||
<PersianNumber
|
||||
number={data.discountPercent}
|
||||
|
@ -38,7 +38,7 @@ const CardCategories = ({ data }) => {
|
|||
</div>
|
||||
)}
|
||||
{data.hasDiscount && (
|
||||
<div className=" m-3 ">
|
||||
<div className="m-3 ">
|
||||
<div className="absolute mt-[30px] ">
|
||||
<div className="w-fit rounded-lg bg-secondary-600 overflow-hidden px-2 !py-0 h-fit ">
|
||||
<p className="mb-0 text-white text-[10px] ">اصالت کالا</p>
|
||||
|
@ -47,10 +47,10 @@ const CardCategories = ({ data }) => {
|
|||
</div>
|
||||
)}
|
||||
<Link href={`/products/${data.id}/${hyphenatedName}`}>
|
||||
<div className="w-full h-fit flex justify-center ">
|
||||
<div className="flex justify-center w-full h-fit ">
|
||||
{!!data.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data?.mainImage}`}
|
||||
width={200}
|
||||
height={200}
|
||||
className="xs:!w-[110px] lg:!w-[130px] mx-auto"
|
||||
|
@ -81,11 +81,11 @@ const CardCategories = ({ data }) => {
|
|||
</div>
|
||||
</>
|
||||
|
||||
<div className=" rounded-full flex ltr p-3 mt-2">
|
||||
<div className="flex p-3 mt-2 rounded-full ltr">
|
||||
<div className="flex w-full">
|
||||
<AddToCart data={data} theme={1} />
|
||||
</div>
|
||||
<div className="w-full text-right rounded-full">
|
||||
<div className="w-full text-right rounded-full">
|
||||
{data?.hasDiscount ? (
|
||||
<div className="flex justify-end">
|
||||
<p className="mb-0 font-bold text-sm absolute opacity-40 mt-[-7px] ml-[20px] text-red-600">
|
||||
|
@ -109,7 +109,7 @@ const CardCategories = ({ data }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber number={(data?.cost / 10).toLocaleString()} />
|
||||
</p>
|
||||
<small className="mr-1 mt-[6px]">تومان</small>
|
||||
|
|
|
@ -17,10 +17,10 @@ const CardCategoriesMobile = ({ data }) => {
|
|||
return (
|
||||
<div className="group border-t-[1px] border-gray-200 w-full hover:bg-white z-40 tr03 flex rtl pt-2 px-3">
|
||||
<Link href={`/products/${data.id}/${hyphenatedName}`}>
|
||||
<div className=" h-fit ">
|
||||
<div className=" h-fit">
|
||||
{!!data.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data?.mainImage}`}
|
||||
width={200}
|
||||
height={200}
|
||||
className="xs:!w-[110px] lg:!w-[130px] mx-auto "
|
||||
|
@ -38,7 +38,7 @@ const CardCategoriesMobile = ({ data }) => {
|
|||
</div>
|
||||
</Link>
|
||||
|
||||
<div className="p-3 text-right w-full">
|
||||
<div className="w-full p-3 text-right">
|
||||
{" "}
|
||||
<Link href={`/products/${data.id}/${hyphenatedName}`}>
|
||||
<p className="mb-0 xs:text-[12px] lg:text-[11px] xl:text-[15px] max-h-[50px] tr03 ">
|
||||
|
@ -50,9 +50,9 @@ const CardCategoriesMobile = ({ data }) => {
|
|||
{data.stock} عدد موجود انبار
|
||||
</p>
|
||||
)}
|
||||
<div className=" rounded-full flex ltr pt-2 mt-2 w-full">
|
||||
<div className="flex w-full pt-2 mt-2 rounded-full ltr">
|
||||
<AddToCart data={data} theme={1} />{" "}
|
||||
<div className="w-full text-right rounded-lg">
|
||||
<div className="w-full text-right rounded-lg">
|
||||
{data?.hasDiscount ? (
|
||||
<div className="flex justify-end">
|
||||
<div className="mb-0 font-bold text-sm absolute mt-[-7px] ml-[20px] text-red-600 flex rtl">
|
||||
|
@ -84,7 +84,7 @@ const CardCategoriesMobile = ({ data }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber number={(data?.cost / 10).toLocaleString()} />
|
||||
</p>
|
||||
<small className="mr-1 mt-[6px]">تومان</small>
|
||||
|
|
|
@ -30,7 +30,7 @@ const CardNormal = ({ data, priority }) => {
|
|||
>
|
||||
{data.hasDiscount && (
|
||||
<div className="absolute m-3 ">
|
||||
<div className="w-fit rounded-lg bg-red-600 overflow-hidden px-1 ">
|
||||
<div className="px-1 overflow-hidden bg-red-600 rounded-lg w-fit ">
|
||||
<p className="mb-0 text-[10px] text-white pt-[3px] ">
|
||||
<PersianNumber
|
||||
number={data.discountPercent}
|
||||
|
@ -42,10 +42,10 @@ const CardNormal = ({ data, priority }) => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="w-full h-fit flex justify-center ">
|
||||
<div className="flex justify-center w-full h-fit ">
|
||||
{!!data.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data?.mainImage}`}
|
||||
width={200}
|
||||
height={200}
|
||||
className="xs:!w-[110px] lg:!w-[130px] mx-auto"
|
||||
|
@ -76,12 +76,12 @@ const CardNormal = ({ data, priority }) => {
|
|||
</div>
|
||||
</Link>
|
||||
</>
|
||||
<div className="bg-gray-50 rounded-lg flex ltr p-1 mt-2 border border-gray-100">
|
||||
<div className="flex p-1 mt-2 border border-gray-100 rounded-lg bg-gray-50 ltr">
|
||||
<div className="flex w-full">
|
||||
<AddToCart data={data} theme={1} />
|
||||
</div>
|
||||
|
||||
<div className="w-full text-right rounded-full pr-2">
|
||||
<div className="w-full pr-2 text-right rounded-full">
|
||||
{data?.hasDiscount ? (
|
||||
<>
|
||||
<p className="mb-0 font-bold text-sm absolute right-3 opacity-30 mt-[-5px] text-red-600">
|
||||
|
@ -105,7 +105,7 @@ const CardNormal = ({ data, priority }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber number={(data?.cost / 10).toLocaleString()} />
|
||||
</p>
|
||||
<small className="mr-1 mt-[6px]">تومان</small>
|
||||
|
|
|
@ -28,7 +28,7 @@ const CardSurprise = ({ data, priority }) => {
|
|||
>
|
||||
{data.hasDiscount && (
|
||||
<div className="absolute m-3 ">
|
||||
<div className="w-fit rounded-lg bg-red-600 overflow-hidden px-1 ">
|
||||
<div className="px-1 overflow-hidden bg-red-600 rounded-lg w-fit ">
|
||||
<p className="mb-0 text-[10px] text-white pt-[3px] ">
|
||||
<PersianNumber
|
||||
number={data.discountPercent}
|
||||
|
@ -40,10 +40,10 @@ const CardSurprise = ({ data, priority }) => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="w-full h-fit flex justify-center ">
|
||||
<div className="flex justify-center w-full h-fit ">
|
||||
{!!data.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${data?.mainImage}`}
|
||||
width={100}
|
||||
height={100}
|
||||
className="xs:!w-[110px] lg:!w-[130px] mx-auto !object-cover"
|
||||
|
@ -74,12 +74,12 @@ const CardSurprise = ({ data, priority }) => {
|
|||
</div>
|
||||
</Link>
|
||||
</>
|
||||
<div className="bg-gray-50 rounded-lg flex ltr p-1 mt-2 border border-gray-100">
|
||||
<div className="flex p-1 mt-2 border border-gray-100 rounded-lg bg-gray-50 ltr">
|
||||
<div className="flex w-full">
|
||||
<AddToCart data={data} theme={1} />
|
||||
</div>
|
||||
|
||||
<div className="w-full text-right rounded-full pr-2">
|
||||
<div className="w-full pr-2 text-right rounded-full">
|
||||
{data?.hasDiscount ? (
|
||||
<>
|
||||
<p className="mb-0 font-bold text-sm absolute right-3 opacity-30 mt-[-5px] text-red-600">
|
||||
|
@ -103,7 +103,7 @@ const CardSurprise = ({ data, priority }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber number={(data?.cost / 10).toLocaleString()} />
|
||||
</p>
|
||||
<small className="mr-1 mt-[6px]">تومان</small>
|
||||
|
|
|
@ -71,12 +71,12 @@ const HeroSection = () => {
|
|||
<Link
|
||||
href={slide.url}
|
||||
key={slide.id}
|
||||
className="w-full flex-shrink-0"
|
||||
className="flex-shrink-0 w-full"
|
||||
>
|
||||
<div className="block lg:hidden xs:mx-2 lg:mx-0">
|
||||
<Image
|
||||
src={slide.imageResponsive}
|
||||
alt={slide.title}
|
||||
src={slide?.imageResponsive}
|
||||
alt={slide?.title}
|
||||
className="!w-full xs:h-[200px] md:h-[400px] lg:h-[400px] xl:h-[650px] rounded-2xl lg:rounded-none object-cover"
|
||||
layout="responsive"
|
||||
width={800}
|
||||
|
@ -85,8 +85,8 @@ const HeroSection = () => {
|
|||
</div>
|
||||
<div className="hidden lg:block">
|
||||
<Image
|
||||
src={slide.image}
|
||||
alt={slide.title}
|
||||
src={slide?.image}
|
||||
alt={slide?.title}
|
||||
className="!w-full xs:h-[200px] md:h-[400px] lg:h-[400px] xl:h-[650px] rounded-2xl lg:rounded-none object-cover "
|
||||
layout="responsive"
|
||||
width={800}
|
||||
|
|
|
@ -36,7 +36,7 @@ const ResultSearchBar = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className=" overflow-x-auto flex whitespace-nowrap hide-scrollBar ">
|
||||
<div className="flex overflow-x-auto whitespace-nowrap hide-scrollBar">
|
||||
<Link
|
||||
href={`/categories/fac3ee2d-19dd-4229-a412-28a1d09cc948/شامپو-بدن`}
|
||||
>
|
||||
|
@ -79,7 +79,7 @@ const ResultSearchBar = ({
|
|||
href={`/categories/${e.id}/${e.name.split(" ").join("-")}`}
|
||||
>
|
||||
<div
|
||||
className="flex "
|
||||
className="flex "
|
||||
onClick={() => CTX.setCloseNavbar(false)}
|
||||
>
|
||||
<div className="w-[20px] h-[40px] rounded-2xl bg-gray-200 ml-2 mt-3">
|
||||
|
@ -95,7 +95,7 @@ const ResultSearchBar = ({
|
|||
</Link>
|
||||
))}
|
||||
|
||||
<div className="w-10 h-1 bg-primary-200 rounded-full opacity-35 my-3"></div>
|
||||
<div className="w-10 h-1 my-3 rounded-full bg-primary-200 opacity-35"></div>
|
||||
|
||||
{searchResultProductData?.map((e, index) => (
|
||||
<Link
|
||||
|
@ -103,14 +103,14 @@ const ResultSearchBar = ({
|
|||
href={`/products/${e.id}/${e.persianName.split(" ").join("-")}`}
|
||||
>
|
||||
<div
|
||||
className="flex relative "
|
||||
className="relative flex "
|
||||
onClick={() => CTX.setCloseNavbar(false)}
|
||||
>
|
||||
<div className="h-fit relative">
|
||||
<div className="relative h-fit">
|
||||
<div className="w-[50px] h-[50px] rounded-2xl bg-gray-200 ml-2 mt-3 overflow-hidden relative ">
|
||||
{!!e.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e?.mainImage}`}
|
||||
width={200}
|
||||
height={200}
|
||||
className="xs:!w-[60px] lg:!w-[60px] mx-auto object-cover "
|
||||
|
@ -127,8 +127,8 @@ const ResultSearchBar = ({
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-2 w-full relative text-right">
|
||||
<p className="mb-0 text-sm ">{e.persianName}</p>
|
||||
<div className="relative w-full my-2 text-right">
|
||||
<p className="mb-0 text-sm ">{e.persianName}</p>
|
||||
<small className="text-[12px] text-gray-500 !text-right">
|
||||
محصول{" "}
|
||||
</small>
|
||||
|
@ -139,7 +139,7 @@ const ResultSearchBar = ({
|
|||
</>
|
||||
) : (
|
||||
<div className="flex justify-center py-5">
|
||||
<div className="bg-white shadow mt-5 w-fit rounded-full text-sm p-4">
|
||||
<div className="p-4 mt-5 text-sm bg-white rounded-full shadow w-fit">
|
||||
چیزی یافت نشد
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4667,6 +4667,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",
|
||||
|
@ -5575,6 +5599,20 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
|
||||
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
|
||||
"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",
|
||||
|
|
|
@ -12,13 +12,13 @@ const GalleryBox = ({ file }) => {
|
|||
const isOpenLightBox = CTX.state.isOpenLightBox;
|
||||
|
||||
return (
|
||||
<div className=" w-full rounded-3xl">
|
||||
<div className="w-full rounded-3xl">
|
||||
<div className="flex justify-center xs:pb-[10px] ">
|
||||
<div className="">
|
||||
{file?.length > 0 ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${
|
||||
file && file[0].fileLocation
|
||||
file && file[0]?.fileLocation
|
||||
}`}
|
||||
width={350}
|
||||
height={350}
|
||||
|
@ -40,16 +40,16 @@ const GalleryBox = ({ file }) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex overflow-x-auto p-3 " id="swich-scrollbar">
|
||||
<div className="flex p-3 overflow-x-auto " id="swich-scrollbar">
|
||||
{file?.map((e) => (
|
||||
<div
|
||||
className="rounded-3xl bg-white border shadow-sm p-3 ml-2"
|
||||
className="p-3 ml-2 bg-white border shadow-sm rounded-3xl"
|
||||
key={e.id}
|
||||
onClick={() => CTX.setIsOpenLightBox(true)}
|
||||
>
|
||||
<div className="xs:w-[50px] lg:w-[50px]">
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e.fileLocation}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e?.fileLocation}`}
|
||||
alt={e.fileName}
|
||||
width={50}
|
||||
height={50}
|
||||
|
|
|
@ -71,7 +71,7 @@ const MovingLogos = () => {
|
|||
</div>
|
||||
))} */}
|
||||
|
||||
<div className="xs:w-4/5 lg:w-3/5 mx-auto">
|
||||
<div className="mx-auto xs:w-4/5 lg:w-3/5">
|
||||
<div className="w-full inline-flex flex-nowrap overflow-hidden [mask-image:_linear-gradient(to_right,transparent_0,_black_100px,_black_calc(100%-100px),transparent_100%)]">
|
||||
<ul
|
||||
x-ref="logos"
|
||||
|
@ -82,7 +82,7 @@ const MovingLogos = () => {
|
|||
<Image
|
||||
key={e.id}
|
||||
id={`logo-${e.id}`}
|
||||
src={e.logo}
|
||||
src={e?.logo}
|
||||
alt={`Logo ${e.id}`}
|
||||
className="xs:w-[60px] lg:w-[100px]"
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
"use client";
|
||||
|
||||
import AppContext from "@ctx/AppContext";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useContext } from "react";
|
||||
import { BottomSheet } from "react-spring-bottom-sheet";
|
||||
|
||||
const BottomSheetComment = ({
|
||||
handleCreateReview,
|
||||
name,
|
||||
content,
|
||||
setContent,
|
||||
handleStarClick,
|
||||
rate,
|
||||
}) => {
|
||||
const CTX = useContext(AppContext);
|
||||
const router = useRouter();
|
||||
|
||||
const renderStars = () => {
|
||||
return [...Array(5)].map((_, index) => {
|
||||
const value = index + 1;
|
||||
return (
|
||||
<svg
|
||||
key={index}
|
||||
onClick={() => handleStarClick(value)}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill={value <= rate ? "yellow" : "gray"}
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={0.5}
|
||||
stroke="currentColor"
|
||||
className="w-8 h-8 cursor-pointer"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M11.048 2.927c.3-.921 1.654-.921 1.954 0l1.614 4.958a1 1 0 00.95.69h5.204c.969 0 1.371 1.24.588 1.81l-4.205 3.053a1 1 0 00-.364 1.118l1.614 4.958c.3.921-.755 1.688-1.538 1.118L12 17.347l-4.205 3.053c-.783.57-1.838-.197-1.538-1.118l1.614-4.958a1 1 0 00-.364-1.118L3.302 10.385c-.783-.57-.38-1.81.588-1.81h5.204a1 1 0 00.95-.69l1.614-4.958z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<BottomSheet
|
||||
open={CTX.state.bottomSheetCommentOpen}
|
||||
onDismiss={() => CTX.setBottomSheetCommentOpen(false)}
|
||||
className={"z-50 relative "}
|
||||
>
|
||||
<div className="p-3 text-center">
|
||||
<p className="pb-3 mb-0 text-sm rtl">
|
||||
شما در حال اضافه کردن نظر برای <strong> {name} </strong> هستید
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="px-4 pb-10 mt-5 rtl">
|
||||
<h3 className="text-sm">دیدگاه خود را وارد کنید</h3>
|
||||
<textarea
|
||||
className="mt-2 form-control"
|
||||
cols="30"
|
||||
rows="8"
|
||||
onChange={(e) => setContent(e.target.value)}
|
||||
value={content}
|
||||
/>
|
||||
|
||||
<div className="mt-4">
|
||||
<h3 className="mb-2 text-sm">امتیاز را انتخاب کنید</h3>
|
||||
<div className="flex">{renderStars()}</div>
|
||||
</div>
|
||||
<div className="flex justify-end" onClick={() => handleCreateReview()}>
|
||||
<button className="w-full py-3 mt-5 text-sm btn btn-primary rounded-3xl">
|
||||
ارسال دیدگاه (برای ارسال دیدگاه ابتدا باید ورود کنید)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</BottomSheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default BottomSheetComment;
|
|
@ -47,8 +47,8 @@ const BottomSheetSeeOrder = ({ id }) => {
|
|||
{/* {bag && bag.length > 0 && ( */}
|
||||
<div className="h-[900px]">
|
||||
{bag.orderProducts?.map((e) => (
|
||||
<div className="text-center p-3">
|
||||
<p className="mb-0 text-sm pb-3 rtl">
|
||||
<div className="p-3 text-center">
|
||||
<p className="pb-3 mb-0 text-sm rtl">
|
||||
<PersianNumber
|
||||
number={bag.orderProducts?.length}
|
||||
style="text-xl font-bold text-base font-bold mx-2 !text-primary-500"
|
||||
|
@ -61,10 +61,10 @@ const BottomSheetSeeOrder = ({ id }) => {
|
|||
{bag.orderProducts.map((e, index) => (
|
||||
<div className="group border-t-[1px] border-gray-100 w-full hover:bg-white z-40 tr03 flex rtl pt-2">
|
||||
<Link href={`/products/${e.id}/${e.persianName}`}>
|
||||
<div className=" h-fit ">
|
||||
<div className=" h-fit">
|
||||
{!!e.mainImage ? (
|
||||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e.mainImage}`}
|
||||
src={`${process.env.NEXT_PUBLIC_STORAGE_URL}/${e?.mainImage}`}
|
||||
width={100}
|
||||
height={100}
|
||||
className="xs:!w-[110px] lg:!w-[130px] mx-auto !object-cover"
|
||||
|
@ -81,16 +81,16 @@ const BottomSheetSeeOrder = ({ id }) => {
|
|||
)}
|
||||
</div>
|
||||
</Link>
|
||||
<div className="p-3 text-right w-full">
|
||||
<div className="w-full p-3 text-right">
|
||||
<Link href={`/products/${e.id}/${e.productName}`}>
|
||||
<p className="mb-0 xs:text-[12px] lg:text-[11px] xl:text-[15px] max-h-[50px] tr03 ">
|
||||
{e?.productName}
|
||||
</p>
|
||||
</Link>
|
||||
|
||||
<div className=" rounded-full flex ltr w-full">
|
||||
<div className="flex w-full rounded-full ltr">
|
||||
<div className="mt-3">
|
||||
<p className="mb-0 rtl text-sm">
|
||||
<p className="mb-0 text-sm rtl">
|
||||
<PersianNumber
|
||||
number={e?.count}
|
||||
style={"text-sm ml-1"}
|
||||
|
@ -98,9 +98,9 @@ const BottomSheetSeeOrder = ({ id }) => {
|
|||
عدد
|
||||
</p>
|
||||
</div>
|
||||
<div className="w-full text-right rounded-full">
|
||||
<div className="w-full text-right rounded-full">
|
||||
{e?.hasDiscount ? (
|
||||
<div className="flex justify-end relative">
|
||||
<div className="relative flex justify-end">
|
||||
<p className="mb-0 font-bold text-sm absolute opacity-40 mt-[-7px] ml-[20px] text-red-600">
|
||||
<del>
|
||||
<PersianNumber
|
||||
|
@ -126,7 +126,7 @@ const BottomSheetSeeOrder = ({ id }) => {
|
|||
) : (
|
||||
<div className="flex rtl mt-[3px]">
|
||||
{" "}
|
||||
<p className="mb-0 font-bold text-lg">
|
||||
<p className="mb-0 text-lg font-bold">
|
||||
<PersianNumber
|
||||
number={(e?.productFee / 10).toLocaleString()}
|
||||
/>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -63,15 +63,15 @@ export async function generateMetadata({ params }) {
|
|||
aggregateRating: {
|
||||
"@type": "AggregateRating",
|
||||
ratingValue:
|
||||
data?.product?.reviews.length > 0
|
||||
data?.product?.reviews?.length > 0
|
||||
? (
|
||||
data?.product?.reviews.reduce(
|
||||
data?.product?.reviews?.reduce(
|
||||
(acc, review) => acc + review.rating,
|
||||
0
|
||||
) / data?.product?.reviews.length
|
||||
).toFixed(1)
|
||||
: "4.5", // Default rating if no reviews
|
||||
reviewCount: data?.product?.reviews.length.toString() || "0",
|
||||
reviewCount: data?.product?.reviews?.length.toString() || "0",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ export async function generateMetadata({ params }) {
|
|||
availability: data?.product?.stock > 0 ? "instock" : "outofstock",
|
||||
guarantee: data?.product?.warranty || "ضمانت دارد",
|
||||
ratingValue:
|
||||
data?.product?.reviews.length > 0
|
||||
data?.product?.reviews?.length > 0
|
||||
? (
|
||||
data?.product?.reviews.reduce(
|
||||
(acc, review) => acc + review.rating,
|
||||
|
|
Loading…
Reference in New Issue