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 */}
+
+
+
+ {/* Sidebar */}
+
+ {/* User Information */}
+
+
+ {/* Order Information */}
+
+
+ {/* Review Metadata */}
+
+
+
+
+ )
+}
+
+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 = () => {
} />
} />
+ } />