Skip to content

Commit 08b9d5a

Browse files
authored
Merge pull request #177 from dnd-side-project/develop
[deploy] release v1.1.0
2 parents 7238959 + 760a0ec commit 08b9d5a

File tree

26 files changed

+321
-301
lines changed

26 files changed

+321
-301
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "dnd-13th-8-frontend",
33
"private": true,
4-
"version": "1.0.4",
4+
"version": "1.1.0",
55
"type": "module",
66
"engines": {
77
"node": "22.12.0"

src/app/providers/ChatProvider.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { createContext, useContext, type ReactNode } from 'react'
2+
3+
import { useChatSocket } from '@/features/chat/model/sendMessage'
4+
5+
interface ChatProviderProps {
6+
roomId: string
7+
children: ReactNode
8+
}
9+
10+
export const ChatContext = createContext<ReturnType<typeof useChatSocket> | null>(null)
11+
12+
export const ChatProvider = ({ roomId, children }: ChatProviderProps) => {
13+
const chat = useChatSocket(roomId)
14+
15+
return <ChatContext.Provider value={chat}>{children}</ChatContext.Provider>
16+
}
17+
18+
export const useChat = () => {
19+
const ctx = useContext(ChatContext)
20+
if (!ctx) throw new Error('useChat 사용 오류: ChatProvider 내부에서 호출하세요')
21+
return ctx
22+
}

src/app/providers/PlayerProvider.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { createContext, useState, useContext, useRef, useCallback, type ReactNode } from 'react'
22

3-
import type { PlaylistInfo } from '@/entities/playlist'
3+
import type { PlaylistDetail } from '@/entities/playlist'
44

55
type PlaylistContextType = {
6-
currentPlaylist: PlaylistInfo | null
6+
currentPlaylist: PlaylistDetail | null
77
currentTrackIndex: number
88
currentTime: number
99
isPlaying: boolean
1010
setPlaylist: (
11-
playlist: PlaylistInfo,
11+
playlist: PlaylistDetail,
1212
trackIndex?: number,
1313
time?: number,
1414
autoPlay?: boolean
@@ -20,6 +20,7 @@ type PlaylistContextType = {
2020
updateCurrentTime: (time: number) => void
2121
playerRef: React.MutableRefObject<YT.Player | null>
2222
handlePlayerStateChange: (event: YT.OnStateChangeEvent) => void
23+
handlePlayerError: (event: YT.OnErrorEvent) => void
2324
unmuteOnce: () => void
2425
}
2526

@@ -30,7 +31,7 @@ interface PlaylistProviderProps {
3031
const PlaylistContext = createContext<PlaylistContextType | undefined>(undefined)
3132

3233
const PlaylistProvider = ({ children }: PlaylistProviderProps) => {
33-
const [currentPlaylist, setCurrentPlaylist] = useState<PlaylistInfo | null>(null)
34+
const [currentPlaylist, setCurrentPlaylist] = useState<PlaylistDetail | null>(null)
3435
const [currentTrackIndex, setCurrentTrackIndex] = useState(0)
3536
const [currentTime, setCurrentTime] = useState(0)
3637
const [isPlaying, setIsPlaying] = useState(false)
@@ -39,7 +40,7 @@ const PlaylistProvider = ({ children }: PlaylistProviderProps) => {
3940
const playerRef = useRef<YT.Player | null>(null)
4041

4142
const setPlaylist = (
42-
playlist: PlaylistInfo,
43+
playlist: PlaylistDetail,
4344
trackIndex?: number,
4445
time?: number,
4546
autoPlay = true
@@ -112,6 +113,10 @@ const PlaylistProvider = ({ children }: PlaylistProviderProps) => {
112113
[nextTrack]
113114
)
114115

116+
const handlePlayerError = useCallback(() => {
117+
nextTrack()
118+
}, [nextTrack])
119+
115120
const value = {
116121
currentPlaylist,
117122
currentTrackIndex,
@@ -128,6 +133,7 @@ const PlaylistProvider = ({ children }: PlaylistProviderProps) => {
128133
unmuteOnce,
129134
isMuted,
130135
setIsMuted,
136+
handlePlayerError,
131137
}
132138

133139
return <PlaylistContext.Provider value={value}>{children}</PlaylistContext.Provider>

src/app/providers/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { ChatProvider } from '@/app/providers/ChatProvider'
2+
13
import { default as PlayerProvider } from './PlayerProvider'
24
import QueryProvider from './QueryProvider'
35
import ThemeProvider from './ThemeProvider'
46
import { ToastProvider, useToast } from './ToastProvider'
57

6-
export { QueryProvider, ThemeProvider, PlayerProvider, ToastProvider, useToast }
8+
export { QueryProvider, ThemeProvider, PlayerProvider, ToastProvider, useToast, ChatProvider }

src/entities/playlist/api/playlist.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type {
22
CdMetaResponse,
3-
PlaylistDetailResponse,
3+
PlaylistDetail,
44
PlaylistParams,
55
PlaylistResponse,
66
} from '@/entities/playlist/types/playlist'
@@ -18,7 +18,7 @@ export const getLikedCdList = (sort: string) => {
1818

1919
// 나의 CD 트랙리스트 조회
2020
export const getTracklist = (cdId: number) => {
21-
return api.get<PlaylistDetailResponse>(`/main/playlist/mypage/me/${cdId}`)
21+
return api.get<PlaylistDetail>(`/main/playlist/mypage/me/${cdId}`)
2222
}
2323

2424
// 나의 CD 공개여부 토글
@@ -33,12 +33,17 @@ export const deleteMyCd = (cdId: number) => {
3333

3434
// 셔플된 플레이리스트 목록 조회
3535
export const getShufflePlaylists = (params: PlaylistParams) => {
36-
return api.get<PlaylistResponse>('/main/playlist/browse', { params })
36+
return api.get<PlaylistResponse>('/main/playlist/browse/v2', { params })
3737
}
3838

3939
// 트랙리스트 상세 조회
4040
export const getPlaylistDetail = (cdId: number) => {
41-
return api.get<PlaylistDetailResponse>(`/main/playlist/${cdId}`)
41+
return api.get<PlaylistDetail>(`/main/playlist/${cdId}`)
42+
}
43+
44+
// 내 트랙리스트 상세 조회
45+
export const getMyPlaylistDetail = (cdId: number) => {
46+
return api.get<PlaylistDetail>(`/main/playlist/mypage/me/${cdId}`)
4247
}
4348

4449
// 하트비트 시작

src/entities/playlist/model/usePlaylists.ts

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,42 @@
11
import {
22
useInfiniteQuery,
33
useMutation,
4+
useQueries,
45
useQuery,
56
useQueryClient,
67
type InfiniteData,
78
} from '@tanstack/react-query'
89

910
import {
11+
getMyPlaylistDetail,
1012
getPlaylistDetail,
1113
getPlaylistViewCounts,
1214
getShufflePlaylists,
1315
postPlaylistConfirm,
1416
postPlaylistStart,
1517
} from '@/entities/playlist/api/playlist'
16-
import type { Cursor, PlaylistResponse } from '@/entities/playlist/types/playlist'
18+
import type { PlaylistDetail, PlaylistResponse } from '@/entities/playlist/types/playlist'
1719
import { useAuthStore } from '@/features/auth/store/authStore'
1820
import { isDowntimeNow } from '@/shared/lib/isDowntimeNow'
1921

2022
export const useShufflePlaylists = (size: number = 5) => {
2123
return useInfiniteQuery<
2224
PlaylistResponse, // queryFn 반환 타입
2325
Error, // 에러 타입
24-
InfiniteData<PlaylistResponse, Cursor>, // select 후 데이터 타입
26+
InfiniteData<PlaylistResponse, number>, // select 후 데이터 타입
2527
['playlists', number], // queryKey 타입
26-
Cursor | undefined // pageParam 타입
28+
number | undefined // pageParam 타입
2729
>({
2830
queryKey: ['playlists', size],
2931
queryFn: ({ pageParam }) =>
3032
getShufflePlaylists({
31-
cursorPosition: pageParam?.position,
32-
cursorCardId: pageParam?.cardId,
33+
cursorId: pageParam,
3334
size,
3435
}),
3536
initialPageParam: undefined, // 첫 호출은 커서 없이 시작
3637
getNextPageParam: (lastPage) => {
37-
if (lastPage.hasNext && lastPage.nextCursor) {
38-
return lastPage.nextCursor // Cursor 타입
38+
if (lastPage.hasNext) {
39+
return lastPage.nextCursor
3940
}
4041
return undefined
4142
},
@@ -53,6 +54,14 @@ export const usePlaylistDetail = (playlistId: number | null, options?: { enabled
5354
})
5455
}
5556

57+
export const useMyPlaylistDetail = (playlistId: number | null, options?: { enabled?: boolean }) => {
58+
return useQuery({
59+
queryKey: ['myPlaylistDetail', playlistId],
60+
queryFn: () => getMyPlaylistDetail(playlistId as number),
61+
enabled: options?.enabled ?? !!playlistId,
62+
})
63+
}
64+
5665
export const usePlaylistStartMutation = () => {
5766
const queryClient = useQueryClient()
5867

@@ -81,3 +90,22 @@ export const usePlaylistViewCounts = (playlistId: number) => {
8190
queryFn: () => getPlaylistViewCounts(playlistId),
8291
})
8392
}
93+
94+
export const usePlaylistDetails = (ids: number[]) => {
95+
const results = useQueries({
96+
queries: ids.map((id) => ({
97+
queryKey: ['playlistDetail', id],
98+
queryFn: () => getPlaylistDetail(id),
99+
enabled: ids.length > 0,
100+
})),
101+
})
102+
103+
const isLoading = results.some((r) => r.isLoading)
104+
const isError = results.some((r) => r.isError)
105+
const data = results.reduce<PlaylistDetail[]>((acc, q) => {
106+
if (q.data) acc.push(q.data)
107+
return acc
108+
}, [])
109+
110+
return { data, isLoading, isError }
111+
}

src/entities/playlist/types/playlist.ts

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export interface CdBasicInfo {
22
playlistId: number
33
playlistName: string
44
creatorNickname?: string
5+
genre: string
56
isPublic: boolean
67
}
78

@@ -43,33 +44,15 @@ export interface Track {
4344
export interface Creator {
4445
creatorId: string
4546
creatorNickname: string
47+
creatorProfileImageUrl?: string
4648
}
4749

48-
export interface PlaylistDetail {
50+
export interface PlaylistDetail extends OnlyCdResponse, Creator {
4951
playlistId: number
5052
playlistName: string
51-
genre: string
52-
songs: Track[]
5353
isPublic: boolean
54-
}
55-
56-
export interface PlaylistDetailResponse extends PlaylistDetail, OnlyCdResponse {
57-
creatorId: string
58-
creatorNickname: string
59-
creatorProfileImageUrl?: string
60-
}
61-
62-
export interface PlaylistInfo extends PlaylistDetail {
63-
cardId?: number
64-
position?: number
65-
shareUrl?: string
66-
totalTime?: string
67-
creator: Creator
68-
69-
cdResponse?: {
70-
cdItems: CdCustomData[]
71-
}
72-
cdItems?: CdCustomData[]
54+
songs: Track[]
55+
genre: string
7356
}
7457

7558
// 커서 정보
@@ -79,14 +62,13 @@ export interface Cursor {
7962
}
8063

8164
export interface PlaylistResponse {
82-
content: PlaylistInfo[]
83-
nextCursor: Cursor | null
65+
content: number[] // playlistId 배열
66+
nextCursor: number | null
8467
size: number
8568
hasNext: boolean
8669
}
8770

8871
export interface PlaylistParams {
89-
cursorPosition?: number
90-
cursorCardId?: number
72+
cursorId?: number
9173
size?: number
9274
}

src/features/chat/api/chat.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
ChatCountResponse,
33
ChatHistoryParams,
44
ChatHistoryResponse,
5+
ListenerNumResponse,
56
} from '@/features/chat/types/chat'
67
import { api } from '@/shared/api/httpClient'
78

@@ -18,3 +19,7 @@ export const deleteChatMessage = async (roomId: string, messageId: string) => {
1819
export const getChatCount = (roomId: string) => {
1920
return api.get<ChatCountResponse>(`/chat/rooms/${roomId}/count/chat`)
2021
}
22+
23+
export const getListenerCount = (roomId: string) => {
24+
return api.get<ListenerNumResponse>(`/chat/rooms/${roomId}/count/member`)
25+
}

0 commit comments

Comments
 (0)