From 4606a8b479f823e80e56a445d9873325c7cfae1d Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Tue, 9 Dec 2025 12:13:11 +0330 Subject: [PATCH] detail of review --- src/langs/fa.json | 12 +- src/pages/review/Detail.tsx | 288 ++++++++++++++++++++++ src/pages/review/hooks/useReviewData.ts | 7 + src/pages/review/service/ReviewService.ts | 11 +- src/pages/review/types/Types.ts | 42 ++++ src/router/Main.tsx | 2 + 6 files changed, 360 insertions(+), 2 deletions(-) create mode 100644 src/pages/review/Detail.tsx diff --git a/src/langs/fa.json b/src/langs/fa.json index a7bd941..60e53cf 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -863,6 +863,16 @@ "review_list": "لیست نظرات", "review_name": "نام نظر", "review_email": "ایمیل نظر", - "review_comment": "نظر" + "review_comment": "نظر", + "great_taste": "طعم عالی", + "fast_delivery": "تحویل سریع", + "good_quality": "کیفیت خوب", + "good_portion_size": "اندازه مناسب پرس", + "friendly_service": "خدمات دوستانه", + "small_portion": "پرس کوچک", + "slow_delivery": "تحویل کند", + "poor_quality": "کیفیت پایین", + "overpriced": "قیمت بالا", + "unfriendly_service": "خدمات نامناسب" } } diff --git a/src/pages/review/Detail.tsx b/src/pages/review/Detail.tsx new file mode 100644 index 0000000..0b27ce4 --- /dev/null +++ b/src/pages/review/Detail.tsx @@ -0,0 +1,288 @@ +import { type FC } from 'react' +import { useGetReviewById } from './hooks/useReviewData' +import { useParams } from 'react-router-dom' +import PageLoading from '@/components/PageLoading' +import Input from '@/components/Input' +import Status from '@/components/Status' +import { Star1, User, ShoppingCart, DocumentText, Like1, Dislike } from 'iconsax-react' +import { formatOptionalDate, formatPrice, formatFaNumber } from '@/helpers/func' +import { useTranslation } from 'react-i18next' + +const DetailReview: FC = () => { + + const { t } = useTranslation('global') + const { id } = useParams() + const { data: reviewData, isLoading } = useGetReviewById(id!) + + if (isLoading) { + return ( +
+ +
+ ) + } + + const review = reviewData?.data + if (!review) { + return ( +
+
+

جزئیات نظر

+
+
نظر یافت نشد
+
+ ) + } + + const getStatusVariant = (status: string): 'success' | 'error' | 'warning' | 'info' | 'pending' => { + const variantMap: Record = { + 'pending': 'pending', + 'approved': 'success', + 'rejected': 'error', + } + return variantMap[status] || 'pending' + } + + const statusLabels: Record = { + 'pending': 'در انتظار', + 'approved': 'تایید شده', + 'rejected': 'رد شده', + } + + const userName = [review.user.firstName, review.user.lastName].filter(Boolean).join(' ') || '-' + + return ( +
+
+

جزئیات نظر

+ +
+ +
+ {/* Main Content */} +
+ {/* Rating Section */} +
+
+ + {review.rating} +
+ از ۵ +
+ + {/* Comment Section */} +
+
+ + نظر +
+
+

+ {review.comment || 'نظری ثبت نشده است'} +

+
+
+ + {/* Positive Points */} + {review.positivePoints && review.positivePoints.length > 0 && ( +
+
+ + نقاط مثبت +
+
+ {review.positivePoints.map((point, index) => ( + + {t(`reviews.${point}`)} + + ))} +
+
+ )} + + {/* Negative Points */} + {review.negativePoints && review.negativePoints.length > 0 && ( +
+
+ + نقاط منفی +
+
+ {review.negativePoints.map((point, index) => ( + + {t(`reviews.${point}`)} + + ))} +
+
+ )} + + {/* Food Information */} +
+
+ + اطلاعات غذا +
+
+ + + + +
+ {review.food.images && review.food.images.length > 0 && ( +
+ تصاویر غذا +
+ {review.food.images.map((image, index) => ( + {`غذا + ))} +
+
+ )} +
+
+ + {/* Sidebar */} +
+ {/* User Information */} +
+
+ + اطلاعات کاربر +
+
+ + + + + +
+
+ + {/* Order Information */} +
+
+ + اطلاعات سفارش +
+
+ + + + + +
+
+ + {/* Review Metadata */} +
+
+ + {review.updatedAt && ( + + )} +
+
+
+
+
+ ) +} + +export default DetailReview \ No newline at end of file diff --git a/src/pages/review/hooks/useReviewData.ts b/src/pages/review/hooks/useReviewData.ts index 72d1054..67c242a 100644 --- a/src/pages/review/hooks/useReviewData.ts +++ b/src/pages/review/hooks/useReviewData.ts @@ -7,3 +7,10 @@ export const useGetReviews = (params?: Record) => { queryFn: () => api.getReviews(params), }); }; + +export const useGetReviewById = (id: string) => { + return useQuery({ + queryKey: ["review", id], + queryFn: () => api.getReviewById(id), + }); +}; diff --git a/src/pages/review/service/ReviewService.ts b/src/pages/review/service/ReviewService.ts index 46a51b3..ce8ec7f 100644 --- a/src/pages/review/service/ReviewService.ts +++ b/src/pages/review/service/ReviewService.ts @@ -1,5 +1,5 @@ import axios from "@/config/axios"; -import type { GetReviewsResponse } from "../types/Types"; +import type { GetReviewsResponse, GetReviewByIdResponse } from "../types/Types"; export const getReviews = async ( params?: Record @@ -9,3 +9,12 @@ export const getReviews = async ( }); return data; }; + +export const getReviewById = async ( + id: string +): Promise => { + const { data } = await axios.get( + `/admin/reviews/${id}` + ); + return data; +}; diff --git a/src/pages/review/types/Types.ts b/src/pages/review/types/Types.ts index c909ad4..5999f43 100644 --- a/src/pages/review/types/Types.ts +++ b/src/pages/review/types/Types.ts @@ -49,6 +49,32 @@ export interface ReviewUser { phone: string; } +export interface ReviewOrder { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + user: string; + restaurant: string; + deliveryMethod: string; + address: string; + paymentMethod: string; + orderNumber: number; + couponDiscount: number; + couponDetail: unknown | null; + itemsDiscount: number; + totalDiscount: number; + subTotal: number; + tax: number; + deliveryFee: number; + total: number; + totalItems: number; + description: string | null; + tableNumber: string | null; + status: string; + paymentStatus: string; +} + export interface Review extends RowDataType { id: string; createdAt: string; @@ -64,4 +90,20 @@ export interface Review extends RowDataType { status: string; } +export interface ReviewDetail { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + order: ReviewOrder; + food: ReviewFood; + user: ReviewUser; + comment: string; + rating: number; + positivePoints: string[]; + negativePoints: string[]; + status: string; +} + export type GetReviewsResponse = IResponse; +export type GetReviewByIdResponse = IResponse; diff --git a/src/router/Main.tsx b/src/router/Main.tsx index f0c1db4..478f6ec 100644 --- a/src/router/Main.tsx +++ b/src/router/Main.tsx @@ -37,6 +37,7 @@ import CouponsList from '@/pages/coupon/List' import CreateCoupon from '@/pages/coupon/Create' import UpdateCoupon from '@/pages/coupon/Update' import ReviewsList from '@/pages/review/List' +import DetailReview from '@/pages/review/Detail' const MainRouter: FC = () => { const { hasSubMenu } = useSharedStore() @@ -90,6 +91,7 @@ const MainRouter: FC = () => { } /> } /> + } />