K1ファクトリー
Next.jsサイトでのFullCalendarカスタマイズ

Next.jsサイトでのFullCalendarカスタマイズ

前回インストールしたFullCalendarに、祝日とか表示させたり、
イベント情報を表示させたりします!

祝日の表示
ググると、よくあるのはGoogleカレンダーAPIから祝日データをゲットしよう。
というものだけど、GoogleカレンダーのAPIの取得がよく分からない。
Googleってよく画面とか変更するからなぁ・・・
しばらくこれで悩んでおりましたが、面倒なので辞めました。

ググってる中で、Holidays JP APIというのを発見!
これを利用することにしました。

URL
https://holidays-jp.github.io/api/v1/date.json

見てみますと、

{
 "2017-01-01": "元日",
 "2017-01-02": "元日 振替休日",
 "2017-01-09": "成人の日"
}

こんな感じのJSONデータです。


イベント情報
これは前回ちょっと書きましたが、
microCMSで入力したデータをAPIで持ってきます。


page/cal.js(カレンダー表示ページ)の全コードです。

import Layout from '../components/layout'
import Link from 'next/link'
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import '@fullcalendar/common/main.css'
import '@fullcalendar/daygrid/main.css'

export default function Callendar({ events, holidaysData }) {

 const allevents = events.map((event) => (
  { title: `${event.title}`, start: `${event.eDateStart}`, end: `${event.eDateEnd}`, url: `/event/${event.id}` }
 ))

 const holidays = Object.keys(holidaysData)
 let holidaysDates = []
 for (let i = 0; i < holidays.length; i++) {
  let holiday = {
   title: holidaysData[holidays[i]],
   start: holidays[i],
   className: "holiday",
   holiday: holidays[i],
   display: 'background',
   color: 'pink',
  }
  holidaysDates.push(holiday)
 }

 const wholeEvents = allevents.concat(holidaysDates)

 return (
  <Layout
   title="カレンダー:K1ファクトリー 浜松市西区雄踏町でホームページ制作・チラシ・ポスターデータ制作ほか"
   description="fullcalendarをお試し中です。"
  >

   <div className="text-center">
    <h1 className="text-sm z-1 pt-8">カレンダー表示</h1>
   </div>

   <div className="px-6 pt-20 text-center bg-white">
    <section>
     <FullCalendar
      plugins={[dayGridPlugin]}
      locale="ja"
      firstDay="1"
      businessHours={false}
      events={wholeEvents}
      dayCellContent={(e) =>
       (e.dayNumberText = e.dayNumberText.replace("日", ""));
      }
      displayEventTime={true}
      displayEventEnd={true}
      eventTimeFormat={{ day: 'numeric', hour: 'numeric', minute: '2-digit' }}
     />
    </section>
    <section>
     <Link href="/" passHref><button className="bg-blue-700 hover:bg-blue-500 text-white font-bold py-2 px-10 mb-10 rounded text-sm md:text-base xl:text-lg">トップページに戻る</button></Link>
    </section>

   </div>
   <style global jsx>{`
    td.fc-day-sun {
     background-color:#ffeaea;
    }
    td.fc-day-sat {
     background-color:#eaf4ff;
    }
    .holiday {
     color: red;
    }
   `}</style>
  </Layout >
 )
}

export const getStaticProps = async () => {
 const key = {
  headers: { 'X-API-KEY': process.env.EVENTS_API_KEY },
 }
 const data = await fetch('https://k1events.microcms.io/api/v1/events?limit=100', key)
  .then(res => res.json())
  .catch(() => null)

 const hdata = await fetch('https://holidays-jp.github.io/api/v1/date.json')
  .then(res => res.json())
  .catch(() => null)

 return {
  props: {
   events: data.contents,
   holidaysData: hdata
  },
 };
};



まずは、
getStaticPropsを使って、イベント情報と日本の祝日情報のAPIを読み込みます。

