react

react

2024년 2월 12일 09:54
'use client';


import Button from '@/components/Button';
import Input from '@/components/Input';
import { useCategories, useTags } from '@/utils/hooks';
import axios from 'axios';
import hljs from 'highlight.js';
import { useSession } from 'next-auth/react';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/navigation';
import { FormEvent, useRef, useState } from 'react';
import { MultiValue } from 'react-select';
import ReactSelect from 'react-select/creatable';
import { toast } from 'react-toastify';


const QuillEidtor = dynamic(
  async () => {
    hljs.configure({
      languages: ['javascript', 'CSS', 'HTML'],
    });
    // @ts-ignore
    window.hljs = hljs;
    return await import('@/components/QuillEditor');
  },
  {
    ssr: false,
  }
);


export default function Page() {
  const { data: session } = useSession();


  const router = useRouter();


  const titleRef = useRef<HTMLInputElement>(null);
  const fileRef = useRef<HTMLInputElement>(null);


  const { data: existingCategories } = useCategories();
  const { data: existingTags } = useTags();


  const [category, setCategory] = useState('');
  const [tags, setTags] = useState<{ label: string; value: string }[]>([]);
  const [content, setContent] = useState('');


  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();


    if (!titleRef.current?.value || titleRef.current.value.length === 0)
      return toast.error('제목을 입력해주세요.');
    if (category.length === 0) return toast.error('카테고리를 입력해주세요.');
    if (tags.length === 0) return toast.error('태그를 입력해주세요.');
    if (content.length === 0) return toast.error('글 내용을 입력해주세요.');


    const tagsValue = JSON.stringify(tags.map((tag) => tag.value));


    const formData = new FormData();
    formData.append('userId', session?.user.id!);
    formData.append('title', titleRef.current?.value);
    formData.append('category', category);
    formData.append('tags', tagsValue);
    formData.append('content', content);


    if (fileRef.current?.files?.[0]) {
      formData.append('previewImage', fileRef.current.files[0]);
    }


    try {
      const response = await axios.post('/api/posts', formData, {
        headers: {
          'Content-Type': 'multipart/form-data', // FormData를 사용할 때 필요한 헤더
        },
      });
      if (response.status === 201) {
        toast.success(response.data.message);
        router.push(`/posts/${response.data.postId}`);
      } else {
        toast.error('글 작성에 실패했습니다.');
      }
    } catch (error) {
      console.error('Post creation failed:', error);
      toast.error('글 작성 중 에러가 발생했습니다.');
    }
  };


  return (
    <div className="container z-10 flex flex-col gap-6 pb-20 pt-12">
      <h1 className="mb-8 text-2xl font-medium">새로운 글</h1>
      <form onSubmit={handleSubmit}>
        <div className="flex flex-col gap-3 text-black">
          <Input type="text" placeholder="제목" ref={titleRef} />
          <Input
            type="file"
            accept="image/*"
            ref={fileRef}
            className="bg-white"
          />
          <ReactSelect
            options={(existingCategories ?? []).map((category) => ({
              label: category,
              value: category,
            }))}
            placeholder="카테고리"
            instanceId="categories"
            onChange={(e) => e && setCategory(e?.value)}
            isMulti={false}
          />
          <ReactSelect
            options={(existingTags ?? []).map((tag) => ({
              label: tag,
              value: tag,
            }))}
            placeholder="태그"
            instanceId="tags"
            value={tags}
            onChange={(
              selectedOptions: MultiValue<{ label: string; value: string }>
            ) => {
              setTags([...selectedOptions]);
            }}
            isMulti
          />
          <QuillEidtor content={content} setContent={setContent} />
        </div>
        <Button type="submit" className="mt-4">
          작성하기
        </Button>
      </form>
    </div>
  );
}


Copyright © 2024 White Mouse Dev