diff --git a/FE/src/GlobalSvgProvider.tsx b/FE/src/GlobalSvgProvider.tsx index 230a824..c18551c 100644 --- a/FE/src/GlobalSvgProvider.tsx +++ b/FE/src/GlobalSvgProvider.tsx @@ -190,6 +190,16 @@ const spliteSvgCode = ( fill="#9299A1" /> + + + + ); diff --git a/FE/src/components/foundation/CardCover/CardCover.tsx b/FE/src/components/foundation/CardCover/CardCover.tsx index 97a0ab1..2daa5e4 100644 --- a/FE/src/components/foundation/CardCover/CardCover.tsx +++ b/FE/src/components/foundation/CardCover/CardCover.tsx @@ -1,11 +1,16 @@ import { css } from '@emotion/react'; +import { HTMLElementTypes } from '@/types/utils'; type CardCoverProps = { children: React.ReactNode; borderRadius: string; -}; +} & HTMLElementTypes; -const CardCover: React.FC = ({ children, borderRadius }) => { +const CardCover: React.FC = ({ + children, + borderRadius, + ...args +}) => { return (
= ({ children, borderRadius }) => { left: 0; right: 0; bottom: 0; - background-color: rgba(0, 0, 0, 0.2); + background-color: rgba(0, 0, 0, 0.3); border-radius: ${borderRadius}; z-index: 1; } `} + {...args} > {children}
diff --git a/FE/src/components/myPage/DeleteCheckModal.tsx b/FE/src/components/myPage/DeleteCheckModal.tsx new file mode 100644 index 0000000..e0e825d --- /dev/null +++ b/FE/src/components/myPage/DeleteCheckModal.tsx @@ -0,0 +1,41 @@ +import Modal from '@foundation/Modal'; +import React from 'react'; +import Typography from '@foundation/Typography/Typography'; +import Button from '@foundation/Button/Button'; +import LightButton from '@common/LightButton/LightButton'; +import { css } from '@emotion/react'; + +type DeleteCheckModalProps = { + isOpen: boolean; + content: string; + closeModal: () => void; + confirmModal: () => void; +}; +const DeleteCheckModal: React.FC = ({ + isOpen, + content, + closeModal, + confirmModal, +}) => { + return ( + + + {content} + + +
+ 취소 + +
+
+
+ ); +}; + +export default DeleteCheckModal; diff --git a/FE/src/components/myPage/TabPanel/VideoListTabPanel.tsx b/FE/src/components/myPage/TabPanel/VideoListTabPanel.tsx index 832cd72..3ac6e86 100644 --- a/FE/src/components/myPage/TabPanel/VideoListTabPanel.tsx +++ b/FE/src/components/myPage/TabPanel/VideoListTabPanel.tsx @@ -3,13 +3,28 @@ import Box from '@foundation/Box/Box'; import { css } from '@emotion/react'; import VideoItem from '@components/myPage/VideoItem/VideoItem'; import Thumbnail from '@components/myPage/Thumbnail'; -import CardCover from '@foundation/CardCover/CardCover'; import useVideoListQuery from '@hooks/queries/video/useVideoListQuery'; import { PATH } from '@constants/path'; import { theme } from '@styles/theme'; +import useDeleteVideoMutation from '@hooks/mutations/video/useDeleteVideoMutation'; +import DeleteCheckModal from '@components/myPage/DeleteCheckModal'; +import { useState } from 'react'; const VideoListTabPanel: React.FC = () => { const { data } = useVideoListQuery(); + const { mutate } = useDeleteVideoMutation(); + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [selectedVideoId, setSelectVideoId] = useState(null); + + const handleDeleteIconClick = (videoId: number) => { + setIsDeleteModalOpen(true); + setSelectVideoId(videoId); + }; + + const handleConfirmModal = () => { + selectedVideoId && mutate(selectedVideoId); + setIsDeleteModalOpen(false); + }; if (!data) return
로딩중
; @@ -34,15 +49,20 @@ const VideoListTabPanel: React.FC = () => { date={dayjs(Number(video.createdAt)).format('YYYY-MM-DD')} path={`${PATH.INTERVIEW_VIDEO(video.id)}`} > - - - + handleDeleteIconClick(video.id)} + /> ))} + setIsDeleteModalOpen(false)} + confirmModal={handleConfirmModal} + /> ); }; diff --git a/FE/src/components/myPage/Thumbnail.tsx b/FE/src/components/myPage/Thumbnail.tsx index 7afdb9e..cb54bfc 100644 --- a/FE/src/components/myPage/Thumbnail.tsx +++ b/FE/src/components/myPage/Thumbnail.tsx @@ -1,49 +1,84 @@ import { theme } from '@styles/theme'; import { css } from '@emotion/react'; +import Icon from '@foundation/Icon/Icon'; +import React, { MouseEventHandler } from 'react'; +import CardCover from '@foundation/CardCover/CardCover'; type ThumbnailProps = { image: string; videoLength: string; videoName: string; + onDeleteIconClick: () => void; }; const Thumbnail: React.FC = ({ videoName, videoLength, image, + onDeleteIconClick, }) => { + const handleDeleteIconClick: MouseEventHandler = (e) => { + e.preventDefault(); //상위 요소의 Link 이벤트를 막기 위해 + onDeleteIconClick(); + }; return ( -
- {videoName} -
+ > +
+ +
+ {videoName} + + ); }; diff --git a/FE/src/hooks/mutations/video/useDeleteVideoMutation.ts b/FE/src/hooks/mutations/video/useDeleteVideoMutation.ts index e8177ec..6f69e16 100644 --- a/FE/src/hooks/mutations/video/useDeleteVideoMutation.ts +++ b/FE/src/hooks/mutations/video/useDeleteVideoMutation.ts @@ -2,10 +2,10 @@ import { QUERY_KEY } from '@/constants/queryKey'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { deleteVideoById } from '@/apis/video'; -const useDeleteVideoMutation = (videoId: number) => { +const useDeleteVideoMutation = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: () => deleteVideoById(videoId), + mutationFn: deleteVideoById, onSuccess: () => { void queryClient.invalidateQueries({ queryKey: QUERY_KEY.VIDEO, diff --git a/FE/src/mocks/handlers/video.ts b/FE/src/mocks/handlers/video.ts index 739f1b5..db04c38 100644 --- a/FE/src/mocks/handlers/video.ts +++ b/FE/src/mocks/handlers/video.ts @@ -77,8 +77,8 @@ const videoHandlers = [ await delay(1000); return HttpResponse.json(null, { status: 200 }); }), - http.delete(API.VIDEO_ID(), ({ request }) => { - return HttpResponse.json(null, { status: 204 }); + http.delete(API.VIDEO_ID(), () => { + return new HttpResponse(null, { status: 204 }); }), ];