Next.jsでFullCalenderをカスタマイズ

# Next.jsでFullCalenderをカスタマイズ

FullCalendarは、JavaScriptで書かれたオープンソースのイベントカレンダーライブラリです。昔作ったメモアプリにカレンダー導入したくて使ったものを、機能を増やしました。
ちょっと苦労したのと、当時はメモを残していなかったので今回の内容メモです。

### カスタマイズする内容

特にそんなに多機能を求めていなかったので、イベントにマウスをホバーするとTooltipでイベントの内容を表示する機能と日本語化だけしていきたいと思います。

ReactだとTooltipを表示させるための情報が少なくて苦労してしまいました。でも1日時間空けてやると拍子抜けするくらい簡単に実装できてしまったので不思議ですね。

メモですので、導入手順も含めて書いていきます。

## 利用環境

- Next.js 13.2.3
- React 17.0.2
- typeScript 4.3.2
- @fullcalendar/react 5.10.1
- @fullcalendar/core 5.10.1
- @fullcalendar/daygrid 5.10.1
- @fullcalendar/interaction 5.10.1

## FullCalendarをインストールする

FullCalendarをインストールするには、npmパッケージマネージャーを使用します。以下のコマンドを使用して、FullCalendarをインストールします。

```
npm install --save @fullcalendar/react @fullcalendar/daygrid @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction

```

## FullCalendarを導入する手順

FullCalendarをカスタマイズするには、以下の手順を実行します。

```tsx
import FullCalendar from '@fullcalendar/react';
// FullCalendarで月表示を可能にするプラグイン。
import dayGridPlugin from '@fullcalendar/daygrid';
// FullCalendarで日付や時間が選択できるようになるプラグイン。
import interactionPlugin from "@fullcalendar/interaction";

//インポートはプラグインを後にするようにしてください。
```

FullCalendarコンポーネントをレンダリングします。

```tsx
//イベントはオブジェクトの配列をPropsとして渡します
const eventExample = [
		//オブジェクトの中身はこんな感じ
	　//satrtとendの日付で日を跨いだ予定を表示できる
　　//背景のカラーもこの中で指定できる
		{
			title: "温泉旅行",
			start: new Date(),
			end: new Date().setDate(new Date().getDate() + 5),
			description: "友達と温泉旅行",
			backgroundColor: "green",
			borderColor: "green"
		},
		{
			title: "期末テスト",
			start: new Date().setDate(new Date().getDate() + 5),
			description: "2年最後の期末テスト",
			backgroundColor: "blue",
			borderColor: "blue"
		}
	];

<FullCalendar
  plugins={[dayGridPlugin]}
  initialView="dayGridMonth"
  events={eventExample}
/>

```

### Next.jsに対応する

**Next.js**の仕様によって、**node_modules** 配下にある**FullCalender**のグローバルCSSが読み込まれないため、このままだとエラーになってしまいます。

エラーの修正は**next-transpile-modules** をインストールして **next.config.js** で設定して対応します。

まずはインストール。

```
npm i next-transpile-modules
```

**next.config.js**に以下のコードを追加します。

```jsx
const withTM = require("next-transpile-modules")([
  "@fullcalendar/common",
  "@fullcalendar/daygrid",
  "@fullcalendar/react",
]);

/** @type {import('next').NextConfig} */
module.exports = withTM({
  // any other next.js settings here
});
```

これで対応できるかと思います。

