diff --git a/components/Loader.tsx b/components/Loader.tsx new file mode 100644 index 00000000..b66dfe18 --- /dev/null +++ b/components/Loader.tsx @@ -0,0 +1,3 @@ +export default function Loader(){ + return
+} \ No newline at end of file diff --git a/components/Logo.tsx b/components/Logo.tsx new file mode 100644 index 00000000..476f0804 --- /dev/null +++ b/components/Logo.tsx @@ -0,0 +1,7 @@ +export default function Logo({small} : {small?: boolean}){ + return

+ + Calendso + +

; +} diff --git a/components/Modal.tsx b/components/Modal.tsx index 658bf706..12232876 100644 --- a/components/Modal.tsx +++ b/components/Modal.tsx @@ -1,4 +1,4 @@ -import { Fragment, useState } from 'react' +import { Fragment } from 'react' import { Dialog, Transition } from '@headlessui/react' import { CheckIcon } from '@heroicons/react/outline' diff --git a/components/Settings.tsx b/components/Settings.tsx index 1969c1ff..6c182c75 100644 --- a/components/Settings.tsx +++ b/components/Settings.tsx @@ -1,87 +1,70 @@ -import ActiveLink from '../components/ActiveLink'; -import {CodeIcon, CreditCardIcon, KeyIcon, UserCircleIcon, UserGroupIcon} from '@heroicons/react/outline'; +import Link from "next/link"; +import { CreditCardIcon, UserIcon, CodeIcon, KeyIcon, UserGroupIcon } from "@heroicons/react/solid"; +import { useRouter } from "next/router"; + +function classNames(...classes) { + return classes.filter(Boolean).join(" "); +} export default function SettingsShell(props) { - return ( -
-
-
-
-
- - - {props.children} -
-
-
-
-
- ); + return ( +
+
+ +
+
{props.children}
+
+ ); } diff --git a/components/Shell.tsx b/components/Shell.tsx index beafc8ed..bce52a41 100644 --- a/components/Shell.tsx +++ b/components/Shell.tsx @@ -1,277 +1,332 @@ import Link from "next/link"; -import { useEffect, useState } from "react"; +import React, { Fragment, useEffect } from "react"; import { useRouter } from "next/router"; -import { signOut, useSession } from "next-auth/client"; -import { MenuIcon, XIcon } from "@heroicons/react/outline"; +import { useSession } from "next-auth/client"; +import { Menu, Transition } from "@headlessui/react"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../lib/telemetry"; +import { SelectorIcon } from "@heroicons/react/outline"; +import { + CalendarIcon, + ClockIcon, + PuzzleIcon, + CogIcon, + ChatAltIcon, + LogoutIcon, + ExternalLinkIcon, + LinkIcon, +} from "@heroicons/react/solid"; +import Logo from "./Logo"; + +function classNames(...classes) { + return classes.filter(Boolean).join(" "); +} export default function Shell(props) { const router = useRouter(); const [session, loading] = useSession(); - const [profileDropdownExpanded, setProfileDropdownExpanded] = useState(false); - const [mobileMenuExpanded, setMobileMenuExpanded] = useState(false); const telemetry = useTelemetry(); + const navigation = [ + { + name: "Event Types", + href: "/event-types", + icon: LinkIcon, + current: router.pathname.startsWith("/event-types"), + }, + { + name: "Bookings", + href: "/bookings", + icon: ClockIcon, + current: router.pathname.startsWith("/bookings"), + }, + { + name: "Availability", + href: "/availability", + icon: CalendarIcon, + current: router.pathname.startsWith("/availability"), + }, + { + name: "Integrations", + href: "/integrations", + icon: PuzzleIcon, + current: router.pathname.startsWith("/integrations"), + }, + { + name: "Settings", + href: "/settings/profile", + icon: CogIcon, + current: router.pathname.startsWith("/settings"), + }, + ]; + useEffect(() => { telemetry.withJitsu((jitsu) => { return jitsu.track(telemetryEventTypes.pageView, collectPageParameters(router.pathname)); }); }, [telemetry]); - const toggleProfileDropdown = () => { - setProfileDropdownExpanded(!profileDropdownExpanded); - }; - - const toggleMobileMenu = () => { - setMobileMenuExpanded(!mobileMenuExpanded); - }; - - const logoutHandler = () => { - signOut({ redirect: false }).then(() => router.push("/auth/logout")); - }; - if (!loading && !session) { router.replace("/auth/login"); } return session ? ( -
-
- +
+
+
- )} - -
-
-

