【Reactアプリ100本ノック 08 Calendar】をやってみて

## はじめに

https://qiita.com/Sicut_study/items/3bd13a266feade56a4d0

今回こちらを行ってみました。100本ノックなんて考えるのも大変なのに、それを無料でこういったハンズオン？力試し？的なものを提供して下さるなんて尊敬しかありません。

筆者は普段`React`で、業務においてはサイト制作や、プライベートでは（変な）個人開発ばかりしているので、カレンダーアプリなんて実用的なものを作る経験はあまりありませんでした。ですから今回すごく勉強になったと感謝しています。

少し前置きが長くなりましたが筆者が制作したものを貼っておきます。

~~https:// benjuwan-react-calendar.netlify.app/~~

::: note
本記事のカレンダー機能を含んだ個人開発を行ったため上記ページは閉鎖しました。関心を持って下さった方は是非こちらの記事をご覧ください。
:::

https://qiita.com/benjuwan/items/631f51ad42575a38fa41

![benjuwan-react-calendar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/631e70a4-9532-81ec-7925-bf74324106fc.gif)

- 利用技術
    - `React`
    - `TypeScript`
    - `vite`
    - `Jotai`（ToDoメモリストと`localstorage`の中身をグローバルステートとして管理）
    - `CSS Modules`

普段は`styled-components`を使っているのですが先日`Next.js`を触った際に（サーバーコンポーネントでは）`styled-components`を使えないことを知りまして、`CSS Modules`に慣れておこうと初めて使ってみました。
元記事にあったライブラリ[date-fns](https://date-fns.org/)は使いませんでした<font color="lightgray">（使いこなせませんでした）</font>

## 概要
今回のノックの達成条件は以下でした。

- カレンダーが表示されている
- 土日は赤色で表示する
- 前の月、次の月をページネーションできる
- 日付に対して予定を複数追加できる
- 予定の編集削除ができる

## 達成条件に対するアプローチ
#### カレンダーが表示されている
初っ端のここで躓きました。元記事にあったライブラリ[date-fns](https://date-fns.org/)のドキュメントを見てもいまいちうまくいかず（スキル不足！）、結局`Chat-GPT`にヒントをもらいました。
生成AIについては色々な意見がありますが、個人的には筆者のように独学スタイルな人間には非常に有難い存在です。壁打ち相手にもそうですが、自身の解釈が合っているかどうかの確認などにも有用なので重宝しています。

#### 土日は赤色で表示する
土日どちらも赤色だと分かりづらいかもと思って筆者は土曜日は青色、日曜日は赤色にしました。
土日の判定はカスタムデータ属性を使用しました。

``` typescript
.
..
<li key={i} data-daydate={day.dayDateNum} className=......>
..
.
```

具体的には`data-daydate={day.dayDateNum}`の部分で`CSS`のスタイルを書き分けています。

``` css
/* 日曜日 */
[data-daydate='0'] {
    background-color: #f5c0c0;
}

/* 土曜日 */
[data-daydate='6'] {
    background-color: #f5c0c0;
}
```

#### 前の月、次の月をページネーションできる
ここは素直に「年」や「月」の`state`を用意して対応。
しかし、手元のiPhoneやPCのカレンダーを見てみると先月の最終週と来月の初週の一部が当月と一緒に表示されていることに気づき『確かにその方が分かりやすいかも』と同じような見た目にすることにしました。

![スクリーンショット 2024-01-24 165016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/37f53a2a-b415-2fe6-49b7-43eab3a5d76a.png)

先月と来月の部分に関しては「月数を表示」+「スケジュール登録機能無し」を行って当月分との差別化を図っています。

#### 日付に対して予定を複数追加できる
複数予定に関しては、配列形式の`state`を用意して入力した内容を随時追加していく方法を採りました。
ただ進める中で『時間も入力できたほうが便利そうだ』と思って開始時刻・終了時刻の項目も追加しています。

![スクリーンショット 2024-01-24 162740.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/5ab605fd-fe43-d5c4-4a72-fcc6790436b1.png)

#### 予定の編集削除ができる
筆者の場合は以下のような型のオブジェクトとしてToDoメモを管理。

``` typescript
export type todoItemType = {
    todoID: string;
    todoContent: string;
    startTime?: string;
    finishTime?: string;
    edit: boolean;
}
```
この型に則ったオブジェクトを先ほど話したように配列形式の`state`として取り回して「編集」や「ToDoの中身（内容と時刻）」を扱うようにしました。

編集したい場合は`edit`を`true`にして「見た目（表示）の変更」と「オブジェクトの登録機能 → 更新機能への切替」を行い、再登録できるようにしています。

![スクリーンショット 2024-01-24 162937.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/8ab64dc6-6458-d668-cd29-56b22c9fa06d.png)

ToDoメモを押下すると詳細画面が開き、

![スクリーンショット 2024-01-24 163026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/88d313f2-503a-80d6-0cc4-54fb1fec317a.png)

この画面で編集します（「削除」を押下すると当該ToDoメモが消えます）

![スクリーンショット 2024-01-24 163037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/80527779-cd7d-4814-ea2d-fc3cf2299e81.png)

編集・削除機能に関しては、シャローコピーしたオブジェクトに`splice`メソッドを使って、それをセッター関数に指定して`state`を更新しています。

## 詰まったところ
**先月・来月へのカレンダー移動時に前月で入力した内容が次月の同じ場所に反映される**という事態が起きました。
結論から言うと、これはToDoメモを管理している`state`を初期化していないために起きたことでした。かなり初歩的で恥ずかしいのですが結構時間を食って最終的に`Chat-GPT`に泣きつくという情けなさでした。
『ここでこの実装をしているから、あーでこーで』と色々関係ないところを怪しんだりして……。そもそもシンプルで可読性の高いコードを書けていれば、このような初歩的なミスに気づけたと思いますので猛省です。

## 自分で追加した機能
`localstorage`を使っているので同ブラウザであれば、ご自身が入力されたスケジュールは保持されたままになります。
地味にこの機能を追加するのが面倒だったので何か楽なライブラリあればなぁとか思っています。
<font color="lightgray">筆者がうまくそのライブラリを使いこなせるかの問題がありますが……。</font>

## さいごに
ここまで読んでいただき、ありがとうございました。
冒頭にも書きましたが、こういった企画を行い、ハンズオンを提供できるほどのスキル・知見は素晴らしいと思います。筆者もぜひ獲得したいものです。今後も興味のあるものがあれば折を見てまたチャレンジできればと思います。

今回制作した内容の`GitHub`を下記に置いておきますので関心のある方はご自由にしてください。

https://github.com/Benjuwan/MyLibs/tree/main/frontend/theCalendar