import {useEffect, useState, useMemo} from 'react'; import Head from 'next/head'; import Link from 'next/link'; import prisma from '../../lib/prisma'; import { useRouter } from 'next/router'; import dayjs, { Dayjs } from 'dayjs'; import { Switch } from '@headlessui/react'; import TimezoneSelect from 'react-timezone-select'; import { ClockIcon, GlobeIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/solid'; import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; import isBetween from 'dayjs/plugin/isBetween'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; dayjs.extend(isSameOrBefore); dayjs.extend(isBetween); dayjs.extend(utc); dayjs.extend(timezone); import getSlots from '../../lib/slots'; import {useTelemetry} from "../../lib/telemetry"; function classNames(...classes) { return classes.filter(Boolean).join(' ') } export default function Type(props) { // Initialise state const [selectedDate, setSelectedDate] = useState(); const [selectedMonth, setSelectedMonth] = useState(dayjs().month()); const [loading, setLoading] = useState(false); const [isTimeOptionsOpen, setIsTimeOptionsOpen] = useState(false); const [is24h, setIs24h] = useState(false); const [busy, setBusy] = useState([]); const telemetry = useTelemetry(); const [selectedTimeZone, setSelectedTimeZone] = useState(''); function toggleTimeOptions() { setIsTimeOptionsOpen(!isTimeOptionsOpen); } useEffect(() => { // Setting timezone only client-side setSelectedTimeZone(dayjs.tz.guess()) }, []) // Get router variables const router = useRouter(); const { user } = router.query; // Handle month changes const incrementMonth = () => { setSelectedMonth(selectedMonth + 1); } const decrementMonth = () => { setSelectedMonth(selectedMonth - 1); } // Need to define the bounds of the 24-hour window const lowerBound = useMemo(() => { if(!selectedDate) { return } return selectedDate.startOf('day') }, [selectedDate]) const upperBound = useMemo(() => { if(!selectedDate) return return selectedDate.endOf('day') }, [selectedDate]) // Set up calendar var daysInMonth = dayjs().month(selectedMonth).daysInMonth(); var days = []; for (let i = 1; i <= daysInMonth; i++) { days.push(i); } // Create placeholder elements for empty days in first week const weekdayOfFirst = dayjs().month(selectedMonth).date(1).day(); const emptyDays = Array(weekdayOfFirst).fill(null).map((day, i) =>
{null}
); // Combine placeholder days with actual days const calendar = [...emptyDays, ...days.map((day) => )]; // Handle date change and timezone change useEffect(() => { const changeDate = async () => { if (!selectedDate) { return } setLoading(true); const res = await fetch(`/api/availability/${user}?dateFrom=${lowerBound.utc().format()}&dateTo=${upperBound.utc().format()}`); const busyTimes = await res.json(); if (busyTimes.length > 0) setBusy(busyTimes); setLoading(false); } changeDate(); }, [selectedDate, selectedTimeZone]); const times = useMemo(() => getSlots({ calendarTimeZone: props.user.timeZone, selectedTimeZone: selectedTimeZone, eventLength: props.eventType.length, selectedDate: selectedDate, dayStartTime: props.user.startTime, dayEndTime: props.user.endTime, }) , [selectedDate, selectedTimeZone]) // Check for conflicts for(let i = times.length - 1; i >= 0; i -= 1) { busy.forEach(busyTime => { let startTime = dayjs(busyTime.start); let endTime = dayjs(busyTime.end); // Check if start times are the same if (dayjs(times[i]).format('HH:mm') == startTime.format('HH:mm')) { times.splice(i, 1); } // Check if time is between start and end times if (dayjs(times[i]).isBetween(startTime, endTime)) { times.splice(i, 1); } }); } // Display available times const availableTimes = times.map((time) =>
{dayjs(time).tz(selectedTimeZone).format(is24h ? "HH:mm" : "hh:mma")}
); return (
{props.eventType.title} | {props.user.name || props.user.username} | Calendso
{props.user.avatar && Avatar}

{props.user.name}

{props.eventType.title}

{props.eventType.length} minutes

{isTimeOptionsOpen &&
Time Options
am/pm Use setting 24h
setSelectedTimeZone(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" />
}

{props.eventType.description}

{dayjs().month(selectedMonth).format("MMMM YYYY")}
Sun
Mon
Tue
Wed
Thu
Fri
Sat
{calendar}
{selectedDate &&
{dayjs(selectedDate).format("dddd DD MMMM YYYY")}
{!loading ? availableTimes :
}
}
); } export async function getServerSideProps(context) { const user = await prisma.user.findFirst({ where: { username: context.query.user, }, select: { id: true, username: true, name: true, bio: true, avatar: true, eventTypes: true, startTime: true, timeZone: true, endTime: true } }); const eventType = await prisma.eventType.findFirst({ where: { userId: user.id, slug: { equals: context.query.type, }, }, select: { id: true, title: true, description: true, length: true } }); return { props: { user, eventType }, } }