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
27 changes: 27 additions & 0 deletions frontend/src/components/ImageLimitModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Modal, Button } from "flowbite-react";

interface ImageLimitModalProps {
show: boolean;
onClose: () => void;
}

export const ImageLimitModal = ({ show, onClose }: ImageLimitModalProps) => {
return (
<Modal show={show} size="md" onClose={onClose} position="center">
<div className="px-6 py-8 text-center">
<p className="mb-2 text-base whitespace-nowrap text-gray-700 dark:text-gray-300">
이미지는 최대 10장까지만 업로드할 수 있습니다.
</p>
<p className="mb-8 text-base text-gray-700 dark:text-gray-300">
다시 선택해주세요.
</p>

<div className="flex justify-center">
<Button color="gray" onClick={onClose}>
확인
</Button>
</div>
</div>
</Modal>
);
};
114 changes: 59 additions & 55 deletions frontend/src/components/ModalBoardForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useState} from "react";
import React, { useState } from "react";
import {
Button,
FileInput,
Expand All @@ -10,20 +10,22 @@ import {
Label,
TextInput,
} from "flowbite-react";
import {TagForm} from "./TagForm";
import api from "../api/axiosInstance.ts";
import { TagForm } from "./TagForm";
import api from "../api/axiosInstance";
import { ImageLimitModal } from "./ImageLimitModal"; // 모달 추가

interface ModalComponentProps {
open: boolean;
onClose: () => void;
}

export const ModalBoardForm = ({open, onClose}: ModalComponentProps) => {
export const ModalBoardForm = ({ open, onClose }: ModalComponentProps) => {
const [tags, setTags] = useState<string[]>([]);
const [title, setTitle] = useState<string>("");
const [content, setContent] = useState<string>("");
const [recruitmentStatus, setRecruitmentStatus] = useState<string>("NONE");
const [files, setFiles] = useState<File[]>([]);
const [showLimitModal, setShowLimitModal] = useState(false); // 모달 상태

const resetForm = () => {
setTags([]);
Expand All @@ -42,11 +44,18 @@ export const ModalBoardForm = ({open, onClose}: ModalComponentProps) => {
const selected = e.target.files;
if (selected) {
const newFiles = Array.from(selected);
setFiles((prev) => [...prev, ...newFiles].slice(0, 10)); // 최대 10개 누적
const totalFiles = files.length + newFiles.length;
if (totalFiles > 10) {
setFiles([]);
e.target.value = "";
setShowLimitModal(true);
} else {
setFiles((prev) => [...prev, ...newFiles]);
}
}
};

const handleSubmit = async () => {
const handleSubmit = async () => {
const formData = new FormData();
formData.append("title", title);
formData.append("content", content);
Expand All @@ -60,7 +69,6 @@ export const ModalBoardForm = ({open, onClose}: ModalComponentProps) => {
"Content-Type": "multipart/form-data",
},
});
console.log("Post created successfully.");
window.location.reload();
handleClose();
} catch (error) {
Expand All @@ -69,93 +77,89 @@ export const ModalBoardForm = ({open, onClose}: ModalComponentProps) => {
};

return (
<>
<Modal show={open} onClose={handleClose}>
<ModalHeader>게시글 작성</ModalHeader>
<ModalBody>
<div className="space-y-4">
<div>
<Label htmlFor="title">제목</Label>
<TextInput
id="title"
placeholder="제목을 입력해주세요"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
id="title"
placeholder="제목을 입력해주세요"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
/>
</div>

<div>
<Label htmlFor="content">내용</Label>
<Textarea
id="content"
placeholder="내용을 입력해주세요"
value={content}
rows={4}
onChange={(e) => setContent(e.target.value)}
required
id="content"
placeholder="내용을 입력해주세요"
value={content}
rows={4}
onChange={(e) => setContent(e.target.value)}
required
/>
</div>

<div className="flex items-center gap-4 mt-2 text-sm">
<div className="mt-2 flex items-center gap-4 text-sm">
<Label className="whitespace-nowrap">모집 상태</Label>
<div className="flex gap-4">
<label className="flex items-center gap-1">
<input
{["NONE", "RECRUITING", "DONE"].map((status) => (
<label key={status} className="flex items-center gap-1">
<input
type="radio"
name="recruitmentStatus"
value="NONE"
checked={recruitmentStatus === "NONE"}
value={status}
checked={recruitmentStatus === status}
onChange={(e) => setRecruitmentStatus(e.target.value)}
/>
선택 안 함
</label>
<label className="flex items-center gap-1">
<input
type="radio"
name="recruitmentStatus"
value="RECRUITING"
checked={recruitmentStatus === "RECRUITING"}
onChange={(e) => setRecruitmentStatus(e.target.value)}
/>
모집 중
</label>
<label className="flex items-center gap-1">
<input
type="radio"
name="recruitmentStatus"
value="DONE"
checked={recruitmentStatus === "DONE"}
onChange={(e) => setRecruitmentStatus(e.target.value)}
/>
모집 마감
</label>
/>
{status === "NONE"
? "선택 안 함"
: status === "RECRUITING"
? "모집 중"
: "모집 마감"}
</label>
))}
</div>
</div>

<div>
<Label htmlFor="file">이미지 (10개까지만 첨부됩니다)</Label>
<FileInput id="file" multiple={true} onChange={handleFileChange}/>
<Label htmlFor="file">
이미지 (최대 10장까지만 업로드할 수 있습니다)
</Label>
<FileInput id="file" multiple onChange={handleFileChange} />
<ul className="mt-2 text-sm text-gray-600">
{files.map((file, idx) => (
<li key={idx}>📎 {file.name}</li>
<li key={idx}>📎 {file.name}</li>
))}
</ul>
</div>

<TagForm
externalTags={tags}
onTagsChange={(updatedTags) => setTags(updatedTags)}
/>
<TagForm externalTags={tags} onTagsChange={setTags} />
</div>
</ModalBody>
<ModalFooter className="flex justify-end space-x-2">
<Button className="!bg-blue-900 hover:!bg-blue-800" onClick={handleSubmit}>
<Button
className="!bg-blue-900 hover:!bg-blue-800"
onClick={handleSubmit}
>
작성
</Button>
<Button color="gray" onClick={handleClose}>
취소
</Button>
</ModalFooter>
</Modal>

{/* 이미지 제한 모달 */}
<ImageLimitModal
show={showLimitModal}
onClose={() => setShowLimitModal(false)}
/>
</>
);
};
};
Loading