Skip to content

Commit dc1fa2d

Browse files
authored
Merge pull request #220 from dnd-side-project/fix/#217/qa-feed-curation
[fix] ν™ˆ, 검색, ν”Όλ“œ, νλ ˆμ΄μ…˜ κ΄€λ ¨ QA
2 parents 7061c17 + 246444f commit dc1fa2d

File tree

26 files changed

+759
-867
lines changed

26 files changed

+759
-867
lines changed

β€Žsrc/app/providers/PlayerProvider.tsxβ€Ž

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,17 @@ const PlaylistProvider = ({ children }: PlaylistProviderProps) => {
5353
if (time !== undefined) setCurrentTime(time)
5454

5555
const isSamePlaylist = currentPlaylist?.playlistId === playlist.playlistId
56-
5756
setIsPlaying((prev) => (isSamePlaylist ? prev : autoPlay))
5857

5958
if (playerRef.current) {
60-
if (time !== undefined) playerRef.current.seekTo(time, true)
61-
62-
if (!isSamePlaylist && autoPlay) {
63-
playerRef.current.playVideo()
59+
try {
60+
const state = playerRef.current.getPlayerState()
61+
if (state === -1 || state === undefined) return
62+
63+
if (time !== undefined) playerRef.current.seekTo(time, true)
64+
if (!isSamePlaylist && autoPlay) playerRef.current.playVideo()
65+
} catch {
66+
// ν”Œλ ˆμ΄μ–΄ λ―Έμ€€λΉ„ μƒνƒœλŠ” onReadyμ—μ„œ 처리
6467
}
6568
}
6669
}

β€Žsrc/entities/playlist/model/usePlaylists.tsβ€Ž

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ export const useShufflePlaylists = (size: number = 5) => {
6464
})
6565
}
6666

