Skip to content

Commit 74edda5

Browse files
authored
feat: 모달 닫기 기능 추가 된 구조로 변경 (#33)
* refactor: 변수명 변경 * feat: 뒤로가기 버튼 위치 조정 * feat: 모달 구조 변경 * refactor: 불필요한 조건 삭제 * refactor: prop이름 변경 * refactor: 변수명 변경, 함수명 변경 - close #32 * refactor: 모달 여백 조정 * refactor: 공통 모달 구조에 버튼 추가 * fix: 에러 모달 확인 시 다시 step1으로 가는 문제 수정
1 parent 1c3bac4 commit 74edda5

File tree

8 files changed

+106
-67
lines changed

8 files changed

+106
-67
lines changed

src/features/videoEditor/hooks/useVideoEditor.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const useVideoEditor = () => {
55
const [duration, setDuration] = useState(0);
66
const [playing, setPlaying] = useState(false);
77
const [error, setError] = useState(null);
8-
const [isDoneEdit, setIsDoneEdit] = useState(false);
8+
const [isModalOpen, setIsModalOpen] = useState(false);
99
const playerRef = useRef(null);
1010

1111
const handleDuration = (videoDuration) => {
@@ -67,7 +67,7 @@ const useVideoEditor = () => {
6767
throw new Error("영상 편집점을 다시 확인해주세요!");
6868
}
6969

70-
setIsDoneEdit(true);
70+
setIsModalOpen(true);
7171
} catch (err) {
7272
setError(err.message || "편집 요청 실패");
7373
}
@@ -79,9 +79,9 @@ const useVideoEditor = () => {
7979
playing,
8080
playerRef,
8181
error,
82-
isDoneEdit,
82+
isModalOpen,
83+
setIsModalOpen,
8384
setError,
84-
setIsDoneEdit,
8585
handlePlay,
8686
handlePause,
8787
handleDuration,

src/features/videoSubmit/components/EmailInputForm.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ const EmailInputForm = ({ email, onEmailChange, goToPreviousStep }) => {
99
<GrFormPreviousLink
1010
size="27"
1111
onClick={goToPreviousStep}
12-
className="cursor-pointer"
12+
className="cursor-pointer absolute top-2 left-2"
1313
/>
14-
<div className="text-2xl mb-8 mt-4 font-mediumm">
14+
<div className="text-2xl mb-6 mt-6 font-mediumm">
1515
결과를 받을 이메일을 입력하세요
1616
</div>
17-
<div className="flex mb-8 text-[#515151]">
17+
<div className="flex mb-6 text-[#515151]">
1818
<Input
1919
type="email"
2020
value={email}

src/features/videoSubmit/components/SubmitResultModal.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import PropTypes from "prop-types";
22

33
import Modal from "@/shared/components/Modal";
44

5-
const SubmitResultModal = ({ onClick }) => {
5+
const SubmitResultModal = ({ onClose, onClick }) => {
66
return (
7-
<Modal onClick={onClick} buttonText="확인">
7+
<Modal onClose={onClose} onClick={onClick}>
88
<div className="text-xl mb-4 font-mediumm">제출이 완료되었습니다</div>
99
<p className="text-[#515151] mb-4">
1010
분석이 끝나면 이메일로 결과를 보내드릴게요
@@ -14,6 +14,7 @@ const SubmitResultModal = ({ onClick }) => {
1414
};
1515

1616
SubmitResultModal.propTypes = {
17+
onClose: PropTypes.func.isRequired,
1718
onClick: PropTypes.func.isRequired,
1819
};
1920

src/features/videoSubmit/components/VideoSubmitModal.jsx

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,24 @@ import axios from "axios";
44
import PropTypes from "prop-types";
55
import { useNavigate } from "react-router-dom";
66

7-
import ErrorModal from "@/shared/components/ErrorModal";
87
import LoadingModal from "@/shared/components/LoadingModal";
98
import Modal from "@/shared/components/Modal";
109

1110
import CharacterSelectFrom from "./CharacterSelectForm";
1211
import EmailInputForm from "./EmailInputForm";
1312
import SubmitResultModal from "./SubmitResultModal";
1413

15-
const VideoSubmitModal = ({ videoId, trim }) => {
16-
const [step, setStep] = useState(1);
14+
const VideoSubmitModal = ({
15+
videoId,
16+
trim,
17+
closeModal,
18+
setError,
19+
step,
20+
setStep,
21+
}) => {
1722
const [selectedCharacter, setSelectedCharacter] = useState(null);
1823
const [email, setEmail] = useState("");
1924
const [isSubmitSuccess, setIsSubmitSuccess] = useState(false);
20-
const [error, setError] = useState(null);
2125
const [isLoading, setIsLoading] = useState(false);
2226
const navigate = useNavigate();
2327

@@ -73,43 +77,44 @@ const VideoSubmitModal = ({ videoId, trim }) => {
7377
setStep(1);
7478
};
7579

76-
const closeModal = () => {
77-
setError(null);
78-
};
79-
8080
return (
81-
<>
82-
{!isSubmitSuccess && !error && (
83-
<Modal
84-
onClick={step === 1 ? selectCharacter : handleSubmit}
85-
buttonText={step === 1 ? "다음" : "제출"}
86-
>
87-
{step === 1 ? (
88-
<CharacterSelectFrom
89-
selectedCharacter={selectedCharacter}
90-
onCharacterSelect={setSelectedCharacter}
91-
/>
92-
) : (
93-
<EmailInputForm
94-
email={email}
95-
onEmailChange={setEmail}
96-
goToPreviousStep={goToPreviousStep}
97-
/>
98-
)}
99-
</Modal>
100-
)}
81+
<div>
82+
<Modal
83+
onClose={closeModal}
84+
onClick={step === 1 ? selectCharacter : handleSubmit}
85+
buttonText={step === 1 ? "다음" : "제출"}
86+
>
87+
{step === 1 ? (
88+
<CharacterSelectFrom
89+
selectedCharacter={selectedCharacter}
90+
onCharacterSelect={setSelectedCharacter}
91+
/>
92+
) : (
93+
<EmailInputForm
94+
email={email}
95+
onEmailChange={setEmail}
96+
goToPreviousStep={goToPreviousStep}
97+
/>
98+
)}
99+
</Modal>
101100
{isSubmitSuccess && (
102-
<SubmitResultModal onClick={handleSuccessModalClose} />
101+
<SubmitResultModal
102+
onClose={handleSuccessModalClose}
103+
onClick={handleSuccessModalClose}
104+
/>
103105
)}
104106
{isLoading && <LoadingModal />}
105-
{error && <ErrorModal onClick={closeModal} message={error} />}
106-
</>
107+
</div>
107108
);
108109
};
109110

110111
VideoSubmitModal.propTypes = {
111112
videoId: PropTypes.string.isRequired,
112113
trim: PropTypes.arrayOf(PropTypes.number).isRequired,
114+
closeModal: PropTypes.func.isRequired,
115+
setError: PropTypes.func.isRequired,
116+
step: PropTypes.number.isRequired,
117+
setStep: PropTypes.func.isRequired,
113118
};
114119

115120
export default VideoSubmitModal;

src/pages/MainPage.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,13 @@ const MainPage = () => {
7070
<Button onClick={handleSubmit}>제출</Button>
7171
</div>
7272
{isLoading && <LoadingModal />}
73-
{error && <ErrorModal onClick={() => setError("")} message={error} />}
73+
{error && (
74+
<ErrorModal
75+
onClose={() => setError("")}
76+
onClick={() => setError("")}
77+
message={error}
78+
/>
79+
)}
7480
<section className="w-full max-w-2xl mt-16">
7581
<h2 className="text-xl font-semibold mb-6">사용 방법</h2>
7682
<div className="grid gap-4 sm:grid-cols-3">

src/pages/VideoEditor.jsx

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const VideoEditor = () => {
2020
playing,
2121
playerRef,
2222
error,
23-
isDoneEdit,
23+
isModalOpen,
24+
setIsModalOpen,
2425
setError,
2526
handlePlay,
2627
handlePause,
@@ -32,6 +33,7 @@ const VideoEditor = () => {
3233

3334
const videoWrapperRef = useRef(null);
3435
const [playerWidth, setPlayerWidth] = useState(0);
36+
const [step, setStep] = useState(1);
3537

3638
useEffect(() => {
3739
if (!videoWrapperRef.current) {
@@ -54,6 +56,11 @@ const VideoEditor = () => {
5456
}, [videoSrc, videoId]);
5557

5658
const closeModal = () => {
59+
setStep(1);
60+
setIsModalOpen(false);
61+
};
62+
63+
const closeError = () => {
5764
setError(null);
5865

5966
if (!videoSrc) navigate("/");
@@ -62,30 +69,43 @@ const VideoEditor = () => {
6269
return (
6370
<>
6471
{videoSrc && videoId && (
65-
<div className="w-full flex flex-col items-center space-y-6">
66-
<div ref={videoWrapperRef} className="w-fit mx-auto">
67-
<VideoPlayer
68-
ref={playerRef}
69-
url={videoSrc}
70-
playing={playing}
71-
onDuration={handleDuration}
72-
onProgress={handleProgress}
73-
onPlay={handlePlay}
74-
onPause={handlePause}
72+
<div className="w-full flex flex-col items-center">
73+
<div className="space-y-6">
74+
<div ref={videoWrapperRef} className="w-fit mx-auto">
75+
<VideoPlayer
76+
ref={playerRef}
77+
url={videoSrc}
78+
playing={playing}
79+
onDuration={handleDuration}
80+
onProgress={handleProgress}
81+
onPlay={handlePlay}
82+
onPause={handlePause}
83+
/>
84+
</div>
85+
<TrimSlider
86+
trim={trim}
87+
duration={duration}
88+
videoSrc={videoSrc}
89+
onChange={handleTrimChange}
90+
width={playerWidth}
7591
/>
92+
<Button onClick={handleEdit}>편집 요청</Button>
7693
</div>
77-
<TrimSlider
78-
trim={trim}
79-
duration={duration}
80-
videoSrc={videoSrc}
81-
onChange={handleTrimChange}
82-
width={playerWidth}
83-
/>
84-
<Button onClick={handleEdit}>편집 요청</Button>
85-
{isDoneEdit && <VideoSubmitModal videoId={videoId} trim={trim} />}
94+
{isModalOpen && !error && (
95+
<VideoSubmitModal
96+
videoId={videoId}
97+
trim={trim}
98+
closeModal={closeModal}
99+
setError={setError}
100+
step={step}
101+
setStep={setStep}
102+
/>
103+
)}
86104
</div>
87105
)}
88-
{error && <ErrorModal onClick={closeModal} message={error} />}
106+
{error && (
107+
<ErrorModal onClose={closeError} onClick={closeError} message={error} />
108+
)}
89109
</>
90110
);
91111
};

src/shared/components/ErrorModal.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ import PropTypes from "prop-types";
22

33
import Modal from "./Modal";
44

5-
const ErrorModal = ({ onClick, message }) => {
5+
const ErrorModal = ({ onClose, message, onClick }) => {
66
return (
7-
<Modal onClick={onClick} buttonText="닫기">
8-
<p className="text-lg text-red-600 mb-4">{message}</p>
7+
<Modal onClose={onClose} onClick={onClick}>
8+
<p className="text-lg text-red-600">{message}</p>
99
</Modal>
1010
);
1111
};
1212

1313
ErrorModal.propTypes = {
1414
onClick: PropTypes.func.isRequired,
15+
onClose: PropTypes.func.isRequired,
1516
message: PropTypes.string.isRequired,
1617
};
1718

src/shared/components/Modal.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import PropTypes from "prop-types";
2+
import { IoCloseOutline } from "react-icons/io5";
23

34
import Button from "./Button";
45

5-
const Modal = ({ children, onClick, buttonText }) => {
6+
const Modal = ({ children, onClick, onClose, buttonText = "확인" }) => {
67
return (
78
<div className="fixed inset-0 flex justify-center items-center bg-slate-200 bg-opacity-50">
8-
<div className="py-8 px-6 bg-white rounded-md">
9+
<div className="py-4 px-6 bg-white rounded-md relative space-y-4">
10+
<IoCloseOutline
11+
className="absolute top-2 right-2 text-2xl cursor-pointer"
12+
onClick={onClose}
13+
/>
914
{children}
1015
<Button onClick={onClick}>{buttonText}</Button>
1116
</div>
@@ -15,6 +20,7 @@ const Modal = ({ children, onClick, buttonText }) => {
1520

1621
Modal.propTypes = {
1722
children: PropTypes.node.isRequired,
23+
onClose: PropTypes.func.isRequired,
1824
onClick: PropTypes.func.isRequired,
1925
buttonText: PropTypes.string.isRequired,
2026
};

0 commit comments

Comments
 (0)