diff --git a/frontend/src/features/killingParts/components/RegisterPart.tsx b/frontend/src/features/killingParts/components/RegisterPart.tsx
index bda70175..e341ac99 100644
--- a/frontend/src/features/killingParts/components/RegisterPart.tsx
+++ b/frontend/src/features/killingParts/components/RegisterPart.tsx
@@ -3,61 +3,48 @@ import styled from 'styled-components';
import { useAuthContext } from '@/features/auth/components/AuthProvider';
import useCollectingPartContext from '@/features/killingParts/hooks/useCollectingPartContext';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
-import useModal from '@/shared/components/Modal/hooks/useModal';
-import Modal from '@/shared/components/Modal/Modal';
+import { useConfirmContext } from '@/shared/components/ConfirmModal/hooks/useConfirmContext';
import Spacing from '@/shared/components/Spacing';
import { useMutation } from '@/shared/hooks/useMutation';
import { toPlayingTimeText } from '@/shared/utils/convertTime';
import { postKillingPart } from '../remotes/killingPart';
const RegisterPart = () => {
- const { isOpen, openModal, closeModal } = useModal();
+ const navigate = useNavigate();
const { user } = useAuthContext();
const { interval, partStartTime, songId } = useCollectingPartContext();
const video = useVideoPlayerContext();
+ const { confirmPopup } = useConfirmContext();
+ const { createKillingPart } = usePostKillingPart();
+ const voteTimeText = toPlayingTimeText(partStartTime, partStartTime + interval);
const { mutateData: createKillingPart } = useMutation(postKillingPart);
const navigate = useNavigate();
// 현재 useMutation 훅이 response 객체를 리턴하지 않고 내부적으로 처리합니다.
// 때문에 컴포넌트 단에서 createKillingPart 성공 여부에 따라 등록 완료 만료를 처리를 할 수 없어요!
- // 현재 비로그인 시에 등록을 누르면 두 개의 모달이 뜹니다.정
- const submitKillingPart = async () => {
- await createKillingPart(songId, { startSecond: partStartTime, length: interval });
- navigate(-1);
- };
-
- const openRegisterModal = () => {
+ // 현재 비로그인 시에 등록을 누르면 두 개의 모달이 뜹니다.
+ const handleClickRegisterPart = async () => {
video.pause();
- openModal();
- };
-
- const voteTimeText = toPlayingTimeText(partStartTime, partStartTime + interval);
- return (
- <>
- 등록
-
-
- {user?.nickname}님의 파트 저장
-
-
-
- {voteTimeText}
-
-
+ const isConfirmed = await confirmPopup({
+ title: `${user?.nickname}님의 파트 저장`,
+ content: (
+
+
+ {voteTimeText}
+
나만의 파트로 등록하시겠습니까?
-
-
-
- 취소
-
-
- 등록
-
-
-
- >
- );
+
+ ),
+ });
+
+ if (isConfirmed) {
+ await createKillingPart(songId, { startSecond: partStartTime, length: interval });
+ navigate(-1);
+ }
+ };
+
+ return 등록;
};
export default RegisterPart;
@@ -80,45 +67,8 @@ const RegisterButton = styled.button`
}
`;
-const ModalTitle = styled.h3``;
-
-const TitleColumn = styled.div`
- text-align: center;
-`;
-
-const ModalContent = styled.div`
- padding: 16px 0;
-
- font-size: 16px;
- color: #b5b3bc;
- text-align: center;
- white-space: pre-line;
-`;
-
const Message = styled.div``;
-const Button = styled.button`
- height: 36px;
- color: ${({ theme: { color } }) => color.white};
- border-radius: 10px;
-`;
-
-const Cancel = styled(Button)`
- flex: 1;
- background-color: ${({ theme: { color } }) => color.secondary};
-`;
-
-const Confirm = styled(Button)`
- flex: 1;
- background-color: ${({ theme: { color } }) => color.primary};
-`;
-
-const ButtonContainer = styled.div`
- display: flex;
- gap: 16px;
- width: 100%;
-`;
-
const Part = styled.span`
padding: 6px 11px;
@@ -128,3 +78,9 @@ const Part = styled.span`
background-color: ${({ theme: { color } }) => color.disabled};
border-radius: 10px;
`;
+
+const ContentContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+`;
diff --git a/frontend/src/features/member/components/WithdrawalModal.tsx b/frontend/src/features/member/components/WithdrawalModal.tsx
deleted file mode 100644
index 8712d36c..00000000
--- a/frontend/src/features/member/components/WithdrawalModal.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import styled from 'styled-components';
-import WITHDRAWAL_MESSAGE from '@/features/member/constants/withdrawalMessage';
-import Modal from '@/shared/components/Modal/Modal';
-import Spacing from '@/shared/components/Spacing';
-
-interface WithdrawalModalProps {
- isOpen: boolean;
- closeModal: () => void;
- onWithdraw: () => void;
-}
-
-const WithdrawalModal = ({ isOpen, closeModal, onWithdraw }: WithdrawalModalProps) => {
- return (
-
- <>
- {WITHDRAWAL_MESSAGE}
-
-
-
- 회원 탈퇴
-
-
- 닫기
-
-
- >
-
- );
-};
-
-export default WithdrawalModal;
-
-const ModalContent = styled.div`
- align-self: start;
-
- font-size: 16px;
- line-height: 200%;
- color: ${({ theme }) => theme.color.subText};
- white-space: pre-line;
-`;
-
-const Button = styled.button`
- cursor: pointer;
-
- height: 36px;
-
- color: ${({ theme: { color } }) => color.white};
-
- border: none;
- border-radius: 10px;
-`;
-
-const ConfirmButton = styled(Button)`
- flex: 1;
- background-color: ${({ theme: { color } }) => color.secondary};
-`;
-
-const CancelButton = styled(Button)`
- flex: 1.5;
- background-color: ${({ theme: { color } }) => color.primary};
-`;
-
-const ButtonContainer = styled.div`
- display: flex;
- gap: 16px;
- width: 100%;
-`;
diff --git a/frontend/src/features/member/constants/withdrawalMessage.ts b/frontend/src/features/member/constants/withdrawalMessage.ts
index 9652ddd8..fb1945d9 100644
--- a/frontend/src/features/member/constants/withdrawalMessage.ts
+++ b/frontend/src/features/member/constants/withdrawalMessage.ts
@@ -1,3 +1,3 @@
-const WITHDRAWAL_MESSAGE = '회원 탈퇴시 활동한 모든 이력이 삭제됩니다.\n정말 회원 탈퇴하겠습니까?';
+const WITHDRAWAL_MESSAGE = '회원 탈퇴시 모든 이력이 삭제됩니다.\n정말 회원 탈퇴하겠습니까?';
export default WITHDRAWAL_MESSAGE;
diff --git a/frontend/src/features/songs/components/KillingPartTrack.tsx b/frontend/src/features/songs/components/KillingPartTrack.tsx
index 6c412c9e..a1b79a5d 100644
--- a/frontend/src/features/songs/components/KillingPartTrack.tsx
+++ b/frontend/src/features/songs/components/KillingPartTrack.tsx
@@ -8,6 +8,7 @@ import { useAuthContext } from '@/features/auth/components/AuthProvider';
import LoginModal from '@/features/auth/components/LoginModal';
import { deleteMemberParts } from '@/features/member/remotes/memberParts';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
+import { useConfirmContext } from '@/shared/components/ConfirmModal/hooks/useConfirmContext';
import useModal from '@/shared/components/Modal/hooks/useModal';
import useTimerContext from '@/shared/components/Timer/hooks/useTimerContext';
import useToastContext from '@/shared/components/Toast/hooks/useToastContext';
@@ -18,7 +19,6 @@ import { toPlayingTimeText } from '@/shared/utils/convertTime';
import copyClipboard from '@/shared/utils/copyClipBoard';
import formatOrdinals from '@/shared/utils/formatOrdinals';
import useKillingPartLikes from '../hooks/useKillingPartLikes';
-import MyPartModal from './MyPartModal';
import type { KillingPart } from '@/shared/types/song';
import type React from 'react';
@@ -45,6 +45,7 @@ const KillingPartTrack = ({
}: KillingPartTrackProps) => {
const { showToast } = useToastContext();
const { seekTo, pause, playerState, videoPlayer } = useVideoPlayerContext();
+ const { confirmPopup } = useConfirmContext();
const { heartIcon, toggleKillingPartLikes } = useKillingPartLikes({
likeCount,
likeStatus,
@@ -57,11 +58,6 @@ const KillingPartTrack = ({
closeModal: closeLoginModal,
openModal: openLoginModal,
} = useModal();
- const {
- isOpen: isMyPartModal,
- closeModal: closeMyPartModal,
- openModal: openMyPartModal,
- } = useModal();
const { user } = useAuthContext();
const isLoggedIn = user !== null;
@@ -148,15 +144,22 @@ const KillingPartTrack = ({
const { mutateData: deleteMemberPart } = useMutation(() => deleteMemberParts(partId));
- const deleteMyPart = async () => {
- if (!hideMyPart) return;
+ const handleClickDeletePart = async () => {
+ const isConfirmed = await confirmPopup({
+ title: '내 파트 삭제',
+ content:
정말 삭제하시겠습니까?
,
+ confirmation: '삭제',
+ denial: '취소',
+ });
- await deleteMemberPart();
+ if (isConfirmed) {
+ if (!hideMyPart) return;
- hideMyPart();
- pause();
- closeMyPartModal();
- showToast('내 파트가 삭제되었습니다.');
+ await deleteMemberPart();
+ hideMyPart();
+ pause();
+ showToast('내 파트가 삭제되었습니다.');
+ }
};
return (
@@ -185,7 +188,7 @@ const KillingPartTrack = ({
<>
@@ -211,12 +214,11 @@ const KillingPartTrack = ({
>
)}
+
{isNowPlayingTrack && (
)}
-
-
void;
- onDelete: () => void;
-}
-
-const MyPartModal = ({ isOpen, closeModal, onDelete }: MyPartModalProps) => {
- return (
-
- 정말 삭제하시겠습니까?
-
-
-
- 취소
-
-
- 삭제
-
-
-
- );
-};
-
-const ModalTitle = styled.h3``;
-
-const Button = styled.button`
- cursor: pointer;
-
- height: 36px;
-
- color: ${({ theme: { color } }) => color.white};
-
- border: none;
- border-radius: 10px;
-`;
-
-const CancelButton = styled(Button)`
- flex: 1;
- background-color: ${({ theme: { color } }) => color.secondary};
-`;
-
-const DeleteButton = styled(Button)`
- flex: 1;
- background-color: ${({ theme: { color } }) => color.primary};
-`;
-
-const ButtonContainer = styled.div`
- display: flex;
- gap: 16px;
- width: 100%;
-`;
-
-export default MyPartModal;
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index 9bbea1b7..01b97e8f 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -4,6 +4,7 @@ import React from 'react';
import { createRoot } from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
+import ConfirmModalProvider from '@/shared/components/ConfirmModal/ConfirmModalProvider';
import GlobalStyles from '@/shared/styles/GlobalStyles';
import AuthProvider from './features/auth/components/AuthProvider';
import { loadIFrameApi } from './features/youtube/remotes/loadIframeApi';
@@ -34,12 +35,14 @@ async function main() {
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/frontend/src/pages/EditProfilePage.tsx b/frontend/src/pages/EditProfilePage.tsx
index 3f5500d8..8a125356 100644
--- a/frontend/src/pages/EditProfilePage.tsx
+++ b/frontend/src/pages/EditProfilePage.tsx
@@ -2,16 +2,17 @@ import { useNavigate } from 'react-router-dom';
import styled, { css } from 'styled-components';
import shookshook from '@/assets/icon/shookshook.svg';
import { useAuthContext } from '@/features/auth/components/AuthProvider';
-import WithdrawalModal from '@/features/member/components/WithdrawalModal';
+import WITHDRAWAL_MESSAGE from '@/features/member/constants/withdrawalMessage';
import { deleteMember } from '@/features/member/remotes/member';
-import useModal from '@/shared/components/Modal/hooks/useModal';
+import { useConfirmContext } from '@/shared/components/ConfirmModal/hooks/useConfirmContext';
import Spacing from '@/shared/components/Spacing';
import ROUTE_PATH from '@/shared/constants/path';
import { useMutation } from '@/shared/hooks/useMutation';
const EditProfilePage = () => {
const { user, logout } = useAuthContext();
- const { isOpen, openModal, closeModal } = useModal();
+ const { confirmPopup } = useConfirmContext();
+ const { mutateData: withdrawMember } = useMutation(deleteMember(user?.memberId));
const { mutateData: withdrawal } = useMutation(deleteMember);
const navigate = useNavigate();
@@ -20,10 +21,19 @@ const EditProfilePage = () => {
return null;
}
- const handleWithdrawal = async () => {
- await withdrawal(user.memberId);
- logout();
- navigate(ROUTE_PATH.ROOT);
+ const handleClickWithdrawal = async () => {
+ const isConfirmed = await confirmPopup({
+ title: '회원 탈퇴',
+ content: {WITHDRAWAL_MESSAGE},
+ confirmation: '탈퇴',
+ denial: '닫기',
+ });
+
+ if (isConfirmed) {
+ await withdrawMember();
+ logout();
+ navigate(ROUTE_PATH.ROOT, { replace: true });
+ }
};
return (
@@ -39,9 +49,8 @@ const EditProfilePage = () => {
- 회원 탈퇴
+ 회원 탈퇴
제출
-
);
};
@@ -126,3 +135,12 @@ const SubmitButton = styled.button<{ disabled: boolean }>`
border: none;
border-radius: 10px;
`;
+
+const ModalContent = styled.div`
+ align-self: start;
+
+ font-size: 16px;
+ line-height: 200%;
+ color: ${({ theme }) => theme.color.subText};
+ white-space: pre-line;
+`;
diff --git a/frontend/src/shared/components/ConfirmModal/ConfirmModal.tsx b/frontend/src/shared/components/ConfirmModal/ConfirmModal.tsx
index d8920af3..0db6f83e 100644
--- a/frontend/src/shared/components/ConfirmModal/ConfirmModal.tsx
+++ b/frontend/src/shared/components/ConfirmModal/ConfirmModal.tsx
@@ -70,7 +70,7 @@ const Container = styled.section`
left: 50%;
transform: translate(-50%, -50%);
- min-width: 300px;
+ min-width: 320px;
margin: 0 auto;
padding: 24px;