# カレンダーの予定作成機能5

では`CreateScheduleModal.tsx`をリファクタしていきます。`CreateScheduleModal.tsx`のロジックをhooksに切り出しましょう。`hooks`配下に`useCreateSchedule.ts`を作成しましょう。

propsとして、`closeModal`と`addSchedule`を受け取れるようにしましょう。そして、`newSchedule`と`errorMessage`のstateと、`changeNewSchedule`、`handleCreateSchedule`の関数を移行して、これらを返却するようにしましょう。

<pre class="language-typescript" data-title="hooks/ useCreateSchedule.ts◎"><code class="lang-typescript"><strong>import { ChangeEvent, FormEvent, useState } from "react"
</strong><strong>import { format, parse } from "date-fns"
</strong><strong>
</strong><strong>import { NewSchedule, Schedule } from "../types/calendar"
</strong><strong>
</strong><strong>type PropsType = {
</strong><strong>  closeModal: () => void
</strong><strong>  addSchedule: (schedule: Schedule) => void
</strong><strong>}
</strong><strong>
</strong><strong>export const useCreateSchedule = ({ closeModal, addSchedule }: PropsType) => {
</strong><strong>  const [newSchedule, setNewSchedule] = useState&#x3C;NewSchedule>({
</strong><strong>    title: "",
</strong><strong>    date: format(new Date(), "yyyy-MM-dd"),
</strong><strong>    description: "",
</strong><strong>  })
</strong><strong>  const [errorMessage, setErrorMessage] = useState("")
</strong><strong>
</strong><strong>  const changeNewSchedule = (
</strong><strong>    event: ChangeEvent&#x3C;HTMLInputElement | HTMLTextAreaElement>
</strong><strong>  ) => {
</strong><strong>    const { name, value } = event.target
</strong><strong>    setNewSchedule({ ...newSchedule, [name]: value })
</strong><strong>  };
</strong><strong>
</strong><strong>  const handleCreateSchedule = (event: FormEvent&#x3C;HTMLFormElement>) => {
</strong><strong>    event.preventDefault()
</strong><strong>    const { title, date, description } = newSchedule
</strong><strong>    if (title === "") {
</strong><strong>      setErrorMessage("タイトルを入力してください")
</strong><strong>      return;
</strong><strong>    } else {
</strong><strong>      setErrorMessage("")
</strong><strong>    }
</strong><strong>    const schedule: Schedule = {
</strong><strong>      id: 100001,
</strong><strong>      title,
</strong><strong>      date: parse(date, "yyyy-MM-dd", new Date()),
</strong><strong>      description: description,
</strong><strong>    };
</strong><strong>    addSchedule(schedule)
</strong><strong>    setNewSchedule({
</strong><strong>      title: "",
</strong><strong>      date: format(new Date(), "yyyy-MM-dd"),
</strong><strong>      description: "",
</strong><strong>    });
</strong><strong>    closeModal()
</strong><strong>  }
</strong><strong>
</strong><strong>  return {
</strong><strong>    errorMessage,
</strong><strong>    newSchedule,
</strong><strong>    changeNewSchedule,
</strong><strong>    handleCreateSchedule,
</strong><strong>  }
</strong><strong>}
</strong></code></pre>

また、`newSchedule`の初期値に関してですが、`handleCreateSchedule`にて再度セットするので、定数として定義して呼び出すようにしましょう。

<pre class="language-typescript" data-title="hooks/ useCreateSchedule.ts◎"><code class="lang-typescript">import { ChangeEvent, FormEvent, useState } from "react"
import { format, parse } from "date-fns"

import { NewSchedule, Schedule } from "../types/calendar"

<strong>const INIT_SCHEDULE: NewSchedule = {
</strong><strong>  title: "",
</strong><strong>  date: format(new Date(), "yyyy-MM-dd"),
</strong><strong>  description: "",
</strong><strong>}
</strong>
type PropsType = {
  closeModal: () => void
  addSchedule: (schedule: Schedule) => void
}

