Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release #135

Merged
merged 10 commits into from
Jan 10, 2024
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"dependencies": {
"ant-design-vue": "^4.0.8",
"axios": "^1.6.2",
"event-source-polyfill": "^1.0.31",
"lodash": "^4.17.21",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
Expand All @@ -28,6 +29,7 @@
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/event-source-polyfill": "^1.0.5",
"@types/jsdom": "^21.1.3",
"@types/lodash": "^4.14.202",
"@types/node": "^18.18.5",
Expand Down
35 changes: 29 additions & 6 deletions src/apis/notification/notification.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// src/apis/notification/notification.ts
import { AxiosError } from 'axios'
import { authAxiosInstance } from '@/apis/utils/index'
import type { Notification } from '@/types/notification' // Notification 타입을 정의해야 합니다.
import type { Notification } from '@/types/notification'
import { NotificationType } from '@/types/notification'
import { EventSourcePolyfill } from 'event-source-polyfill'

const BASE_URL = import.meta.env.VITE_API_BASE_URL
const NOTIFICATION_PREFIX_PATH = '/notification-service'
const NOTIFICATION_DOMAIN_PREFIX_PATH = '/notifications'

Expand Down Expand Up @@ -59,29 +62,49 @@ export const deleteAllNotifications = async (): Promise<void> => {
// 알림 구독
export const subscribeToNotifications = (
onMessage: (notification: Notification) => void,
onError?: (event: Event) => void
onError?: (event: Event | MessageEvent) => void
): (() => void) => {
console.log('SSE connection을 시도합니다.')
const accessToken = localStorage.getItem('accessToken')

const eventSource = new EventSource(
`${NOTIFICATION_PREFIX_PATH}${NOTIFICATION_DOMAIN_PREFIX_PATH}/subscription`
if (accessToken === null) {
console.log('accessToken을 찾을 수 없습니다.')
return () => {
console.log('No active SSE connection to close because accessToken was null.')
}
}

const eventSource = new EventSourcePolyfill(
`${BASE_URL}${NOTIFICATION_PREFIX_PATH}${NOTIFICATION_DOMAIN_PREFIX_PATH}/subscription`,
{
headers: {
Authorization: `Bearer ${accessToken}`
}
}
)

eventSource.onopen = (event) => {
console.log('SSE connection이 연결되었습니다.', event)
}

eventSource.onmessage = (event) => {
const notification: Notification = JSON.parse(event.data)

if (notification.notificationType === NotificationType.HEARTBEAT) {
console.log('하트비트 수신')
return // 하트비트일 경우 처리하지 않음
}

console.log('새로운 메세지가 도착했습니다.')
console.log(event)
const notification: Notification = JSON.parse(event.data)

onMessage(notification)
}

eventSource.onerror = (event) => {
console.error('EventSource error:', event)
if (onError) {
onError(event)
onError(event as Event)
}
}

Expand Down
24 changes: 15 additions & 9 deletions src/components/ootd/OOTDPostCardComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ const likeButtonClickListener = async (postId: number, isLike: boolean | undefin
alert('로그인이 필요합니다.')
} else {
const postIndex = props.posts.findIndex((post) => post.id === postId)
console.log(postIndex)
console.log(props.posts[postIndex].isLike)
if (postIndex !== -1) {
const hasPostLike = postLikeStore.hasPostLike(postId)
if (hasPostLike) {
props.posts[postIndex].isLike ? props.posts[postIndex].likeCount += 1 : props.posts[postIndex].likeCount -= 1
} else {
props.posts[postIndex].isLike ? props.posts[postIndex].likeCount -= 1 : props.posts[postIndex].likeCount += 1
}
await postLikeStore.togglePostLikes(postId)
}
}
Expand Down Expand Up @@ -106,8 +102,18 @@ const handleImageLoad = async () => {
d='M8.82563 15L7.64035 13.921C3.43054 10.1035 0.651245 7.57766 0.651245 4.49591C0.651245 1.97003 2.62945 0 5.14716 0C6.5695 0 7.93462 0.662125 8.82563 1.70027C9.71664 0.662125 11.0818 0 12.5041 0C15.0218 0 17 1.97003 17 4.49591C17 7.57766 14.2207 10.1035 10.0109 13.921L8.82563 15Z'
fill='#FF0000' />
</svg>
<div v-if='post.likeCount <= 999' class='ootd-post-card-like-view-count-text'>{{ post.likeCount }}</div>
<div v-else class='ootd-post-card-like-view-count-text'>{{ post.likeCount }}+</div>
<div v-if='post.likeCount <= 999' class='ootd-post-card-like-view-count-text'>
<div v-if='post.isLike !== undefined && postLikeStore.hasPostLike(post.id) && post.isLike'>
{{ post.likeCount - 1 }}
</div>
<div v-else-if='post.isLike !== undefined && postLikeStore.hasPostLike(post.id) && !post.isLike'>
{{ post.likeCount + 1 }}
</div>
<div v-else>
{{ post.likeCount }}
</div>
</div>
<div v-else class='ootd-post-card-like-view-count-text'>999+</div>
</div>
<div class='ootd-post-card-count-view-wrapper'>
<svg class='ootd-post-card-view-count-icon' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 15'
Expand All @@ -117,7 +123,7 @@ const handleImageLoad = async () => {
fill='#C6C6C6' />
</svg>
<div v-if='post.viewCount <= 999' class='ootd-post-card-count-view-count-text'>{{ post.viewCount }}</div>
<div v-else class='ootd-post-card-count-view-count-text'>{{ post.viewCount }}+</div>
<div v-else class='ootd-post-card-count-view-count-text'>999+</div>
</div>
</div>
</div>
Expand Down
36 changes: 17 additions & 19 deletions src/components/ootd/OOTDProfileCardComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ const followButtonClickListener = (followingId: number, isFollowing: boolean | u
if(isFollowing === undefined) {
alert('로그인이 필요합니다.')
} else {
member.value!.isFollowing
? (member.value!.followerCount -= 1)
: (member.value!.followerCount += 1)
member.value!.isFollowing = !isFollowing
// member.value!.isFollowing
// ? (member.value!.followerCount -= 1)
// : (member.value!.followerCount += 1)
// member.value!.isFollowing = !isFollowing
followStore.toggleFollows(followingId)
}

Expand All @@ -85,19 +85,6 @@ onBeforeRouteLeave(async (to, from) => {
await flushFollowStore()
})

// 새로고침 or 브라우저 창 닫을 때 이벤트
window.addEventListener('beforeunload', async (event) => {
flushFollowStore()
.then((res) => {
window.location.reload()
})
.catch((error) => {
console.error(error)
event.preventDefault()
event.returnValue = ''
})
})

const img = ref<HTMLImageElement | null>(null)
const imageSize = ref({
width: 0,
Expand Down Expand Up @@ -140,12 +127,23 @@ const handleImageLoad = async () => {
/>
<div class="nickname">{{ member.nickname }}</div>
<div class="follow-wrapper">
팔로워 <span class="follow-count">{{ member.followerCount }}</span> | 팔로우
팔로워
<span class="follow-count">
<span v-if='member.isFollowing !== undefined && followStore.hasFollowingId(member.id) && member.isFollowing'>
{{ member.followerCount - 1 }}
</span>
<span v-else-if='member.isFollowing !== undefined && followStore.hasFollowingId(member.id) && !member.isFollowing'>
{{ member.followerCount + 1 }}
</span>
<span v-else>
{{ member.followerCount }}
</span>
</span> | 팔로우
<span class="follow-count">{{ member.followingCount }}</span>
</div>
<div v-if="member.id === memberId"></div>
<div
v-else-if="member.isFollowing"
v-else-if='member.isFollowing === undefined ? true : (followStore.hasFollowingId(member.id) ? !member.isFollowing : member.isFollowing)'
class="follow-inactive-btn"
@click="followButtonClickListener(member.id, member.isFollowing)"
>
Expand Down
9 changes: 8 additions & 1 deletion src/types/notification.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// src/types/notification.ts

export enum NotificationType {
PRODUCT_RESTOCK = 'PRODUCT_RESTOCK',
ORDER_COMPLETE = 'ORDER_COMPLETE',
ORDER_SHIPPED = 'ORDER_SHIPPED'
ORDER_SHIPPED = 'ORDER_SHIPPED',
ORDER_ARRIVED = 'ORDER_ARRIVED',
AUCTION_END = 'AUCTION_END',
GIFT_RECEIVED = 'GIFT_RECEIVED',
POINTS_EARNED_SNS = 'POINTS_EARNED_SNS',
HEARTBEAT = 'HEARTBEAT'
// ... 계속 추가됨.
}

Expand Down
55 changes: 34 additions & 21 deletions src/views/OOTDDetailView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,6 @@ const likeButtonClickListener = (isLike: boolean | undefined) => {
if (isLike === undefined) {
alert('로그인이 필요합니다.')
} else {
if (postLikeStore.hasPostLike(postId.value)) {
post.value.isLike ? post.value.likeCount += 1 : post.value.likeCount -= 1
} else {
post.value.isLike ? post.value.likeCount -= 1 : post.value.likeCount += 1
}
postLikeStore.togglePostLikes(postId.value)
}
}
Expand All @@ -97,7 +92,6 @@ const followButtonClickListener = (followingId: number, isFollowing: boolean | u
if(isFollowing === undefined) {
alert('로그인이 필요합니다.')
} else {
post.value.member.isFollowing = !isFollowing
followStore.toggleFollows(followingId)
}
}
Expand Down Expand Up @@ -230,14 +224,9 @@ const onTagedProductMouseLeave = async (productId: number) => {
</RouterLink>
<div class='ootd-detail-header-follow-wrapper'>
<div v-if='post.member.id === memberId'></div>
<div v-else-if='!post.member.isFollowing'
@click='followButtonClickListener(post.member.id, post.member.isFollowing)'
class='ootd-detail-header-follow'>
<div class='ootd-detail-header-follow-text'>
+팔로우
</div>
</div>
<div v-else class='ootd-detail-header-following'

<div v-else-if='post.member.isFollowing === undefined ? true : (followStore.hasFollowingId(post.member.id) ? !post.member.isFollowing : post.member.isFollowing)'
class='ootd-detail-header-following'
@click='followButtonClickListener(post.member.id, post.member.isFollowing)'>
<svg class='ootd-detail-header-following-icon' xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 14 10' fill='none'>
Expand All @@ -249,6 +238,13 @@ const onTagedProductMouseLeave = async (productId: number) => {
팔로잉
</div>
</div>
<div v-else
@click='followButtonClickListener(post.member.id, post.member.isFollowing)'
class='ootd-detail-header-follow'>
<div class='ootd-detail-header-follow-text'>
+팔로우
</div>
</div>
</div>
</div>
<div class='ootd-detail-header-content-created-date-wrapper'>
Expand All @@ -270,7 +266,15 @@ const onTagedProductMouseLeave = async (productId: number) => {
</div>
<div class='ootd-detail-like-text-wrapper'>
<div v-if='post.likeCount <= 999' class='ootd-detail-like-text'>
{{ post.likeCount }}
<div v-if='post.isLike !== undefined && postLikeStore.hasPostLike(post.id) && post.isLike'>
{{ post.likeCount - 1 }}
</div>
<div v-else-if='post.isLike !== undefined && postLikeStore.hasPostLike(post.id) && !post.isLike'>
{{ post.likeCount + 1 }}
</div>
<div v-else>
{{ post.likeCount }}
</div>
</div>
<div v-else class='ootd-detail-like-text'>
999+
Expand Down Expand Up @@ -409,12 +413,21 @@ const onTagedProductMouseLeave = async (productId: number) => {
<div class='ootd-detail-footer-count-wrapper'>
<div class='ootd-detail-footer-like-count-wrapper'>
<div class='ootd-detail-footer-like-count'>
좋아요 <span class='count-wrapper'>{{ post.likeCount }}</span>
</div>
</div>
<div class='ootd-detail-footer-comment-count-wrapper'>
<div class='ootd-detail-footer-comment-count'>
댓글 <span class='count-wrapper'>{{ post.commentCount }}</span>
좋아요
<span v-if='post.likeCount <= 999' class='count-wrapper'>
<span v-if='post.isLike !== undefined && postLikeStore.hasPostLike(post.id) && post.isLike'>
{{ post.likeCount - 1 }}
</span>
<span v-else-if='post.isLike !== undefined && postLikeStore.hasPostLike(post.id) && !post.isLike'>
{{ post.likeCount + 1 }}
</span>
<span v-else>
{{ post.likeCount }}
</span>
</span>
<span v-else class='count-wrapper'>
999+
</span>
</div>
</div>
<div class='ootd-detail-footer-view-count-wrapper'>
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.vitest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"exclude": [],
"compilerOptions": {
"composite": true,
"lib": [],
"types": ["node", "jsdom"]
"lib": ["es2020", "dom"],
"types": ["vitest/globals", "vitest"]
}
}