# 予定をカレンダーに反映させる1

次に、カレンダーに予定を反映させます。

`feature/insert-schedule`にて作業します。

```bash
git switch -c feature/insert-schedule
```

実際はAPIを叩いて予定を取得し、表示させるかと思いますが、今回は予定を取得するAPIを模した関数を作成します。その前に`Schedule`というオブジェクトの型を宣言しておきましょう。

`types`配下に`calendar.ts`を作成しましょう。その中に`Schedule`という型を宣言します。

<pre class="language-typescript" data-title="types/calendar.ts◎"><code class="lang-typescript"><strong>export type Schedule = {
</strong><strong>  id: number;
</strong><strong>  date: Date;
</strong><strong>  title: string;
</strong><strong>  description: string;
</strong><strong>};
</strong></code></pre>

そして、予定を取得する関数を作成します。

`api`配下に`calendar.ts`を作成します。

<pre class="language-typescript" data-title="api/calendar.ts◎"><code class="lang-typescript"><strong>import { addDays } from "date-fns";
</strong><strong>import { Schedule } from "../types/calendar";
</strong><strong>
</strong><strong>export const getScheduleList = (): Schedule[] => {
</strong><strong>  const today = new Date();
</strong><strong>  return [
</strong><strong>    {
</strong><strong>      id: 1,
</strong><strong>      title: "予定1",
</strong><strong>      description:
</strong><strong>        "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos itaque pariatur maxime explicabo necessitatibus consequuntur dolorum eligendi vitae corporis culpa quis corrupti aliquid, quisquam sunt iste aliquam suscipit obcaecati quam assumenda nemo error esse molestiae cupiditate repellendus. Recusandae maxime neque id! Eius harum, eum aut necessitatibus architecto quia obcaecati fugiat possimus repellat molestiae nobis facilis ad quasi, maiores velit asperiores culpa voluptatibus rem praesentium a. Quia ullam consequatur repellat quidem natus facilis illo, dolorem voluptate dicta. Id voluptatibus quidem officia cupiditate voluptatem, iste a animi aut nostrum maiores, tenetur mollitia sit sed. Nostrum ad impedit rem, saepe deleniti voluptate error!",
</strong><strong>      date: today,
</strong><strong>    },
</strong><strong>    {
</strong><strong>      id: 2,
</strong><strong>      title: "予定2",
</strong><strong>      description:
</strong><strong>        "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos itaque pariatur maxime explicabo necessitatibus consequuntur dolorum eligendi vitae corporis culpa quis corrupti aliquid, quisquam sunt iste aliquam suscipit obcaecati quam assumenda nemo error esse molestiae cupiditate repellendus. Recusandae maxime neque id! Eius harum, eum aut necessitatibus architecto quia obcaecati fugiat possimus repellat molestiae nobis facilis ad quasi, maiores velit asperiores culpa voluptatibus rem praesentium a. Quia ullam consequatur repellat quidem natus facilis illo, dolorem voluptate dicta. Id voluptatibus quidem officia cupiditate voluptatem, iste a animi aut nostrum maiores, tenetur mollitia sit sed. Nostrum ad impedit rem, saepe deleniti voluptate error!",
</strong><strong>      date: today,
</strong><strong>    },
</strong><strong>    {
</strong><strong>      id: 3,
</strong><strong>      title: "予定3",
</strong><strong>      description:
</strong><strong>        "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos itaque pariatur maxime explicabo necessitatibus consequuntur dolorum eligendi vitae corporis culpa quis corrupti aliquid, quisquam sunt iste aliquam suscipit obcaecati quam assumenda nemo error esse molestiae cupiditate repellendus. Recusandae maxime neque id! Eius harum, eum aut necessitatibus architecto quia obcaecati fugiat possimus repellat molestiae nobis facilis ad quasi, maiores velit asperiores culpa voluptatibus rem praesentium a. Quia ullam consequatur repellat quidem natus facilis illo, dolorem voluptate dicta. Id voluptatibus quidem officia cupiditate voluptatem, iste a animi aut nostrum maiores, tenetur mollitia sit sed. Nostrum ad impedit rem, saepe deleniti voluptate error!",
</strong><strong>      date: addDays(today, 1),
</strong><strong>    },
</strong><strong>    {
</strong><strong>      id: 4,
</strong><strong>      title: "予定4",
</strong><strong>      description:
</strong><strong>        "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos itaque pariatur maxime explicabo necessitatibus consequuntur dolorum eligendi vitae corporis culpa quis corrupti aliquid, quisquam sunt iste aliquam suscipit obcaecati quam assumenda nemo error esse molestiae cupiditate repellendus. Recusandae maxime neque id! Eius harum, eum aut necessitatibus architecto quia obcaecati fugiat possimus repellat molestiae nobis facilis ad quasi, maiores velit asperiores culpa voluptatibus rem praesentium a. Quia ullam consequatur repellat quidem natus facilis illo, dolorem voluptate dicta. Id voluptatibus quidem officia cupiditate voluptatem, iste a animi aut nostrum maiores, tenetur mollitia sit sed. Nostrum ad impedit rem, saepe deleniti voluptate error!",
</strong><strong>      date: addDays(today, 7),
</strong><strong>    },
</strong><strong>    {
</strong><strong>      id: 5,
</strong><strong>      title: "予定5",
</strong><strong>      description:
</strong><strong>        "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos itaque pariatur maxime explicabo necessitatibus consequuntur dolorum eligendi vitae corporis culpa quis corrupti aliquid, quisquam sunt iste aliquam suscipit obcaecati quam assumenda nemo error esse molestiae cupiditate repellendus. Recusandae maxime neque id! Eius harum, eum aut necessitatibus architecto quia obcaecati fugiat possimus repellat molestiae nobis facilis ad quasi, maiores velit asperiores culpa voluptatibus rem praesentium a. Quia ullam consequatur repellat quidem natus facilis illo, dolorem voluptate dicta. Id voluptatibus quidem officia cupiditate voluptatem, iste a animi aut nostrum maiores, tenetur mollitia sit sed. Nostrum ad impedit rem, saepe deleniti voluptate error!",
</strong><strong>      date: addDays(today, -9),
</strong><strong>    },
</strong><strong>  ]
</strong><strong>}
</strong></code></pre>

