answer crud file

KoEunseo·2022년 11월 4일
0

project

목록 보기
3/37
post-custom-banner

AnswerList

import { useEffect, useState } from 'react';
import styled from 'styled-components';
import axios from 'axios';
import AnswerEditor from './AnswerEditor';
import AnswerItem from './AnswerItem';

const AnswersWrapper = styled.div`
  padding: 24px 0;
`;

const Answer = styled.div`
  padding-bottom: 24px;
  border-bottom: 1px solid #d6d9dc;
`;

const AnswerList = ({ questionId }) => {
  const [answers, setAnswers] = useState([]);
  useEffect(() => {
    const fetchData = async () => {
      const url = `http://localhost:3001/answer?questionId=${questionId}`;
      try {
        await axios.get(url).then((res) => {
          setAnswers(res.data);
        });
      } catch (err) {
        console.log('error', err);
      }
    };
    fetchData();
  }, [questionId]);
  return (
    <AnswersWrapper>
      {answers
        ? answers.map((answer) => {
            return (
              <>
                <AnswerItem key={answer.answerId} answer={answer} />
              </>
            );
          })
        : null}
      <AnswerEditor
        questionId={questionId}
        answers={answers}
        setAnswers={setAnswers}
      />
    </AnswersWrapper>
  );
};

export default AnswerList;

AnswerEditor

import axios from 'axios';
import { useState } from 'react';
import styled from 'styled-components';
import { useParams } from 'react-router-dom';

const AnswerEditorWrapper = styled.div`
  /* border-top: 1px solid #d6d9dc; */
  padding: 24px 0;
  textarea {
    width: 100%;
    height: 200px;
    margin-bottom: 24px;
  }
`;
const AnswerEditor = ({ questionId, answers, setAnswers }) => {
  const [answer, setAnswer] = useState([]);

  const onChange = (e) => {
    setAnswer(e.target.value);
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    const data = {
      // eslint-disable-next-line no-const-assign, no-undef
      questionId: 2,
      body: answer,
    };
    const fetchData = async () => {
      try {
        // const url = `${process.env.REACT_APP_ANSWER}`;
        const url = `http://localhost:3001/answer`;
        await axios.post(url, data);
        window.location.reload();
      } catch (err) {
        console.log('error', err);
      }
    };
    fetchData();
  };

  return (
    <>
      <AnswerEditorWrapper className="answerEditor">
        <h2>Your Answer</h2>
        <form onSubmit={handleSubmit}>
          <textarea onChange={onChange} />
          <button className="button">Post Your Answer</button>
        </form>
      </AnswerEditorWrapper>
    </>
  );
};

export default AnswerEditor;

AnswerItem

import styled from 'styled-components';
import Writer from '../components/Writer';
import axios from 'axios';
import { useEffect, useState } from 'react';
import AnswerEditor from './AnswerEditor';
import AnswerUpdate from './AnswerUpdate';

const Answer = styled.div`
  padding-bottom: 24px;
  border-bottom: 1px solid #d6d9dc;
  .handleBtns {
    button {
      border: none;
      margin: 4px;
      color: #6a737c;
      font-size: 13px;
      cursor: pointer;
    }
  }
`;
const AnswerItem = ({ answer }) => {
  const [isEdit, setIsEdit] = useState(false);
  const { id, body, userId } = answer;
  //DELETE
  const handleDelete = () => {
    console.log(id, body);
    const url = `http://localhost:3001/answer/${id}`;
    const fetchData = async () => {
      try {
        await axios.delete(url).then(() => {
          console.log(id, body);
          window.location.reload();
        });
      } catch (err) {
        console.log('error', err);
      }
    };
    fetchData();
  };
  const handleEditBtn = () => {
    setIsEdit(!isEdit);
  };

  return (
    <>
      {answer ? (
        <Answer id={id}>
          <div>
            <h2>Answers</h2>
            {isEdit ? (
              <AnswerUpdate
                body={body}
                setIsEdit={setIsEdit}
                isEdit={isEdit}
                answerId={id}
              />
            ) : (
              <div>{body}</div>
            )}
          </div>
          <Writer props={userId} />
          <div className="handleBtns">
            <button onClick={handleEditBtn}>edit</button>
            <button onClick={handleDelete}>delete</button>
          </div>
        </Answer>
      ) : null}
    </>
  );
};

export default AnswerItem;

AnswerUpdate

import axios from 'axios';
import { useEffect, useState } from 'react';
import styled from 'styled-components';

const Button = styled.button`
  background-color: #0a95ff;
  padding: 0.8em;
  border-radius: 5px;
  color: white;
  border: 1px solid transparent;
  white-space: nowrap;
  font-size: 13px;
  cursor: pointer;
  &:hover {
    background-color: #0074cc;
  }
`;
const Textarea = styled.textarea`
  width: 100%;
  height: 200px;
  margin-bottom: 24px;
`;
const AnswerUpdate = ({ setIsEdit, isEdit, body, answerId }) => {
  const [editText, setEditText] = useState();

  // UPDATE
  const onChange = (e) => {
    setEditText(e.target.value);
  };
  const handleEditBtn = () => {
    // const url = REACT_APP_ANSWER + ${answerId};
    const url = `http://localhost:3001/answer/${answerId}`;
    const data = {
      id: answerId,
      answerStatus: 'ANSWER_NOT_EXIST',
      body: editText,
    };
    const fetchData = async () => {
      try {
        await axios.patch(url, data).then((res) => {
          console.log(res);
          setIsEdit(false);
        });
      } catch (err) {
        console.log('error', err);
      }
    };
    fetchData();
  };
  return (
    <>
      <Textarea value={editText ? editText : body} onChange={onChange} />
      <Button onClick={handleEditBtn}>Save Edits</Button>
    </>
  );
};

