From 1e3c566f12e4705c6b0dc6c3a758fff23ab696bb Mon Sep 17 00:00:00 2001 From: Thomas Ruoff Date: Sat, 19 Feb 2022 01:10:13 +0100 Subject: [PATCH] add/delete entry in google calendar --- context/book.tsx | 2 +- db/booking.ts | 19 ++++++++++- lib/googlecalendar.ts | 79 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 lib/googlecalendar.ts diff --git a/context/book.tsx b/context/book.tsx index 8266b95..c7858ff 100644 --- a/context/book.tsx +++ b/context/book.tsx @@ -5,7 +5,7 @@ import { clearBookingData, loadBookingData } from '../helpers/storage' import { createBooking } from '../helpers/booking' import { Booking } from '../db/booking' -export type BookFormData = Omit & { +export type BookFormData = Omit & { storeData?: boolean } diff --git a/db/booking.ts b/db/booking.ts index 11a8d61..52b7bad 100644 --- a/db/booking.ts +++ b/db/booking.ts @@ -1,6 +1,7 @@ import * as mongoose from 'mongoose' import { v4 as uuidv4 } from 'uuid' import { dateFormatBackend, getDays, nowInTz } from '../helpers/date' +import { createCalendarEvent, deleteCalendarEvent } from '../lib/googlecalendar' import { Bill } from './bill' import { BOOKING_STATUS, VALIDATION_ERRORS } from './enums' @@ -21,7 +22,8 @@ export type Booking = { purpose?: string org?: string destination?: string - days?: string[] + days?: string[], + calendarEventId: string, } export type BookingDocument = Booking & @@ -103,6 +105,7 @@ const BookingSchema = new mongoose.Schema( purpose: { type: String, required: false }, org: { type: String, required: false }, destination: { type: String, required: false }, + calendarEventId: { type: String, required: false }, }, { timestamps: true, @@ -120,6 +123,20 @@ BookingSchema.pre('validate', function (next: () => void): void { next() }) +BookingSchema.pre('save', async function (next: () => void): Promise { + const booking = this as BookingDocument + + if (!booking.calendarEventId) { + // create calendar event before saving to database + await createCalendarEvent(booking); + } else if ([BOOKING_STATUS.CANCELED, BOOKING_STATUS.REJECTED].includes(booking.status)) { + // event has been canceled or rejected, delete calendar event again to free up the slot + await deleteCalendarEvent(booking); + } + + next(); +}); + BookingSchema.static('findBookedDays', async function ( uuidsToIngore: string[] = [] ): Promise { diff --git a/lib/googlecalendar.ts b/lib/googlecalendar.ts new file mode 100644 index 0000000..44b2d75 --- /dev/null +++ b/lib/googlecalendar.ts @@ -0,0 +1,79 @@ + +import {google} from 'googleapis'; +import { Booking } from '../db/booking'; + +const keyFile = process.env.GOOGLE_SERVICE_ACCOUNT_KEY_FILE; +const calendarId = process.env.GOOGLE_CALENDAR_ID; + +const auth = new google.auth.GoogleAuth({ + keyFile, + scopes: [ + 'https://www.googleapis.com/auth/calendar', + 'https://www.googleapis.com/auth/calendar.readonly' + ], +}); + +const calendar = google.calendar({ + version: 'v3', + auth, +}); + +export async function getNewEvents() { + const { data } = await calendar.events.list({ + calendarId, + timeMin: new Date().toISOString()} + ); + + return data.items; +} + +function getSummary(booking: Partial) : string { + let summary = ""; + + if (booking.org) { + summary += `${booking.org} - `; + } + + summary += booking.name; + + return summary; +} + +export async function createCalendarEvent(booking : Booking) : Promise { + + const response = await calendar.events.insert({ + auth, + calendarId, + requestBody: { + summary: getSummary(booking), + // description, + start: { date: booking.startDate }, + end: { date: booking.endDate }, + } + }); + + booking.calendarEventId = response.data.id; + + return booking; +} + +export async function deleteCalendarEvent(booking: Booking) { + await calendar.events.delete({ + auth, + calendarId, + eventId: booking.calendarEventId, + }); + + booking.calendarEventId = null; +} + +//export async function patchCalendarEvent(booking: { calendarEventId: string } & Partial ) : Promise { +// const response = await calendar.events.patch({ +// auth, +// calendarId, +// eventId: booking.calendarEventId, +// }); +// +// return booking; +//} +