Skip to content

Commit

Permalink
Feature/upload pdf in whitebook (#90)
Browse files Browse the repository at this point in the history
Co-authored-by: Seokyun Ha <[email protected]>
  • Loading branch information
khkim6040 and BlueHorn07 authored Feb 12, 2025
1 parent f6e1f2e commit 8cfdfbc
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 53 deletions.
128 changes: 104 additions & 24 deletions components/board/whitebook/whitebook.create.modal.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
import { Form, Modal } from 'semantic-ui-react';
import { Form, Modal, Radio } from 'semantic-ui-react';
import { useState } from 'react';
import { PoPoAxios } from '@/utils/axios.instance';

const WhitebookCreateModal = (props) => {
const [open, setOpen] = useState(false);
const [title, setTitle] = useState('');
const [link, setLink] = useState('');
const [content, setContent] = useState('');
const [showOnlyLogin, setShowOnlyLogin] = useState(false);

const [inputType, setInputType] = useState('link');
const [link, setLink] = useState('');
const [pdfFile, setPdfFile] = useState(null);

const handleFileChange = (file) => {
if (!file || file.type !== 'application/pdf') {
alert('PDF 파일만 업로드 가능합니다.');
setPdfFile(null);
return;
}
setPdfFile(file);
};

const handleSubmit = async () => {
try {
await PoPoAxios.post(
'/whitebook',
{
title: title,
link: link,
content: content,
show_only_login: showOnlyLogin,
},
{ withCredentials: true },
);
setOpen(false);
window.location.reload();
} catch (e) {
alert('생활백서 생성에 실패했습니다.');
console.log(e);
const formData = new FormData();
formData.append('title', title);
formData.append('content', content);
formData.append('show_only_login', showOnlyLogin);

if (inputType === 'link' && link) {
formData.append('link', link);
} else if (inputType === 'pdf' && pdfFile) {
formData.append('pdf_file', pdfFile);
} else {
alert('링크 또는 PDF 파일을 입력해주세요.');
return;
}

await PoPoAxios.post(`/whitebook`, formData, {
withCredentials: true,
headers: { 'Content-Type': 'multipart/form-data' },
})
.then(() => {
alert('생활백서를 생성 했습니다.');
window.location.reload();
})
.catch((err) => {
alert('생활백서 생성에 실패했습니다.');
console.error(err);
});
};

return (
Expand All @@ -45,12 +66,71 @@ const WhitebookCreateModal = (props) => {
label={'생활백서 제목'}
onChange={(e) => setTitle(e.target.value)}
/>
<Form.Input
required
label={'생활백서 링크'}
placeholder={'https://xxxx.postech.ac.kr'}
onChange={(e) => setLink(e.target.value)}
/>

{/* PDF 또는 링크 선택 */}
<Form.Group inline>
<label>파일 타입 선택:</label>
<Form.Field>
<Radio
label="링크 입력"
name="inputType"
value="link"
checked={inputType === 'link'}
onChange={() => {
setInputType('link');
}}
/>
</Form.Field>
<Form.Field>
<Radio
label="PDF 업로드"
name="inputType"
value="pdf"
checked={inputType === 'pdf'}
onChange={() => {
setInputType('pdf');
}}
/>
</Form.Field>
</Form.Group>

{/* 조건부 렌더링: 링크 입력 필드 */}
{inputType === 'link' && (
<Form.Input
required
label={'생활백서 링크'}
placeholder={'https://xxxx.postech.ac.kr'}
onChange={(e) => setLink(e.target.value)}
/>
)}

{/* 조건부 렌더링: PDF 업로드 필드 */}
{inputType === 'pdf' && (
<Form.Field>
<Form.Input
required
label={'생활백서 PDF'}
type="file"
accept="application/pdf"
onChange={(e) => handleFileChange(e.target.files[0])}
/>
<label>
{pdfFile && (
<a
href={URL.createObjectURL(pdfFile)}
target="_blank"
rel="noopener noreferrer"
style={{
textDecoration: 'underline',
}}
>
{pdfFile.name}
</a>
)}
</label>
</Form.Field>
)}

<Form.TextArea
required
label={'생활백서 설명글'}
Expand Down
2 changes: 1 addition & 1 deletion components/board/whitebook/whitebook.table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const WhitebookTable = ({ whitebooks }) => {
<Table celled selectable textAlign={'center'}>
<Table.Header>
<Table.Row>
<Table.HeaderCell>idx.</Table.HeaderCell>
<Table.HeaderCell>번호</Table.HeaderCell>
<Table.HeaderCell>제목</Table.HeaderCell>
<Table.HeaderCell>내용</Table.HeaderCell>
<Table.HeaderCell>생성일</Table.HeaderCell>
Expand Down
158 changes: 131 additions & 27 deletions components/board/whitebook/whitebook.update.modal.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Form, Icon, Modal } from 'semantic-ui-react';
import { Button, Form, Icon, Modal, Radio } from 'semantic-ui-react';
import { useState } from 'react';
import DeleteConfirmModal from '../../common/delete.confirm.modal';
import { PoPoAxios } from '@/utils/axios.instance';
Expand All @@ -8,28 +8,70 @@ const WhitebookUpdateModal = ({ trigger, whitebook }) => {
const [deleteModalOpen, setDeleteModalOpen] = useState(false);

const [title, setTitle] = useState(whitebook.title);
const [link, setLink] = useState(whitebook.link);
const [content, setContent] = useState(whitebook.content);
const [showOnlyLogin, setShowOnlyLogin] = useState(whitebook.show_only_login);
const [inputType, setInputType] = useState(whitebook.link ? 'link' : 'pdf');
const [link, setLink] = useState(whitebook.link || '');
const [uploadedPDFLink, setUploadedPDFLink] = useState(null);
const [pdfFile, setPdfFile] = useState(null);

const handleModalOpen = () => {
setOpen(true);
// 링크에 whitebook이 들어간다면 S3에 있는 pdf 파일임
if (whitebook.link && whitebook.link.includes('whitebook')) {
const link = whitebook.link;
setLink('');
setUploadedPDFLink(link);
setInputType('pdf');
}
};

const handleFileChange = (file) => {
if (!file || file.type !== 'application/pdf') {
alert('PDF 파일만 업로드 가능합니다.');
setPdfFile(null);
return;
}
setPdfFile(file);
};

const handleSubmit = async () => {
try {
await PoPoAxios.put(
`/whitebook/${whitebook.uuid}`,
{
title: title,
link: link,
content: content,
show_only_login: showOnlyLogin,
},
{ withCredentials: true },
);
setOpen(false);
window.location.reload();
} catch (e) {
alert('생활백서 수정에 실패했습니다.');
console.log(e);
const formData = new FormData();
formData.append('title', title);
formData.append('content', content);
formData.append('show_only_login', showOnlyLogin);

if (inputType === 'link' && link) {
formData.append('link', link);
} else if (inputType === 'pdf' && pdfFile) {
formData.append('pdf_file', pdfFile);
} else {
// title, content, show_only_login 중 하나라도 변경되었다면 수정 가능
if (
title !== whitebook.title ||
content !== whitebook.cotent ||
showOnlyLogin !== whitebook.show_only_login
) {
const link = inputType === 'link' ? link : uploadedPDFLink;
formData.append('link', link);
} else {
alert('링크 또는 PDF 파일을 입력해주세요.');
return;
}
}

await PoPoAxios.put(`/whitebook/${whitebook.uuid}`, formData, {
withCredentials: true,
headers: { 'Content-Type': 'multipart/form-data' },
})
.then(() => {
alert('생활백서 정보를 수정 했습니다.');
window.location.reload();
})
.catch((err) => {
alert('생활백서 수정에 실패했습니다.');
console.error(err);
});
};

return (
Expand All @@ -38,7 +80,7 @@ const WhitebookUpdateModal = ({ trigger, whitebook }) => {
open={open}
trigger={trigger}
onClose={() => setOpen(false)}
onOpen={() => setOpen(true)}
onOpen={handleModalOpen}
>
<Modal.Header>생활백서 수정</Modal.Header>
<Modal.Content>
Expand All @@ -49,19 +91,81 @@ const WhitebookUpdateModal = ({ trigger, whitebook }) => {
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<Form.Input
required
label={'생활백서 링크'}
value={link}
placeholder={'https://xxxx.postech.ac.kr'}
onChange={(e) => setLink(e.target.value)}
/>

{/* PDF 또는 링크 선택 */}
<Form.Group inline>
<label>파일 타입 선택:</label>
<Form.Field>
<Radio
label="링크 입력"
name="inputType"
value="link"
checked={inputType === 'link'}
onChange={() => {
setInputType('link');
}}
/>
</Form.Field>
<Form.Field>
<Radio
label="PDF 업로드"
name="inputType"
value="pdf"
checked={inputType === 'pdf'}
onChange={() => {
setInputType('pdf');
}}
/>
</Form.Field>
</Form.Group>

{/* 조건부 렌더링: 링크 입력 필드 */}
{inputType === 'link' && (
<Form.Input
required
label={'생활백서 링크'}
placeholder={'https://xxxx.postech.ac.kr'}
value={link}
onChange={(e) => setLink(e.target.value)}
/>
)}

{/* 조건부 렌더링: PDF 업로드 필드 */}
{inputType === 'pdf' && (
<Form.Field>
<Form.Input
required
label={'생활백서 PDF'}
type="file"
accept="application/pdf"
onChange={(e) => handleFileChange(e.target.files[0])}
/>
<label>
{(pdfFile || uploadedPDFLink) && (
<a
href={
pdfFile ? URL.createObjectURL(pdfFile) : uploadedPDFLink
}
target="_blank"
rel="noopener noreferrer"
style={{
textDecoration: 'underline',
}}
>
{pdfFile ? pdfFile.name : '기존 PDF 확인'}
</a>
)}
</label>
</Form.Field>
)}

<Form.TextArea
required
label={'생활백서 설명글'}
value={content}
onChange={(e) => setContent(e.target.value)}
/>

<Form.Checkbox
required
label={'로그인 유저에게만 보이기'}
Expand All @@ -76,7 +180,7 @@ const WhitebookUpdateModal = ({ trigger, whitebook }) => {
</Form.Button>
<DeleteConfirmModal
open={deleteModalOpen}
target={name}
target={whitebook.title}
deleteURI={`whitebook/${whitebook.uuid}`}
trigger={
<Button negative onClick={() => setDeleteModalOpen(true)}>
Expand Down
5 changes: 4 additions & 1 deletion pages/board/whitebook.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ const WhitebookPage = () => {
<div style={{ marginBottom: '1rem' }}>
<WhitebookCreateModal trigger={<Button>생활백서 생성</Button>} />
</div>
<p>생활백서는 조회순으로 정렬되어 표시됩니다!</p>
<p>
생활백서는 조회순으로 정렬되어 표시됩니다. 박스 안을 클릭하면 수정할 수
있습니다.
</p>
<div>
<WhitebookTable whitebooks={whitebooks} />
</div>
Expand Down

0 comments on commit 8cfdfbc

Please sign in to comment.