From b7aaf7b4d4c8622051d21217850ee04dea53c702 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 18 Sep 2024 18:10:54 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=8B=A4=EB=A6=84=20=EC=82=AC=EB=9E=8C?= =?UTF-8?q?=EC=9D=98=20=ED=94=8C=EB=A6=AC=EC=97=90=EC=84=9C=20=EB=B9=84?= =?UTF-8?q?=EB=94=94=EC=98=A4=EB=A5=BC=20=EB=82=B4=20=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=97=90=20=EC=B6=94=EA=B0=80=ED=95=A0=EB=95=8C=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EB=90=9C=20=EB=B9=84=EB=94=94=EC=98=A4=EA=B0=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#177)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/playlist/Playlists.tsx | 24 +++++++++++--- src/pages/SelectPli.tsx | 45 ++++++++++++++++++++------- 2 files changed, 53 insertions(+), 16 deletions(-) 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`