67-
export const usePlaylistDetail = (playlistId: number | null, options?: { enabled?: boolean }) => {
67+
export const usePlaylistDetail = (
68+
playlistId: number | null | undefined, // TODO: mycd λ ˆκ±°μ‹œ 정리 μ‹œ null νƒ€μž…λ„ μ‚­μ œ
69+
options?: { enabled?: boolean }
70+
) => {
6871
return useQuery({
6972
queryKey: ['playlistDetail', playlistId],
7073
queryFn: () => getPlaylistDetail(playlistId as number),
@@ -157,10 +160,11 @@ type PageParam = { cursor: number; direction: CarouselDirection } | undefined
157160
export const useCarouselCdList = (
158161
type: FEED_CD_LIST_TAB_TYPE, // cds or likes
159162
shareCode: string,
160-
params: CarouselParams
163+
params: CarouselParams,
164+
options?: { enabled?: boolean }
161165
) => {
162166
return useInfiniteQuery({
163-
queryKey: ['feedCdList', type, shareCode, params.sort],
167+
queryKey: ['feedCdList', type, shareCode, params.sort, params.anchorId],
164168

165169
queryFn: ({ pageParam }: { pageParam: PageParam }) => {
166170
const fetchFn = type === 'cds' ? getCdCarousel : getLikedCdCarousel
@@ -195,6 +199,6 @@ export const useCarouselCdList = (
195199
return { cursor: firstPage.prevCursor, direction: 'PREV' }
196200
},
197201

198-
enabled: !!shareCode,
202+
enabled: options?.enabled !== false && !!shareCode,
199203
})
200204
}

β€Žsrc/features/like/model/useLike.tsβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const useLikeStatus = (playlistId: number, options?: { enabled?: boolean
1818
interface UseLikeOptions {
1919
shouldNavigate?: boolean
2020
getNextId?: () => number | undefined
21+
openLoginModal?: () => void
2122
}
2223

2324
const useLike = (playlistId: number, options?: UseLikeOptions) => {
@@ -89,7 +90,7 @@ const useLike = (playlistId: number, options?: UseLikeOptions) => {
8990

9091
const toggleLike = () => {
9192
if (!isLogin) {
92-
navigate('/login')
93+
options?.openLoginModal?.()
9394
return
9495
}
9596

β€Žsrc/features/like/ui/LikeButton.tsxβ€Ž

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React from 'react'
1+
import React, { useState } from 'react'
2+
import { useNavigate } from 'react-router-dom'
23

34
import styled, { useTheme } from 'styled-components'
45

@@ -7,6 +8,7 @@ import type { CdMetaResponse } from '@/entities/playlist'
78
import { useLike } from '@/features/like'
89
import { getNextId } from '@/shared/lib'
910
import { myCdButton } from '@/shared/styles/mixins'
11+
import { Modal } from '@/shared/ui'
1012
import SvgButton from '@/shared/ui/SvgButton'
1113

1214
interface LikeButtonProps {
@@ -23,13 +25,16 @@ const ICON_STYLE = {
2325
} as const
2426

2527
const LikeButton = ({ playlistId, type = 'HOME', playlistData, activeIndex }: LikeButtonProps) => {
28+
const [isModalOpen, setIsModalOpen] = useState(false)
2629
const theme = useTheme()
30+
const navigate = useNavigate()
2731
const { liked, toggleLike } = useLike(playlistId, {
2832
shouldNavigate: type === 'MY',
2933
getNextId: () => {
3034
if (!playlistData || activeIndex === undefined) return undefined
3135
return getNextId(activeIndex, playlistData)
3236
},
37+
openLoginModal: () => setIsModalOpen(true),
3338
})
3439

3540
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
@@ -41,25 +46,45 @@ const LikeButton = ({ playlistId, type = 'HOME', playlistData, activeIndex }: Li
4146
const opacity = type === 'HOME' ? (liked ? 1 : 0.2) : 1
4247

4348
return (
44-
<Wrapper $opacity={opacity} $isMy={type === 'MY'}>
45-
<SvgButton
46-
icon={Icon}
47-
onClick={handleClick}
48-
width={size}
49-
height={size}
50-
fill={
51-
type === 'HOME'
52-
? liked
53-
? theme.COLOR['primary-normal']
54-
: theme.COLOR['gray-200']
55-
: liked
56-
? theme.COLOR['primary-normal']
57-
: 'none'
58-
}
59-
stroke={liked ? theme.COLOR['primary-normal'] : theme.COLOR['gray-200']}
60-
/>
61-
{type === 'MY' && <p>μ’‹μ•„μš”</p>}
62-
</Wrapper>
49+
<>
50+
<Wrapper $opacity={opacity} $isMy={type === 'MY'}>
51+
<SvgButton
52+
icon={Icon}
53+
onClick={handleClick}
54+
width={size}
55+
height={size}
56+
fill={
57+
type === 'HOME'
58+
? liked
59+
? theme.COLOR['primary-normal']
60+
: theme.COLOR['gray-200']
61+
: liked
62+
? theme.COLOR['primary-normal']
63+
: 'none'
64+
}
65+
stroke={liked ? theme.COLOR['primary-normal'] : theme.COLOR['gray-200']}
66+
/>
67+
{type === 'MY' && <p>μ’‹μ•„μš”</p>}
68+
</Wrapper>
69+
70+
{isModalOpen && (
71+
<Modal
72+
isOpen={isModalOpen}
73+
title="둜그인 ν›„ μ΄μš©ν•  수 μžˆμ–΄μš”"
74+
ctaType="double"
75+
onConfirm={() => {
76+
navigate('/login')
77+
setIsModalOpen(false)
78+
}}
79+
onCancel={() => {
80+
setIsModalOpen(false)
81+
}}
82+
onClose={() => setIsModalOpen(false)}
83+
confirmText="λ‘œκ·ΈμΈν•˜κΈ°"
84+
cancelText="λ‹€μŒμ— ν•˜κΈ°"
85+
/>
86+
)}
87+
</>
6388
)
6489
}
6590

β€Žsrc/pages/curation/CurationLayout.tsxβ€Ž

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useMemo } from 'react'
2-
import { Outlet, useLocation, useNavigate, useParams } from 'react-router-dom'
2+
import { Outlet, useLocation, useMatch, useNavigate, useParams } from 'react-router-dom'
33

44
import { LeftArrow } from '@/assets/icons'
55
import { useBundlePlaylist } from '@/entities/bundle'
@@ -12,6 +12,8 @@ const CurationLayout = () => {
1212
const location = useLocation()
1313
const { bundleId, id: playlistId } = useParams()
1414

15+
const isTracklistPage = useMatch('/curation/:bundleId/play/:id/tracklist')
16+
1517
const sectionTitle = useMemo(() => {
1618
return location.state?.sectionTitle || getRandomItem(HOME_SECTION_TITLES.TIME)
1719
}, [location.state?.sectionTitle])
@@ -26,15 +28,17 @@ const CurationLayout = () => {
2628

2729
return (
2830
<div>
29-
<Header
30-
left={
31-
<SvgButton
32-
icon={LeftArrow}
33-
onClick={() => navigate(playlistId ? `/curation/${bundleId}` : '/')}
34-
/>
35-
}
36-
center={<span>{playlistId ? data?.title : sectionTitle}</span>}
37-
/>
31+
{!isTracklistPage && (
32+
<Header
33+
left={
34+
<SvgButton
35+
icon={LeftArrow}
36+
onClick={() => navigate(playlistId ? `/curation/${bundleId}` : '/')}
37+
/>
38+
}
39+
center={<span>{playlistId ? data?.title : sectionTitle}</span>}
40+
/>
41+
)}
3842

3943
<Outlet context={data} />
4044
</div>

β€Žsrc/pages/curation/index.tsxβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ const TotalCount = styled.p`
128128
`
129129

130130
const ContentSection = styled.section`
131-
padding: 24px 0 0 0;
131+
padding: 24px 0 60px 0;
132132
`
133133

134134
const PlaylistItems = styled.div`

β€Žsrc/pages/curation/play/index.tsxβ€Ž

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ import { useNavigate, useOutletContext, useParams } from 'react-router-dom'
33

44
import type { BundleInfo } from '@/entities/bundle'
55
import { usePlaylistDetail, usePlaylistDetails } from '@/entities/playlist'
6-
import { CurationCarousel } from '@/pages/curation/ui'
6+
import { PlaylistCarousel } from '@/widgets/playlist'
77

88
const CurationPlayer = () => {
99
const bundle = useOutletContext<BundleInfo>()
10+
1011
const navigate = useNavigate()
1112
const { id: routePlaylistId } = useParams()
1213

1314
const ids = useMemo(() => bundle.playlists.map((p) => p.playlistId), [bundle])
1415
const { data: playlistData } = usePlaylistDetails(ids)
1516

16-
const routeId = routePlaylistId ? Number(routePlaylistId) : null
17+
const routeId = Number(routePlaylistId)
1718

1819
useEffect(() => {
1920
if (!playlistData || routeId) return
@@ -40,10 +41,11 @@ const CurationPlayer = () => {
4041
if (!playlistDetail || !playlistData) return null
4142

4243
return (
43-
<CurationCarousel
44+
<PlaylistCarousel
4445
playlistData={playlistData}
4546
playlistDetail={playlistDetail}
4647
onCenterChange={handleCenterChange}
48+
basePath={`/curation/${bundle.bundleId}/play`}
4749
/>
4850
)
4951
}

0 commit comments

Comments
Β (0)