From 554312ddc6e49d2bce4b2afc7940d0130fee77a5 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 7 Sep 2025 15:37:00 +0330 Subject: [PATCH] add comments --- package-lock.json | 54 +++++ package.json | 1 + src/app/globals.css | 20 ++ src/app/product/components/AddComment.tsx | 255 ++++++++++++++++++++++ src/app/product/components/Reviews.tsx | 7 +- src/app/product/hooks/useProductData.ts | 8 +- src/app/product/service/Service.ts | 9 + src/app/product/types/Types.ts | 8 + src/components/DefaulModal.tsx | 57 +++++ src/components/HeaderModal.tsx | 21 ++ src/components/ui/textarea.tsx | 32 ++- 11 files changed, 460 insertions(+), 12 deletions(-) create mode 100644 src/app/product/components/AddComment.tsx create mode 100644 src/app/product/types/Types.ts create mode 100644 src/components/DefaulModal.tsx create mode 100644 src/components/HeaderModal.tsx diff --git a/package-lock.json b/package-lock.json index 6bf54bd..e270c56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "iconsax-react": "^0.0.8", "lucide-react": "^0.539.0", "next": "15.4.5", + "rc-rate": "^2.13.1", "react": "19.1.0", "react-dom": "19.1.0", "react-hook-form": "^7.62.0", @@ -74,6 +75,15 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@emnapi/core": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", @@ -2882,6 +2892,12 @@ "url": "https://polar.sh/cva" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -5773,6 +5789,44 @@ ], "license": "MIT" }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", diff --git a/package.json b/package.json index 74d3a06..51113ba 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "iconsax-react": "^0.0.8", "lucide-react": "^0.539.0", "next": "15.4.5", + "rc-rate": "^2.13.1", "react": "19.1.0", "react-dom": "19.1.0", "react-hook-form": "^7.62.0", diff --git a/src/app/globals.css b/src/app/globals.css index fe3a65e..79f1518 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -244,3 +244,23 @@ textarea.place-black::placeholder { .filterBlack { filter: brightness(0) saturate(100%); } + +.modalGlass { + background: rgba(0, 0, 0, 0.436); + background-blend-mode: multiply; + + backdrop-filter: blur(7px); +} +.modalGlass2 { + background: rgba(255, 255, 255, 0.502); + background-blend-mode: multiply; + + /* backdrop-filter: blur(5px); */ +} + +.modalGlass3 { + background: rgba(62, 61, 61, 0.2); + background-blend-mode: multiply; + + backdrop-filter: blur(44px); +} diff --git a/src/app/product/components/AddComment.tsx b/src/app/product/components/AddComment.tsx new file mode 100644 index 0000000..f7c5869 --- /dev/null +++ b/src/app/product/components/AddComment.tsx @@ -0,0 +1,255 @@ +import DefaulModal from '@/components/DefaulModal' +import Input from '@/components/Input' +import { Button } from '@/components/ui/button' +import { FC, useState } from 'react' +import { useForm } from 'react-hook-form' +import { AddCommentProps } from '../types/Types' +import * as yup from 'yup' +import { yupResolver } from '@hookform/resolvers/yup' +import { Add } from 'iconsax-react' +import { PRIMARY_COLOR } from '@/config/const' +import Rate from 'rc-rate' +import 'rc-rate/assets/index.css' +import { Textarea } from '@/components/ui/textarea' +import { useParams } from 'next/navigation' +import { useAddComment, useGetDetailProduct } from '../hooks/useProductData' +import { toast } from '@/components/Toast' +import { extractErrorMessage } from '@/helpers/errorUtils' + + +type Props = { + open: boolean, + close: () => void, +} + +const AddComment: FC = (props) => { + + + const { open, close } = props + const { id } = useParams() + const [advantages, setAdvantages] = useState([]) + const [disadvantages, setDisadvantages] = useState([]) + const [currentAdvantage, setCurrentAdvantage] = useState('') + const [currentDisadvantage, setCurrentDisadvantage] = useState('') + const [rating, setRating] = useState(0) + const { refetch } = useGetDetailProduct(id as string) + const { mutate: addComment, isPending } = useAddComment() + + const validationSchema = yup.object({ + title: yup.string().required('عنوان خود را وارد کنید'), + advantage: yup.array().of(yup.string().required()).required('مزایای خود را وارد کنید'), + disAdvantage: yup.array().of(yup.string().required()).required('معایب خود را وارد کنید'), + content: yup.string().required('محتوای خود را وارد کنید'), + rate: yup.number().required('رای خود را وارد کنید'), + productId: yup.string().optional() + }) + + const { + register, + handleSubmit, + formState: { errors }, + setValue + } = useForm({ + resolver: yupResolver(validationSchema), + defaultValues: { + title: '', + advantage: [], + disAdvantage: [], + content: '', + rate: 0, + productId: id as string + } + }) + + const addAdvantage = () => { + if (currentAdvantage.trim()) { + const newAdvantages = [...advantages, currentAdvantage.trim()] + setAdvantages(newAdvantages) + setValue('advantage', newAdvantages) + setCurrentAdvantage('') + } + } + + const removeAdvantage = (index: number) => { + const newAdvantages = advantages.filter((_, i) => i !== index) + setAdvantages(newAdvantages) + setValue('advantage', newAdvantages) + } + + const addDisadvantage = () => { + if (currentDisadvantage.trim()) { + const newDisadvantages = [...disadvantages, currentDisadvantage.trim()] + setDisadvantages(newDisadvantages) + setValue('disAdvantage', newDisadvantages) + setCurrentDisadvantage('') + } + } + + const removeDisadvantage = (index: number) => { + const newDisadvantages = disadvantages.filter((_, i) => i !== index) + setDisadvantages(newDisadvantages) + setValue('disAdvantage', newDisadvantages) + } + + const handleRating = (rate: number) => { + setRating(rate) + setValue('rate', rate, { shouldValidate: true, shouldDirty: true }) + } + + const onSubmit = (data: AddCommentProps) => { + addComment(data, { + onSuccess: (res) => { + toast(res?.results?.message, 'success') + refetch() + close() + }, + onError: (error: Error) => { + toast(extractErrorMessage(error), 'error') + } + }) + } + + return ( + +
+ {/* عنوان نظر */} + + +
+ setCurrentAdvantage(e.target.value)} + placeholder="نکته مثبت خود را وارد کنید" + className="flex-1" + label="نکته مثبت" + onKeyPress={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + addAdvantage() + } + }} + /> + + +
+ + {/* لیست نکات مثبت اضافه شده */} + {advantages.length > 0 && ( +
+ {advantages.map((advantage, index) => ( +
+ {advantage} + +
+ ))} +
+
+ )} + + {/* نکات منفی */} +
+ setCurrentDisadvantage(e.target.value)} + placeholder="نکته منفی خود را وارد کنید" + className="flex-1" + label="نکته منفی" + onKeyPress={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + addDisadvantage() + } + }} + /> + + +
+ + {/* لیست نکات منفی اضافه شده */} + {disadvantages.length > 0 && ( +
+ {disadvantages.map((disadvantage, index) => ( +
+ {disadvantage} + +
+ ))} +
+
+ )} + + {/* امتیاز */} +
+ +
+ +
+ +
+ + {/* توضیحات */} +