### ページを表示してみる
![Untitled (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/78513335-f581-8cae-82c4-eae984d91c37.png)


これだけでも十分いいですがもう少しカスタマイズします。

### 日本語化

日本語にしていくのは最初にインストールした**@fullcalendar/core**を使います。

日本語に対応するためのモジュールをインポートしましょう。

```tsx
import FullCalendar from '@fullcalendar/react';
// FullCalendarで月表示を可能にするプラグイン。
import dayGridPlugin from '@fullcalendar/daygrid';
// FullCalendarで日付や時間が選択できるようになるプラグイン。
import interactionPlugin from "@fullcalendar/interaction";
//日本語対応のためのインポート
import jaLocale from "@fullcalendar/core/locales/ja";　//追加

//インポートはプラグインを後にするようにしてください。
```

こんな感じです。
![Untitled (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/75a134fa-b4fb-e725-ffd1-8036187a0df2.png)


ヘッダーを少しだけ修正と全体の高さを調整

```tsx
//イベントはオブジェクトの配列をPropsとして渡します
const eventExample = [
		//オブジェクトの中身はこんな感じ
	　//satrtとendの日付で日を跨いだ予定を表示できる
　　//背景のカラーもこの中で指定できる
		{
			title: "温泉旅行",
			start: new Date(),
			end: new Date().setDate(new Date().getDate() + 5),
			description: "友達と温泉旅行",
			backgroundColor: "green",
			borderColor: "green"
		},
		{
			title: "期末テスト",
			start: new Date().setDate(new Date().getDate() + 5),
			description: "2年最後の期末テスト",
			backgroundColor: "blue",
			borderColor: "blue"
		}
	];

<FullCalendar
  plugins={[dayGridPlugin]}
  initialView="dayGridMonth"
  events={eventExample}
　weekends={true} //falseにすると土日が含まれなくなるdefault値がtrueなので省略可
	
　//以下を追加
　headerToolbar={{
	  start: "prevYear,nextYear",
		center: "title",
		end: "today prev,next"
		}}
	contentHeight={"700px"}
/>

```

こんな感じで並び替えて、月と年をそれぞれ移動できるようにしました。
![Untitled (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/f0bbca4f-160a-b4d0-4b65-39b68b306968.png)


### Tooltipでイベントの内容を表示させる

ここに非常にはまりました。ドキュメントを読んでもReact情報少なく、どのHooksを使えばいいのかよくわからなくてエラーを連発しました。

次の日にやったらあっさりできたんですが。。。orz

**結論から申しますとeventContentを使ってeventをレンダリングすることで解決できました！**

公式では

> `eventContent`- a Content Injection Input
 Generated content is inserted *inside*
the inner-most wrapper of the event element. If supplied as a callback function, it is called every time the associated event data changes.
> 

eventContent - コンテンツ・インジェクション入力。生成されたコンテンツは、イベント要素の最も内側のラッパーの中に挿入されます。コールバック関数として提供された場合、関連するイベントデータが変更されるたびに呼び出されます。

ちょっと何言ってるかわかんない。

とりあえずコードで動かしてみましょう！

TooltipはChakraUIのTooltipコンポーネントを使いました！他のライブラリでもいいと思います。

```tsx
//省略

//tooltipを追加するために生成するコンポーネント
	const EventComponent = (arg: EventContentArg) => (
		<Tooltip
			label={arg.event.extendedProps.description}　//イベントの中身
			aria-label="tooltip"
			placement="top-start"
			hasArrow
			arrowSize={5}
		>
			<div>{arg.event.title}</div>　//イベントのタイトル
		</Tooltip>
	);

<FullCalendar
  plugins={[dayGridPlugin]}
  initialView="dayGridMonth"
  events={eventExample}
　weekends={true} //falseにすると土日が含まれなくなるdefault値がtrueなので省略可
　headerToolbar={{
	  start: "prevYear,nextYear",
		center: "title",
		end: "today prev,next"
		}}
	contentHeight={"700px"}
　
　//追加
　eventContent={(arg: EventContentArg) => EventComponent(arg)}
/>

```

このようにホバーするとTooltipで内容が表示されました。
![Untitled (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/a7cccfa5-e32b-e4ea-bca6-13e2cdce6a61.png)


その他いろいろカスタマイズできるようですが、自分には現状必要ないのでまた何か追加したくなったら試してみます。

自前でカレンダーの実装は大変だと思うのでぜひ試してみてください！

## 参考にさせていただいたサイト

****[【Next】FullCalendarをNext.jsで使うまでのメモ](https://qiita.com/tak001/items/b57459db58f6ff8658a4)****

****[Next.js + Fullcalendar v5 を攻略する](https://qiita.com/yk2220s/items/8ed4d781412f6c4e9c45)****

[公式Doc](https://fullcalendar.io/)