posting.tsx 8.36 KB
Newer Older
Lee Soobeom's avatar
Lee Soobeom committed
1
import React, { FormEvent, useEffect, useState } from "react";
Lee Soobeom's avatar
Lee Soobeom committed
2
import { useNavigate } from "react-router-dom";
3
4
5
import isLength from "validator/lib/isLength";
import equals from "validator/lib/equals";
import { catchErrors } from "../helpers";
Lee Soobeom's avatar
Lee Soobeom committed
6
import { PostType } from "../types";
7
import { postApi } from "../apis";
Lee Soobeom's avatar
Lee Soobeom committed
8
import { File } from "formidable";
Kim, MinGyu's avatar
Kim, MinGyu committed
9

10
export default function Posting() {
Lee Soobeom's avatar
Lee Soobeom committed
11
12
  const [city, setCity] = useState<string>("city");
  const [theme, setTheme] = useState<string>("theme");
13
14
  const [title, setTitle] = useState<string>("");
  const [text, setText] = useState<string>("");
Lee Soobeom's avatar
Lee Soobeom committed
15
  const [file, setFile] = useState<FileList>();
Lee Soobeom's avatar
Lee Soobeom committed
16
  const [imgSrc, setImgSrc] = useState<string[]>();
Lee Soobeom's avatar
Lee Soobeom committed
17
  const navigate = useNavigate();
Kim, MinGyu's avatar
Kim, MinGyu committed
18

Lee Soobeom's avatar
Lee Soobeom committed
19
  const [user, setUser] = useState<PostType>({
20
21
22
23
    title: "",
    text: "",
    theme: "",
    city: "",
Lee Soobeom's avatar
Lee Soobeom committed
24
25
    date: "",
    user: "",
Lee Soobeom's avatar
Lee Soobeom committed
26
    counts: 0,
Lee Soobeom's avatar
Lee Soobeom committed
27
    _id: "",
28
  });
Kim, MinGyu's avatar
Kim, MinGyu committed
29

30
31
32
33
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [disabled, setDisabled] = useState(false);
  const [success, setSuccess] = useState(false);
Kim, MinGyu's avatar
Kim, MinGyu committed
34

Lee Soobeom's avatar
Lee Soobeom committed
35
36
37
38
  const imgArr = new Array();

  const sendImg2Db = async (filelist: FileList) => {
    const formdata = new FormData();
Lee Soobeom's avatar
Lee Soobeom committed
39
40
41
42
    formdata.append("title", user.title);
    formdata.append("text", user.text);
    formdata.append("theme", user.theme);
    formdata.append("city", user.city);
Lee Soobeom's avatar
Lee Soobeom committed
43
44
    if (!(filelist === undefined || filelist === null)) {
      for (var i = 0; i < filelist.length; i++) {
Lee Soobeom's avatar
Lee Soobeom committed
45
        formdata.append("picture", filelist?.[i]);
Lee Soobeom's avatar
Lee Soobeom committed
46
      }
Lee Soobeom's avatar
Lee Soobeom committed
47
48
      // formdata: post, imgs
      const res = await postApi.createImgAndPost(formdata);
Lee Soobeom's avatar
Lee Soobeom committed
49
    }
Lee Soobeom's avatar
Lee Soobeom committed
50
51
52
    // else {
    //   const res = await postApi.createImgAndPostTable(formdata);
    // }
Lee Soobeom's avatar
Lee Soobeom committed
53
54
  };

55
  async function handlePostSubmit(event: FormEvent) {
Lee Soobeom's avatar
Lee Soobeom committed
56
    event.preventDefault();
57
58
59
    try {
      setError("");
      console.log("user data", user);
Lee Soobeom's avatar
Lee Soobeom committed
60
      if (postingFormMatch(user)) {
61
        setLoading(true);
Lee Soobeom's avatar
Lee Soobeom committed
62
        if (file) {
Lee Soobeom's avatar
Lee Soobeom committed
63
64
          const res = sendImg2Db(file);
          console.log(res);
Lee Soobeom's avatar
Lee Soobeom committed
65
66
67
68
        }
        // const res = await postApi.posting(user);
        // console.log("서버연결됬나요", res);

Lee Soobeom's avatar
Lee Soobeom committed
69
        navigate("/board", { replace: true });
70
71
72
73
74
75
76
77
78
        setSuccess(true);
        setError("");
      }
    } catch (error) {
      console.log("에러발생");
      catchErrors(error, setError);
    } finally {
      setLoading(false);
    }
Kim, MinGyu's avatar
Kim, MinGyu committed
79
80
  }

Lee Soobeom's avatar
Lee Soobeom committed
81
  function postingFormMatch(user: PostType) {
82
83
84
85
86
87
    if (!isLength(user.title ?? "", { min: 1 })) {
      setError("제목을 입력해 주세요.");
      return false;
    } else if (!isLength(user.text ?? "", { min: 1 })) {
      setError("내용을 입력해 주세요.");
      return false;
Lee Soobeom's avatar
Lee Soobeom committed
88
    } else if (equals(city, "city")) {
89
90
      setError("도시를 선택해 주세요.");
      return false;
Lee Soobeom's avatar
Lee Soobeom committed
91
92
93
    } else if (equals(theme, "theme")) {
      setError("테마를 선택해 주세요.");
      return false;
94
95
96
    } else {
      return true;
    }
Kim, MinGyu's avatar
Kim, MinGyu committed
97
98
  }

99
100
101
102
103
104
105
  const titleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    const title = event.currentTarget.value;
    const newUser = { ...user, title: title };
    console.log(event.currentTarget.value);
    setTitle(event.currentTarget.value);
    setUser(newUser);
  };