export default AnswerUpdate;

detail

import Footer from '../components/Footer';
import Header from '../components/Header';
import Nav, { headerHeight } from '../components/Nav';
import Sidebar from '../components/Sidebar';
import styled from 'styled-components';
import Writer from '../components/Writer';
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import AnswerList from '../components/AnswerList';

const Container = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  max-width: 1264px;
  margin: 0 auto;
  min-height: 100vh;
  font-size: 13px;
  a {
    text-decoration: none;
  }
  .wrapper {
    margin-top: ${headerHeight}px;
    border-left: 1px solid #d6d9dc;
    width: 100%;
    h1 {
      line-height: 1.35;
      font-weight: normal;
      margin: 0;
    }
    .content {
      max-width: 1100px;
      padding: 24px;
      .header {
        width: 100%;
        border-bottom: 1px solid #d6d9dc;
        .title {
          display: flex;
          flex-direction: row;
          justify-content: space-between;
          align-items: flex-start;
          div {
            margin-left: 12px;
          }
        }
        .detail {
          display: flex;
          flex-direction: row;
          div {
            margin: 8px 16px 8px 0;
            span {
              margin-right: 4px;
            }
          }
        }
      }
      .contentBody {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        .mainbar {
          width: 100%;
          max-width: 728px;
          font-size: 15px;
          .post {
            padding-right: 16px;
          }
        }
      }
    }
  }
  .button {
    background-color: #0a95ff;
    padding: 0.8em;
    border-radius: 5px;
    color: white;
    border: 1px solid transparent;
    white-space: nowrap;
    font-size: 13px;
    cursor: pointer;
    &:hover {
      background-color: #0074cc;
    }
  }
  h2 {
    font-weight: 400;
    font-size: 19px;
  }
`;

const Detail = () => {
  let { id } = useParams();
  const [question, setQuestion] = useState(null);
  useEffect(() => {
    const url = `http://localhost:3001/question?questionId=${id}`;
    const fetchData = async () => {
      try {
        await axios.get(url).then((res) => {
          setQuestion(res.data[0]);
        });
      } catch (err) {
        console.log('error', err);
      }
    };
    fetchData();
  }, []);
  return (
    <>
      (
      <Header />
      <Container>
        <Nav />
        <div className="wrapper">
          <div className="content">
            <div className="header">
              <div className="title">
                {<h1>{question?.title}</h1>}
                <div>
                  <button href="#!" className="button">
                    Ask Question
                  </button>
                </div>
              </div>
              <div className="detail">
                <div>
                  <span>Asked</span>
                  {question?.createdAt}
                </div>
                <div>
                  <span>Modified</span>
                  며칠전
                </div>
                <div>
                  <span>Viewed</span>
                  {question?.view}
                </div>
              </div>
            </div>
            <div className="contentBody">
              <div className="mainbar">
                <div className="post">
                  <p>{question?.body}</p>
                </div>
                <Writer props={question?.questionId} />
                <AnswerList questionId={id} />
              </div>
              <Sidebar />
            </div>
          </div>
        </div>
      </Container>
      <Footer />)
    </>
  );
};

export default Detail;

mock data

{
  "question": {
    "data": [
      {
        "questionId": 5,
        "questionStatus": "QUESTION_EXIST",
        "title": "string",
        "body": "string",
        "view": 0,
        "createdAt": "2022-11-02T20:12:47.809521",
        "updatedAt": "2022-11-02T20:12:47.719745"
      },
      {
        "questionId": 4,
        "questionStatus": "QUESTION_EXIST",
        "title": "test",
        "body": "qwdawdawdawdawd",
        "view": 0,
        "createdAt": "2022-11-02T15:23:23.614035",
        "updatedAt": "2022-11-02T15:23:23.523276"
      },
      {
        "questionId": 3,
        "questionStatus": "QUESTION_EXIST",
        "title": "string",
        "body": "string",
        "view": 0,
        "createdAt": "2022-11-02T15:02:40.439374",
        "updatedAt": "2022-11-02T15:02:40.381612"
      },
      {
        "questionId": 2,
        "questionStatus": "QUESTION_EXIST",
        "title": "string1",
        "body": "string2",
        "view": 0,
        "createdAt": "2022-11-02T14:18:35.093064",
        "updatedAt": "2022-11-02T14:18:35.076376"
      }
    ],
    "pageInfo": {
      "page": 1,
      "size": 10,
      "totalElements": 4,
      "totalPages": 1
    }
  },
  "answer": [
    {
      "id": 2,
      "questionId": 2,
      "userId": "바쁘다",
      "body": "bye world!aa",
      "answerStatus": "ANSWER_NOT_EXIST"
    },
    {
      "questionId": 2,
      "body": "sdfs",
      "id": 3
    }
  ]
}
profile
주니어 플러터 개발자의 고군분투기
post-custom-banner

0개의 댓글