ぴよログみたいな育児記録Webアプリを作る②～2人分のスケジュール表示の巻～

# はじめに
:::note warn
いきなり何言ってんだ、とならないように補足
・[前回](https://qiita.com/mcmc0802/items/7033609b3108a832f50e)の続きです
・バグが若干残った状態で終わっています（後述）
:::
- 課題としてあった「2人分のスケジュールが表示できるようにする」に挑戦していくぞ！

# 今回の成果物
- 画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557424/989989a7-5b99-907a-895f-54c7a015eaf2.png)

- コード
```tsx:App.tsx
import {
  addHours,
  format,
  getDay,
  parse,
  startOfHour,
  startOfWeek,
} from "date-fns";
import { ja } from "date-fns/locale";
import { Calendar, dateFnsLocalizer } from "react-big-calendar";
import "react-big-calendar/lib/sass/styles.scss";

const App = () => {
  // 日本語設定定義
  const locales = {
    ja: ja,
  };

  // 双子表示用リソースの定義
  const resourceMap: { resourceId: number; resourceTitle: string }[] = [
    { resourceId: 1, resourceTitle: "もりっち" },
    { resourceId: 2, resourceTitle: "ぶくっち" },
  ];

  // 例としてのEvent定義用で時間計算しているだけ。おそらく後ほど淘汰される
  const endOfHour = (date: Date): Date => addHours(startOfHour(date), 1);
  const now = new Date();
  const start = endOfHour(now);
  const end = addHours(start, 2);
  const localizer = dateFnsLocalizer({
    format,
    parse,
    startOfWeek,
    getDay,
    locales,
  });

  // サンプルイベント定義
  const events = [
    { id: 0, title: "血祭り", start, end, resourceId: 1 },
    { id: 1, title: "わっしょい", start, end, resourceId: 2 },
  ];

  return (
    <Calendar
      defaultView="day"
      events={events}
      localizer={localizer}
      formats={{
        dayHeaderFormat: "yyyy年MM月dd日(EEEE)",
      }}
      culture={"ja"}
      resources={resourceMap}
      resourceIdAccessor="resourceId"
      resourceTitleAccessor="resourceTitle"
      views={["day", "agenda"]}
    />
  );
};

export default App;
```

