diff --git a/.gitignore b/.gitignore index 17568606..126df069 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ yarn-error.log* # vercel .vercel + +# Webstorm +.idea diff --git a/calendso.yaml b/calendso.yaml index bb6d6866..69adf616 100644 --- a/calendso.yaml +++ b/calendso.yaml @@ -112,6 +112,17 @@ paths: summary: Deletes an event type tags: - Availability + /api/availability/calendars: + post: + description: Selects calendar for availability checking. + summary: Adds selected calendar + tags: + - Availability + delete: + description: Removes a calendar from availability checking. + summary: Deletes a selected calendar + tags: + - Availability /api/book/:user: post: description: Creates a booking in the user's calendar. @@ -147,8 +158,9 @@ paths: summary: Updates a user's profile tags: - User + /api/availability/schedule: path: description: "Updates a schedule" tags: - - Availability \ No newline at end of file + - Availability diff --git a/components/ActiveLink.tsx b/components/ActiveLink.tsx index f4da7d65..d7ae61c3 100644 --- a/components/ActiveLink.tsx +++ b/components/ActiveLink.tsx @@ -1,5 +1,4 @@ import { useRouter } from 'next/router' -import PropTypes from 'prop-types' import Link from 'next/link' import React, { Children } from 'react' diff --git a/components/Settings.tsx b/components/Settings.tsx index ff23e35b..bfbfd19c 100644 --- a/components/Settings.tsx +++ b/components/Settings.tsx @@ -1,5 +1,5 @@ import ActiveLink from '../components/ActiveLink'; -import { UserCircleIcon, KeyIcon, CodeIcon, UserGroupIcon } from '@heroicons/react/outline'; +import { UserCircleIcon, KeyIcon, CodeIcon, UserGroupIcon, CreditCardIcon } from '@heroicons/react/outline'; export default function SettingsShell(props) { return ( @@ -37,6 +37,11 @@ export default function SettingsShell(props) { Teams + {/* Change/remove me, if you're self-hosting */} + + Billing + + {/*

Loading...

; @@ -49,11 +50,12 @@ export default function EventType(props) { const enteredDescription = descriptionRef.current.value; const enteredLength = lengthRef.current.value; const enteredIsHidden = isHiddenRef.current.checked; + const enteredEventName = eventNameRef.current.value; // TODO: Add validation const response = await fetch('/api/availability/eventtype', { method: 'PATCH', - body: JSON.stringify({id: props.eventType.id, title: enteredTitle, slug: enteredSlug, description: enteredDescription, length: enteredLength, hidden: enteredIsHidden, locations }), + body: JSON.stringify({id: props.eventType.id, title: enteredTitle, slug: enteredSlug, description: enteredDescription, length: enteredLength, hidden: enteredIsHidden, locations, eventName: enteredEventName }), headers: { 'Content-Type': 'application/json' } @@ -266,7 +268,13 @@ export default function EventType(props) { -
+
+ +
+ +
+
+
-
+

@@ -368,6 +376,7 @@ export async function getServerSideProps(context) { if (!session) { return { redirect: { permanent: false, destination: '/auth/login' } }; } + const user = await prisma.user.findFirst({ where: { email: session.user.email, @@ -393,6 +402,7 @@ export async function getServerSideProps(context) { length: true, hidden: true, locations: true, + eventName: true, availability: true, } }); @@ -414,4 +424,4 @@ export async function getServerSideProps(context) { schedules }, } -} \ No newline at end of file +} diff --git a/pages/availability/index.tsx b/pages/availability/index.tsx index d79b5072..1b7bbc67 100644 --- a/pages/availability/index.tsx +++ b/pages/availability/index.tsx @@ -25,6 +25,8 @@ export default function Availability(props) { const startMinsRef = useRef(); const endHoursRef = useRef(); const endMinsRef = useRef(); + const bufferHoursRef = useRef(); + const bufferMinsRef = useRef(); if (loading) { return

Loading...

; @@ -80,15 +82,18 @@ export default function Availability(props) { const enteredStartMins = parseInt(startMinsRef.current.value); const enteredEndHours = parseInt(endHoursRef.current.value); const enteredEndMins = parseInt(endMinsRef.current.value); + const enteredBufferHours = parseInt(bufferHoursRef.current.value); + const enteredBufferMins = parseInt(bufferMinsRef.current.value); const startMins = enteredStartHours * 60 + enteredStartMins; const endMins = enteredEndHours * 60 + enteredEndMins; + const bufferMins = enteredBufferHours * 60 + enteredBufferMins; // TODO: Add validation const response = await fetch('/api/availability/day', { method: 'PATCH', - body: JSON.stringify({start: startMins, end: endMins}), + body: JSON.stringify({start: startMins, end: endMins, buffer: bufferMins}), headers: { 'Content-Type': 'application/json' } @@ -298,7 +303,7 @@ export default function Availability(props) {

- Set the start and end time of your day. + Set the start and end time of your day and a minimum buffer between your meetings.

@@ -316,7 +321,7 @@ export default function Availability(props) {
-
+
@@ -328,6 +333,18 @@ export default function Availability(props) {
+
+ +
+ + +
+ : +
+ + +
+
-
+
{integrations.filter( (ig) => ig.credential ).length !== 0 ?
    {integrations.filter(ig => ig.credential).map( (ig) => (
  • @@ -165,6 +218,104 @@ export default function Home({ integrations }) {
} +
+
+

+ Select calendars +

+
+

+ Select which calendars are checked for availability to prevent double bookings. +

+
+
+ +
+
+
+ {showSelectCalendarModal && +
+
+ {/* */} + + + {/* */} +
+
+
+ +
+
+ +
+

+ If no entry is selected, all calendars will be checked +

+
+
+
+
+
    + {selectableCalendars.map( (calendar) => (
  • +
    + {calendar.integration} +
    +
    +

    { calendar.name }

    +
    +
    + + Select calendar + +
    +
  • ))} +
+
+
+ +
+
+
+
+ }
); @@ -225,4 +376,4 @@ export async function getServerSideProps(context) { return { props: {integrations}, } -} \ No newline at end of file +} diff --git a/pages/settings/billing.tsx b/pages/settings/billing.tsx new file mode 100644 index 00000000..57acc64f --- /dev/null +++ b/pages/settings/billing.tsx @@ -0,0 +1,66 @@ +import Head from 'next/head'; +import Shell from '../../components/Shell'; +import SettingsShell from '../../components/Settings'; +import prisma from '../../lib/prisma'; +import {getSession, useSession} from 'next-auth/client'; + +export default function Billing(props) { + const [ session, loading ] = useSession(); + + if (loading) { + return

Loading...

; + } + + return ( + + + Billing | Calendso + + +
+
+

+ Change your Subscription +

+

+ Cancel, update credit card or change plan +

+
+
+