export const useCreateSchedule = ({ closeModal, addSchedule }: PropsType) => {
<strong>  const [newSchedule, setNewSchedule] = useState&#x3C;NewSchedule>(INIT_SCHEDULE)
</strong>  const [errorMessage, setErrorMessage] = useState("")

  const changeNewSchedule = (
    event: ChangeEvent&#x3C;HTMLInputElement | HTMLTextAreaElement>
  ) => {
    const { name, value } = event.target
    setNewSchedule({ ...newSchedule, [name]: value })
  };

  const handleCreateSchedule = (event: FormEvent&#x3C;HTMLFormElement>) => {
    event.preventDefault()
    const { title, date, description } = newSchedule
    if (title === "") {
      setErrorMessage("タイトルを入力してください")
      return;
    } else {
      setErrorMessage("")
    }
    const schedule: Schedule = {
      id: 100001,
      title,
      date: parse(date, "yyyy-MM-dd", new Date()),
      description: description,
    }
    addSchedule(schedule)
<strong>    setNewSchedule(INIT_SCHEDULE);
</strong>    closeModal()
  }
</code></pre>

こちらを`CreateScheduleModal.tsx`にて呼び出すようにしましょう。

<pre class="language-tsx" data-title="organisms/CreateScheduleModal.tsx◎"><code class="lang-tsx">import Modal from "react-modal"
import { format } from "date-fns"
import { Input } from "../atoms/Input"
import { PrimaryBtn } from "../atoms/PrimaryBtn"
import { Schedule } from "../../types/calendar"
import { Textarea } from "../atoms/Textarea"
<strong>import { useCreateSchedule } from "../../hooks/useCreateSchedule"
</strong>
type PropsType = {
  isOpen: boolean
  closeModal: () => void
  addSchedule: (schedule: Schedule) => void
};

const customStyles = {
  content: {
    top: "50%",
    left: "50%",
    width: "30%",
    height: "50vh",
    transform: "translate(-50%, -50%)",
  },
};

export const CreateScheduleModal = ({
  isOpen,
  closeModal,
  addSchedule,
}: PropsType) => {
<strong>  const { newSchedule, errorMessage, changeNewSchedule, handleCreateSchedule } =  useCreateSchedule({ closeModal, addSchedule })
</strong>
  return (
    &#x3C;Modal isOpen={isOpen} style={customStyles} onRequestClose={closeModal}>
      &#x3C;div>
        &#x3C;h3 className="text-center text-3xl text-lime-800 font-bold pb-5">
          予定作成
        &#x3C;/h3>
        {errorMessage !== "" &#x26;&#x26; (
          &#x3C;div className="p-5 mb-5 bg-red-500 text-white text-center rounded-lg">
            {errorMessage}
          &#x3C;/div>
        )}
        &#x3C;form className="flex flex-col gap-8" onSubmit={handleCreateSchedule}>
          &#x3C;div className="w-[100%] flex items-center">
            &#x3C;label className="w-[30%] text-lime-800">タイトル&#x3C;/label>
            &#x3C;Input
              name="title"
              type="text"
              value={newSchedule.title}
              onChange={changeNewSchedule}
            />
          &#x3C;/div>
          &#x3C;div className="w-[100%] flex items-center">
            &#x3C;label className="w-[30%] text-lime-800">日付&#x3C;/label>
            &#x3C;Input
              name="date"
              type="date"
              value={format(newSchedule.date, "yyyy-MM-dd")}
              onChange={changeNewSchedule}
            />
          &#x3C;/div>
          &#x3C;div className="w-[100%] flex items-center">
            &#x3C;label className="w-[30%] text-lime-800">内容&#x3C;/label>
            &#x3C;Textarea
              name="description"
              value={newSchedule.description}
              onChange={changeNewSchedule}
            />
          &#x3C;/div>
          &#x3C;div className="flex justify-center">
            &#x3C;PrimaryBtn size="lg" onClick={() => null}>
              作成
            &#x3C;/PrimaryBtn>
          &#x3C;/div>
        &#x3C;/form>
      &#x3C;/div>
    &#x3C;/Modal>
  )
}
</code></pre>

ここまでの作業をcommitしましょう。

```bash
git add .
```

```bash
git commit
```

commitメッセージは

```
refactor: CreateScheduleModalのロジックをuseCreateScheduleに切り出した
```

としましょう。

では予定作成機能の実装が完了したので、GitHubにpushしましょう。

```basic
git push origin feature/add-schedule-func
```

これでGitHubのリポジトリのページにいき、main <- feature/add-schedule-funcのPRを作成しましょう。

PRのタイトルは

```
feat: カレンダーの予定を作成できるようにした
```

としましょう。

作成したら自身で`Merge pull request`を押してmergeしましょう。

mergeが完了したらWarpに戻り、mainをpullしましょう。

```bash
git switch main
```

```bash
git pull origin main
```
