Merge branch 'main' of github.com:calendso/calendso
This commit is contained in:
		
						commit
						e2d88f1a55
					
				
					 5 changed files with 142 additions and 126 deletions
				
			
		|  | @ -14,6 +14,7 @@ const AvailableTimes = ({ | |||
|   timeFormat, | ||||
|   user, | ||||
|   organizerTimeZone, | ||||
|   height, | ||||
| }) => { | ||||
|   const router = useRouter(); | ||||
|   const { rescheduleUid } = router.query; | ||||
|  | @ -27,9 +28,11 @@ const AvailableTimes = ({ | |||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
|     <div className="sm:pl-4 mt-8 sm:mt-0 text-center sm:w-1/3  md:max-h-97 overflow-y-auto"> | ||||
|       <div className="text-gray-600 font-light text-xl mb-4 text-left"> | ||||
|         <span className="w-1/2 dark:text-white text-gray-600">{date.format("dddd DD MMMM YYYY")}</span> | ||||
|     <div | ||||
|       className="sm:pl-4 mt-16 pt-4 pr-6 bg-neutral-50 dark:bg-neutral-800 rounded-r-sm border border-l-0 border-neutral-300 dark:border-neutral-700 text-center h-full overflow-y-auto" | ||||
|       style={{ maxHeight: height }}> | ||||
|       <div className="font-semibold mb-4 text-left border-b border-neutral-200 pb-4"> | ||||
|         <span className="w-1/2 dark:text-white text-primary-500">{date.format("dddd DD MMMM YYYY")}</span> | ||||
|       </div> | ||||
|       {slots.length > 0 && | ||||
|         slots.map((slot) => ( | ||||
|  | @ -39,7 +42,7 @@ const AvailableTimes = ({ | |||
|                 `/${user.username}/book?date=${slot.utc().format()}&type=${eventTypeId}` + | ||||
|                 (rescheduleUid ? "&rescheduleUid=" + rescheduleUid : "") | ||||
|               }> | ||||
|               <a className="block font-medium mb-4 text-blue-600 border border-blue-600 rounded hover:text-white hover:bg-blue-600 py-4"> | ||||
|               <a className="block font-medium mb-4 bg-white dark:bg-neutral-700 text-primary-500 dark:text-neutral-200 border border-primary-500 dark:border-neutral-600 rounded hover:text-white hover:bg-primary-500 dark:hover:bg-primary-500 dark:hover:border-primary-500 py-4"> | ||||
|                 {slot.format(timeFormat)} | ||||
|               </a> | ||||
|             </Link> | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/solid"; | ||||
| import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/outline"; | ||||
| import { useEffect, useState } from "react"; | ||||
| import dayjs, { Dayjs } from "dayjs"; | ||||
| import utc from "dayjs/plugin/utc"; | ||||
|  | @ -24,6 +24,7 @@ const DatePicker = ({ | |||
|   periodDays, | ||||
|   periodCountCalendarDays, | ||||
|   minimumBookingNotice, | ||||
|   setHeight, | ||||
| }) => { | ||||
|   const [calendar, setCalendar] = useState([]); | ||||
|   const [selectedMonth, setSelectedMonth] = useState<number>(); | ||||
|  | @ -147,12 +148,14 @@ const DatePicker = ({ | |||
|           onClick={() => setSelectedDate(inviteeDate.date(day))} | ||||
|           disabled={isDisabled(day)} | ||||
|           className={ | ||||
|             "text-center w-10 h-10 rounded-full mx-auto" + | ||||
|             (isDisabled(day) ? " text-gray-400 font-light" : " text-blue-600 font-medium") + | ||||
|             "w-36 mx-auto h-28 mx-auto p-3 text-left flex self-start" + | ||||
|             (isDisabled(day) | ||||
|               ? " text-neutral-400 font-light" | ||||
|               : " text-neutral-900 dark:text-neutral-200 font-medium") + | ||||
|             (selectedDate && selectedDate.isSame(inviteeDate.date(day), "day") | ||||
|               ? " bg-blue-600 text-white-important" | ||||
|               ? " bg-neutral-100 dark:bg-neutral-700 border border-neutral-900 dark:border-neutral-600 dark:text-white" | ||||
|               : !isDisabled(day) | ||||
|               ? " bg-blue-50 dark:bg-gray-900 dark:bg-opacity-30" | ||||
|               ? " bg-neutral-100 dark:bg-neutral-700 dark:bg-opacity-30" | ||||
|               : "") | ||||
|           }> | ||||
|           {day} | ||||
|  | @ -162,35 +165,44 @@ const DatePicker = ({ | |||
|   }, [selectedMonth, inviteeTimeZone, selectedDate]); | ||||
| 
 | ||||
|   return selectedMonth ? ( | ||||
|     <div | ||||
|       className={ | ||||
|         "mt-8 sm:mt-0 " + | ||||
|         (selectedDate ? "sm:w-1/3 sm:border-r sm:dark:border-gray-900 sm:px-4" : "sm:w-1/2 sm:pl-4") | ||||
|       }> | ||||
|       <div className="flex text-gray-600 font-light text-xl mb-4 ml-2"> | ||||
|         <span className="w-1/2 text-gray-600 dark:text-white"> | ||||
|           {dayjs().month(selectedMonth).format("MMMM YYYY")} | ||||
|     <div className="mt-8 sm:mt-0"> | ||||
|       <div className="flex text-gray-600 text-xl mb-8"> | ||||
|         <div className="w-1/2 text-2xl"> | ||||
|           <span className="font-semibold text-neutral-900 dark:text-white"> | ||||
|             {dayjs().month(selectedMonth).format("MMMM")} | ||||
|           </span> | ||||
|             | ||||
|           <span className="text-neutral-400">{dayjs().month(selectedMonth).format("YYYY")}</span> | ||||
|         </div> | ||||
|         <div className="w-1/2 text-right text-gray-600 dark:text-gray-400"> | ||||
|           <button | ||||
|             onClick={decrementMonth} | ||||
|             className={ | ||||
|               "mr-4 " + | ||||
|               (selectedMonth <= dayjs().tz(inviteeTimeZone).month() && "text-gray-400 dark:text-gray-600") | ||||
|               "p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 dark:text-white rounded-sm border border-neutral-300 text-black mr-4 " + | ||||
|               (selectedMonth <= dayjs().tz(inviteeTimeZone).month() && "opacity-50") | ||||
|             } | ||||
|             disabled={selectedMonth <= dayjs().tz(inviteeTimeZone).month()}> | ||||
|             <ChevronLeftIcon className="w-5 h-5" /> | ||||
|           </button> | ||||
|           <button onClick={incrementMonth}> | ||||
|           <button | ||||
|             className="p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 dark:text-white rounded-sm border border-neutral-300" | ||||
|             onClick={incrementMonth}> | ||||
|             <ChevronRightIcon className="w-5 h-5" /> | ||||
|           </button> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div className="grid grid-cols-7 gap-y-4 text-center"> | ||||
|       <div | ||||
|         className="bg-white dark:bg-neutral-800 p-6 rounded-l-sm border border-neutral-300 dark:border-neutral-700 grid grid-cols-7 gap-y-4" | ||||
|         ref={(el) => { | ||||
|           if (!el) return; | ||||
|           setHeight(el.getBoundingClientRect().height); | ||||
|         }}> | ||||
|         {["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] | ||||
|           .sort((a, b) => (weekStart.startsWith(a) ? -1 : weekStart.startsWith(b) ? 1 : 0)) | ||||
|           .map((weekDay) => ( | ||||
|             <div key={weekDay} className="uppercase text-gray-400 text-xs tracking-widest"> | ||||
|             <div | ||||
|               key={weekDay} | ||||
|               className="uppercase text-neutral-600 text-xs tracking-widest border-b border-neutral-200 dark:border-neutral-700 pb-4"> | ||||
|               {weekDay} | ||||
|             </div> | ||||
|           ))} | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { useEffect, useState } from "react"; | ||||
| import { GetServerSideProps, GetServerSidePropsContext } from "next"; | ||||
| import Head from "next/head"; | ||||
| import { ChevronDownIcon, ClockIcon, GlobeIcon } from "@heroicons/react/solid"; | ||||
| import { ChevronDownIcon, ClockIcon, GlobeIcon, InformationCircleIcon } from "@heroicons/react/solid"; | ||||
| import { useRouter } from "next/router"; | ||||
| import dayjs, { Dayjs } from "dayjs"; | ||||
| import * as Collapsible from "@radix-ui/react-collapsible"; | ||||
|  | @ -30,6 +30,8 @@ export default function Type(props): Type { | |||
|   const [timeFormat, setTimeFormat] = useState("h:mma"); | ||||
|   const telemetry = useTelemetry(); | ||||
| 
 | ||||
|   const [calHeight, setCalHeight] = useState(0); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     handleToggle24hClock(localStorage.getItem("timeOption.is24hClock") === "true"); | ||||
|     telemetry.withJitsu((jitsu) => jitsu.track(telemetryEventTypes.pageView, collectPageParameters())); | ||||
|  | @ -79,7 +81,7 @@ export default function Type(props): Type { | |||
| 
 | ||||
|   return ( | ||||
|     isReady && ( | ||||
|       <div> | ||||
|       <div className="bg-neutral-50 dark:bg-neutral-900 h-screen"> | ||||
|         <Head> | ||||
|           <title> | ||||
|             {rescheduleUid && "Reschedule"} {props.eventType.title} | {props.user.name || props.user.username}{" "} | ||||
|  | @ -126,29 +128,22 @@ export default function Type(props): Type { | |||
|             } | ||||
|           /> | ||||
|         </Head> | ||||
|         <main | ||||
|           className={ | ||||
|             "mx-auto my-0 sm:my-24 transition-max-width ease-in-out duration-500 " + | ||||
|             (selectedDate ? "max-w-6xl" : "max-w-3xl") | ||||
|           }> | ||||
|           <div className="dark:bg-gray-800 bg-white sm:shadow sm:rounded-lg"> | ||||
|             <div className="sm:flex px-4 py-5 sm:p-4"> | ||||
|               <div | ||||
|                 className={ | ||||
|                   "pr-8 sm:border-r sm:dark:border-gray-900 " + (selectedDate ? "sm:w-1/3" : "sm:w-1/2") | ||||
|                 }> | ||||
|                 <Avatar user={props.user} className="w-16 h-16 rounded-full mb-4" /> | ||||
|                 <h2 className="font-medium dark:text-gray-300 text-gray-500">{props.user.name}</h2> | ||||
|                 <h1 className="text-3xl font-semibold dark:text-white text-gray-800 mb-4"> | ||||
|                   {props.eventType.title} | ||||
|         <main className={"flex sm:py-12 w-11/12 mx-auto"}> | ||||
|           <div className="w-2/12 md:pt-32"> | ||||
|             <Avatar user={props.user} className="w-12 h-12 rounded-full mb-4" /> | ||||
|             <h1 className="text-xl font-semibold dark:text-neutral-100 text-neutral-900 mb-2"> | ||||
|               {props.user.name} | ||||
|             </h1> | ||||
|                 <p className="text-gray-500 mb-1 px-2 py-1 -ml-2"> | ||||
|             <p className="text-neutral-500 mb-1 px-2 py-1 -ml-2"> | ||||
|               <InformationCircleIcon className="inline-block w-4 h-4 mr-1 -mt-1" /> | ||||
|               {props.eventType.title} | ||||
|             </p> | ||||
|             <p className="text-neutral-500 mb-1 px-2 py-1 -ml-2"> | ||||
|               <ClockIcon className="inline-block w-4 h-4 mr-1 -mt-1" /> | ||||
|               {props.eventType.length} minutes | ||||
|             </p> | ||||
| 
 | ||||
|             <Collapsible.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}> | ||||
|                   <Collapsible.Trigger className="text-gray-500 mb-1 px-2 py-1 -ml-2"> | ||||
|               <Collapsible.Trigger className="text-neutral-500 mb-1 px-2 py-1 -ml-2"> | ||||
|                 <GlobeIcon className="inline-block w-4 h-4 mr-1 -mt-1" /> | ||||
|                 {timeZone()} | ||||
|                 <ChevronDownIcon className="inline-block w-4 h-4 ml-1 -mt-1" /> | ||||
|  | @ -160,9 +155,8 @@ export default function Type(props): Type { | |||
|                 /> | ||||
|               </Collapsible.Content> | ||||
|             </Collapsible.Root> | ||||
| 
 | ||||
|                 <p className="dark:text-gray-200 text-gray-600 mt-3 mb-8">{props.eventType.description}</p> | ||||
|           </div> | ||||
|           <div className="w-8/12"> | ||||
|             <DatePicker | ||||
|               date={selectedDate} | ||||
|               periodType={props.eventType?.periodType} | ||||
|  | @ -177,7 +171,10 @@ export default function Type(props): Type { | |||
|               inviteeTimeZone={timeZone()} | ||||
|               eventLength={props.eventType.length} | ||||
|               minimumBookingNotice={props.eventType.minimumBookingNotice} | ||||
|               setHeight={setCalHeight} | ||||
|             /> | ||||
|           </div> | ||||
|           <div className="w-2/12"> | ||||
|             {selectedDate && ( | ||||
|               <AvailableTimes | ||||
|                 workingHours={props.workingHours} | ||||
|  | @ -188,11 +185,15 @@ export default function Type(props): Type { | |||
|                 eventLength={props.eventType.length} | ||||
|                 date={selectedDate} | ||||
|                 user={props.user} | ||||
|                 height={calHeight} | ||||
|               /> | ||||
|             )} | ||||
|           </div> | ||||
|           {!props.user.hideBranding && ( | ||||
|             <div className="absolute top-4 right-4"> | ||||
|               <PoweredByCalendso /> | ||||
|             </div> | ||||
|           {!props.user.hideBranding && <PoweredByCalendso />} | ||||
|           )} | ||||
|         </main> | ||||
|       </div> | ||||
|     ) | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class MyDocument extends Document { | |||
|           <meta name="msapplication-TileColor" content="#ff0000" /> | ||||
|           <meta name="theme-color" content="#ffffff" /> | ||||
|         </Head> | ||||
|         <body className="dark:bg-gray-900 bg-white"> | ||||
|         <body className="dark:bg-neutral-900 bg-white"> | ||||
|           <Main /> | ||||
|           <NextScript /> | ||||
|         </body> | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ export default function Success(props) { | |||
| 
 | ||||
|   return ( | ||||
|     isReady && ( | ||||
|       <div> | ||||
|       <div className="bg-neutral-50 dark:bg-neutral-900 h-screen"> | ||||
|         <Head> | ||||
|           <title> | ||||
|             Booking {props.eventType.requiresConfirmation ? "Submitted" : "Confirmed"} | {eventName} | | ||||
|  | @ -68,7 +68,7 @@ export default function Success(props) { | |||
|           </title> | ||||
|           <link rel="icon" href="/favicon.ico" /> | ||||
|         </Head> | ||||
|         <main className="max-w-3xl mx-auto my-24"> | ||||
|         <main className="max-w-3xl mx-auto py-24"> | ||||
|           <div className="fixed z-50 inset-0 overflow-y-auto"> | ||||
|             <div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> | ||||
|               <div className="fixed inset-0 my-4 sm:my-0 transition-opacity" aria-hidden="true"> | ||||
|  | @ -76,61 +76,61 @@ export default function Success(props) { | |||
|                   ​ | ||||
|                 </span> | ||||
|                 <div | ||||
|                   className="inline-block align-bottom dark:bg-gray-800 bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6" | ||||
|                   className="inline-block align-bottom dark:bg-gray-800 bg-white rounded-sm px-8 pt-5 pb-4 text-left overflow-hidden border border-neutral-200 dark:border-neutral-700 transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:py-6" | ||||
|                   role="dialog" | ||||
|                   aria-modal="true" | ||||
|                   aria-labelledby="modal-headline"> | ||||
|                   <div> | ||||
|                     <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100"> | ||||
|                       {!props.eventType.requiresConfirmation && ( | ||||
|                         <CheckIcon className="h-6 w-6 text-green-600" /> | ||||
|                         <CheckIcon className="h-8 w-8 text-green-600" /> | ||||
|                       )} | ||||
|                       {props.eventType.requiresConfirmation && ( | ||||
|                         <ClockIcon className="h-6 w-6 text-green-600" /> | ||||
|                         <ClockIcon className="h-8 w-8 text-green-600" /> | ||||
|                       )} | ||||
|                     </div> | ||||
|                     <div className="mt-3 text-center sm:mt-5"> | ||||
|                       <h3 | ||||
|                         className="text-lg leading-6 font-medium dark:text-white text-gray-900" | ||||
|                         className="text-2xl leading-6 font-semibold dark:text-white text-neutral-900" | ||||
|                         id="modal-headline"> | ||||
|                         Booking {props.eventType.requiresConfirmation ? "Submitted" : "Confirmed"} | ||||
|                         {props.eventType.requiresConfirmation ? "Submitted" : "This meeting is scheduled"} | ||||
|                       </h3> | ||||
|                       <div className="mt-2"> | ||||
|                         <p className="text-sm text-gray-500 dark:text-gray-300"> | ||||
|                       <div className="mt-3"> | ||||
|                         <p className="text-sm text-neutral-600 dark:text-gray-300"> | ||||
|                           {props.eventType.requiresConfirmation | ||||
|                             ? `${ | ||||
|                                 props.user.name || props.user.username | ||||
|                               } still needs to confirm or reject the booking.` | ||||
|                             : `You are scheduled in with ${props.user.name || props.user.username}.`} | ||||
|                             : `We emailed you and the other attendees a calendar invitation with all the details.`} | ||||
|                         </p> | ||||
|                       </div> | ||||
|                       <div className="mt-4 border-t border-b dark:border-gray-900 py-4"> | ||||
|                         <h2 className="text-lg font-medium text-gray-600 dark:text-gray-100 mb-2"> | ||||
|                           {eventName} | ||||
|                         </h2> | ||||
|                         <p className="text-gray-500 dark:text-gray-50 mb-1"> | ||||
|                           <ClockIcon className="inline-block w-4 h-4 mr-1 -mt-1" /> | ||||
|                           {props.eventType.length} minutes | ||||
|                         </p> | ||||
|                       <div className="mt-4 text-gray-700 dark:text-gray-300 border-t border-b dark:border-gray-900 py-4 grid grid-cols-3 text-left"> | ||||
|                         <div className="font-medium">What</div> | ||||
|                         <div className="mb-6 col-span-2">{eventName}</div> | ||||
|                         <div className="font-medium">When</div> | ||||
|                         <div className="mb-6 col-span-2"> | ||||
|                           {date.format("dddd, DD MMMM YYYY")} | ||||
|                           <br /> | ||||
|                           {date.format(is24h ? "H:mm" : "h:mma")} - {props.eventType.length} mins{" "} | ||||
|                           <span className="text-gray-500"> | ||||
|                             ({localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess()}) | ||||
|                           </span> | ||||
|                         </div> | ||||
|                         {location && ( | ||||
|                           <p className="text-gray-500 mb-1"> | ||||
|                             <LocationMarkerIcon className="inline-block w-4 h-4 mr-1 -mt-1" /> | ||||
|                             {location} | ||||
|                           </p> | ||||
|                           <> | ||||
|                             <div className="font-medium">Where</div> | ||||
|                             <div className="col-span-2">{location}</div> | ||||
|                           </> | ||||
|                         )} | ||||
|                         <p className="text-gray-500 dark:text-gray-50"> | ||||
|                           <CalendarIcon className="inline-block w-4 h-4 mr-1 -mt-1" /> | ||||
|                           {date.format((is24h ? "H:mm" : "h:mma") + ", dddd DD MMMM YYYY")} | ||||
|                         </p> | ||||
|                       </div> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   {!props.eventType.requiresConfirmation && ( | ||||
|                     <div className="mt-5 sm:mt-0 pt-2 text-center"> | ||||
|                       <span className="font-medium text-gray-500 dark:text-gray-50"> | ||||
|                         Add to your calendar | ||||
|                     <div className="mt-5 sm:mt-0 sm:pt-4 pt-2 text-center flex"> | ||||
|                       <span className="font-medium text-gray-700 dark:text-gray-50 flex self-center mr-6"> | ||||
|                         Add to calendar | ||||
|                       </span> | ||||
|                       <div className="flex mt-2"> | ||||
|                       <div className="flex"> | ||||
|                         <Link | ||||
|                           href={ | ||||
|                             `https://calendar.google.com/calendar/r/eventedit?dates=${date | ||||
|  | @ -142,9 +142,9 @@ export default function Success(props) { | |||
|                               props.eventType.description | ||||
|                             }` + (location ? "&location=" + encodeURIComponent(location) : "")
 | ||||
|                           }> | ||||
|                           <a className="mx-2 btn-wide btn-white"> | ||||
|                           <a className="mx-2 rounded-sm border border-neutral-200 dark:border-neutral-700 py-2 px-3"> | ||||
|                             <svg | ||||
|                               className="inline-block w-4 h-4 mr-1 -mt-1" | ||||
|                               className="inline-block w-4 h-4 -mt-1" | ||||
|                               fill="currentColor" | ||||
|                               xmlns="http://www.w3.org/2000/svg" | ||||
|                               viewBox="0 0 24 24"> | ||||
|  | @ -166,7 +166,7 @@ export default function Success(props) { | |||
|                                 eventName | ||||
|                             ) + (location ? "&location=" + location : "") | ||||
|                           }> | ||||
|                           <a className="mx-2 btn-wide btn-white" target="_blank"> | ||||
|                           <a className="mx-2 rounded-sm border border-neutral-200 dark:border-neutral-700 py-2 px-3" target="_blank"> | ||||
|                             <svg | ||||
|                               className="inline-block w-4 h-4 mr-1 -mt-1" | ||||
|                               fill="currentColor" | ||||
|  | @ -190,7 +190,7 @@ export default function Success(props) { | |||
|                                 eventName | ||||
|                             ) + (location ? "&location=" + location : "") | ||||
|                           }> | ||||
|                           <a className="mx-2 btn-wide btn-white" target="_blank"> | ||||
|                           <a className="mx-2 rounded-sm border border-neutral-200 dark:border-neutral-700 py-2 px-3" target="_blank"> | ||||
|                             <svg | ||||
|                               className="inline-block w-4 h-4 mr-1 -mt-1" | ||||
|                               fill="currentColor" | ||||
|  | @ -202,7 +202,7 @@ export default function Success(props) { | |||
|                           </a> | ||||
|                         </Link> | ||||
|                         <Link href={"data:text/calendar," + eventLink()}> | ||||
|                           <a className="mx-2 btn-wide btn-white" download={props.eventType.title + ".ics"}> | ||||
|                           <a className="mx-2 rounded-sm border border-neutral-200 dark:border-neutral-700 py-2 px-3" download={props.eventType.title + ".ics"}> | ||||
|                             <svg | ||||
|                               version="1.1" | ||||
|                               xmlns="http://www.w3.org/2000/svg" | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Peer Richelsen
						Peer Richelsen