From becf30f3d6c5a96d4424a0661e55fddeaecc19ff Mon Sep 17 00:00:00 2001
From: iOdiO89 <117376841+iOdiO89@users.noreply.github.com>
Date: Tue, 20 Oct 2026 21:28:17 +0900
Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EC=9C=84=EC=8B=9C=20=EB=AA=A9?=
=?UTF-8?q?=EB=A1=9D=20=EC=9D=91=EB=8B=B5=EC=97=90=20=EC=9A=B0=EC=8A=B9=20?=
=?UTF-8?q?=ED=86=A0=EB=84=88=EB=A8=BC=ED=8A=B8=20id=20=ED=95=84=EB=93=9C?=
=?UTF-8?q?=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- GetWishlistResponseT 에 winnerTournamentIds 추가
- 서버 계약: TeamPiKi/core#1237
- 내 플레이 결과 기준 우승 토너먼트 id 목록
- e2e 위시 목에 빈 배열 추가
- 원인: 필수 필드 누락으로 타입 에러
---
apps/web/e2e/mocks/wish.ts | 1 +
apps/web/src/types/wish.ts | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/apps/web/e2e/mocks/wish.ts b/apps/web/e2e/mocks/wish.ts
index ac8f9a33..991d2969 100644
--- a/apps/web/e2e/mocks/wish.ts
+++ b/apps/web/e2e/mocks/wish.ts
@@ -23,6 +23,7 @@ export const MOCK_WISHLIST_ENTRIES: GetWishlistResponseT[] = MOCK_TOURNAMENT_ITE
},
reused: null,
refreshNeeded: null,
+ winnerTournamentIds: [],
})
);
diff --git a/apps/web/src/types/wish.ts b/apps/web/src/types/wish.ts
index 25347ff4..96b1389e 100644
--- a/apps/web/src/types/wish.ts
+++ b/apps/web/src/types/wish.ts
@@ -21,6 +21,10 @@ export type GetWishlistResponseT = {
* - 링크로 등록한 경우: boolean
*/
reused: boolean | null;
+ /**
+ * 내가 플레이한 토너먼트 중 이 위시가 우승한 토너먼트 id 목록
+ */
+ winnerTournamentIds: number[];
};
export type PostWishLinkResponseT = {
From 7fa2529307a67b39ef386d418d58503ab49806d9 Mon Sep 17 00:00:00 2001
From: iOdiO89 <117376841+iOdiO89@users.noreply.github.com>
Date: Tue, 20 Oct 2026 21:28:17 +0900
Subject: [PATCH 2/5] =?UTF-8?q?feat:=20caption=20medium=20=ED=83=80?=
=?UTF-8?q?=EC=9D=B4=ED=8F=AC=20=EC=9C=A0=ED=8B=B8=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- caption-1-medium 추가: 12px · 행간 18px · Medium
- 아카이브 우승템 칩용
- caption-2-medium 추가: 10px · 행간 18px · Medium
- /wish 1위 칩용
---
apps/web/src/styles/typography.css | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/apps/web/src/styles/typography.css b/apps/web/src/styles/typography.css
index 602af2a8..fb105e99 100644
--- a/apps/web/src/styles/typography.css
+++ b/apps/web/src/styles/typography.css
@@ -82,9 +82,23 @@
font-weight: 600;
}
+@utility caption-1-medium {
+ font-size: 12px;
+ line-height: 18px;
+ letter-spacing: -0.4px;
+ font-weight: 500;
+}
+
@utility caption-1-regular {
font-size: 12px;
line-height: 18px;
letter-spacing: -0.4px;
font-weight: 400;
}
+
+@utility caption-2-medium {
+ font-size: 10px;
+ line-height: 18px;
+ letter-spacing: -0.4px;
+ font-weight: 500;
+}
From 681cf5c9d7f564829ae8b22622211c0551dd8f30 Mon Sep 17 00:00:00 2001
From: iOdiO89 <117376841+iOdiO89@users.noreply.github.com>
Date: Tue, 20 Oct 2026 21:28:17 +0900
Subject: [PATCH 3/5] =?UTF-8?q?feat:=20/wish=20=EC=9C=84=EC=8B=9C=20?=
=?UTF-8?q?=EC=B9=B4=EB=93=9C=EC=97=90=201=EC=9C=84=20=EC=B9=A9=20?=
=?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- WishCard 이미지 좌하단에 배지 아이콘과 1위 칩 렌더링
- 이미지와 정보 영역 경계에 맞춤
- 크기는 패딩으로만 결정
- WishGrid 가 winnerTournamentIds 길이로 우승 여부 판정
- 폴더 상세도 같은 그리드라 함께 적용
- MOCK_WISHES 4개 중 1개에 우승 id 추가
---
.../app/wish/_common/_components/WishCard.tsx | 16 +++++++++++++++-
.../app/wish/_common/_components/WishGrid.tsx | 3 ++-
.../web/src/app/wish/_common/_consts/wishMock.ts | 1 +
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/apps/web/src/app/wish/_common/_components/WishCard.tsx b/apps/web/src/app/wish/_common/_components/WishCard.tsx
index ca183896..b5d5cfbf 100644
--- a/apps/web/src/app/wish/_common/_components/WishCard.tsx
+++ b/apps/web/src/app/wish/_common/_components/WishCard.tsx
@@ -1,6 +1,8 @@
+import { BadgeIconFill } from '@/assets/icons';
import ImageIconOutline from '@/assets/icons/outline/image.svg';
import BaseImage from '@/components/base-image';
import Skeleton from '@/components/skeleton';
+import { Z_INDEX } from '@/consts/zIndex';
import formatPrice from '@/utils/formatPrice';
type WishCardProps = {
@@ -9,6 +11,8 @@ type WishCardProps = {
imageUrl: string | null;
sourcePlatform: string | null;
discountRate: number | null;
+ /** 내가 플레이한 토너먼트에서 우승한 적 있는지 */
+ isWinner?: boolean;
preload?: boolean;
};
@@ -18,13 +22,14 @@ const imageFallback = (
);
-/** 3열 그리드용 위시 카드 — 이미지·상품명·할인율·가격·커머스 칩 */
+/** 3열 그리드용 위시 카드 */
function WishCard({
name,
price,
imageUrl,
sourcePlatform,
discountRate,
+ isWinner = false,
preload = false,
}: WishCardProps) {
return (
@@ -43,6 +48,15 @@ function WishCard({
) : (
imageFallback
)}
+ {isWinner && (
+
+
+ 1위
+
+ )}
diff --git a/apps/web/src/app/wish/_common/_components/WishGrid.tsx b/apps/web/src/app/wish/_common/_components/WishGrid.tsx
index 766d35db..d684aa7f 100644
--- a/apps/web/src/app/wish/_common/_components/WishGrid.tsx
+++ b/apps/web/src/app/wish/_common/_components/WishGrid.tsx
@@ -17,7 +17,7 @@ const PRELOAD_COUNT = 6;
function WishGrid({ wishes, selectedWishIds, onToggleSelect }: WishGridProps) {
return (
- {wishes.map(({ wish, item }, index) => {
+ {wishes.map(({ wish, item, winnerTournamentIds }, index) => {
const card = (
0}
preload={index < PRELOAD_COUNT}
/>
);
diff --git a/apps/web/src/app/wish/_common/_consts/wishMock.ts b/apps/web/src/app/wish/_common/_consts/wishMock.ts
index 44a3a394..37444d88 100644
--- a/apps/web/src/app/wish/_common/_consts/wishMock.ts
+++ b/apps/web/src/app/wish/_common/_consts/wishMock.ts
@@ -21,6 +21,7 @@ export const MOCK_WISHES: WishListItemT[] = Array.from({ length: 12 }, (_, index
},
refreshNeeded: null,
reused: null,
+ winnerTournamentIds: index % 4 === 0 ? [index + 100] : [],
}));
export const MOCK_FOLDERS: WishFolderT[] = [
From 8ca49d69b7b4ef00cf4e8df5d1b5d6b4c6a41031 Mon Sep 17 00:00:00 2001
From: iOdiO89 <117376841+iOdiO89@users.noreply.github.com>
Date: Tue, 20 Oct 2026 21:28:17 +0900
Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=EC=95=84=EC=B9=B4=EC=9D=B4?=
=?UTF-8?q?=EB=B8=8C=20=EC=9C=84=EC=8B=9C=20=EC=B9=B4=EB=93=9C=EC=97=90=20?=
=?UTF-8?q?=EC=9A=B0=EC=8A=B9=ED=85=9C=20=EC=B9=A9=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- WishReadyCard 이미지 좌하단에 우승템 칩 렌더링
- 시안 184:1602 축소본 수치를 카드 폭 201px 기준으로 환산
- 배경 #404040 은 대응 토큰 없음
- 크기는 패딩으로만 결정
- archive WishGrid 가 winnerTournamentIds 길이로 우승 여부 판정
- 삭제 모드 체크박스는 좌상단이라 겹침 없음
---
.../archive/wish/_components/wish-grid/index.tsx | 3 ++-
.../components/common/wish-card/WishReadyCard.tsx | 14 +++++++++++++-
apps/web/src/components/common/wish-card/index.tsx | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/apps/web/src/app/archive/wish/_components/wish-grid/index.tsx b/apps/web/src/app/archive/wish/_components/wish-grid/index.tsx
index f8209181..31083f23 100644
--- a/apps/web/src/app/archive/wish/_components/wish-grid/index.tsx
+++ b/apps/web/src/app/archive/wish/_components/wish-grid/index.tsx
@@ -26,7 +26,7 @@ function WishGrid({ items, isDeleteMode = false, selectedIds, onToggleSelect }:
return (
- {items.map(({ wish, item }, index) => {
+ {items.map(({ wish, item, winnerTournamentIds }, index) => {
const card = (
0}
preload={index < 4}
/>
);
diff --git a/apps/web/src/components/common/wish-card/WishReadyCard.tsx b/apps/web/src/components/common/wish-card/WishReadyCard.tsx
index 8876a683..fae38993 100644
--- a/apps/web/src/components/common/wish-card/WishReadyCard.tsx
+++ b/apps/web/src/components/common/wish-card/WishReadyCard.tsx
@@ -1,14 +1,17 @@
import ImageIconOutline from '@/assets/icons/outline/image.svg';
import BaseImage from '@/components/base-image';
import Skeleton from '@/components/skeleton';
+import { Z_INDEX } from '@/consts/zIndex';
import formatPrice from '@/utils/formatPrice';
-/** READY 위시 카드 — 이미지·상품명·가격·커머스 칩 */
+/** READY 위시 카드 — 이미지·우승 칩·상품명·가격·커머스 칩 */
type WishReadyCardProps = {
name: string | null;
price: number | null;
imageUrl: string | null;
sourcePlatform?: string | null;
+ /** 내가 플레이한 토너먼트에서 우승한 적 있는지 */
+ isWinner?: boolean;
preload?: boolean;
};
@@ -17,6 +20,7 @@ function WishReadyCard({
price,
imageUrl,
sourcePlatform,
+ isWinner = false,
preload = false,
}: WishReadyCardProps) {
return (
@@ -42,6 +46,14 @@ function WishReadyCard({
)}
+ {isWinner && (
+
+ 우승템
+
+ )}
{/* 상품명 + 가격 + 커머스칩 */}
diff --git a/apps/web/src/components/common/wish-card/index.tsx b/apps/web/src/components/common/wish-card/index.tsx
index eefc1201..e213db78 100644
--- a/apps/web/src/components/common/wish-card/index.tsx
+++ b/apps/web/src/components/common/wish-card/index.tsx
@@ -12,6 +12,7 @@ type WishCardProps = {
price: number | null;
imageUrl: string | null;
sourcePlatform?: string | null;
+ isWinner?: boolean;
preload?: boolean;
};
From 1bd7d005a1cb03227bb75dcf8559707eee601bce Mon Sep 17 00:00:00 2001
From: iOdiO89 <117376841+iOdiO89@users.noreply.github.com>
Date: Tue, 20 Oct 2026 21:42:23 +0900
Subject: [PATCH 5/5] =?UTF-8?q?test:=20=EB=A7=81=ED=81=AC=20=EB=8B=B4?=
=?UTF-8?q?=EA=B8=B0=20E2E=20=EB=AA=A9=EB=A1=9D=20=EB=AA=A9=EC=97=90=20win?=
=?UTF-8?q?nerTournamentIds=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 담기 후 목록 재조회 목에 winnerTournamentIds 빈 배열 추가
- 원인: POST 응답 목을 목록 항목으로 그대로 넣어 필드 없음
- 결과: archive WishGrid 의 winnerTournamentIds.length 접근에서 렌더링 실패
---
apps/web/e2e/specs/archive/wishAddByLink.spec.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/apps/web/e2e/specs/archive/wishAddByLink.spec.ts b/apps/web/e2e/specs/archive/wishAddByLink.spec.ts
index a816179c..4d325f31 100644
--- a/apps/web/e2e/specs/archive/wishAddByLink.spec.ts
+++ b/apps/web/e2e/specs/archive/wishAddByLink.spec.ts
@@ -30,7 +30,10 @@ test('링크를 입력해 담으면 다이얼로그가 닫히고 목록에 추
await page.getByLabel('링크 URL').fill(ADDED_URL);
api.post(ENDPOINTS.WISHLISTS, MOCK_WISH_ADDED_BY_LINK);
- api.getPage(ENDPOINTS.WISHLISTS, [...MOCK_WISHLIST_ENTRIES, MOCK_WISH_ADDED_BY_LINK]);
+ api.getPage(ENDPOINTS.WISHLISTS, [
+ ...MOCK_WISHLIST_ENTRIES,
+ { ...MOCK_WISH_ADDED_BY_LINK, winnerTournamentIds: [] },
+ ]);
const postRequest = page.waitForRequest(
request => request.method() === 'POST' && request.url().includes(ENDPOINTS.WISHLISTS)