Skip to content

Commit 75e7b9a

Browse files
authored
Merge pull request #174 from dnd-side-project/chore/#173/discover-api-v2
[chore] ๋‘˜๋Ÿฌ๋ณด๊ธฐ ์„œ๋ฒ„ ๋กœ์ง ๋ณ€๊ฒฝ ๋Œ€์‘
2 parents 1f2d2ed + 5080bbe commit 75e7b9a

File tree

18 files changed

+168
-181
lines changed

18 files changed

+168
-181
lines changed

โ€Ž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/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/swipe/ui/SwipeCarousel.tsxโ€Ž

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,21 @@ import { useLocation, useNavigate, useParams } from 'react-router-dom'
44
import useEmblaCarousel from 'embla-carousel-react'
55
import styled from 'styled-components'
66

7-
import type { PlaylistInfo } from '@/entities/playlist'
8-
9-
interface SwipeCarouselProps {
7+
interface SwipeCarouselProps<T extends { playlistId: number }> {
108
children: React.ReactNode
11-
data: PlaylistInfo[]
9+
data: T[]
1210
axis: 'x' | 'y'
1311
onSelectIndexChange?: (activeIndex: number) => void
1412
basePath: string
1513
}
1614

17-
const SwipeCarousel = ({
15+
const SwipeCarousel = <T extends { playlistId: number }>({
1816
children,
1917
data,
2018
axis,
2119
onSelectIndexChange,
2220
basePath,
23-
}: SwipeCarouselProps) => {
21+
}: SwipeCarouselProps<T>) => {
2422
const navigate = useNavigate()
2523
const { id: playlistId } = useParams()
2624
const location = useLocation()
@@ -36,6 +34,7 @@ const SwipeCarousel = ({
3634
startIndex: initialIndex > 0 ? initialIndex : 0, // ๋งค์น˜ ์‹คํŒจ ์‹œ 0๋ฒˆ์œผ๋กœ
3735
containScroll: axis === 'x' && data.length <= 3 ? false : 'trimSnaps',
3836
})
37+
3938
// ์Šฌ๋ผ์ด๋“œ ์„ ํƒ ์‹œ URL ์—…๋ฐ์ดํŠธ
4039
const onSelect = useCallback(() => {
4140
if (!emblaApi || data.length === 0) return

โ€Žsrc/pages/discover/DiscoverLayout.tsxโ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const Content = () => {
2525
currentTime,
2626
isPlaying,
2727
handlePlayerStateChange,
28+
handlePlayerError,
2829
} = usePlaylist()
2930

3031
const deviceType = useDevice()
@@ -69,6 +70,7 @@ const Content = () => {
6970
}}
7071
onStateChange={handlePlayerStateChange}
7172
setIsMuted={setIsMuted}
73+
onError={handlePlayerError}
7274
/>
7375
)}
7476

0 commit comments

Comments
ย (0)