Kim, MinGyu's avatar
Kim, MinGyu committed
106

107
108
109
110
111
112
113
  const textChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    const text = event.currentTarget.value;
    const newUser = { ...user, text: text };
    console.log(event.currentTarget.value);
    setText(event.currentTarget.value);
    setUser(newUser);
  };
Kim, MinGyu's avatar
Kim, MinGyu committed
114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  const cityChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    const city = event.currentTarget.value;
    const newUser = { ...user, city: city };
    console.log(event.currentTarget.value);
    setCity(event.currentTarget.value);
    setUser(newUser);
  };

  const themeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    const theme = event.currentTarget.value;
    const newUser = { ...user, theme: theme };
    console.log(event.currentTarget.value);
    setTheme(event.currentTarget.value);
    setUser(newUser);
  };
Lee Soobeom's avatar
Lee Soobeom committed
130

Lee Soobeom's avatar
Lee Soobeom committed
131
132
133
  const handleInputPic = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const maxImg = 10;
    const { files } = event.target;
Lee Soobeom's avatar
Lee Soobeom committed
134
135
136
137
138

    if (!(files === null)) {
      setFile(files);
    }

Lee Soobeom's avatar
Lee Soobeom committed
139
140
141
142
143
144
145
146
147
148
    if (!(files?.length === undefined)) {
      if (files?.length <= maxImg) {
        for (var i = 0; i < files.length; i++) {
          const reader = new FileReader();
          reader.readAsDataURL(files?.[i]);

          reader.onload = (e) => {
            imgArr.push(e.target?.result);
            setImgSrc(imgArr);
          };
Lee Soobeom's avatar
Lee Soobeom committed
149
150
        }
      } else {
Lee Soobeom's avatar
Lee Soobeom committed
151
        alert(`사진은 최대 ${maxImg}장까지 업로드 가능합니다!`);
Lee Soobeom's avatar
Lee Soobeom committed
152
153
154
155
      }
    }
  };

Kim, MinGyu's avatar
Kim, MinGyu committed
156
  return (
Lee Soobeom's avatar
Lee Soobeom committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    <div className="flex place-content-center">
      <form
        onSubmit={handlePostSubmit}
        className="flex flex-col w-96 items-center"
      >
        <div className="flex flex-row h-8 gap-x-1">
          <div className="flex border-2 border-sky-400 rounded-full w-20 place-content-center transition ease-in-out delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300">
            <input
              id="files"
              type="file"
              multiple
              onChange={handleInputPic}
              className="hidden"
            />
            <label htmlFor="files" className="text-xs text-center mt-1.5 ml-1 ">
              파일 선택
            </label>
          </div>

          <div className="flex w-20">
            <select
              name="city"
              className="border-2 border-sky-400 rounded-full w-20 text-xs"
              onChange={cityChange}
              defaultValue="질문종류"
            >
              <option value="질문종류">도시</option>
              <option value="Seoul">서울</option>
              <option value="Busan">부산</option>
              <option value="Incheon">인천</option>
              <option value="Daegoo">대구</option>
              <option value="Kwangjoo">광주</option>
              <option value="Daejeon">대전</option>
              <option value="Woolsan">울산</option>
              <option value="Sejong">세종</option>
              <option value="Dokdo">독도</option>
              <option value="Jeju">제주</option>
            </select>
          </div>

          <div className="flex w-20">
            <select
              name="theme"
              className="border-2 border-sky-400 rounded-full w-20 text-xs"
              onChange={themeChange}
              defaultValue="질문종류"
            >
              <option value="질문종류">테마</option>
              <option value="cycling">사이클링</option>
              <option value="surfing">서핑</option>
              <option value="activity">액티비티</option>
              <option value="camping">캠핑</option>
              <option value="sking">스키</option>
              <option value="boat">보트</option>
              <option value="desert">사막</option>
              <option value="golf">골프</option>
              <option value="cave">동굴</option>
              <option value="history">문화재</option>
              <option value="zoo">동물원</option>
              <option value="cycling">사이클링</option>
            </select>
          </div>

          <div className="flex w-20">
            <button
              type="submit"
              className="border-2 border-sky-400 rounded-full w-20 text-xs text-center transition ease-in-out delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
            >
              글쓰기
            </button>
Lee Soobeom's avatar
Lee Soobeom committed
227
          </div>
Kim, MinGyu's avatar
Kim, MinGyu committed
228
229
        </div>

Lee Soobeom's avatar
Lee Soobeom committed
230
        <div className="flex flex-col">
Kim, MinGyu's avatar
Kim, MinGyu committed
231
          <textarea
232
233
            name="title"
            onChange={titleChange}
Lee Soobeom's avatar
Lee Soobeom committed
234
235
236
237
238
239
240
241
242
            placeholder="제목을 입력해 주세요!"
            className="flex w-96 border-2 border-sky-500 rounded"
          />
          <div className="flex flex-col mt-1 mb-1">
            <div className="flex gap-x-2 h-48 overflow-x-scroll">
              {imgSrc?.map((img, i) => (
                <img key={i} src={img} width={200} height={200} />
              ))}
            </div>
Lee Soobeom's avatar
Lee Soobeom committed
243
          </div>
244
245
246
          <textarea
            onChange={textChange}
            name="text"
Lee Soobeom's avatar
Lee Soobeom committed
247
248
249
            placeholder="여행 후기를 알려주세요!"
            className="flex w-96 h-96 border-2 border-sky-500 rounded"
          />
Lee Soobeom's avatar
Lee Soobeom committed
250
        </div>
Kim, MinGyu's avatar
Kim, MinGyu committed
251
252
253
254
      </form>
    </div>
  );
}