Skip to content

Commit aef8583

Browse files
authored
Merge pull request #109 from hamlsy/release/shop-info
change shop-info api spec
2 parents a108d51 + 8ed41d6 commit aef8583

5 files changed

Lines changed: 161 additions & 71 deletions

File tree

src/core/constants/markerSizes.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
*/
55

66
// 유저 마커 크기 (플레이어가 선택한 위치에 표시되는 마커)
7-
export const USER_MARKER_SIZE = { width: 24, height: 35 };
7+
export const USER_MARKER_SIZE = { width: 26, height: 37 };
88

99
// 결과 마커 크기 (정답 위치에 표시되는 마커)
10-
export const RESULT_MARKER_SIZE = { width: 24, height: 35 };
10+
export const RESULT_MARKER_SIZE = { width: 26, height: 37 };
1111

1212
// 게임 중 마커 크기 (지도 클릭 시 표시되는 인터랙티브 마커)
13-
export const GAME_MARKER_SIZE = { width: 24, height: 35 };
13+
export const GAME_MARKER_SIZE = { width: 26, height: 37 };
1414

1515
// 게임 중 마커 offset (마커 이미지의 앵커 포인트)
1616
export const GAME_MARKER_OFFSET = { x: 12, y: 35 };

src/features/friend/components/FriendChatWindow.vue

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
>
1717
<div class="chat-header-left">
1818
<div class="chat-avatar-wrap">
19-
<div class="chat-avatar" :style="{ background: friend.avatarColor }">
19+
<img
20+
v-if="friend.markerImageUrl"
21+
:src="friend.markerImageUrl"
22+
class="chat-avatar-img"
23+
:alt="friend.nickname"
24+
/>
25+
<div v-else class="chat-avatar" :style="{ background: friend.avatarColor }">
2026
{{ friend.nickname[0].toUpperCase() }}
2127
</div>
2228
<span class="chat-online-dot" :class="{ online: friend.isOnline }"></span>
@@ -60,20 +66,32 @@
6066
<p>{{ friend.nickname }}님과 대화를 시작해보세요</p>
6167
</div>
6268

63-
<div
64-
v-for="(msg, i) in messages"
65-
:key="msg.id"
66-
class="message-item"
67-
:class="{
68-
'is-mine': msg.isMine,
69-
'show-avatar': shouldShowAvatar(i),
70-
}"
71-
>
69+
<template v-for="(msg, i) in messages" :key="msg.id">
70+
<!-- 날짜 구분선 -->
71+
<div v-if="shouldShowDateSeparator(i)" class="chat-date-separator">
72+
<span>{{ formatDateSeparator(msg.timestamp) }}</span>
73+
</div>
74+
75+
<div
76+
class="message-item"
77+
:class="{
78+
'is-mine': msg.isMine,
79+
'show-avatar': shouldShowAvatar(i),
80+
}"
81+
>
7282
<!-- 상대방 메시지 -->
7383
<template v-if="!msg.isMine">
74-
<div v-if="shouldShowAvatar(i)" class="msg-avatar" :style="{ background: friend.avatarColor }">
75-
{{ friend.nickname[0].toUpperCase() }}
76-
</div>
84+
<template v-if="shouldShowAvatar(i)">
85+
<img
86+
v-if="friend.markerImageUrl"
87+
:src="friend.markerImageUrl"
88+
class="msg-avatar-img"
89+
:alt="friend.nickname"
90+
/>
91+
<div v-else class="msg-avatar" :style="{ background: friend.avatarColor }">
92+
{{ friend.nickname[0].toUpperCase() }}
93+
</div>
94+
</template>
7795
<div v-else class="msg-avatar-spacer"></div>
7896
<div class="msg-bubble other-bubble">
7997
<p class="msg-text">{{ msg.text }}</p>
@@ -88,7 +106,8 @@
88106
<span v-if="shouldShowTime(i)" class="msg-time">{{ formatTime(msg.timestamp) }}</span>
89107
</div>
90108
</template>
91-
</div>
109+
</div>
110+
</template>
92111
</div>
93112

