2
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

nuxtからGoogleカレンダーの予定を作る

※ element ui使ってます

nuxtjs上でgoogle calendarに予定を作成する方法を勉強したのでqiitaにメモ
※もっと良いやり方があれば教えてください

以下インラインコメントで簡単に説明

add-event.vue
<template>
  <section>
    <el-button v-if="auth2 && !isLogined" @click="login" type="primary">
      ログイン
    </el-button>
    <el-button v-if="auth2 && isLogined" @click="logout" type="primary">
      ログアウト
    </el-button>
    <label>予定作成</label>
    <div v-if="auth2 && isLogined">
      <!-- 予定のある日をカレンダーで選ぶ -->
      <el-date-picker
        v-model="calendarDate"
        :picker-options="pickerOptionsFuture"
        type="date"
        format="yyyy/MM/dd"
      />
      <!-- 開始時間を8時から21時まで15分刻みで選ぶ -->
      <el-time-select
        v-model="calendarStartTime"
        :picker-options="{
          start: '08:00',
          step: '00:15',
          end: '21:00'
        }"
        placeholder="開始時間"
      >
      </el-time-select>
      <!-- 予定の継続時間を選ぶ -->
      <el-select v-model="calendarTerm" placeholder="継続時間">
        <el-option :value="15" label="15" />
        <el-option :value="30" label="30" />
        <el-option :value="45" label="45" />
        <el-option :value="60" label="60" />
        <el-option :value="75" label="75" />
        <el-option :value="90" label="90" />
        <el-option :value="105" label="105" />
        <el-option :value="120" label="120" />
      </el-select><!-- 予定の要約を記入する -->
      <el-input v-model="calendarSummray" placeholder="予定内容" />
      <el-button @click="addCalendar" type="primary">登録</el-button>
    </div>
  </section>
</template>

<script>
import moment from 'moment'

const SCOPE = 'https://www.googleapis.com/auth/calendar.events'
const CLIENT_ID = '<!-- gcp OAuth 2.0 クライアント ID -->'
const API_KEY = '<!-- firebase api key -->'
export default {
  head() {
    return {
      script: [{ hid: 'gapi', src: 'https://apis.google.com/js/client.js' }]
    }
  },
  data() {
    const isLogined = false
    const auth2 = undefined
    const pickerOptionsFuture = {
      disabledDate(time) {
        return moment(time).format('YYYY-MM-DD') < moment().format('YYYY-MM-DD')
      }
    }

    return {
      calendarDate: '',
      calendarStartTime: '',
      calendarTerm: '',
      calendarSummray: '',
      isLogined,
      auth2,
      pickerOptionsFuture
    }
  },
  async mounted() {
    // google apiが読み込まれるのを待つ
    while (!window.gapi || !window.gapi.auth2) {
      await new Promise(resolve => setTimeout(resolve, 10))
    }
    // google api auth2の初期化
    window.gapi.auth2.init({
      apiKey: API_KEY,
      client_id: CLIENT_ID,
      scope: SCOPE,
      immediate: true
    })
    this.auth2 = window.gapi.auth2.getAuthInstance()

    // ログイン済みかチェック
    if (this.auth2.isSignedIn.get()) {
      this.isLogined = true
    }

    // カレンダーの初期化
    window.gapi.load('client')
    window.gapi.client.init({
      discoveryDocs: [
        'https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'
      ],
      scope: SCOPE,
      apiKey: API_KEY,
      clientId: CLIENT_ID
    })
    window.gapi.client.load('calendar', 'v3')
  },
  methods: {
    async login() {
      if (this.auth2.isSignedIn.get()) {
        this.isLogined = true
        return
      }
      await this.auth2.signIn()
      this.isLogined = true
    },
    logout() {
      this.auth2.signOut()
      this.isLogined = false
    },
    addCalendar() {
      // ガードブロック
      if (!this.auth2.isSignedIn.get()) {
        this.$message({
          message: 'ログインしてください',
          type: 'error'
        })
        return
      }
      if (!this.calendarDate) {
        this.$message({
          message: '日付を選択してください',
          type: 'error'
        })
        return
      }
      if (!this.calendarStartTime) {
        this.$message({
          message: '開始時間を選択してください',
          type: 'error'
        })
        return
      }
      if (!this.calendarTerm) {
        this.$message({
          message: '期間を選択してください',
          type: 'error'
        })
        return
      }
      if (!this.calendarSummray) {
        this.$message({
          message: '予定内容を入力してください',
          type: 'error'
        })
        return
      }

      // 予定開始時刻・終了時刻を作る
      const eventDate = moment(this.calendarDate).format('YYYY-MM-DD')
      const eventFrom = this.calendarStartTime + ':00'
      const eventTo = moment(this.calendarStartTime, 'HH:mm')
        .add(this.calendarTerm, 'minutes')
        .format('HH:mm:00')
      const event = {
        summary: this.calendarSummray,
        start: {
          dateTime: `${eventDate}T${eventFrom}+09:00`,
          timeZone: 'Asia/Tokyo' // time zoneを日本にする
        },
        end: {
          dateTime: `${eventDate}T${eventTo}+09:00`,
          timeZone: 'Asia/Tokyo' // time zoneを日本にする
        },
        recurrence: [],
        attendees: [],
        reminders: {
          useDefault: false,
          overrides: [
            { method: 'email', minutes: 24 * 60 }, // 1日前にリマインドメール
            { method: 'popup', minutes: 10 } // 10分前にリマインドノーティフィケーション
          ]
        }
      }
      // 予定作成
      const request = window.gapi.client.calendar.events.insert({
        calendarId: 'primary',
        resource: event
      })
      request.execute(() => {
        this.$message({
          message: 'カレンダー登録しました。',
          type: 'success'
        })
      })
    }
  }
}
</script>
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
2
Help us understand the problem. What are the problem?