diff --git a/src/components/playlist/Playlists.tsx b/src/components/playlist/Playlists.tsx index 51f7b80..73ebce4 100644 --- a/src/components/playlist/Playlists.tsx +++ b/src/components/playlist/Playlists.tsx @@ -9,11 +9,12 @@ import theme from '@/styles/theme'; import { PlaylistModel } from '@/types/playlist'; interface PlaylistListProps { - playlists: PlaylistModel[]; + playlists: (PlaylistModel & { containsVideo?: boolean })[]; customStyle?: SerializedStyles; customVideoStyle?: SerializedStyles; isColumn?: boolean; - onPlaylistClick?: (playlistId: string, title: string) => void; + onPlaylistClick?: (playlistId: string, title: string, containsVideo: boolean) => void; + disabledPlaylists?: boolean; } const Playlists: React.FC = ({ @@ -22,6 +23,7 @@ const Playlists: React.FC = ({ customVideoStyle, onPlaylistClick, isColumn = true, + disabledPlaylists = false, }) => { const currentUser = useAuth(); @@ -31,12 +33,19 @@ const Playlists: React.FC = ({ {playlists.length > 0 && playlists .filter(({ isPublic, userId }) => isPublic || userId === currentUser?.uid) - .map(({ playlistId, title, videos, isPublic }) => ( + .map(({ playlistId, title, videos, isPublic, containsVideo }) => (
(onPlaylistClick ? onPlaylistClick(playlistId, title) : null)} + css={[ + itemStyle(isColumn), + disabledPlaylists && containsVideo && disabledPlaylistStyle, + ]} + onClick={() => + onPlaylistClick && !containsVideo + ? onPlaylistClick(playlistId, title, !!containsVideo) + : null + } > css` } `; +const disabledPlaylistStyle = css` + opacity: 0.5; + pointer-events: none; +`; + export default Playlists; diff --git a/src/pages/SelectPli.tsx b/src/pages/SelectPli.tsx index 34bf963..da5f3ce 100644 --- a/src/pages/SelectPli.tsx +++ b/src/pages/SelectPli.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import { css } from '@emotion/react'; import { HiOutlineBookmark, HiOutlinePlay } from 'react-icons/hi2'; @@ -21,6 +21,7 @@ import { useAddVideosToMyPlaylist } from '@/hooks/useVideoToPlaylist'; import SelectVideoPage from '@/pages/SelectVideo'; import { useToastStore } from '@/stores/toastStore'; import theme from '@/styles/theme'; +import { PlaylistModel, VideoModel } from '@/types/playlist'; import { makeVideoObj } from '@/utils/video'; const tabs = [ @@ -59,12 +60,24 @@ const SelectPliPage: React.FC = ({ close: closeSelectVideoModal, } = useModalWithOverlay('selectVideoModal', 'selectPli'); + const isVideoInPlaylist = useMemo(() => { + return (playlist: PlaylistModel) => + playlist.videos.some((video: VideoModel) => video.videoId === videoObj.videoId); + }, [videoObj.videoId]); + + const filteredPlaylists = useMemo(() => { + return (myPlaylists || []).map((playlist) => ({ + ...playlist, + containsVideo: isVideoInPlaylist(playlist), + })); + }, [myPlaylists, isVideoInPlaylist]); + const handleAddPlaylist = (title: string, isPublic: boolean) => { addPlaylistMutation.mutate({ title, isPublic }); addToast('새로운 플리를 추가했습니다.'); }; - const handlePlaylistClick = (playlistId: string, title: string) => { + const handlePlaylistClick = (playlistId: string, title: string, containsVideo: boolean) => { if (type === 'fromPli') { setSelectedPlaylistId(playlistId); openSelectVideoModal(); @@ -72,7 +85,7 @@ const SelectPliPage: React.FC = ({ if (onSelectPlaylist) { onSelectPlaylist(playlistId, title); } - } else if (videoId) { + } else if (videoId && !containsVideo) { addVideoToPlaylistMutation.mutate( { playlistId, videos: [videoObj] }, { @@ -85,7 +98,7 @@ const SelectPliPage: React.FC = ({ }, }, ); - } else { + } else if (!containsVideo) { navigate(`${PATH.PLAYLIST}/${playlistId}`); } }; @@ -112,8 +125,6 @@ const SelectPliPage: React.FC = ({ return

{error.message}

; } - const filteredPlaylists = myPlaylists?.filter((playlist) => playlist.videos.length > 0) || []; - return ( <>
@@ -139,22 +150,28 @@ const SelectPliPage: React.FC = ({ onAddPlaylist={handleAddPlaylist} /> + handlePlaylistClick(id, title, containsVideo) + } isColumn={false} + disabledPlaylists={!type && videoId ? true : false} /> ) : ( playlist.videos.length > 0)} customStyle={playlistStyle} customVideoStyle={videoStyle} - onPlaylistClick={handlePlaylistClick} + onPlaylistClick={(id, title, containsVideo) => + handlePlaylistClick(id, title, containsVideo) + } isColumn={false} + disabledPlaylists={false} /> @@ -162,8 +179,9 @@ const SelectPliPage: React.FC = ({ playlists={subscribedPlaylists || []} customStyle={playlistStyle} customVideoStyle={videoStyle} - onPlaylistClick={handlePlaylistClick} + onPlaylistClick={(id, title) => handlePlaylistClick(id, title, false)} isColumn={false} + disabledPlaylists={false} /> @@ -214,6 +232,11 @@ const playlistStyle = css` margin-left: 12px; } } + + .disabled-playlist { + opacity: 0.5; + pointer-events: none; + } `; const videoStyle = css`