{props.heading}

-
+
+
+ {/* show top navigation for md and smaller (tablet and phones) */} + -
-
{props.children}
-
+
+
+
+
+

{props.heading}

+

{props.subtitle}

+
+
{props.CTA}
+
+
{props.children}
+ + {/* show bottom navigation for md and smaller (tablet and phones) */} + + + {/* add padding to content for mobile navigation*/} +
+
+
+
) : null; } + +function UserDropdown({ session, small, bottom }: { session: any; small?: boolean; bottom?: boolean }) { + return ( + + {({ open }) => ( + <> +
+ + + + + {!small && ( + + {session.user.name} + + {session.user.username} + + + )} + + {!small && ( + + +
+ + +
+ + View public page + +
+
+ + {({ active }) => ( + + + + + + + + + + Join our Slack + + )} + + + {({ active }) => ( + + + )} + +
+
+ + {({ active }) => ( + + + + + )} + +
+
+
+ + )} +
+ ); +} diff --git a/components/booking/TimeOptions.tsx b/components/booking/TimeOptions.tsx index dc51f486..52023e79 100644 --- a/components/booking/TimeOptions.tsx +++ b/components/booking/TimeOptions.tsx @@ -41,7 +41,7 @@ const TimeOptions = (props) => { onChange={setIs24hClock} className={classNames( is24hClock ? "bg-blue-600" : "dark:bg-gray-600 bg-gray-200", - "relative inline-flex flex-shrink-0 h-5 w-8 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" + "relative inline-flex flex-shrink-0 h-5 w-8 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black" )}> Use setting { id="timeZone" value={selectedTimeZone} onChange={(tz) => setSelectedTimeZone(tz.value)} - className="mb-2 shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md" + className="mb-2 shadow-sm focus:ring-black focus:border-black mt-1 block w-full sm:text-sm border-gray-300 rounded-md" /> ) diff --git a/components/team/EditTeamModal.tsx b/components/team/EditTeamModal.tsx index f32e21a1..d6991a1e 100644 --- a/components/team/EditTeamModal.tsx +++ b/components/team/EditTeamModal.tsx @@ -40,8 +40,8 @@ export default function EditTeamModal(props) {
-
- +
+
@@ -82,7 +82,7 @@ export default function EditTeamModal(props) {

Tick the box to disband this team.

diff --git a/components/team/MemberInvitationModal.tsx b/components/team/MemberInvitationModal.tsx index 2e9a8261..f355abe1 100644 --- a/components/team/MemberInvitationModal.tsx +++ b/components/team/MemberInvitationModal.tsx @@ -38,60 +38,93 @@ export default function MemberInvitationModal(props) { }); }; - return (
-
- + return ( +
+
+ - + -
-
-
- +
+
+
+ +
+
+ +
+

Invite someone to your team.

+
+
-
- +
-

- Invite someone to your team. +

+ + +
+
+ + +
+
+
+ +
+
+ +
+
+
+ {errorMessage && ( +

+ Error: + {errorMessage}

+ )} +
+ +
-
+
-
-
-
- - -
-
- - -
-
- -
-
- {errorMessage &&

Error: {errorMessage}

} -
- - -
-
-
); + ); } \ No newline at end of file diff --git a/components/team/TeamList.tsx b/components/team/TeamList.tsx index 7f04d322..2015bd79 100644 --- a/components/team/TeamList.tsx +++ b/components/team/TeamList.tsx @@ -22,7 +22,7 @@ export default function TeamList(props) { }; return (
-
    +
      {props.teams.map( (team: any) => selectAction(action, team) @@ -39,4 +39,4 @@ export default function TeamList(props) { onExit={() => setShowMemberInvitationModal(false)}> }
); -} \ No newline at end of file +} diff --git a/components/team/TeamListItem.tsx b/components/team/TeamListItem.tsx index a7413d72..7e7c7eaa 100644 --- a/components/team/TeamListItem.tsx +++ b/components/team/TeamListItem.tsx @@ -26,30 +26,30 @@ export default function TeamListItem(props) {
- {props.team.name} + {props.team.name} {props.team.role.toLowerCase()}
{props.team.role === 'INVITEE' &&
- +
} {props.team.role === 'MEMBER' &&
- +
} {props.team.role === 'OWNER' &&
- -
} - - + +
}*/} ); -} \ No newline at end of file +} diff --git a/components/ui/Scheduler.tsx b/components/ui/Scheduler.tsx index fcb4688c..a10fe998 100644 --- a/components/ui/Scheduler.tsx +++ b/components/ui/Scheduler.tsx @@ -69,10 +69,13 @@ export const Scheduler = ({ }; const OpeningHours = ({ idx, item }) => ( -
  • -
    +
  • +
    (item.days = selected)} /> -
    diff --git a/components/ui/UsernameInput.tsx b/components/ui/UsernameInput.tsx index bc611937..61aa858e 100644 --- a/components/ui/UsernameInput.tsx +++ b/components/ui/UsernameInput.tsx @@ -7,7 +7,7 @@ const UsernameInput = React.forwardRef((props, ref) => ( Username
    - + {typeof window !== "undefined" && window.location.hostname}/ ( autoComplete="username" required {...props} - className="focus:ring-blue-500 focus:border-blue-500 flex-grow block w-full min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300 lowercase" + className="focus:ring-black focus:border-black flex-grow block w-full min-w-0 rounded-none rounded-r-sm sm:text-sm border-gray-300 lowercase" />
  • diff --git a/components/ui/WeekdaySelect.tsx b/components/ui/WeekdaySelect.tsx index a9f371d8..24ee655e 100644 --- a/components/ui/WeekdaySelect.tsx +++ b/components/ui/WeekdaySelect.tsx @@ -25,9 +25,9 @@ export const WeekdaySelect = (props) => { @@ -107,7 +107,7 @@ export default function Page({ resetPasswordRequest, csrfToken }: Props) { @@ -151,7 +151,7 @@ export default function Page({ resetPasswordRequest, csrfToken }: Props) { type="password" autoComplete="password" required - className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" + className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-black focus:border-black sm:text-sm" />
    @@ -160,7 +160,7 @@ export default function Page({ resetPasswordRequest, csrfToken }: Props) {
    @@ -113,7 +113,7 @@ export default function Page({ csrfToken }) { diff --git a/pages/auth/login.tsx b/pages/auth/login.tsx index 76514aa4..bf83b392 100644 --- a/pages/auth/login.tsx +++ b/pages/auth/login.tsx @@ -4,21 +4,22 @@ import { getCsrfToken } from "next-auth/client"; export default function Login({ csrfToken }) { return ( -
    +
    Login
    -

    Sign in to your account

    + Calendso Logo +

    Sign in to your account

    -
    +
    -
    - +
    +
    + +
    +
    + + Forgot? + +
    +
    @@ -54,19 +62,18 @@ export default function Login({ csrfToken }) {
    - - -
    +
    + Don't have an account? {/* replace this with your account creation flow */} + + Create an account + +
    ); diff --git a/pages/auth/logout.tsx b/pages/auth/logout.tsx index 86f8b0da..f2dd5bd8 100644 --- a/pages/auth/logout.tsx +++ b/pages/auth/logout.tsx @@ -29,7 +29,7 @@ export default function Logout() {
    - + Go back to the login page diff --git a/pages/auth/signup.tsx b/pages/auth/signup.tsx index 7527e45c..dfb4d7a9 100644 --- a/pages/auth/signup.tsx +++ b/pages/auth/signup.tsx @@ -75,20 +75,20 @@ export default function Signup(props) {
    - +
    - +
    - +
    + className="btn btn-primary w-7/12 mr-2 inline-flex justify-center rounded-md border border-transparent cursor-pointer shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black sm:text-sm" /> signIn('Calendso', { callbackUrl: (router.query.callbackUrl || '') as string })} className="w-5/12 inline-flex justify-center text-sm text-gray-500 font-medium border px-4 py-2 rounded btn cursor-pointer">Login instead
    diff --git a/pages/availability/event/[type].tsx b/pages/availability/event/[type].tsx index 1fec9038..0aad0665 100644 --- a/pages/availability/event/[type].tsx +++ b/pages/availability/event/[type].tsx @@ -316,7 +316,7 @@ export default function EventTypePage({ name="address" id="address" required - className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" + className="shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md" defaultValue={locations.find((location) => location.type === LocationType.InPerson)?.address} />
    @@ -390,7 +390,7 @@ export default function EventTypePage({ name="title" id="title" required - className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" + className="shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md" placeholder="Quick Chat" defaultValue={eventType.title} /> @@ -411,7 +411,7 @@ export default function EventTypePage({ name="slug" id="slug" required - className="flex-1 block w-full focus:ring-blue-500 focus:border-blue-500 min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300" + className="flex-1 block w-full focus:ring-black focus:border-black min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300" defaultValue={eventType.slug} />
    @@ -429,7 +429,8 @@ export default function EventTypePage({ id="location" options={locationOptions} isSearchable="false" - className="flex-1 block w-full focus:ring-blue-500 focus:border-blue-500 min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300" + classNamePrefix="react-select" + className="react-select-container rounded-sm border border-gray-300 flex-1 block w-full focus:ring-primary-500 focus:border-primary-500 min-w-0 sm:text-sm" onChange={(e) => openLocationModal(e.value)} /> @@ -551,7 +552,7 @@ export default function EventTypePage({ ref={descriptionRef} name="description" id="description" - className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" + className="shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md" placeholder="A quick video meeting." defaultValue={eventType.description}> @@ -566,7 +567,7 @@ export default function EventTypePage({ type="text" name="title" id="title" - className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" + className="shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md" placeholder="Meeting with {USER}" defaultValue={eventType.eventName} /> @@ -626,7 +627,7 @@ export default function EventTypePage({ id="ishidden" name="ishidden" type="checkbox" - className="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-300 rounded" + className="focus:ring-black h-4 w-4 text-blue-600 border-gray-300 rounded" defaultChecked={eventType.hidden} /> @@ -648,7 +649,7 @@ export default function EventTypePage({ id="requiresConfirmation" name="requiresConfirmation" type="checkbox" - className="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-300 rounded" + className="focus:ring-black h-4 w-4 text-blue-600 border-gray-300 rounded" defaultChecked={eventType.requiresConfirmation} /> @@ -677,7 +678,7 @@ export default function EventTypePage({ name="minimumAdvance" id="minimumAdvance" required - className="focus:ring-blue-500 focus:border-blue-500 block w-full pr-20 sm:text-sm border-gray-300 rounded-md" + className="focus:ring-black focus:border-black block w-full pr-20 sm:text-sm border-gray-300 rounded-md" defaultValue={eventType.minimumBookingNotice} />
    @@ -734,7 +735,7 @@ export default function EventTypePage({ type="text" name="periodDays" id="" - className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-12 sm:text-sm border-gray-300 rounded-md" + className="shadow-sm focus:ring-black focus:border-indigo-500 block w-12 sm:text-sm border-gray-300 rounded-md" placeholder="30" defaultValue={eventType.periodDays || 30} /> @@ -742,7 +743,7 @@ export default function EventTypePage({ ref={periodDaysTypeRef} id="" name="periodDaysType" - className=" block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md" + className=" block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-black focus:border-indigo-500 sm:text-sm rounded-md" defaultValue={eventType.periodCountCalendarDays ? "1" : "0"}> @@ -793,7 +794,7 @@ export default function EventTypePage({ name="length" id="length" required - className="focus:ring-blue-500 focus:border-blue-500 block w-full pr-20 sm:text-sm border-gray-300 rounded-md" + className="focus:ring-black focus:border-black block w-full pr-20 sm:text-sm border-gray-300 rounded-md" placeholder="15" defaultValue={eventType.length} /> @@ -863,7 +864,7 @@ export default function EventTypePage({
    - +