そして、カレンダーにて予定を表示するため、CalendarPageで取り扱っているstateのdateListの型を変更します。元々は

```
[
   [Date(), Date(), Date(), Date()],
   [Date(), Date(), Date(), Date()],   
   ... 
]
```

というDateオブジェクトの二次元配列でしたが、

```
[
    [{ date: Date(),  schedules: [] }, { date: Date(),  schedules: [] }.... ]
]
```

のような`date`, `schedules`をプロパティとして持ったオブジェクトの二次元配列を格納するようにします。

まずはその型を`types/calendar.ts`にDateListという型を宣言しましょう。

<pre class="language-typescript" data-title="types/calendar.ts◎"><code class="lang-typescript">export type Schedule = {
  id: number;
  date: Date;
  title: string;
  description: string;
}

<strong>export type DateList = {
</strong><strong>  date: Date;
</strong><strong>  schedules: Schedule[]
</strong><strong>}[][]
</strong></code></pre>

そして、`CalendarPage`の`dateList`の型を`DateList`に修正します。

次にuseEffectの処理を修正していきます。まず、`newDateList`の型をDateListに修正し、eachDayOfIntervalで`[Date(), Date(), Date()....]`のようなDateオブジェクトの配列が作られますが、その配列をさらにmapにて、`{ date: Date(), schedules: [] }`という形式の配列に作り直します。

