diff --git a/client/src/atoms/buttons/ListToggle.js b/client/src/atoms/buttons/ListToggle.js
index a8a5a0e1..4402b782 100644
--- a/client/src/atoms/buttons/ListToggle.js
+++ b/client/src/atoms/buttons/ListToggle.js
@@ -3,11 +3,16 @@ import { useSelector } from "react-redux";
import { styled } from "styled-components";
import tokens from "../../styles/tokens.json";
import axios from "axios";
+import { AlertModal } from "../modal/Modal";
const ListToggle = ({ OnOff, videoId }) => {
const isDark = useSelector((state) => state.uiSetting.isDark);
const token = useSelector((state) => state.loginInfo.accessToken);
const [isOnOff, setOnOff] = useState(OnOff);
+ const [isModalOpen, setIsModalOpen] = useState({
+ isModalOpen: false,
+ content: "",
+ });
const patchVideoStatus = () => {
return axios
@@ -17,27 +22,53 @@ const ListToggle = ({ OnOff, videoId }) => {
.then((res) => {
setOnOff(!res.data.data);
if (res.data.data) {
- alert("강의를 활성화 했습니다.");
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "강의를 활성화 했습니다.",
+ });
} else {
- alert("강의를 비활성화 했습니다.");
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "강의를 비활성화 했습니다.",
+ });
}
})
.catch((err) => {
- console.log(err);
- alert("강의 비활성화를 실패했습니다.");
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "강의 비활성화를 실패했습니다.",
+ });
});
};
return (
- {
- patchVideoStatus();
- }}
- >
-
-
-
-
+ <>
+ {
+ patchVideoStatus();
+ }}
+ >
+
+
+
+
+
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: false,
+ })
+ }
+ />
+ >
);
};
@@ -56,10 +87,13 @@ export const ToggleContainer = styled.div`
top: 0;
left: 0; // "rgba(24,35,51,0.7)"
background-color: ${(props) =>
- props.isDark && !props.isOnOff ? globalTokens.LightNavy.value
- : !props.isDark && !props.isOnOff ? globalTokens.Negative.value
- : props.isDark && props.isOnOff ? 'rgba(255,255,255,0.1)'
- : 'rgba(0,0,0,0.15)'};
+ props.isDark && !props.isOnOff
+ ? globalTokens.LightNavy.value
+ : !props.isDark && !props.isOnOff
+ ? globalTokens.Negative.value
+ : props.isDark && props.isOnOff
+ ? "rgba(255,255,255,0.1)"
+ : "rgba(0,0,0,0.15)"};
border-radius: ${globalTokens.BigRadius.value}px;
width: 48px;
height: 24px;
diff --git a/client/src/atoms/modal/Modal.js b/client/src/atoms/modal/Modal.js
index 66a59cb1..198ef0e5 100644
--- a/client/src/atoms/modal/Modal.js
+++ b/client/src/atoms/modal/Modal.js
@@ -1,124 +1,153 @@
-import React from 'react';
-import { styled } from 'styled-components';
-import tokens from '../../styles/tokens.json';
-import { useDispatch, useSelector } from 'react-redux';
-import { BodyTextTypo } from '../typographys/Typographys'
-import { NegativeTextButton, PositiveTextButton } from '../buttons/Buttons';
+import { useSelector } from "react-redux";
+import { styled } from "styled-components";
+import tokens from "../../styles/tokens.json";
+import { BodyTextTypo } from "../typographys/Typographys";
+import { NegativeTextButton, PositiveTextButton } from "../buttons/Buttons";
-const globalTokens = tokens.global;
-
-export const ModalBackdrop = styled.div`
- width: 100vw;
- height: 100vh;
- position: fixed;
- z-index: 1001;
- top: 0;
- left: 0;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- background-color: ${(props)=>props.isDark?'rgba(255, 255, 255, 0.25)':'rgba(0, 0, 0, 0.25)'};
- opacity: ${(props) => (props.isModalOpen ? `1` : `0`)};
- visibility: ${(props) => (props.isModalOpen ? "visible" : "hidden")};
-`
-export const ModalContainer = styled.div`
- width: 320px;
- height: 150px;
- padding: ${globalTokens.Spacing20.value}px ${globalTokens.Spacing8.value}px;
- background-color: ${(props)=>props.isDark?globalTokens.Black.value:globalTokens.White.value};
- border-radius: ${globalTokens.BigRadius.value}px;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-`
-export const ModalContent = styled(BodyTextTypo)`
- flex-grow: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-`
-export const ModalButtonContainer = styled.div`
- display: flex;
- flex-direction: row;
- justify-content: space-around;
- align-items: start;
-`
-export const ModalPositiveButton = styled(PositiveTextButton)`
- margin: ${globalTokens.Spacing4.value}px;
- padding: 0 ${globalTokens.Spacing24.value}px;
-`
-export const ModalNegativeButton = styled(NegativeTextButton)`
- margin: ${globalTokens.Spacing4.value}px;
- padding: 0 ${globalTokens.Spacing24.value}px;
-`
//예, 아니오를 선택하는 모달
export const ConfirmModal = ({
- isModalOpen,
- setIsModalOpen,
- isBackdropClickClose,
- content,
- negativeButtonTitle,
- positiveButtonTitle,
- handleNegativeButtonClick,
- handlePositiveButtonClick,
+ isModalOpen,
+ setIsModalOpen,
+ isBackdropClickClose,
+ content,
+ negativeButtonTitle,
+ positiveButtonTitle,
+ handleNegativeButtonClick,
+ handlePositiveButtonClick,
}) => {
- const isDark = useSelector(state=>state.uiSetting.isDark);
+ const isDark = useSelector((state) => state.uiSetting.isDark);
- return (
- {
+ isBackdropClickClose && setIsModalOpen(false);
+ }}
+ >
+ {
+ e.stopPropagation();
+ }}
+ >
+ {content}
+
+ {
+ handlePositiveButtonClick();
+ }}
+ >
+ {positiveButtonTitle}
+
+ { isBackdropClickClose && setIsModalOpen(false) }}>
- {e.stopPropagation();}}>
- {content}
-
- {
- handleNegativeButtonClick();
- }}>
- {negativeButtonTitle}
-
- {
- handlePositiveButtonClick();
- }}>
- {positiveButtonTitle}
-
-
-
-
- );
+ onClick={(e) => {
+ handleNegativeButtonClick();
+ }}
+ >
+ {negativeButtonTitle}
+
+
+
+
+ );
};
+
//확인 버튼만 있는 모달
export const AlertModal = ({
- isModalOpen,
- setIsModalOpen,
- isBackdropClickClose,
- content,
- buttonTitle,
- handleButtonClick,
+ isModalOpen,
+ setIsModalOpen,
+ isBackdropClickClose,
+ content,
+ buttonTitle,
+ handleButtonClick,
}) => {
- const isDark = useSelector(state=>state.uiSetting.isDark);
+ const isDark = useSelector((state) => state.uiSetting.isDark);
- return (
- {
+ isBackdropClickClose && setIsModalOpen(false);
+ }}
+ >
+ {
+ e.stopPropagation();
+ }}
+ >
+ {content}
+
+ { isBackdropClickClose && setIsModalOpen(false) }}>
- {e.stopPropagation();}}>
- {content}
-
-
- {buttonTitle}
-
-
-
-
- );
-}
+ onClick={handleButtonClick}
+ >
+ {buttonTitle}
+
+
+
+
+ );
+};
+
+const globalTokens = tokens.global;
+
+export const ModalBackdrop = styled.div`
+ width: 100vw;
+ height: 100vh;
+ position: fixed;
+ z-index: 1001;
+ top: 0;
+ left: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ background-color: ${(props) =>
+ props.isDark ? "rgba(255, 255, 255, 0.25)" : "rgba(0, 0, 0, 0.25)"};
+ opacity: ${(props) => (props.isModalOpen ? `1` : `0`)};
+ visibility: ${(props) => (props.isModalOpen ? "visible" : "hidden")};
+`;
+
+export const ModalContainer = styled.div`
+ width: 320px;
+ height: 150px;
+ padding: ${globalTokens.Spacing20.value}px ${globalTokens.Spacing8.value}px;
+ background-color: ${(props) =>
+ props.isDark ? globalTokens.Black.value : globalTokens.White.value};
+ border-radius: ${globalTokens.BigRadius.value}px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+`;
+
+export const ModalContent = styled(BodyTextTypo)`
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+`;
+
+export const ModalButtonContainer = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ align-items: start;
+`;
+
+export const ModalPositiveButton = styled(PositiveTextButton)`
+ margin: ${globalTokens.Spacing4.value}px;
+ padding: 0 ${globalTokens.Spacing24.value}px;
+`;
+
+export const ModalNegativeButton = styled(NegativeTextButton)`
+ margin: ${globalTokens.Spacing4.value}px;
+ padding: 0 ${globalTokens.Spacing24.value}px;
+`;
diff --git a/client/src/components/CartPage/CartPayInfo.js b/client/src/components/CartPage/CartPayInfo.js
index 7a54b5e3..7fbd0082 100644
--- a/client/src/components/CartPage/CartPayInfo.js
+++ b/client/src/components/CartPage/CartPayInfo.js
@@ -9,6 +9,7 @@ import {
import { RegularInput } from "../../atoms/inputs/Inputs";
import { RegularButton } from "../../atoms/buttons/Buttons";
import PaymentBtn from "../../pages/contents/CartPage/TossPayment";
+import { AlertModal } from "../../atoms/modal/Modal";
const globalTokens = tokens.global;
@@ -23,6 +24,9 @@ const CartPayInfo = () => {
const myCartInfo = useSelector((state) => state.cartSlice.myCartInfo);
const checkedItems = useSelector((state) => state.cartSlice.checkedItem);
const [isDiscount, setDiscount] = useState(0);
+ const [countModal, setCountModal] = useState(false);
+ const [overPointModal, setOverPointModal] = useState(false);
+ const [spendPointModal, setSpendPointModal] = useState(false);
const getTotal = () => {
const cartsArr = cartsData.map((el) => el.videoId);
@@ -52,17 +56,17 @@ const CartPayInfo = () => {
const regExp = /[a-z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;
if (regExp.test(reward)) {
setDiscount(0);
- return alert("숫자만 입력할 수 있습니다.");
+ return setCountModal(true)
}
if (totalPrice < parseInt(reward)) {
setDiscount(totalPrice);
- return alert("선택하신 상품 금액을 넘어서 포인트를 사용할 수 없습니다.");
+ return setOverPointModal(true)
}
if (reward > myCartInfo.reward) {
- alert(`현재 사용할 수 있는 포인트는 ${myCartInfo.reward}포인트 입니다.`);
setDiscount(myCartInfo.reward);
+ return setSpendPointModal(true)
}
};
@@ -73,48 +77,76 @@ const CartPayInfo = () => {
}, [totalPrice]);
return (
-
-
- 포인트
- 보유 : {priceToString(myCartInfo.reward)}
-
-
- handleChangeDiscount(e.target.value)}
- onBlur={(e) => handleBlurDiscount(e.target.value)}
- />
- {
- e.preventDefault();
- handleAllDiscount(myCartInfo.reward);
- }}
- >
- 전액 사용
-
-
-
-
- 선택 상품 금액
- {priceToString(totalPrice)}원
-
-
- 할인 금액
- {priceToString(isDiscount)}원
-
-
- 총 결제금액
-
- {priceToString(totalPrice - isDiscount)}원
-
-
-
-
-
+ <>
+
+
+ 포인트
+
+ 보유 : {priceToString(myCartInfo.reward)}
+
+
+
+ handleChangeDiscount(e.target.value)}
+ onBlur={(e) => handleBlurDiscount(e.target.value)}
+ />
+ {
+ e.preventDefault();
+ handleAllDiscount(myCartInfo.reward);
+ }}
+ >
+ 전액 사용
+
+
+
+
+ 선택 상품 금액
+ {priceToString(totalPrice)}원
+
+
+ 할인 금액
+ {priceToString(isDiscount)}원
+
+
+ 총 결제금액
+
+ {priceToString(totalPrice - isDiscount)}원
+
+
+
+
+
+ setCountModal(false)}
+ />
+ setOverPointModal(false)}
+ />
+ setSpendPointModal(false)}
+ />
+ >
);
};
diff --git a/client/src/components/DetailPage/AddCart.js b/client/src/components/DetailPage/AddCart.js
index aa048dd2..c7789a1c 100644
--- a/client/src/components/DetailPage/AddCart.js
+++ b/client/src/components/DetailPage/AddCart.js
@@ -6,12 +6,14 @@ import { useToken } from "../../hooks/useToken";
import tokens from "../../styles/tokens.json";
import { ReactComponent as Cart } from "../../assets/images/icons/listItem/Cart.svg";
import { RoundButton } from "../../atoms/buttons/Buttons";
+import { AlertModal } from "../../atoms/modal/Modal";
const AddCart = ({ videoId, isInCart, content = "", border = false }) => {
const refreshToken = useToken();
const isDark = useSelector((state) => state.uiSetting.isDark);
const token = useSelector((state) => state.loginInfo.accessToken);
const [isCart, setCart] = useState(isInCart);
+ const [isModalOpen, setIsModalOpen] = useState(false);
const handlePahctCart = () => {
return axios
@@ -19,14 +21,13 @@ const AddCart = ({ videoId, isInCart, content = "", border = false }) => {
headers: { Authorization: token.authorization },
})
.then((res) => {
- // console.log(res.data.data);
setCart(res.data.data);
})
.catch((err) => {
if (err.response.data.message === "만료된 토큰입니다.") {
refreshToken();
} else if (err.response.data.code === 403) {
- alert("로그인 시 이용 가능합니다.");
+ setIsModalOpen(true)
} else {
console.log(err);
}
@@ -42,6 +43,14 @@ const AddCart = ({ videoId, isInCart, content = "", border = false }) => {
) : (
handlePahctCart()} />
)}
+ setIsModalOpen(false)}
+ />
>
);
};
diff --git a/client/src/components/DetailPage/ReviewList.js b/client/src/components/DetailPage/ReviewList.js
index ac6231e1..e7d430ac 100644
--- a/client/src/components/DetailPage/ReviewList.js
+++ b/client/src/components/DetailPage/ReviewList.js
@@ -3,15 +3,22 @@ import { useState } from "react";
import { useSelector } from "react-redux";
import { styled } from "styled-components";
import Stars from "../contentListItems/Stars";
-import tokens from '../../styles/tokens.json';
-import { NegativeTextButton, PositiveTextButton } from "../../atoms/buttons/Buttons";
-import { BodyTextTypo, SmallTextTypo } from "../../atoms/typographys/Typographys";
+import tokens from "../../styles/tokens.json";
+import {
+ NegativeTextButton,
+ PositiveTextButton,
+} from "../../atoms/buttons/Buttons";
+import {
+ BodyTextTypo,
+ SmallTextTypo,
+} from "../../atoms/typographys/Typographys";
import { RegularInput } from "../../atoms/inputs/Inputs";
+import { ConfirmModal } from "../../atoms/modal/Modal";
const globalTokens = tokens.global;
const ReviewList = ({ el, getReview }) => {
- const isDark = useSelector(state=>state.uiSetting.isDark);
+ const isDark = useSelector((state) => state.uiSetting.isDark);
const myId = useSelector((state) => state.loginInfo.myid);
const token = useSelector((state) => state.loginInfo.accessToken);
const [isEditMode, setEditMode] = useState(false);
@@ -19,6 +26,8 @@ const ReviewList = ({ el, getReview }) => {
content: el.content,
star: 0,
});
+ const [saveReview, setSaveReview] = useState(false);
+ const [delReview, setDelReview] = useState(false);
const patchReview = (replyId) => {
return axios
@@ -28,7 +37,6 @@ const ReviewList = ({ el, getReview }) => {
.then((res) => {
console.log(res);
if (res.status === 204) {
- // window.location.reload();
getReview();
}
})
@@ -43,7 +51,6 @@ const ReviewList = ({ el, getReview }) => {
.then((res) => {
console.log(res);
if (res.status === 204) {
- // window.location.reload();
getReview();
}
})
@@ -51,65 +58,102 @@ const ReviewList = ({ el, getReview }) => {
};
return (
-
- {myId === el.member.memberId && (
- <>
- {isEditMode ? (
-
+
+ {myId === el.member.memberId && (
+ <>
+ {isEditMode ? (
+ {
+ setSaveReview(true);
+ // if (window.confirm("댓글을 저장 하시겠습니까?")) {
+ // setEditMode(false);
+ // patchReview(el.replyId);
+ // }
+ }}
+ >
+ 저장
+
+ ) : (
+ {
+ setEditMode(true);
+ setEditReply({ ...editReply, star: el.star });
+ }}
+ >
+ 수정
+
+ )}
+ {
- if (window.confirm("댓글을 저장 하시겠습니까?")) {
- setEditMode(false);
- patchReview(el.replyId);
- }
+ setDelReview(true);
+ // if (window.confirm("댓글을 삭제 하시겠습니까?")) {
+ // deleteReview(el.replyId);
+ // }
}}
>
- 저장
-
- ) : (
- {
- setEditMode(true);
- setEditReply({ ...editReply, star: el.star });
- }}
- >
- 수정
-
- )}
-
+ >
+ )}
+
+
+
+
+ {isEditMode ? (
+ {
- if (window.confirm("댓글을 삭제 하시겠습니까?")) {
- deleteReview(el.replyId);
- }
- }}
- >
- 삭제
-
- >
- )}
-
-
-
-
- {isEditMode ? (
-
- setEditReply({ ...editReply, content: e.target.value })
- }
- />
- ) : (
- {el.content}
- )}
-
-
- {el.member.nickname}
- {el.createdDate.split("T")[0]}
-
-
+ value={editReply.content}
+ onChange={(e) =>
+ setEditReply({ ...editReply, content: e.target.value })
+ }
+ />
+ ) : (
+ {el.content}
+ )}
+
+
+ {el.member.nickname}
+
+ {el.createdDate.split("T")[0]}
+
+
+
+ {
+ setSaveReview(false);
+ }}
+ handlePositiveButtonClick={() => {
+ setEditMode(false);
+ patchReview(el.replyId);
+ setSaveReview(false);
+ }}
+ />
+ {
+ setDelReview(false);
+ }}
+ handlePositiveButtonClick={() => {
+ deleteReview(el.replyId);
+ setDelReview(false);
+ }}
+ />
+ >
);
};
@@ -131,7 +175,9 @@ export const ReList = styled.li`
flex-direction: column;
justify-content: space-around;
align-items: start;
- border: 1px solid ${props=>props.isDark?globalTokens.Gray.value:globalTokens.LightGray.value};
+ border: 1px solid
+ ${(props) =>
+ props.isDark ? globalTokens.Gray.value : globalTokens.LightGray.value};
border-radius: ${globalTokens.RegularRadius.value}px;
padding: ${globalTokens.Spacing16.value}px ${globalTokens.Spacing20.value}px;
margin-top: 15px;
@@ -159,7 +205,8 @@ export const ReviewEdit = styled(RegularInput)`
margin: 5px 0px;
padding: 5px 10px;
border: none;
- background-color: ${props=>props.isDark?'rgba(255,255,255,0.15)':globalTokens.White.value};
+ background-color: ${(props) =>
+ props.isDark ? "rgba(255,255,255,0.15)" : globalTokens.White.value};
&:focus {
outline: none;
}
@@ -168,7 +215,7 @@ export const ReviewContent = styled(BodyTextTypo)`
width: 100%;
flex-wrap: wrap;
margin: 5px 0px;
- padding: 5px 0px
+ padding: 5px 0px;
`;
export const ReviewInfo = styled(SmallTextTypo)`
@@ -176,20 +223,17 @@ export const ReviewInfo = styled(SmallTextTypo)`
flex-direction: row;
justify-content: start;
align-items: center;
- color: ${ props=>props.isDark ?
- globalTokens.LightGray.value
- : globalTokens.Gray.value };
+ color: ${(props) =>
+ props.isDark ? globalTokens.LightGray.value : globalTokens.Gray.value};
`;
export const ReviewName = styled(SmallTextTypo)`
margin-right: 10px;
- color: ${ props=>props.isDark ?
- globalTokens.LightGray.value
- : globalTokens.Gray.value };
+ color: ${(props) =>
+ props.isDark ? globalTokens.LightGray.value : globalTokens.Gray.value};
`;
export const ReviewDate = styled(SmallTextTypo)`
- color: ${ props=>props.isDark ?
- globalTokens.LightGray.value
- : globalTokens.Gray.value };
+ color: ${(props) =>
+ props.isDark ? globalTokens.LightGray.value : globalTokens.Gray.value};
`;
diff --git a/client/src/components/DetailPage/VideoPlayer.js b/client/src/components/DetailPage/VideoPlayer.js
index 0a40db78..85655711 100644
--- a/client/src/components/DetailPage/VideoPlayer.js
+++ b/client/src/components/DetailPage/VideoPlayer.js
@@ -1,12 +1,12 @@
import axios from "axios";
import { useEffect, useMemo, useRef, useState } from "react";
+import screenfull from "screenfull";
import ReactPlayer from "react-player";
import styled from "styled-components";
import { ReactComponent as Play } from "../../assets/images/icons/Play.svg";
import { ReactComponent as Pause } from "../../assets/images/icons/Pause.svg";
import { ReactComponent as Volume } from "../../assets/images/icons/Volume.svg";
import { ReactComponent as FullScreen } from "../../assets/images/icons/FullScreen.svg";
-import screenfull from "screenfull";
const VideoPlayer = ({
videoId,
diff --git a/client/src/components/UploadPage/CourseUpload.js b/client/src/components/UploadPage/CourseUpload.js
index 4b5fab0c..20ea8236 100644
--- a/client/src/components/UploadPage/CourseUpload.js
+++ b/client/src/components/UploadPage/CourseUpload.js
@@ -17,6 +17,7 @@ import { useToken } from "../../hooks/useToken";
import Loading from "../../atoms/loading/Loading";
import tokens from "../../styles/tokens.json";
import { BigButton } from "../../atoms/buttons/Buttons";
+import { AlertModal, ConfirmModal } from "../../atoms/modal/Modal";
const globalToken = tokens.global;
@@ -49,6 +50,12 @@ const CourseUpload = ({ isTags }) => {
const tagsData = isTags.map((el) => el.categoryName); // 실제 tag data 리스트
const tagsDataLower = tagsData.map((el) => el.toLowerCase()); // tagsData 대소문자 판별
const [tagOpen, setTagOpen] = useState(false); // tag 드롭다운 열고 닫기
+ const [isModalOpen, setIsModalOpen] = useState({
+ isModalOpen: false,
+ content: "",
+ });
+ const [alertUpload, setAlertUpload] = useState(false);
+ const [confirmUpload, setConfirmUpload] = useState(false);
const handleSaveFile = (e) => {
const file = e.target.files[0];
@@ -74,27 +81,51 @@ const CourseUpload = ({ isTags }) => {
const regExp = /[a-z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;
if (regExp.test(price)) {
setUploadDetail({ ...uploadDetail, price: 0 });
- alert("숫자만 입력해주세요.");
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "숫자만 입력해주세요.",
+ });
}
};
const handleVideoPost = () => {
if (!uploadDetail.price) {
- return alert("가격을 설정해 주세요.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "가격을 설정해 주세요.",
+ });
}
if (!uploadDetail.categories.length) {
- return alert("1개 이상의 카테고리를 설정해 주세요.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "1개 이상의 카테고리를 설정해 주세요.",
+ });
}
if (!imgFile) {
- return alert("썸네일 이미지 파일을 올려주세요");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "썸네일 이미지 파일을 올려주세요",
+ });
}
if (!videoFile) {
- return alert("동영상 파일을 올려주세요");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "동영상 파일을 올려주세요",
+ });
}
if (imgRef.current.files[0].name.split(".")[0] !== uploadDetail.videoName) {
- return alert("동일한 이름의 이미지와 동영상 파일을 업로드 해주세요.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "동일한 이름의 이미지와 동영상 파일을 업로드 해주세요.",
+ });
}
if (uploadVideo.fileName && uploadVideo.imageType) {
@@ -113,7 +144,11 @@ const CourseUpload = ({ isTags }) => {
.catch((err) => {
console.log(err);
if (err.response.data.code === 409) {
- alert(`${err.response.data.message}`);
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: `${err.response.data.message}`,
+ });
} else if (err.response.data.code === 401) {
refreshToken(() => handleVideoPost());
} else {
@@ -142,7 +177,6 @@ const CourseUpload = ({ isTags }) => {
.catch((err) => {
if (err.response.status === 503) {
console.log(err);
- // handleImgUpload();
}
});
}
@@ -164,12 +198,13 @@ const CourseUpload = ({ isTags }) => {
.catch((err) => {
if (err.response.status === 503) {
console.log(err);
- // handleVideoUpload();
}
});
}
};
+ const [isLocation, setLocation] = useState("");
+
const handleDetailPost = () => {
if (!isComplete) {
return axios
@@ -179,12 +214,8 @@ const CourseUpload = ({ isTags }) => {
.then((res) => {
setLoading(false);
setComplete(true);
- alert("성공적으로 강의가 등록 되었습니다.");
- if (window.confirm("강의 문제를 업로드 하시겠습니까?")) {
- navigate(`${res.headers.location}/problems/upload`);
- } else {
- navigate("/lecture");
- }
+ setAlertUpload(true);
+ setLocation(`${res.headers.location}/problems/upload`);
})
.catch((err) => {
console.log(err);
@@ -203,15 +234,21 @@ const CourseUpload = ({ isTags }) => {
uploadDetail.categories.includes(e.target.value) ||
tagListLower.includes(e.target.value.toLowerCase())
) {
- alert("이미 존재하는 카테고리입니다.");
- return;
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "이미 존재하는 카테고리입니다.",
+ });
}
if (
!tagsData.includes(e.target.value) &&
!tagsDataLower.includes(e.target.value.toLowerCase())
) {
- alert("존재하지 않는 카테고리 입니다.");
- return;
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "존재하지 않는 카테고리 입니다.",
+ });
}
if (e.target.value && !uploadDetail.categories.includes(e.target.value)) {
setUploadDetail({
@@ -223,11 +260,12 @@ const CourseUpload = ({ isTags }) => {
}
} else if (e.key === "Backspace" && !e.target.value) {
if (uploadDetail.categories.length) {
- setUploadDetail(
- uploadDetail.categories.filter(
+ setUploadDetail({
+ ...uploadDetail,
+ categories: uploadDetail.categories.filter(
(el, idx) => idx !== uploadDetail.categories.length - 1
- )
- );
+ ),
+ });
return;
}
}
@@ -238,8 +276,11 @@ const CourseUpload = ({ isTags }) => {
uploadDetail.categories.includes(el) ||
tagListLower.includes(el.toLowerCase())
) {
- alert("이미 존재하는 카테고리입니다.");
- return;
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "이미 존재하는 카테고리입니다.",
+ });
}
if (!uploadDetail.categories.includes(el)) {
setUploadDetail({
@@ -257,147 +298,192 @@ const CourseUpload = ({ isTags }) => {
};
return (
-
- 강의 등록하기
- 강의 정보를 입력합니다.
-
-
- 강의명
-
-
-
- 강의 소개
- {
- setUploadDetail({ ...uploadDetail, description: e.target.value });
- }}
- />
-
-
- 가격
- {
- setUploadDetail({ ...uploadDetail, price: e.target.value });
- }}
- onBlur={(e) => handleBlurPrice(e.target.value)}
- />
-
-
- 카테고리
-
-
- {uploadDetail.categories.map((el, idx) => (
-
- {el}
- removeTagList(el)}
- >
- ×
-
-
- ))}
-
-
+
+ 강의 등록하기
+ 강의 정보를 입력합니다.
+
+
+ 강의명
+
+
+
+ 강의 소개
+ {
+ setUploadDetail({
+ ...uploadDetail,
+ description: e.target.value,
+ });
+ }}
+ />
+
+
+ 가격
+ addTagList(e)}
- onFocus={() => setTagOpen(true)}
- onBlur={() => {
- setTimeout(() => {
- setTagOpen(false);
- }, 100);
+ placeholder="가격을 설정해 주세요."
+ value={uploadDetail.price}
+ onChange={(e) => {
+ setUploadDetail({ ...uploadDetail, price: e.target.value });
}}
+ onBlur={(e) => handleBlurPrice(e.target.value)}
/>
- {tagOpen && (
-
- {tagsData.map((el, idx) => (
- {
- handleAddTags(el);
- setTagOpen(false);
- }}
- >
+
+
+ 카테고리
+
+
+ {uploadDetail.categories.map((el, idx) => (
+
{el}
-
+ removeTagList(el)}
+ >
+ ×
+
+
))}
-
- )}
-
-
-
-
- 썸네일 이미지
-
-
-
- {imgFile ? (
-
- ) : (
- 썸네일을 등록해 주세요.
+
+ addTagList(e)}
+ onFocus={() => setTagOpen(true)}
+ onBlur={() => {
+ setTimeout(() => {
+ setTagOpen(false);
+ }, 100);
+ }}
+ />
+ {tagOpen && (
+
+ {tagsData.map((el, idx) => (
+ {
+ handleAddTags(el);
+ setTagOpen(false);
+ }}
+ >
+ {el}
+
+ ))}
+
)}
-
-
- 썸네일 이미지는 png, jpg, jpeg 확장자만 등록이 가능합니다.
-
-
- 권장 이미지 크기 : 291px × 212px
-
-
-
-
-
- 강의 영상
-
-
-
- 강의 영상은 mp4만 등록이 가능합니다.
-
-
- 권장 화면 비율 : 1920 × 1080
-
- 최대 영상 크기 : 1GB
-
-
-
- 강의 등록 완료
-
-
-
-
+
+
+
+
+ 썸네일 이미지
+
+
+
+ {imgFile ? (
+
+ ) : (
+
+ 썸네일을 등록해 주세요.
+
+ )}
+
+
+ 썸네일 이미지는 png, jpg, jpeg 확장자만 등록이 가능합니다.
+
+
+ 권장 이미지 크기 : 291px × 212px
+
+
+
+
+
+ 강의 영상
+
+
+
+ 강의 영상은 mp4만 등록이 가능합니다.
+
+
+ 권장 화면 비율 : 1920 × 1080
+
+ 최대 영상 크기 : 1GB
+
+
+
+ 강의 등록 완료
+
+
+
+
+
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: false,
+ })
+ }
+ />
+ {
+ setAlertUpload(false);
+ setConfirmUpload(true);
+ }}
+ />
+ {
+ navigate("/lecture");
+ }}
+ handlePositiveButtonClick={() => {
+ navigate(isLocation);
+ }}
+ />
+ >
);
};
diff --git a/client/src/components/UploadPage/Modal/UploadModal.js b/client/src/components/UploadPage/Modal/UploadModal.js
index 131cbf55..cd38d152 100644
--- a/client/src/components/UploadPage/Modal/UploadModal.js
+++ b/client/src/components/UploadPage/Modal/UploadModal.js
@@ -1,11 +1,16 @@
import { styled } from "styled-components";
import SelectToggle from "./SelectToggle";
-import { useSelector } from 'react-redux';
-import tokens from '../../../styles/tokens.json';
-import { BodyTextTypo, Heading5Typo } from '../../../atoms/typographys/Typographys';
-import { RegularInput } from '../../../atoms/inputs/Inputs';
-import { RegularTextArea } from '../../../atoms/inputs/TextAreas';
+import { useSelector } from "react-redux";
+import tokens from "../../../styles/tokens.json";
+import {
+ BodyTextTypo,
+ Heading5Typo,
+} from "../../../atoms/typographys/Typographys";
+import { RegularInput } from "../../../atoms/inputs/Inputs";
+import { RegularTextArea } from "../../../atoms/inputs/TextAreas";
import { RegularButton } from "../../../atoms/buttons/Buttons";
+import { useState } from "react";
+import { AlertModal } from "../../../atoms/modal/Modal";
const globalTokens = tokens.global;
@@ -18,114 +23,147 @@ const UploadModal = ({
selectMode,
setSelectMode,
}) => {
- const isDark = useSelector(state=>state.uiSetting.isDark);
+ const isDark = useSelector((state) => state.uiSetting.isDark);
+ const [contentModal, setContentModal] = useState(false);
+ const [answerModal, setAnswerModal] = useState(false);
+ const [checkedModal, setCheckedModal] = useState(false);
+
+ const handleSubmit = () => {
+ const find = isProblem.selections.find((el) => el === "");
+
+ if (!isProblem.content) {
+ return setContentModal(true);
+ }
+ if (!isProblem.questionAnswer) {
+ return setAnswerModal(true);
+ }
+ if (find === "" && selectMode) {
+ return setCheckedModal(true);
+ }
+ handleCreateProblem();
+ setModal(false);
+ initProblem();
+ document.body.style.overflow = "unset";
+ };
return (
-
- {
- e.stopPropagation();
- }}>
-
-
+
+ {
- setModal(false);
- initProblem();
- document.body.style.overflow = "unset";
+ onClick={(e) => {
+ e.stopPropagation();
}}
>
- ×
-
-
- 문제 등록하기
- handleChangeContent(e)}
- value={isProblem.content}
+ setSelectMode={setSelectMode}
+ initProblem={initProblem}
/>
-
-
-
- {selectMode ? (
- [1, 2, 3, 4].map((el) => (
+ {
+ setModal(false);
+ initProblem();
+ document.body.style.overflow = "unset";
+ }}
+ >
+ ×
+
+
+ 문제 등록하기
+ handleChangeContent(e)}
+ value={isProblem.content}
+ />
+
+
+
+ {selectMode ? (
+ [1, 2, 3, 4].map((el) => (
+
+ {
+ handleChangeContent(e, el);
+ }}
+ checked={isProblem.questionAnswer === el}
+ />
+ {el}번 문항
+ handleChangeContent(e, el)}
+ value={isProblem.selections[el - 1]}
+ />
+
+ ))
+ ) : (
- 정답
+ {
- handleChangeContent(e, el);
+ handleChangeContent(e, e.target.value);
}}
- checked={isProblem.questionAnswer === el}
- />
- {el}번 문항
- handleChangeContent(e, el)}
- value={isProblem.selections[el - 1]}
/>
- ))
- ) : (
+ )}
- 정답
- 해설
+ {
- handleChangeContent(e, e.target.value);
- }}/>
+ selectMode={selectMode}
+ id="ProblemDiscribe"
+ type="text"
+ placeholder="해설을 입력해 주세요."
+ onChange={(e) => handleChangeContent(e)}
+ value={isProblem.description}
+ />
- )}
-
- 해설
- handleChangeContent(e)}
- value={isProblem.description}
- />
-
-
-
- {
- if (!isProblem.content) {
- return alert("지문을 입력해 주세요.");
- }
- if (!isProblem.questionAnswer) {
- return alert("정답을 체크해 주세요.");
- }
- if (!isProblem.selections.length && selectMode) {
- return alert("선택지들을 입력해 주세요.");
- }
- handleCreateProblem();
- setModal(false);
- initProblem();
- }}
- >
- 문제 추가
-
-
-
+
+
+
+ 문제 추가
+
+
+
+ setContentModal(false)}
+ />
+ setAnswerModal(false)}
+ />
+ setCheckedModal(false)}
+ />
+ >
);
};
@@ -139,7 +177,8 @@ export const ModalBackground = styled.div`
display: flex;
justify-content: center;
align-items: center;
- background-color: ${props=>props.isDark? 'rgba(255,255,255,0.15)' : 'rgba(0,0,0,0.15)'};
+ background-color: ${(props) =>
+ props.isDark ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"};
width: 100vw;
height: 100vh;
`;
@@ -155,13 +194,17 @@ export const Close = styled.button`
right: 3%;
font-size: 18px;
font-weight: bold;
- color: ${props=>props.isDark?globalTokens.White.value:globalTokens.Black.value}
+ color: ${(props) =>
+ props.isDark ? globalTokens.White.value : globalTokens.Black.value};
`;
export const ProblemModal = styled.div`
position: relative;
- background-color: ${props=>props.isDark?globalTokens.Black.value:globalTokens.White.value};
- border: 1px solid ${props=>props.isDark?globalTokens.Gray.value:globalTokens.LightGray.value};
+ background-color: ${(props) =>
+ props.isDark ? globalTokens.Black.value : globalTokens.White.value};
+ border: 1px solid
+ ${(props) =>
+ props.isDark ? globalTokens.Gray.value : globalTokens.LightGray.value};
border-radius: 8px;
width: 100%;
max-width: 600px;
@@ -226,7 +269,7 @@ export const CheckNumber = styled.input`
export const TitleInput = styled(RegularTextArea)`
width: 100%;
- height: ${props=>props.selectMode?'80px':'120px'};
+ height: ${(props) => (props.selectMode ? "80px" : "120px")};
margin-top: 20px;
padding: 10px 0px 0px 10px;
resize: none;
@@ -249,7 +292,7 @@ export const CommentInput = styled(RegularTextArea)`
export const DiscribeInput = styled(RegularTextArea)`
width: 100%;
- height: ${props=>props.selectMode? '100px' : '150px'};
+ height: ${(props) => (props.selectMode ? "100px" : "150px")};
margin-left: 15px;
padding: 10px 0px 0px 10px;
resize: none;
diff --git a/client/src/components/UploadPage/ProblemUpload.js b/client/src/components/UploadPage/ProblemUpload.js
index 7df04136..9987f3a1 100644
--- a/client/src/components/UploadPage/ProblemUpload.js
+++ b/client/src/components/UploadPage/ProblemUpload.js
@@ -12,6 +12,7 @@ import plus_circle from "../../assets/images/icons/plus_circle.svg";
import { useToken } from "../../hooks/useToken";
import tokens from "../../styles/tokens.json";
import { RoundButton } from "../../atoms/buttons/Buttons";
+import { AlertModal } from "../../atoms/modal/Modal";
const globalTokens = tokens.global;
@@ -31,6 +32,7 @@ const ProblemUpload = () => {
const [isProblemList, setProblemList] = useState([]);
const [isProblem, setProblem] = useState(initialState);
const [selectMode, setSelectMode] = useState(true); // ture(객관식), false(주관식)
+ const [isModalOpen, setIsModalOpen] = useState(false);
const handleChangeContent = (e, answer) => {
switch (e.target.id) {
@@ -98,9 +100,7 @@ const ProblemUpload = () => {
.then((res) => {
console.log(res.data);
if (res.data.code === 201) {
- alert("성공적으로 강의 문제가 등록되었습니다.");
- navigate(`/videos/${videoId}/problems`);
- setProblemList([]);
+ setIsModalOpen(true);
}
})
.catch((err) => {
@@ -112,53 +112,70 @@ const ProblemUpload = () => {
};
return (
-
- 문제 등록하기
-
- 수강 후 성취도를 검사할 문제를 등록합니다.
-
-
-
- {isProblemList.map((el, idx) => (
-
- {/* {idx + 1}번 문제 */}
- {el.content}
- handleDeleteList(idx + 1)}>
- ×
-
-
- ))}
-
-
-
+
+ 문제 등록하기
+
+ 수강 후 성취도를 검사할 문제를 등록합니다.
+
+
+
+ {isProblemList.map((el, idx) => (
+
+ {/* {idx + 1}번 문제 */}
+ {el.content}
+ handleDeleteList(idx + 1)}>
+ ×
+
+
+ ))}
+
+
+ {
+ setModal(!isModal);
+ document.body.style.overflow = "hidden";
+ }}
+ >
+
+ 문제를 등록해 주세요.
+
+ handleSubmitProblem()}
+ >
+ 강의 등록 완료
+
+
+
+ {isModal && (
+ {
- setModal(!isModal);
- document.body.style.overflow = "hidden";
- }}
- >
-
- 문제를 등록해 주세요.
-
- handleSubmitProblem()}>
- 강의 등록 완료
-
-
-
- {isModal && (
-
- )}
-
+ setModal={setModal}
+ isProblem={isProblem}
+ setProblem={setProblem}
+ handleChangeContent={handleChangeContent}
+ handleCreateProblem={handleCreateProblem}
+ initProblem={initProblem}
+ selectMode={selectMode}
+ setSelectMode={setSelectMode}
+ />
+ )}
+
+ {
+ setIsModalOpen(false);
+ navigate(`/videos/${videoId}/problems`);
+ setProblemList([]);
+ }}
+ />
+ >
);
};
diff --git a/client/src/pages/contents/CartPage/CartPage.js b/client/src/pages/contents/CartPage/CartPage.js
index 0bbf9187..87375953 100644
--- a/client/src/pages/contents/CartPage/CartPage.js
+++ b/client/src/pages/contents/CartPage/CartPage.js
@@ -1,5 +1,5 @@
import axios from "axios";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { styled } from "styled-components";
import { useDispatch, useSelector } from "react-redux";
import CartLeft from "./CartLeft";
@@ -9,8 +9,8 @@ import { useToken } from "../../../hooks/useToken";
import { setCarts } from "../../../redux/createSlice/CartsSlice";
import { PageContainer } from "../../../atoms/layouts/PageContainer";
import { HomeTitle } from "../../../components/contentListItems/ChannelHome";
-import { setIsLoading } from "../../../redux/createSlice/UISettingSlice";
import { useNavigate } from "react-router-dom";
+import { AlertModal, ConfirmModal } from "../../../atoms/modal/Modal";
const globalTokens = tokens.global;
@@ -21,6 +21,8 @@ const CartPage = () => {
const isDark = useSelector((state) => state.uiSetting.isDark);
const token = useSelector((state) => state.loginInfo.accessToken);
const checkedItems = useSelector((state) => state.cartSlice.checkedItem);
+ const [isModalOpen, setIsModalOpen] = useState(false);
+ const [isConfirmOpen, setIsConfirmOpen] = useState(false);
const getCartsData = () => {
return axios
@@ -29,7 +31,6 @@ const CartPage = () => {
})
.then((res) => {
dispatch(setCarts(res.data.data));
- console.log(res.data.data);
})
.catch((err) => {
if (err.response.data?.code === 401) {
@@ -49,13 +50,7 @@ const CartPage = () => {
}
)
.then((res) => {
- console.log(res.data);
- alert("성공적으로 결제가 완료되었습니다.");
- if (window.confirm("구매한 목록 페이지로 가시겠습니까?")) {
- navigate(`/purchased`);
- } else {
- navigate(`/lecture`);
- }
+ setIsModalOpen(true);
})
.catch((err) => {
console.log(err);
@@ -75,22 +70,47 @@ const CartPage = () => {
}, [checkedItems]);
return (
-
-
- 수강 바구니
-
-
-
-
-
-
+ <>
+
+
+ 수강 바구니
+
+
+
+
+
+
+ {
+ setIsModalOpen(false);
+ setIsConfirmOpen(true);
+ }}
+ />
+ {
+ navigate(`/lecture`);
+ }}
+ handlePositiveButtonClick={() => {
+ navigate(`/purchased`);
+ }}
+ />
+ >
);
};
export default CartPage;
-// const globalTokens = tokens.global;
-
export const CartContainer = styled.div`
width: 100%;
max-width: 1170px;
diff --git a/client/src/pages/contents/CartPage/TossPayment.js b/client/src/pages/contents/CartPage/TossPayment.js
index 2004febc..6e0844c7 100644
--- a/client/src/pages/contents/CartPage/TossPayment.js
+++ b/client/src/pages/contents/CartPage/TossPayment.js
@@ -1,14 +1,13 @@
import axios from "axios";
import { useState } from "react";
import { styled } from "styled-components";
-import { useDispatch, useSelector } from "react-redux";
+import { useSelector } from "react-redux";
import { loadTossPayments } from "@tosspayments/payment-sdk";
import { BigButton } from "../../../atoms/buttons/Buttons";
-import { setIsLoading } from "../../../redux/createSlice/UISettingSlice";
import Loading from "../../../atoms/loading/Loading";
+import { AlertModal } from "../../../atoms/modal/Modal";
const PaymentBtn = ({ isDiscount }) => {
- const dispatch = useDispatch();
const [isLoading, setLoading] = useState(false);
const isDark = useSelector((state) => state.uiSetting.isDark);
const cartsItems = useSelector((state) => state.cartSlice.data);
@@ -19,10 +18,11 @@ const PaymentBtn = ({ isDiscount }) => {
const orderName = orderList && orderList.videoName;
const orderDetail =
checkedItems.length > 1 ? ` 외 ${checkedItems.length - 1}건` : "";
+ const [isModalOpen, setIsModalOpen] = useState(false);
const handlePostPayment = () => {
if (!checkedItems.length) {
- return alert("선택된 강의가 없습니다.");
+ return setIsModalOpen(true);
}
return axios
.post(
@@ -79,6 +79,14 @@ const PaymentBtn = ({ isDiscount }) => {
결제하기
+ setIsModalOpen(false)}
+ />
>
);
};
diff --git a/client/src/pages/contents/DetailPage/DetailReview.js b/client/src/pages/contents/DetailPage/DetailReview.js
index 4a1f6674..d5175c5e 100644
--- a/client/src/pages/contents/DetailPage/DetailReview.js
+++ b/client/src/pages/contents/DetailPage/DetailReview.js
@@ -14,6 +14,7 @@ import {
Heading5Typo,
} from "../../../atoms/typographys/Typographys";
import { RegularButton, TextButton } from "../../../atoms/buttons/Buttons";
+import { AlertModal } from "../../../atoms/modal/Modal";
const globalTokens = tokens.global;
@@ -36,6 +37,10 @@ const DetailReview = () => {
const myId = useSelector((state) => state.loginInfo.myid);
const videoDatas = useSelector((state) => state.videoInfo.data);
const token = useSelector((state) => state.loginInfo.accessToken);
+ const [isModalOpen, setIsModalOpen] = useState({
+ isModalOpen: false,
+ content: "",
+ });
const getReview = () => {
const queryString = new URLSearchParams(isParams).toString();
@@ -55,13 +60,25 @@ const DetailReview = () => {
const postReview = () => {
if (myId === videoDatas.channel.memberId) {
- return alert("내 강의에는 리뷰를 쓸 수 없습니다.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "내 강의에는 리뷰를 쓸 수 없습니다.",
+ });
}
if (!isReply.content) {
- return alert("감상평을 입력해주세요.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "감상평을 입력해주세요.",
+ });
}
if (!isReply.star) {
- return alert("별점을 선택해주세요.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "별점을 선택해주세요.",
+ });
}
return axios
.post(`https://api.itprometheus.net/videos/${videoId}/replies`, isReply, {
@@ -69,18 +86,29 @@ const DetailReview = () => {
})
.then((res) => {
if (res.status === 201) {
- alert("성공적으로 댓글이 등록되었습니다.");
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "성공적으로 댓글이 등록되었습니다.",
+ });
}
setReply({ content: "", star: 0 });
- // window.location.reload();
getReview();
})
.catch((err) => {
if (err.response.status === 403) {
- alert("구매한 강의만 리뷰를 남길 수 있습니다.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "구매한 강의만 리뷰를 남길 수 있습니다.",
+ });
}
if (err.response.status === 404) {
- alert("수강평은 한 번만 작성할 수 있습니다.");
+ return setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: true,
+ content: "수강평은 한 번만 작성할 수 있습니다.",
+ });
}
});
};
@@ -91,104 +119,123 @@ const DetailReview = () => {
useEffect(() => {
getReview();
- }, []); // isParams.page, isParams.sort, isParams.star
+ }, []);
useMemo(() => {
getReview();
}, [isParams.page, isParams.sort, isParams.star]);
return (
-
- 수강평 {isReviews.length}
- { videoDatas.isPurchased &&
-
- 리뷰
- 별점을 선택해주세요.
-
-
-
+
+ 수강평 {isReviews.length}
+ {videoDatas.isPurchased && (
+
+ 리뷰
+ 별점을 선택해주세요.
+
+
+ handleChangeReply(e)}
+ />
+ {
+ e.preventDefault();
+ postReview();
+ }}
+ >
+ 등록
+
+
+
+ )}
+
+
+ handleChangeReply(e)}
- />
- {
+ setActive(1);
+ setParams({ ...isParams, sort: "created-date" });
+ }}
+ >
+ 최신순
+
+ {
- e.preventDefault();
- postReview();
+ isActive={isActive === 2}
+ onClick={() => {
+ setActive(2);
+ setParams({ ...isParams, sort: "star" });
}}
>
- 등록
-
-
-
- }
-
-
- {
- setActive(1);
- setParams({ ...isParams, sort: "created-date" });
- }}
- >
- 최신순
-
- {
- setActive(2);
- setParams({ ...isParams, sort: "star" });
- }}
- >
- 별점순
-
- {
- setActive(3);
- }}
- >
- 별점별
- {isActive === 3 && (
- <>
-
- {isParams.star}
- {
- setParams({ ...isParams, sort: "", star: e.target.value });
- }}
- />
- >
- )}
-
-
- {!isReviews.length ? (
- 현재 리뷰가 없습니다.
- ) : (
-
- {isReviews.map((el, idx) => (
-
- ))}
-
- )}
-
-
+ {
+ setActive(3);
+ }}
+ >
+ 별점별
+ {isActive === 3 && (
+ <>
+
+ {isParams.star}
+ {
+ setParams({
+ ...isParams,
+ sort: "",
+ star: e.target.value,
+ });
+ }}
+ />
+ >
+ )}
+
+
+ {!isReviews.length ? (
+ 현재 리뷰가 없습니다.
+ ) : (
+
+ {isReviews.map((el, idx) => (
+
+ ))}
+
+ )}
+
+
+
+
+ setIsModalOpen({
+ ...isModalOpen,
+ isModalOpen: false,
+ })
+ }
/>
-
+ >
);
};
diff --git a/client/src/pages/contents/DetailPage/DetailVideo.js b/client/src/pages/contents/DetailPage/DetailVideo.js
index 4b07ac95..6b50d9a1 100644
--- a/client/src/pages/contents/DetailPage/DetailVideo.js
+++ b/client/src/pages/contents/DetailPage/DetailVideo.js
@@ -21,6 +21,7 @@ import {
import profileGray from "../../../assets/images/icons/profile/profileGray.svg";
import AddCart from "../../../components/DetailPage/AddCart";
import VideoPlayer from "../../../components/DetailPage/VideoPlayer";
+import { AlertModal } from "../../../atoms/modal/Modal";
const globalTokens = tokens.global;
@@ -36,6 +37,8 @@ const DetailVideo = () => {
const [isSub, setSub] = useState("");
const [channelInfo, setChannelInfo] = useState({});
const [isPrevMode, setPrevMode] = useState(false);
+ const [purchaseModal, setPurchaseModal] = useState(false);
+ const [alertModal, setAlertModal] = useState(false);
useEffect(() => {
getChannelInfo();
@@ -69,8 +72,7 @@ const DetailVideo = () => {
}
)
.then((res) => {
- alert("성공적으로 강의가 구매 되었습니다.");
- window.location.reload();
+ setPurchaseModal(true);
})
.catch((err) => {
if (err.response.data.message === "만료된 토큰입니다.") {
@@ -104,99 +106,43 @@ const DetailVideo = () => {
const handleNavProblem = () => {
if (!videoDatas.isPurchased && myId !== videoDatas.channel.memberId) {
- alert("강의를 먼저 구매해주세요.");
+ setAlertModal(true);
} else {
navigate(`/videos/${videoId}/problems`);
}
};
return (
-
-
- 강의를 다 들었다면?
-
- 문제 풀러가기 →
-
-
+ <>
+
+
+ 강의를 다 들었다면?
+
+ 문제 풀러가기 →
+
+
- {videoDatas.isPurchased || myId === videoDatas.channel.memberId ? (
-
- ) : (
-
- {
- setPrevMode(true);
- dispatch(setPrev(true));
- setTimeout(() => {
- dispatch(setPrev(false));
- }, 61000);
- }}
- >
- 1분 미리보기
-
- {
- if (videoDatas.price > 0) {
- handleCartNav();
- } else {
- handlePurchase();
- }
- }}
- >
- 강의 구매하기
-
-
- )}
-
-
- {videoDatas.videoName}
- {!videoDatas.isPurchased && myId !== videoDatas.channel.memberId && (
- {videoDatas.price ? `${videoDatas.price}원` : "무료"}
- )}
-
-
-
-
-
-
-
- {videoDatas.channel.channelName}
-
-
- 구독자 {channelInfo.subscribers}명
-
-
-
-
- {myId === videoDatas.channel.memberId || (
-
- )}
-
- {!videoDatas.isPurchased && myId !== videoDatas.channel.memberId && (
-
- {videoDatas.price > 0 && (
-
- )}
-
+ {
+ setPrevMode(true);
+ dispatch(setPrev(true));
+ setTimeout(() => {
+ dispatch(setPrev(false));
+ }, 61000);
+ }}
+ >
+ 1분 미리보기
+
+ {
if (videoDatas.price > 0) {
handleCartNav();
@@ -206,11 +152,88 @@ const DetailVideo = () => {
}}
>
강의 구매하기
-
-
+
+
)}
-
-
+
+
+ {videoDatas.videoName}
+ {!videoDatas.isPurchased && myId !== videoDatas.channel.memberId && (
+ {videoDatas.price ? `${videoDatas.price}원` : "무료"}
+ )}
+
+
+
+
+
+
+
+ {videoDatas.channel.channelName}
+
+
+ 구독자 {channelInfo.subscribers}명
+
+
+
+
+ {myId === videoDatas.channel.memberId || (
+
+ )}
+
+ {!videoDatas.isPurchased && myId !== videoDatas.channel.memberId && (
+
+ {videoDatas.price > 0 && (
+
+ )}
+ {
+ if (videoDatas.price > 0) {
+ handleCartNav();
+ } else {
+ handlePurchase();
+ }
+ }}
+ >
+ 강의 구매하기
+
+
+ )}
+
+
+ {
+ setPurchaseModal(false);
+ window.location.reload();
+ }}
+ />
+ setAlertModal(false)}
+ />
+ >
);
};