export const getStaticProps = async () => {
 const key = {
  headers: { 'X-API-KEY': process.env.EVENTS_API_KEY },
 }
 const data = await fetch('https://k1events.microcms.io/api/v1/events?limit=100', key)
  .then(res => res.json())
  .catch(() => null)

 const hdata = await fetch('https://holidays-jp.github.io/api/v1/date.json')
  .then(res => res.json())
  .catch(() => null)

 return {
  props: {
   events: data.contents,
   holidaysData: hdata
  },
 };
};


headers: { 'X-API-KEY': process.env.EVENTS_API_KEY }
.env .env.development.localファイルで EVENTS_API_KEYを設定しておきます。
※API_KEYはmicroCMSの管理画面で確認してね。

 const data = await fetch('https://k1events.microcms.io/api/v1/events?limit=100', key)
  .then(res => res.json())
  .catch(() => null)
ここで、microCMSからAPIでイベント情報をゲット!

 const hdata = await fetch('https://holidays-jp.github.io/api/v1/date.json')
  .then(res => res.json())
  .catch(() => null)
日本の休日も同じようにゲット!こちらはとくにKEYとかないのです。

returnでAPIで取得したデータを返しています。


そして、ページ表示部分へ 
returnされたprops(プロパティ)データがページ表示に使われます。
export default function Callendar({ events, holidaysData }) {

}

「allevents」配列定数に、APIでゲットしたイベント情報データを fullcalendar表示に適応・変形したデータを代入。
{ title: "イベント名", start: "イベント開始日時", end: "イベント終了日時", url: "リンク(詳細ページへの)"},
map関数でイベント数分のデータを作っていきます。

 const allevents = events.map((event) => (
  { title: `${event.title}`, start: `${event.eDateStart}`, end: `${event.eDateEnd}`, url: `/event/${event.id}` }
 ))

  
「holidaysDates」配列変数に、日本の祝日データを適応・変形したデータを代入。

 const holidays = Object.keys(holidaysData)
 let holidaysDates = []
 for (let i = 0; i < holidays.length; i++) {
  let holiday = {
   title: holidaysData[holidays[i]],
   start: holidays[i],
   className: "holiday",
   holiday: holidays[i],
   display: 'background',
   color: 'pink',
  }
  holidaysDates.push(holiday)
 }


APIからよみこんだ「holidaysData」をObject.keys関数で変形させて、「holidays」に代入。
「holidays」の1つ1つを「holiday」としてそれらを push関数で合わせて配列「holidaysDates」にします。
「holiday」それぞれのデータには、
className「holiday」をつけて、
display: 'background',
color: 'pink', で、背景にピンク色をつける表示にしています。



最後に、イベント情報の配列「allevents」と、祝日の配列「holidaysDates」を合体!
 const wholeEvents = allevents.concat(holidaysDates)
「wholeEvents」というデータが完成!これをFullCalendarで表示してやります。

<FullCalendar
	plugins={[dayGridPlugin]}
	locale="ja"
	firstDay="1"
	events={wholeEvents}
	dayCellContent={(e) =>
		(e.dayNumberText = e.dayNumberText.replace("日", ""));
	}
	displayEventTime={true}
	displayEventEnd={true}
	eventTimeFormat={{ day: 'numeric', hour: 'numeric', minute: '2-digit' }}
/>


plugins={[dayGridPlugin]}:月表示
locale="ja":日本語表記
firstDay="1":月曜日から表示
events={wholeEvents}:イベント情報と祝日情報指定(上で作ったデータですね)

dayCellContent={(e) =>
(e.dayNumberText = e.dayNumberText.replace("日", ""))
}:カレンダーの日にちの「日」を削除

displayEventTime={true}
displayEventEnd={true}
eventTimeFormat={{ day: 'numeric', hour: 'numeric', minute: '2-digit' }}
:イベント情報の表示の仕方「何日 xx:xx - 何日 xx:xx」

土日と祝日の文字色は、スタイルシートで変更しています。

<style global jsx>{`
	td.fc-day-sun {
		background-color:#ffeaea;
	}
	td.fc-day-sat {
		background-color:#eaf4ff;
	}
	.holiday {
		color: red;
	}
`}</style>


以上です!
出来上がりのカレンダーページ。
あとは、イベント情報のリンク先(詳細)ページを作ってあげれば完成ですね。

HTML is loading comments...