diff --git a/db/index.ts b/db/index.ts index c3dc958..70d16eb 100644 --- a/db/index.ts +++ b/db/index.ts @@ -2,6 +2,7 @@ import * as mongoose from 'mongoose' import Booker from './booker' import Booking from './booking' import { dateFormatFrontend } from '../helpers/date' +import { BOOKING_STATUS } from './bookingStatus' let connectedPromise: Promise @@ -29,6 +30,15 @@ export async function getBookingByUUID(uuid: string) { return booking?.populate('booker').execPopulate() } +export async function getBookings() { + await connect() + const bookings = await Booking.find({ + status: { $in: [BOOKING_STATUS.REQUESTED, BOOKING_STATUS.CONFIRMED] }, + }) + // populate? + return bookings +} + export async function createBooking({ startDate, endDate, diff --git a/helpers/ical.ts b/helpers/ical.ts new file mode 100644 index 0000000..509e51d --- /dev/null +++ b/helpers/ical.ts @@ -0,0 +1,20 @@ +import { createEvents } from 'ics' +import { BookingDocument } from '../db/booking' + +export function generateBookedCalendar(bookings: BookingDocument[]) { + const events = bookings.map((booking) => ({ + title: `Buchung ${booking.booker.name}`, + description: `UUID: ${booking.uuid} +Link: http://${process.env.VERCEL_URL}/booking/${booking.uuid}`, + start: booking.days[0].split('-'), + end: booking.days[booking.days.length - 1].split('-'), + })) + // ts-ignore + const { error, value } = createEvents(events) + + if (error) { + throw new Error(error) + } + + return value +} diff --git a/package-lock.json b/package-lock.json index 0bcc40f..c7a9ed8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1308,6 +1308,49 @@ "purgecss": "^2.3.0" } }, + "@hapi/address": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.1.0.tgz", + "integrity": "sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@hapi/formula": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", + "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==" + }, + "@hapi/hoek": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.0.tgz", + "integrity": "sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==" + }, + "@hapi/joi": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz", + "integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==", + "requires": { + "@hapi/address": "^4.0.1", + "@hapi/formula": "^2.0.0", + "@hapi/hoek": "^9.0.0", + "@hapi/pinpoint": "^2.0.0", + "@hapi/topo": "^5.0.0" + } + }, + "@hapi/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==" + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3857,6 +3900,11 @@ "whatwg-url": "^8.0.0" } }, + "dayjs": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -5023,6 +5071,24 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ics": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/ics/-/ics-2.24.0.tgz", + "integrity": "sha512-JmPUqwKHog1aZWT0+8x9zCawLac+P6LVxbRWSdHMjJX0063nXbxuXbLBPxDxP0lWRK2a2OxxnlPbe3N7xDUsXA==", + "requires": { + "@hapi/joi": "^17.1.1", + "dayjs": "^1.8.33", + "lodash": "^4.17.15", + "uuid": "^3.3.3" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, "icss-utils": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", diff --git a/package.json b/package.json index cbe36a0..e04a3e6 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test:ci": "jest" }, "dependencies": { + "ics": "^2.24.0", "moment": "^2.28.0", "mongoose": "^5.10.5", "next": "^9.5.3", diff --git a/pages/api/daysbooked.ical.tsx b/pages/api/daysbooked.ical.tsx new file mode 100644 index 0000000..4b89ea3 --- /dev/null +++ b/pages/api/daysbooked.ical.tsx @@ -0,0 +1,24 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import { getBookings } from '../../db/index' +import { generateBookedCalendar } from '../../helpers/ical' + +export default async function useHandler( + req: NextApiRequest, + res: NextApiResponse +) { + const { method } = req + + switch (method) { + case 'GET': + const bookings = await getBookings() + const ical = generateBookedCalendar(bookings) + res.statusCode = 200 + //res.set('Content-Type', 'text/calendar;charset=utf-8') + //res.set('Content-Disposition', 'attachment; filename="pfadi-bussle.ics"') + res.send(ical) + break + default: + res.setHeader('Allow', ['GET']) + res.status(405).end(`Method ${method} Not Allowed`) + } +}