Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 32 additions & 18 deletions front-end/src/components/modal/FileUploadPopupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,44 @@ import CloseIcon from '@/assets/icons/close.svg?react';
import { validateFile } from '@/utils/util';

type FileUploadPopupModalProps = {
fileName?: string;
onClickCloseButton: () => void;
onClickSaveButton: (file: File) => void;
onClickSaveButton: (file: File | null) => void;
};

const FileUploadPopupModal = ({
fileName,
onClickCloseButton,
onClickSaveButton,
}: FileUploadPopupModalProps) => {
const [file, setFile] = useState<File | null>(null);
const [currentFileName, setCurrentFileName] = useState<string | null>(
fileName || null
);
const fileInputRef = useRef<HTMLInputElement>(null);

function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
const files = event.target.files;
if (files) {
validateFile(files[0]);
setFile(files[0]);
setCurrentFileName(files[0].name);
}
}

function handleDeleteFile() {
setFile(null);
setCurrentFileName(null);
if (fileInputRef.current) fileInputRef.current.value = '';
}

function checkIsFileChanged() {
if (!fileName && !file) return false;
if (fileName === currentFileName && !file) return false;

return true;
}

return (
<div className={S.modal} onClick={(e) => e.stopPropagation()}>
<button className={S.closeButton} onClick={onClickCloseButton}>
Expand All @@ -38,21 +57,16 @@ const FileUploadPopupModal = ({
열지 않아도 자동으로 열려요.
</p>
</div>
{file && (
<div className={S.fileContainer}>
<span className={S.fileInfo}>{file.name} </span>
<p className={S.fileSize}>({Math.floor(file.size / 1000)}K)</p>
<button
className={S.deleteButton}
onClick={() => {
setFile(null);
if (fileInputRef.current) fileInputRef.current.value = '';
}}
>
<CloseIcon width="16px" height="16px" color="white" />
</button>
</div>
)}
<div className={S.fileContainer}>
{currentFileName && (
<>
<span className={S.fileInfo}>{currentFileName} </span>
<button className={S.deleteButton} onClick={handleDeleteFile}>
<CloseIcon width="16px" height="16px" color="white" />
</button>
</>
)}
</div>
<div className={S.buttonContainer}>
<input
type="file"
Expand All @@ -74,8 +88,8 @@ const FileUploadPopupModal = ({
size="web4"
height="80px"
text="저장하기"
onClick={() => file && onClickSaveButton(file)}
isActive={!!file}
onClick={() => onClickSaveButton(file)}
isActive={checkIsFileChanged()}
/>
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions front-end/src/repository/courseRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,15 @@ class CourseRepository {
await throwError(response);
}

async uploadCourseFile(courseId: Course['id'], file: File): Promise<string> {
async uploadCourseFile(
courseId: Course['id'],
file: File | null
): Promise<string> {
// API: POST /professors/courses/{courseId}/file
// Request body: FormData { key: 'file', value: file }

const form = new FormData();
form.append('file', file);
if (file) form.append('file', file);

const response = await fetch(`/api/professors/courses/${courseId}/file`, {
method: 'POST',
Expand Down
60 changes: 41 additions & 19 deletions front-end/src/utils/courseAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,23 @@ type courseActionsProps = {
const fileSuccessModal = (
setModal: React.Dispatch<React.SetStateAction<React.ReactNode | null>>,
openModal: () => void,
closeModal: () => void
closeModal: () => void,
navigate: NavigateFunction
) => {
setModal(
<AlertModal
type="success"
message="파일이 성공적으로 업로드되었습니다."
message="파일이 성공적으로 수정되었습니다."
buttonText="확인"
onClickCloseButton={() => {
closeModal();
setModal(null);
navigate(0);
}}
onClickModalButton={async () => {
closeModal();
setModal(null);
navigate(0);
}}
/>
);
Expand Down Expand Up @@ -126,27 +129,45 @@ const courseActions = ({
};

const handleFileCourse = (course: CourseMeta) => {
const handleFileSave = async (file: File) => {
const handleFileSave = async (file: File | null) => {
try {
if (course?.fileName) {
setModal(
<AlertModal
type="caution"
message="새 파일을 저장하시겠습니까?"
description="이미 저장된 강의자료가 있습니다. 삭제하고 새 파일을 저장하시겠습니까?"
buttonText="새 파일 저장"
onClickModalButton={async () => {
await courseRepository.uploadCourseFile(course.id, file);
fileSuccessModal(setModal, openModal, closeModal);
}}
onClickCloseButton={() => {
offModal();
}}
/>
);
if (file) {
setModal(
<AlertModal
type="caution"
message="새 파일을 저장하시겠습니까?"
description="이미 저장된 강의자료가 있습니다. 삭제하고 새 파일을 저장하시겠습니까?"
buttonText="새 파일 저장"
onClickModalButton={async () => {
await courseRepository.uploadCourseFile(course.id, file);
fileSuccessModal(setModal, openModal, closeModal, navigate);
}}
onClickCloseButton={() => {
offModal();
}}
/>
);
} else {
setModal(
<AlertModal
type="caution"
message="파일을 삭제하시겠습니까?"
description="이미 저장된 강의자료를 삭제하시겠습니까?"
buttonText="삭제"
onClickModalButton={async () => {
await courseRepository.uploadCourseFile(course.id, file);
fileSuccessModal(setModal, openModal, closeModal, navigate);
}}
onClickCloseButton={() => {
offModal();
}}
/>
);
}
} else {
await courseRepository.uploadCourseFile(course.id, file);
fileSuccessModal(setModal, openModal, closeModal);
fileSuccessModal(setModal, openModal, closeModal, navigate);
}
} catch (error) {
popupError(error);
Expand All @@ -155,6 +176,7 @@ const courseActions = ({

setModal(
<FileUploadPopupModal
fileName={course?.fileName}
onClickCloseButton={() => {
offModal();
}}
Expand Down