본문 바로가기
Daily Life

05.26 기록

by JungSeung 2023. 5. 26.
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

'Daily Life' 카테고리의 다른 글

05.30 기록  (0) 2023.05.30
05.25 기록  (0) 2023.05.25
05.24 기록  (0) 2023.05.24
05.23 기록  (0) 2023.05.23
05.22 기록  (0) 2023.05.22