# 修正点まとめ
## リソース定義追加
- [公式リファレンス](https://jquense.github.io/react-big-calendar/examples/?path=/story/about-big-calendar--page)にないかな～～と物色していたら[それっぽい記載](https://jquense.github.io/react-big-calendar/examples/?path=/docs/examples--example-11)を発見
    - ソースコードは[ここ](https://github.com/jquense/react-big-calendar/blob/master/stories/demos/exampleCode/resource.js)と連携している
- 見てみる感じ、リソースを定義して、カレンダー表示部分にプロパティとして渡してやれば良さそう

```tsx:App.tsx
  // 以下追加
  // 双子表示用リソースの定義
  const resourceMap: { resourceId: number; resourceTitle: string }[] = [
    { resourceId: 1, resourceTitle: "もりっち" },
    { resourceId: 2, resourceTitle: "ぶくっち" },
  ];
  
  // 中略
    return (
    <DnDCalendar
      defaultView="day"
      events={events}
      localizer={localizer}
      formats={{
        dayHeaderFormat: "yyyy年MM月dd日(EEEE)",
      }}
      culture={"ja"}
      // 追加部分↓
      resources={resourceMap}
      resourceIdAccessor="resourceId"
      resourceTitleAccessor="resourceTitle"
      // 追加部分↑
      onEventDrop={onEventDrop}
      onEventResize={onEventResize}
      resizable
    />
  );
```
~~※余談：もりっちぶくっちとは子どもの胎児ネーム。好きな芸人「さらば青春の光」がYoutubeの企画で名乗っていた名前が由来~~

## `DnDCalendar`コンポーネントから`Calendar`コンポーネントに変更

- 上記の通りにすると、returnブロックの`resourceIdAccessor`でエラーが発生する
- `DnDCalendar`（イベントをドラッグ＆ドロップで動かせるカレンダー）だと、上記の記載だといけないらしい（型が合わないとかで怒られた）
- 今回、登録したイベントを動かす予定はないので、思い切って`DnDCalendar`→`Calendar`にコンポーネントを変更
    - そうすると、一部他プロパティもじゃまになってくる（Calendarコンポーネントには存在しない）ため、削除
- ついでに、今回「Day」と「Agenda」しか使う予定がないため`views`プロパティを追加して表示制限

```tsx:App.tsx
  // 削除部分↓
  
  // const DnDCalendar = withDragAndDrop(Calendar);
  // const [events] = useState<Event[]>([
  //   {
  //     title: "Learn cool stuff",
  //     start: start,
  //     end: end,
  //     resource: resourceMap[0],
  //   },
  // ]);

  // const onEventResize: withDragAndDropProps["onEventResize"] = (data) => {
  //   const { start, end } = data;

  //   setEvents((currentEvents) => {
  //     const firstEvent = {
  //       start: new Date(start),
  //       end: new Date(end),
  //     };
  //     return [...currentEvents, firstEvent];
  //   });
  // };

  // const onEventDrop: withDragAndDropProps["onEventDrop"] = (data) => {
  //   console.log(data);
  // };
  
  // 削除部分↑

return (
    // `DnDCalendar`→`Calendar`に変更
    <Calendar
      defaultView="day"
      events={events}
      localizer={localizer}
      formats={{
        dayHeaderFormat: "yyyy年MM月dd日(EEEE)",
      }}
      culture={"ja"}
      resources={resourceMap}
      resourceIdAccessor="resourceId"
      resourceTitleAccessor="resourceTitle"
      // 削除部分↓
      // onEventDrop={onEventDrop}
      // onEventResize={onEventResize}
      // resizable
      // 削除部分↑
      
      // 以下追加
      views={["day", "agenda"]}
    />
  );
```

## サンプルイベント定義の追加
- 前章の対応をした結果、イベント定義が消えてしまったのでサンプル用のイベント定義を追加
    - イベントは後ほど、クリックにより追加できるよう動的になる予定
```tsx:App.tsx
  // 追加
  // サンプルイベント定義
  const events = [
    { id: 0, title: "血祭り", start, end, resourceId: 1 },
    { id: 1, title: "わっしょい", start, end, resourceId: 2 },
  ];
```

## SCSSファイルへの対応
- 成果物の画面にもある通り、時間表示部分が背景白色になってしまい時間が見えなくなった。あとで見た目修正がしたい
- [公式](https://jquense.github.io/react-big-calendar/examples/?path=/docs/guides-custom-styling--page)にもある通り、見た目のカスタマイズをしたい場合のためにscssファイルがあるそうなので対応（今回見た目修正まではしていない）
- [viteの公式](https://ja.vite.dev/guide/features.html#css-pre-processors)によると、viteでscssファイルを扱うためにはインストールが必要らしい

```powershell
npm install -D sass-embedded
```

- インポートファイルを修正
```tsx:App.tsx
// 削除部分↓
// import "react-big-calendar/lib/addons/dragAndDrop/styles.css";
// import "react-big-calendar/lib/css/react-big-calendar.css";
// 削除部分↑

// 追加
import "react-big-calendar/lib/sass/styles.scss";
```

# 課題
- 課題を一つ消化したら課題が増えたね、ハム太郎！
----

- 見た目の修正
    - 時間表示部分の背景
    - 双子それぞれの背景を変える
    - Today以外の表示の修正
        - Today以外の表示がバグっているので修正
- Agendaページの修正
    - Agendaページがバグっているので修正
- （できたら）時間以外の日本語表記（ボタンとか）
    - [ここ](https://github.com/jquense/react-big-calendar/blob/master/stories/demos/exampleCode/cultures.js)見る限りできそう～～まあ優先度は低いが