728x90
프로젝트 중심
-----------------------------------------------------------------------------------------------------
갤러리(Gallery) 컴포넌트 기능 구현
GalleryDetail 컴포넌트
import React, { Component } from "react";
import "../../css/Gallery/GalleryDetail.css";
import axios from "axios";
class GalleryDetail extends Component {
constructor(props) {
super(props);
this.state = {
showEditForm: false,
title: "",
file: null,
imgPreview: null,
contents: "",
writer: "",
writeDate: "",
};
}
componentDidUpdate(prevProps) {
if (prevProps !== this.props) {
const { title, contents, writer, writeDate } = this.props;
this.setState({
title,
contents,
writer,
writeDate,
});
}
}
handleBackClick = () => {
const { onBack } = this.props;
if (onBack) {
onBack();
}
};
handleEditClick = () => {
const { gallery } = this.props;
const { title, contents, writer, writeDate } = gallery;
this.setState((prevState) => ({
showEditForm: !prevState.showEditForm,
title,
contents,
writer,
writeDate,
}));
};
handleDeleteClick = () => {
const { gallery, onDelete } = this.props;
axios
.delete(`/gallery/${gallery.no}`)
.then((response) => {
alert("게시글이 삭제되었습니다.");
onDelete(gallery.no);
console.log("Gallery deleted successfully:", response.data);
})
.catch((error) => {
console.error("Error deleting gallery:", error);
});
};
handleImgSelect = (e) => {
const file = e.target.files[0];
const imgPreview = URL.createObjectURL(file);
if (file) {
// 파일 유효성 검사 로직 추가
const allowedTypes = ["image/jpeg", "image/png"]; // 허용된 파일 유형
if (allowedTypes.includes(file.type)) {
// 유효한 파일 유형인 경우
this.setState({ file, imgPreview });
} else {
// 유효하지 않은 파일 유형인 경우에 대한 처리
console.error("Invalid file type. Please select a JPEG or PNG image.");
// 파일 선택을 초기화하거나 사용자에게 알림을 표시할 수 있습니다.
alert(
"유효하지 않은 이미지 유형입니다. JPEG 또는 PNG 파일을 사용해주세요."
);
}
} else {
// 파일 선택하지 않은 경우에 대한 처리
console.error("No img selected. Please choose an image.");
// 사용자에게 알림을 표시할 수 있습니다.
alert("이미지가 선택되지 않았습니다. 이미지를 첨부해주세요.");
}
};
handleInputChange = (e) => {
const { name, value } = e.target;
this.setState({
[name]: value,
});
};
handleUpdateClick = () => {
const { gallery, onUpdate } = this.props;
const { title, file, contents, writer, writeDate } = this.state;
const updatedGallery = new FormData();
updatedGallery.append("title", title);
if (file) {
updatedGallery.append("img", file);
}
updatedGallery.append("contents", contents);
updatedGallery.append("writer", writer);
updatedGallery.append("writeDate", writeDate);
axios
.put(`/gallery/${gallery.no}`, updatedGallery)
.then((response) => {
alert("게시글이 수정되었습니다.");
onUpdate(updatedGallery);
this.setState({ showEditForm: false });
console.log("Gallery updated successfully:", response.data);
})
.catch((error) => {
console.error("Error updating gallery:", error);
});
};
render() {
const { gallery } = this.props;
const {
showEditForm,
title,
imgPreview,
contents,
writer,
writeDate,
} = this.state;
const show = `/uploads/gallery/${gallery.img}`;
if (!gallery) {
return <div>Loading...</div>;
}
return (
<div id="gallery-detail">
{showEditForm ? (
<form id="re-gallery">
<div id="gal-title">
<label htmlFor="title">제목:</label>
<input
type="text"
id="title"
name="title"
value={title}
onChange={this.handleInputChange}
/>
</div>
<div id="gal-img">
<label htmlFor="img">이미지:</label>
<input
type="file"
id="img"
name="img"
onChange={this.handleImgSelect}
/>
<div id="show-imgpre">
{imgPreview && <img src={imgPreview} alt="show-imgpre" />}
</div>
</div>
<div id="gal-contents">
<label htmlFor="contents">내용:</label>
<textarea
id="contents"
name="contents"
value={contents}
onChange={this.handleInputChange}
></textarea>
</div>
<div id="gal-writer">
<label htmlFor="writer">작성자:</label>
<input
type="text"
id="writer"
name="writer"
value={writer}
onChange={this.handleInputChange}
/>
</div>
<div id="gal-writeDate">
<label htmlFor="writeDate">작성일:</label>
<input
type="date"
id="writeDate"
name="writeDate"
value={writeDate}
onChange={this.handleInputChange}
/>
</div>
<button onClick={this.handleUpdateClick}>확인</button>
<button onClick={this.handleEditClick}>취소</button>
</form>
) : (
<>
<div id="title">{gallery.title}</div>
<div id="img">
<img src={show} alt="gallery-img" />
</div>
<div id="contents">{gallery.contents}</div>
<div id="writer">{gallery.writer}</div>
<div id="writeDate">{gallery.writeDate}</div>
<button onClick={this.handleBackClick}>뒤로 가기</button>
<button onClick={this.handleEditClick}>수정</button>
<button onClick={this.handleDeleteClick}>삭제</button>
</>
)}
</div>
);
}
}
export default GalleryDetail;
GalleryList 컴포넌트
import React, { Component } from "react";
import "../../css/Board/BoardList.css";
import TakeGallery from "./TakeGallery.js";
import GalleryDetail from "./GalleryDetail.js";
import axios from "axios";
class GalleryList extends Component {
constructor(props) {
super(props);
this.state = {
selectedGallery: null,
showGalleryDetail: false,
galleryList: [], // 초기값을 빈 배열로 설정
};
}
componentDidMount() {
// 초기 galleryList 값을 props로부터 받아와 설정
this.setState({
galleryList: this.props.galleryList || [],
});
}
handleGalleryClick = (gallery) => {
this.setState({
selectedGallery: gallery,
showGalleryDetail: true,
});
};
addGalleryInfo = async (title, file, contents, writer, writeDate) => {
try {
const formData = new FormData();
formData.append("img", file);
const uploadResponse = await axios.post("/gallery/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
const { imgName } = uploadResponse.data;
const response = await axios.post("/gallery", {
title,
img: imgName,
contents,
writer,
writeDate,
});
console.log(response.data);
// 추가한 갤러리 정보를 현재 갤러리 목록에 추가
const newGallery = {
no: response.data.no,
title,
img: imgName,
contents,
writer,
writeDate,
};
this.setState((prevState) => ({
galleryList: [...prevState.galleryList, newGallery],
}));
} catch (error) {
console.error("Error adding gallery info:", error);
}
};
handleBack = () => {
this.setState({
showGalleryDetail: false,
});
};
handleDelete = async (galleryNo) => {
try {
// 게시글 삭제 요청
await axios.delete(`/gallery/${galleryNo}`);
// 삭제한 갤러리를 현재 갤러리 목록에서 제거
this.setState((prevState) => ({
galleryList: prevState.galleryList.filter((gallery) => gallery.no !== galleryNo),
}));
} catch (error) {
console.error("Error deleting gallery:", error);
}
};
handleUpdate = async (updatedGallery) => {
try {
// 게시글 수정 요청
await axios.put(`/gallery/${updatedGallery.no}`, updatedGallery);
// 수정한 갤러리 정보를 현재 갤러리 목록에 업데이트
this.setState((prevState) => ({
galleryList: prevState.galleryList.map((gallery) =>
gallery.no === updatedGallery.no ? updatedGallery : gallery
),
}));
} catch (error) {
console.error("Error updating gallery:", error);
}
};
componentDidUpdate(prevProps) {
if (prevProps.galleryList !== this.props.galleryList) {
this.setState({
galleryList: this.props.galleryList || [], // galleryList를 업데이트
});
}
}
render() {
const { galleryList, selectedGallery, showGalleryDetail } = this.state;
const result = galleryList.map((data) => (
<TakeGallery
key={data.no}
no={data.no}
title={data.title}
img={data.img}
contents={data.contents}
writer={data.writer}
writeDate={data.writeDate}
onClick={() => this.handleGalleryClick(data)}
/>
));
if (showGalleryDetail) {
return (
<div id="gallery-list">
<GalleryDetail
gallery={selectedGallery}
onBack={this.handleBack}
onDelete={this.handleDelete}
onUpdate={this.handleUpdate}
/>
</div>
);
}
return <div id="gallery-list">{result}</div>;
}
}
export default GalleryList;
Input 컴포넌트
import React, { Component } from "react";
import "../../css/Gallery/Input.css";
import axios from "axios";
class Input extends Component {
constructor(props) {
super(props);
this.state = {
title: "",
file: null,
imgPreview: null,
contents: "",
writer: "",
writeDate: "",
};
}
addGalleryInfo = async () => {
const { title, file, contents, writer, writeDate } = this.state;
try {
const formData = new FormData();
formData.append("img", file);
const uploadResponse = await axios.post("/gallery/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
const { imgName } = uploadResponse.data;
await axios.post("/gallery", {
title,
img: imgName,
contents,
writer,
writeDate,
});
this.setState({
title: "",
file: null,
imgPreview: null,
contents: "",
writer: "",
writeDate: "",
});
// 추가한 갤러리 정보를 상위 컴포넌트로 전달
this.props.addGalleryInfo(title, file, contents, writer, writeDate);
} catch (error) {
console.error("Error adding gallery info:", error);
alert("이미지가 업로드되지 않았습니다.");
}
};
handleImgSelect = (e) => {
const file = e.target.files[0];
const imgPreview = URL.createObjectURL(file);
if (file) {
// 파일 유효성 검사 로직 추가
const allowedTypes = ["image/jpeg", "image/png"]; // 허용된 파일 유형
if (allowedTypes.includes(file.type)) {
// 유효한 파일 유형인 경우
this.setState({ file, imgPreview });
} else {
// 유효하지 않은 파일 유형인 경우에 대한 처리
console.error("Invalid file type. Please select a JPEG or PNG image.");
// 파일 선택을 초기화하거나 사용자에게 알림을 표시할 수 있습니다.
alert(
"유효하지 않은 이미지 유형입니다. JPEG 또는 PNG 파일을 사용해주세요."
);
}
} else {
// 파일 선택하지 않은 경우에 대한 처리
console.error("No img selected. Please choose an image.");
// 사용자에게 알림을 표시할 수 있습니다.
alert("이미지가 선택되지 않았습니다. 이미지를 첨부해주세요.");
}
};
handleChange = (e) => {
const { name, value } = e.target;
this.setState({
[name]: value,
});
};
render() {
const { title, imgPreview, contents, writer, writeDate } = this.state;
return (
<div id="input">
<div id="input-head">갤러리 추가</div>
<div id="input-title">
<label htmlFor="title">제목:</label>
<input
type="text"
placeholder="제목 입력"
name="title"
value={title}
onChange={this.handleChange}
/>
</div>
<div id="input-img">
<label htmlFor="img">이미지:</label>
<input type="file" name="img" onChange={this.handleImgSelect} />
<div id="show-img">
{imgPreview && <img src={imgPreview} alt="show-img" />}
</div>
</div>
<div id="input-contents">
<label htmlFor="contents">내용:</label>
<textarea
id="contents"
name="contents"
value={contents}
onChange={this.handleChange}
></textarea>
</div>
<div id="input-write">
<label htmlFor="writer">작성자:</label>
<input
type="text"
placeholder="작성자 입력"
name="writer"
value={writer}
onChange={this.handleChange}
/>
</div>
<div id="input-writeDate">
<label htmlFor="writeDate">작성일:</label>
<input
type="date"
placeholder="날짜 입력"
name="writeDate"
value={writeDate}
onChange={this.handleChange}
/>
</div>
<button onClick={this.addGalleryInfo}>추가</button>
</div>
);
}
}
export default Input;
TakeGallery 컴포넌트
import React from 'react';
import '../../css/Gallery/TakeGallery.css';
const TakeGallery = (props) => {
const handleClick = () => {
const { no, title, img, contents, writer, writeDate } = props;
const galleryData = {
no,
title,
img,
contents,
writer,
writeDate
};
props.onClick(galleryData);
};
const imgSrc = props.img ? `/uploads/gallery/${props.img}` : '';
return (
<div id="takegallery" onClick={handleClick}>
<div>{props.title}</div>
<div><img src={imgSrc} alt="Gallery" /></div>
<div>{props.contents}</div>
<div>{props.writer} {props.writeDate}</div>
</div>
);
};
export default TakeGallery;
728x90