<pre class="language-tsx" data-title="pages/CalendarPage.tsx◎"><code class="lang-tsx">import { eachDayOfInterval, eachWeekOfInterval, endOfMonth, endOfWeek, getMonth, startOfMonth } from "date-fns";
import { useEffect, useState } from "react";
import { CalendarHeader } from "../organisms/CalendarHeader";
import { CalendarBody } from "../organisms/CalendarBody";
<strong>import { DateList, Schedule } from "../../types/calendar";
</strong>
export const CalendarPage = () => {
  const today = new Date()
<strong>  const [dateList, setDateList] = useState&#x3C;DateList>([]);
</strong>
  useEffect(() => {
    const monthOfSundayList = eachWeekOfInterval({
      start: startOfMonth(today),
      end: endOfMonth(today),
    })
<strong>    const newDateList: DateList = monthOfSundayList.map((date) => {
</strong>      return eachDayOfInterval({
        start: date,
        end: endOfWeek(date),
<strong>      }).map((date) => ({ date, schedules: [] as Schedule[] }));
</strong>    });

    setDateList(newDateList)
  }, [])
...

</code></pre>

次に、先ほど定義して`getScheduleList`にてスケジュール一覧を取得し、`scheduleList`に格納します。そして、`scheduleList`を`each`で回し、日付が一致するオブジェクトの`schedules`に格納するような処理を実装します。今回dateListは二次元配列なので、`firstindex`と`secondIndex`を取得して格納するので、少々ロジックが複雑になります。

<pre class="language-tsx" data-title="pages/CalendarPage.tsx◎"><code class="lang-tsx">...
  useEffect(() => {
    const monthOfSundayList = eachWeekOfInterval({
      start: startOfMonth(today),
      end: endOfMonth(today),
    })
    const newDateList: DateList = monthOfSundayList.map((date) => {
      return eachDayOfInterval({
        start: date,
        end: endOfWeek(date),
      }).map((date) => ({ date, schedules: [] as Schedule[] }))
    });

<strong>    const scheduleList = getScheduleList()
</strong><strong>    scheduleList.forEach((schedule) => {
</strong><strong>      const firstIndex = newDateList.findIndex((oneWeek) =>
</strong><strong>        oneWeek.some((item) => isSameDay(item.date, schedule.date))
</strong><strong>      )
</strong><strong>      if (firstIndex === -1) return;
</strong><strong>      const secondIndex = newDateList[firstIndex].findIndex((item) =>
</strong><strong>        isSameDay(item.date, schedule.date)
</strong><strong>      )
</strong><strong>
</strong><strong>      newDateList[firstIndex][secondIndex].schedules = [
</strong><strong>        ...newDateList[firstIndex][secondIndex].schedules,
</strong><strong>        schedule,
</strong><strong>      ]
</strong><strong>    })
</strong><strong>
</strong><strong>    setDateList(newDateList)
</strong>  }, [])
...
</code></pre>

これで、`dateList`の各日付に予定を格納することができました。`dateList`の型を修正したので、`CalendarBody.tsx`を修正しましょう。propsの`dateList`の型を`DateList`として、`oneWeek[0]`の部分を`oneWeek[0].date`、`item`の部分を`item.date`に修正しましょう。

<pre class="language-tsx" data-title="organisms/CalendarBody.tsx◎"><code class="lang-tsx">import { getDate } from "date-fns";
import { dateColor } from "../../libs/date";
<strong>import { DateList } from "../../types/calendar";
</strong>
type PropsType = {
  currentDate: Date;
<strong>  dateList: DateList
</strong>};

export const CalendarBody = ({ currentDate, dateList }: PropsType) => {
  return (
    &#x3C;tbody>
<strong>      {dateList.map((oneWeek, weekIndex) => (
</strong><strong>        &#x3C;tr key={`week-${weekIndex}`} className="mx-10">
</strong><strong>          {oneWeek.map((item, dayIndex) => (
</strong>            &#x3C;td
<strong>              key={`day-${weekIndex}-${dayIndex}`} 
</strong>              className="bg-white h-[10vh] border-2 border-solid border-lime-800"
            >
              &#x3C;span
                className={`inline-block w-[20px] leading-[20px] text-center ${dateColor(
<strong>                  item.date,
</strong>                  currentDate
                )}`}
              >
<strong>                {getDate(item.date)}
</strong>              &#x3C;/span>
            &#x3C;/td>
          ))}
        &#x3C;/tr>
      ))}
    &#x3C;/tbody>
  );
}

</code></pre>

これでカレンダーは変わりなく表示されているかと思います。

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2FUk3uG7WH2oQqNoO9QgH8%2Fccl.png?alt=media&#x26;token=e7f140e4-a785-4824-bbd0-bba654bba500" alt=""><figcaption></figcaption></figure>

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

```bash
git add .
```

```bash
git commit
```

commitメッセージは

```
feat: dateListの各日付に予定を格納するようにした
```

としましょう。
