JS 9 - Build a Calendar With Vue.js, Vuetify & Firebase

By Sheldon L Published at 2020-03-11 Updated at 2020-03-11


Get started

cd project_folder
vue create calendar
cd calendar
vue add fuetify

npm i firebase vue-textarea-autosize

code .
npm run serve

Calendar

import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import VueTextareaAutosize from 'vue-textarea-autosize';
import firebase from 'firebase/app';
import 'firebase/firestore';

Vue.use(VueTextareaAutosize);

Vue.config.productionTip = false

// the values come from firebase code when registered
firebase.initializeApp({
  apiKey: "AIzaSyCaGGG0Q4Z9W9iSNL_NyzHkf72QDbUIUgU",
  authDomain: "hello-c87c9.firebaseapp.com",
  databaseURL: "https://hello-c87c9.firebaseio.com",
  projectId: "hello-c87c9",
  storageBucket: "hello-c87c9.appspot.com",
  messagingSenderId: "785652861759",
  appId: "1:785652861759:web:be443f7c41ee4655fa618a",
  measurementId: "G-T8VZH0F019"
})

export const db = firebase.firestore();

new Vue({
  vuetify,
  render: h => h(App)
}).$mount('#app')
<template>
  <v-app>
    <v-content>
      <Calender />
    </v-content>
  </v-app>
</template>

<script>
import Calender from "./components/Calendar"
export default {
  name: 'App',

  components: {
    Calender
  },

  data: () => ({
    // in @/main.js
  }),
};
</script>
// copy `Events` code: https://vuetifyjs.com/en/components/calendars/


// Add/Modify these code in script
import { db } from '@/main';

export default {
  data: () => ({
    today: new Date().toISOString().substring(0,10),
    focus: new Date().toISOString().substring(0,10),
    type: 'month',
    typeToLabel: {
    month: 'Month',
    week: 'Week',
    day: 'Day',
    '4day': '4 Days',
    },
    // db
    name: null,
    details: null,
    start: null,
    end: null,
    color: "#1976D2",

    currentlyEditing: null,
    selectedEvent: {},
    selectedElement: null,
    selectedOpen: false,
    events: [],
    dialog: false,
  }),
  mounted () {
    this.getEvents();
  },
  methods: {
    // Work with firebase
    async getEvents () {
      let snapshot = await db.collection('calendarEvent').get();
      let events = [];
      snapshot.forEach(doc => {
        let appData = doc.data()
        appData.id = doc.id;
        events.push(appData)
      });
      this.events = events
    },
    editEvent(event) {
      this.currentlyEditing = event.id;
    },
    async updateEvent(event) {
      await db
        .collection('calendarEvent')
        .doc(this.currentlyEditing)
        .update({details: event.details})
      this.selectedOpen = false
      this.currentlyEditing = null
    },
    async deleteEvent(event) {
      await db
        .collection('calendarEvent')
        .doc(event)
        .delete();
      this.selectedOpen = false
      this.getEvents()
    },
    async addEvent() {
      if (this.name && this.start && this.end) {
        await db.collection('calendarEvent').add({
          name: this.name,
          details: this.details,
          start: this.start,
          end: this.end,
          color: this.color,
        });
        this.getEvents();
        this.name = "";
        this.details = "";
        this.start = "";
        this.end = "";
        this.color = "";
      } else {
        alert('Name, start and end date are required')
      }
    },
    updateRange ({ start, end }) {
      this.start = start
      this.end = end
    },
  }
<!-- copy `Events` code: https://vuetifyjs.com/en/components/calendars/ -->


<!-- Add/Modify these code in script -->

      <!-- Vsheet ... -->
        <!-- Vtoolbar -->
          <v-btn class="mr-4" color="primary" @click="dialog = true" dark>
            New Event
          </v-btn>
          <v-btn outlined class="mr-4" color="grey darken-2" @click="setToday">
            Today
          </v-btn>
        <!-- Vtoolbar -->
      <!-- Vsheet ... -->

      <!-- Add event dialog: -->
      <v-dialog v-model="dialog" max-width="500">
        <v-card>
          <v-container>
            <v-form @submit.prevent="addEvent">
              <v-text-field v-model="name" type="text" label="event name (required)">
              </v-text-field>
              <v-text-field v-model="details" type="text" label="event detail">
              </v-text-field>
              <v-text-field v-model="start" type="date" label="start (required)">
              </v-text-field>
              <v-text-field v-model="end" type="date" label="end (required)">
              </v-text-field>
              <v-text-field v-model="color" type="color" label="color (click to open color menu)">
              </v-text-field>
              <v-btn
                type = "submit"
                color = "primary"
                class = "mr-4"
                @click.stop="dialog = false"
              >Create Event</v-btn>
            </v-form>
          </v-container>
        </v-card>
      </v-dialog>

      <!-- Vsheet ... -->
        <!-- Vcalendar ... -->

        <!-- pop up events: -->
        <v-menu
          v-model="selectedOpen"
          :close-on-content-click="false"
          :activator="selectedElement"
          offset-x
        >
          <v-card
            color="grey lighten-4"
            min-width="350px"
            flat
          >
            <v-toolbar
              :color="selectedEvent.color"
              dark
            >
              <v-btn @click="deleteEvent(selectedEvent.id)" icon>
                <v-icon>mdi-delete</v-icon>
              </v-btn>
              <v-toolbar-title v-html="selectedEvent.name"></v-toolbar-title>
              <v-spacer></v-spacer>
            </v-toolbar>
            <v-card-text>
              <from v-if="currentlyEditing !== selectedEvent.id">
                
              </from>
              <form v-else>
                <textarea-autosize
                  v-model="selectedEvent.details"
                  type="text"
                  style="width: 100%"
                  min-height="100"
                  placeholder="add note"
                ></textarea-autosize>
              </form>
            </v-card-text>
            <v-card-actions>
              <v-btn
                text
                color="secondary"
                @click="selectedOpen = false"
              >Close
              </v-btn>
              <v-btn
                text v-if="currentlyEditing !== selectedEvent.id"
                @click.prevent="editEvent(selectedEvent)"
              >Edit</v-btn>
              <v-btn
                text v-else
                @click.prevent="updateEvent(selectedEvent)"
              >Save</v-btn>
            </v-card-actions>
          </v-card>
        </v-menu>