2021-04-11 17:12:18 +00:00
import Head from 'next/head' ;
import Link from 'next/link' ;
import { useRouter } from 'next/router' ;
2021-05-08 19:03:47 +00:00
import { ClockIcon , CalendarIcon , LocationMarkerIcon } from '@heroicons/react/solid' ;
2021-04-11 17:12:18 +00:00
import prisma from '../../lib/prisma' ;
2021-05-07 17:05:33 +00:00
import { collectPageParameters , telemetryEventTypes , useTelemetry } from "../../lib/telemetry" ;
2021-05-08 19:03:47 +00:00
import { useEffect , useState } from "react" ;
import dayjs from 'dayjs' ;
import 'react-phone-number-input/style.css' ;
import PhoneInput from 'react-phone-number-input' ;
import { LocationType } from '../../lib/location' ;
2021-05-08 20:26:19 +00:00
import Avatar from '../../components/Avatar' ;
2021-03-22 13:48:48 +00:00
export default function Book ( props ) {
2021-04-11 17:12:18 +00:00
const router = useRouter ( ) ;
const { date , user } = router . query ;
2021-05-08 21:53:10 +00:00
const locations = props . eventType . locations || [ ] ;
const [ selectedLocation , setSelectedLocation ] = useState < LocationType > ( locations . length === 1 ? locations [ 0 ] . type : '' ) ;
2021-04-27 14:19:12 +00:00
const telemetry = useTelemetry ( ) ;
useEffect ( ( ) = > {
2021-05-07 17:05:33 +00:00
telemetry . withJitsu ( jitsu = > jitsu . track ( telemetryEventTypes . timeSelected , collectPageParameters ( ) ) ) ;
2021-05-08 19:03:47 +00:00
} ) ;
2021-05-08 21:53:10 +00:00
const locationInfo = ( type : LocationType ) = > locations . find (
2021-05-08 19:03:47 +00:00
( location ) = > location . type === type
) ;
// TODO: Move to translations
const locationLabels = {
[ LocationType . InPerson ] : 'In-person meeting' ,
[ LocationType . Phone ] : 'Phone call' ,
} ;
2021-03-22 13:48:48 +00:00
const bookingHandler = event = > {
2021-04-11 17:12:18 +00:00
event . preventDefault ( ) ;
2021-05-08 19:03:47 +00:00
2021-05-08 21:53:10 +00:00
let payload = {
start : dayjs ( date ) . format ( ) ,
end : dayjs ( date ) . add ( props . eventType . length , 'minute' ) . format ( ) ,
name : event.target.name.value ,
email : event.target.email.value ,
notes : event.target.notes.value
} ;
if ( selectedLocation ) {
payload [ 'location' ] = selectedLocation === LocationType . Phone ? event.target.phone.value : locationInfo ( selectedLocation ) . address ;
}
2021-05-08 19:03:47 +00:00
2021-05-07 17:05:33 +00:00
telemetry . withJitsu ( jitsu = > jitsu . track ( telemetryEventTypes . bookingConfirmed , collectPageParameters ( ) ) ) ;
2021-03-22 13:48:48 +00:00
const res = fetch (
2021-04-07 20:41:08 +00:00
'/api/book/' + user ,
2021-03-22 13:48:48 +00:00
{
2021-05-08 21:53:10 +00:00
body : JSON.stringify ( payload ) ,
2021-03-22 13:48:48 +00:00
headers : {
'Content-Type' : 'application/json'
} ,
method : 'POST'
}
2021-04-11 17:12:18 +00:00
) ;
2021-05-08 19:03:47 +00:00
2021-05-08 21:53:10 +00:00
let successUrl = ` /success?date= ${ date } &type= ${ props . eventType . id } &user= ${ props . user . username } ` ;
if ( payload [ 'location' ] ) {
successUrl += "&location=" + encodeURIComponent ( payload [ 'location' ] ) ;
}
router . push ( successUrl ) ;
2021-03-22 13:48:48 +00:00
}
return (
< div >
< Head >
2021-03-31 20:10:53 +00:00
< title > Confirm your { props . eventType . title } with { props . user . name || props . user . username } | Calendso < / title >
2021-03-22 13:48:48 +00:00
< link rel = "icon" href = "/favicon.ico" / >
< / Head >
< main className = "max-w-3xl mx-auto my-24" >
< div className = "bg-white overflow-hidden shadow rounded-lg" >
< div className = "sm:flex px-4 py-5 sm:p-6" >
< div className = "sm:w-1/2 sm:border-r" >
2021-05-08 20:26:19 +00:00
< Avatar user = { props . user } className = "w-16 h-16 rounded-full mb-4" / >
2021-03-22 13:48:48 +00:00
< h2 className = "font-medium text-gray-500" > { props . user . name } < / h2 >
< h1 className = "text-3xl font-semibold text-gray-800 mb-4" > { props . eventType . title } < / h1 >
< p className = "text-gray-500 mb-2" >
2021-04-21 10:10:27 +00:00
< ClockIcon className = "inline-block w-4 h-4 mr-1 -mt-1" / >
2021-03-22 13:48:48 +00:00
{ props . eventType . length } minutes
< / p >
2021-05-08 19:03:47 +00:00
{ selectedLocation === LocationType . InPerson && < p className = "text-gray-500 mb-2" >
< LocationMarkerIcon className = "inline-block w-4 h-4 mr-1 -mt-1" / >
{ locationInfo ( selectedLocation ) . address }
< / p > }
2021-03-22 13:48:48 +00:00
< p className = "text-blue-600 mb-4" >
2021-04-21 10:10:27 +00:00
< CalendarIcon className = "inline-block w-4 h-4 mr-1 -mt-1" / >
2021-03-22 13:48:48 +00:00
{ dayjs ( date ) . format ( "hh:mma, dddd DD MMMM YYYY" ) }
< / p >
< p className = "text-gray-600" > { props . eventType . description } < / p >
< / div >
< div className = "sm:w-1/2 pl-8 pr-4" >
< form onSubmit = { bookingHandler } >
< div className = "mb-4" >
< label htmlFor = "name" className = "block text-sm font-medium text-gray-700" > Your name < / label >
< div className = "mt-1" >
2021-05-03 20:56:33 +00:00
< input type = "text" name = "name" id = "name" required className = "shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" placeholder = "John Doe" / >
2021-03-22 13:48:48 +00:00
< / div >
< / div >
< div className = "mb-4" >
< label htmlFor = "email" className = "block text-sm font-medium text-gray-700" > Email address < / label >
< div className = "mt-1" >
2021-05-03 20:56:33 +00:00
< input type = "email" name = "email" id = "email" required className = "shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" placeholder = "you@example.com" / >
2021-03-22 13:48:48 +00:00
< / div >
< / div >
2021-05-08 21:53:10 +00:00
{ locations . length > 1 && (
2021-05-08 19:03:47 +00:00
< div className = "mb-4" >
< span className = "block text-sm font-medium text-gray-700" > Location < / span >
2021-05-08 21:53:10 +00:00
{ locations . map ( ( location ) = > (
2021-05-08 19:03:47 +00:00
< label key = { location . type } className = "block" >
< input type = "radio" required onChange = { ( e ) = > setSelectedLocation ( e . target . value ) } className = "location" name = "location" value = { location . type } checked = { selectedLocation === location . type } / >
< span className = "text-sm ml-2" > { locationLabels [ location . type ] } < / span >
< / label >
) ) }
< / div >
) }
{ selectedLocation === LocationType . Phone && ( < div className = "mb-4" >
< label htmlFor = "phone" className = "block text-sm font-medium text-gray-700" > Phone Number < / label >
< div className = "mt-1" >
< PhoneInput name = "phone" placeholder = "Enter phone number" id = "phone" required className = "shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" onChange = { ( ) = > { } } / >
< / div >
< / div > ) }
2021-03-22 13:48:48 +00:00
< div className = "mb-4" >
< label htmlFor = "notes" className = "block text-sm font-medium text-gray-700 mb-1" > Additional notes < / label >
< textarea name = "notes" id = "notes" rows = { 3 } className = "shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md" placeholder = "Please share anything that will help prepare for our meeting." > < / textarea >
< / div >
< div >
< button type = "submit" className = "btn btn-primary" > Confirm < / button >
2021-04-30 12:06:04 +00:00
< Link href = { "/" + props . user . username + "/" + props . eventType . slug } >
2021-03-22 13:48:48 +00:00
< a className = "ml-2 btn btn-white" > Cancel < / a >
< / Link >
< / div >
< / form >
< / div >
< / div >
< / div >
< / main >
< / div >
)
}
export async function getServerSideProps ( context ) {
const user = await prisma . user . findFirst ( {
where : {
username : context.query.user ,
} ,
select : {
username : true ,
name : true ,
2021-05-08 20:26:19 +00:00
email :true ,
2021-03-22 13:48:48 +00:00
bio : true ,
avatar : true ,
eventTypes : true
}
} ) ;
const eventType = await prisma . eventType . findUnique ( {
where : {
id : parseInt ( context . query . type ) ,
} ,
select : {
id : true ,
title : true ,
2021-04-30 12:06:04 +00:00
slug : true ,
2021-03-22 13:48:48 +00:00
description : true ,
2021-05-08 19:03:47 +00:00
length : true ,
locations : true ,
2021-03-22 13:48:48 +00:00
}
} ) ;
return {
props : {
user ,
eventType
} ,
}
}