94113
<!-- 맨 아래로 이동 버튼 -->
@@ -290,6 +309,25 @@ export default {
290309
return !sameMinute
291310
}
292311
312+
// 날짜 구분선
313+
function shouldShowDateSeparator(index) {
314+
if (index === 0) return true
315+
const msg = props.messages[index]
316+
const prev = props.messages[index - 1]
317+
const msgDate = new Date(msg.timestamp).toLocaleDateString()
318+
const prevDate = new Date(prev.timestamp).toLocaleDateString()
319+
return msgDate !== prevDate
320+
}
321+
322+
function formatDateSeparator(timestamp) {
323+
if (!timestamp) return ''
324+
return new Date(timestamp).toLocaleDateString('ko-KR', {
325+
year: 'numeric',
326+
month: 'long',
327+
day: 'numeric'
328+
})
329+
}
330+
293331
function formatTime(timestamp) {
294332
if (!timestamp) return ''
295333
return new Date(timestamp).toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit' })
@@ -308,7 +346,8 @@ export default {
308346
isAtBottom,
309347
onHeaderClick, onWindowFocus, onScroll,
310348
scrollToBottomManual,
311-
sendMessage, shouldShowAvatar, shouldShowTime, formatTime, autoResize,
349+
sendMessage, shouldShowAvatar, shouldShowTime,
350+
shouldShowDateSeparator, formatDateSeparator, formatTime, autoResize,
312351
}
313352
},
314353
}
@@ -396,6 +435,15 @@ export default {
396435
color: #ffffff;
397436
}
398437
438+
.chat-avatar-img {
439+
width: 32px;
440+
height: 32px;
441+
border-radius: 50%;
442+
object-fit: contain;
443+
border: 1.5px solid var(--color-border);
444+
background: var(--color-background);
445+
}
446+
399447
.chat-online-dot {
400448
position: absolute;
401449
bottom: 0;
@@ -525,6 +573,23 @@ export default {
525573
.chat-empty-icon { font-size: 22px; color: var(--color-border-dark); }
526574
.chat-empty p { margin: 0; }
527575
576+
.chat-date-separator {
577+
text-align: center;
578+
margin: 16px 0 8px;
579+
font-size: 11px;
580+
font-weight: 500;
581+
color: var(--color-text-secondary);
582+
display: flex;
583+
justify-content: center;
584+
}
585+
586+
.chat-date-separator span {
587+
background: var(--color-surface-hover);
588+
padding: 4px 12px;
589+
border-radius: 12px;
590+
border: 1px solid var(--color-border);
591+
}
592+
528593
/* ── 메시지 아이템 ───────────────────────────────────────── */
529594
.message-item {
530595
display: flex;
@@ -549,6 +614,17 @@ export default {
549614
margin-bottom: 2px;
550615
}
551616
617+
.msg-avatar-img {
618+
width: 24px;
619+
height: 24px;
620+
border-radius: 50%;
621+
object-fit: contain;
622+
border: 1.5px solid var(--color-border);
623+
background: var(--color-background);
624+
flex-shrink: 0;
625+
margin-bottom: 2px;
626+
}
627+
552628
.msg-avatar-spacer {
553629
width: 24px;
554630
flex-shrink: 0;

src/features/friend/components/FriendPanel.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ export default {
576576
}
577577
578578
.avatar-img {
579-
object-fit: cover;
579+
object-fit: contain;
580580
border: 1.5px solid var(--color-border);
581581
background: var(--color-background);
582582
}

src/features/shop/services/shop.service.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ const SHOP_ENDPOINTS = {
3131
* @property {number} price - 아이템 가격
3232
* @property {number} stock - 재고 수량
3333
* @property {string} imageUrl - 이미지 URL
34-
* @property {boolean} owned - 보유 여부
35-
* @property {number} [memberItemId] - 사용자 보유 아이템 ID (owned가 true일 때)
36-
* @property {boolean} [equipped] - 장착 여부 (마커 등에서 사용)
34+
* @property {boolean} isOwned - 보유 여부
35+
* @property {number|null} [ownedMemberItemId] - 사용자 보유 아이템 ID (isOwned가 true일 때)
36+
* @property {boolean} [isEquipped] - 현재 장착 여부
3737
*/
3838

3939
/**
@@ -50,7 +50,7 @@ const SHOP_ENDPOINTS = {
5050
*/
5151
class ShopService {
5252
/**
53-
* 상점 내 정보 조회 (내 포인트, 장착 아이템, 보유 아이템)
53+
* 상점 내 정보 조회 (내 포인트, 장착 아이템)
5454
* @returns {Promise<ApiResponse>} API 응답 데이터
5555
*/
5656
async getShopInfo() {
@@ -191,9 +191,9 @@ class ShopService {
191191
price: item.price,
192192
stock: 999, // 더미 재고
193193
imageUrl: item.image,
194-
owned: item.owned,
195-
memberItemId: item.owned ? Math.floor(Math.random() * 10000) : null,
196-
equipped: item.equipped || false,
194+
isOwned: item.owned,
195+
ownedMemberItemId: item.owned ? Math.floor(Math.random() * 10000) : null,
196+
isEquipped: item.equipped || false,
197197
rarity: item.rarity,
198198
isNew: item.isNew,
199199
currencyType: item.currencyType
@@ -217,9 +217,9 @@ class ShopService {
217217
image: apiItem.imageUrl,
218218
category: categoryId,
219219
isNew: apiItem.isNew || false,
220-
owned: apiItem.owned,
221-
memberItemId: apiItem.memberItemId,
222-
equipped: apiItem.equipped || false,
220+
owned: apiItem.isOwned ?? apiItem.owned ?? false,
221+
memberItemId: apiItem.ownedMemberItemId ?? apiItem.memberItemId ?? null,
222+
equipped: apiItem.isEquipped ?? apiItem.equipped ?? false,
223223
stock: apiItem.stock,
224224
itemId: apiItem.itemId
225225
};

0 commit comments

Comments
 (0)