diff --git a/apps/web/src/assets/icon/icon-thumb-up.svg b/apps/web/src/assets/icon/icon-thumb-up.svg
new file mode 100644
index 00000000..76f32532
--- /dev/null
+++ b/apps/web/src/assets/icon/icon-thumb-up.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/web/src/components/review/item.tsx b/apps/web/src/components/review/item.tsx
index 8cf65441..1e23f0b2 100644
--- a/apps/web/src/components/review/item.tsx
+++ b/apps/web/src/components/review/item.tsx
@@ -9,28 +9,33 @@ import {
generateShadowCSS,
} from '@review-canvas/theme';
+// import ThumbUpIcon from '@/assets/icon/icon-thumb-up.svg';
import { Star } from '@/components/review/star.tsx';
import { useReviewItemStyle } from '@/contexts/style/review-item.ts';
import useMessageToShop from '@/hooks/use-message-to-shop.ts';
-import type { ReplyItem } from '@/services/api-types/review';
+import type { ReviewItemProps } from '@/services/api-types/review';
+import { useReviewService } from '@/services/review.tsx';
import { useConnectedShop } from '@/state/shop.ts';
import { MESSAGE_TYPES } from '@/utils/message';
import Reply from './reply';
-
-interface ReviewItemProps {
- id: number;
- rate: number;
- content: string;
- reviewerID: string;
- reviewer: string;
- replies: ReplyItem[];
-}
+import { useEffect, useState } from 'react';
export default function ReviewItem(props: ReviewItemProps) {
const style = useReviewItemStyle();
const { userID } = useConnectedShop();
+ const reviewService = useReviewService();
const message = useMessageToShop();
+ const [count, setCount] = useState(0);
+
+ useEffect(() => {
+ async function fetchData() {
+ return reviewService.userReviewLike(props.id);
+ }
+ void fetchData().then((response) => {
+ setCount(response.data.count);
+ });
+ }, [props.id, reviewService]);
const edit = () => {
message(MESSAGE_TYPES.OPEN_MODAL, {
@@ -38,14 +43,12 @@ export default function ReviewItem(props: ReviewItemProps) {
url: `/reviews/${props.id}/edit`,
});
};
-
const deleteReview = () => {
message(MESSAGE_TYPES.OPEN_SELECTING_MODAL, {
type: 'delete',
url: `/reviews/${props.id}/delete`,
});
};
-
const showReviewDetail = () => {
message(MESSAGE_TYPES.OPEN_MODAL, {
type: 'detail',
@@ -53,6 +56,8 @@ export default function ReviewItem(props: ReviewItemProps) {
});
};
+ const createLike = () => {};
+
return (
{props.reviewer}
{props.content}
+ {/*{style.reviewLike.buttonType !== 'NONE' ? (*/}
+ {/* */}
+ {/*) : null}*/}
+
{userID === props.reviewerID ? (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions -- This is intentional
(null);
diff --git a/apps/web/src/models/design-property.ts b/apps/web/src/models/design-property.ts
index a375e9e1..db71141b 100644
--- a/apps/web/src/models/design-property.ts
+++ b/apps/web/src/models/design-property.ts
@@ -1,3 +1,5 @@
+import {ReviewLikeButtonProps} from "@review-canvas/theme";
+
export type Shadow = 'NONE' | 'SMALL' | 'MEDIUM' | 'LARGE';
export type FocusAreaLayout = 'BEST_REVIEW_TOP' | 'BEST_REVIEW_BOTTOM' | 'BEST_REVIEW_LEFT' | 'BEST_REVIEW_RIGHT';
export type ReviewAreaLayout = 'REVIEW_TOP' | 'REVIEW_BOTTOM' | 'REVIEW_LEFT' | 'REVIEW_RIGHT';
@@ -6,6 +8,7 @@ export type AlignmentPosition = 'LEFT' | 'CENTER' | 'RIGHT';
export type DetailViewType = 'SPREAD' | 'MODAL';
export type PagingType = 'PAGE_NUMBER' | 'SEE_MORE_SCROLL';
export type FilterType = 'LIST' | 'DROPDOWN';
+export type ReviewLikeButtonType = 'NONE' | 'THUMB_UP_WITH_TEXT' | 'THUMB_UP';
export interface Margin {
left: string;
@@ -43,11 +46,11 @@ export interface Round {
}
export interface ReviewLike {
- buttonType: string;
- iconColor: string;
- textColor: string;
buttonBorderColor: string;
buttonRound: Round;
+ buttonType: ReviewLikeButtonType;
+ iconColor: string;
+ textColor: string;
}
export interface ReviewLayout {
diff --git a/apps/web/src/services/api-types/review.tsx b/apps/web/src/services/api-types/review.tsx
index 8378b742..07c34784 100644
--- a/apps/web/src/services/api-types/review.tsx
+++ b/apps/web/src/services/api-types/review.tsx
@@ -30,6 +30,14 @@ export interface RetrieveReviewListResponse {
content: ReviewItem[];
};
}
+
+export interface UserReviewLikeResponse {
+ success: boolean;
+ data: {
+ count: number;
+ };
+}
+
export interface RetrieveReplyListResponse {
success: boolean;
data: ReplyItem[];
@@ -45,6 +53,15 @@ export interface ReplyItem {
nickname: string;
}
+export interface ReviewItemProps {
+ id: number;
+ rate: number;
+ content: string;
+ reviewerID: string;
+ reviewer: string;
+ replies: ReplyItem[];
+}
+
export type ReviewListSort = 'LATEST' | 'HIGH_SCORE' | 'LOW_SCORE';
export type ReviewListFilter = 'ALL' | 'IMAGE_VIDEO' | 'GENERAL';
@@ -57,6 +74,11 @@ export interface RetrieveReviewListRequest {
filter?: ReviewListFilter;
}
+export interface CreateUserReviewLike {
+ mallId: string;
+ memberId: string;
+}
+
export interface RetrieveReviewItemResponse {
success: boolean;
data: ReviewItem;
diff --git a/apps/web/src/services/design-property.tsx b/apps/web/src/services/design-property.tsx
index 8e0ef690..12c6bba5 100644
--- a/apps/web/src/services/design-property.tsx
+++ b/apps/web/src/services/design-property.tsx
@@ -48,6 +48,14 @@ class DesignPropertyService {
shadow: reviewDesignView.shadow,
shadowColor: 'rgba(0, 0, 0, 0.3)',
backgroundColor: reviewDesignView.reviewBackgroundColor,
+ replyBackgroundColor: reviewDesignView.replyBackgroundColor,
+ reviewLike: {
+ buttonBorderColor: reviewDesignView.reviewLike.buttonBorderColor,
+ buttonRound: reviewDesignView.reviewLike.buttonRound,
+ buttonType: reviewDesignView.reviewLike.buttonType,
+ iconColor: reviewDesignView.reviewLike.iconColor,
+ textColor: reviewDesignView.reviewLike.textColor,
+ },
};
}
}
diff --git a/apps/web/src/services/review.tsx b/apps/web/src/services/review.tsx
index 69eac851..a1346567 100644
--- a/apps/web/src/services/review.tsx
+++ b/apps/web/src/services/review.tsx
@@ -6,6 +6,11 @@ import type * as TYPE from '@/services/api-types/review.tsx';
import API from '@/utils/api.ts';
class ReviewService {
+ async userReviewLike(reviewId: number): Promise {
+ const response = await API.get(`/api/v1/reviews/${reviewId}/like/count`);
+ return response.data;
+ }
+
async list({
mallId,
productNo,