import { ExclamationIcon } from "@heroicons/react/solid"; import { SchedulingType } from "@prisma/client"; import { Dayjs } from "dayjs"; import Link from "next/link"; import { useRouter } from "next/router"; import React, { FC, useEffect, useState } from "react"; import classNames from "@lib/classNames"; import { useLocale } from "@lib/hooks/useLocale"; import { useSlots } from "@lib/hooks/useSlots"; import Loader from "@components/Loader"; type AvailableTimesProps = { timeFormat: string; minimumBookingNotice: number; eventTypeId: number; eventLength: number; slotInterval: number | null; date: Dayjs; users: { username: string | null; }[]; schedulingType: SchedulingType | null; }; const AvailableTimes: FC<AvailableTimesProps> = ({ date, eventLength, eventTypeId, slotInterval, minimumBookingNotice, timeFormat, users, schedulingType, }) => { const { t, i18n } = useLocale(); const router = useRouter(); const { rescheduleUid } = router.query; const { slots, loading, error } = useSlots({ date, slotInterval, eventLength, schedulingType, users, minimumBookingNotice, eventTypeId, }); const [brand, setBrand] = useState("#292929"); useEffect(() => { setBrand(getComputedStyle(document.documentElement).getPropertyValue("--brand-color").trim()); }, []); return ( <div className="mt-8 flex flex-col text-center sm:mt-0 sm:w-1/3 sm:pl-4 md:-mb-5"> <div className="mb-4 text-left text-lg font-light text-gray-600"> <span className="w-1/2 text-gray-600 dark:text-white"> <strong>{date.toDate().toLocaleString(i18n.language, { weekday: "long" })}</strong> <span className="text-gray-500"> {date.format(", D ")} {date.toDate().toLocaleString(i18n.language, { month: "long" })} </span> </span> </div> <div className="flex-grow overflow-y-auto md:h-[364px]"> {!loading && slots?.length > 0 && slots.map((slot) => { type BookingURL = { pathname: string; query: Record<string, string | number | string[] | undefined>; }; const bookingUrl: BookingURL = { pathname: "book", query: { ...router.query, date: slot.time.format(), type: eventTypeId, }, }; if (rescheduleUid) { bookingUrl.query.rescheduleUid = rescheduleUid as string; } if (schedulingType === SchedulingType.ROUND_ROBIN) { bookingUrl.query.user = slot.users; } return ( <div key={slot.time.format()}> <Link href={bookingUrl}> <a className={classNames( "mb-2 block rounded-sm border bg-white py-4 font-medium text-primary-500 hover:bg-brand hover:text-white hover:text-brandcontrast dark:border-transparent dark:bg-gray-600 dark:text-neutral-200 dark:hover:border-black dark:hover:bg-brand dark:hover:text-brandcontrast", brand === "#fff" || brand === "#ffffff" ? "border-brandcontrast" : "border-brand" )} data-testid="time"> {slot.time.format(timeFormat)} </a> </Link> </div> ); })} {!loading && !error && !slots.length && ( <div className="-mt-4 flex h-full w-full flex-col content-center items-center justify-center"> <h1 className="my-6 text-xl text-black dark:text-white">{t("all_booked_today")}</h1> </div> )} {loading && <Loader />} {error && ( <div className="border-l-4 border-yellow-400 bg-yellow-50 p-4"> <div className="flex"> <div className="flex-shrink-0"> <ExclamationIcon className="h-5 w-5 text-yellow-400" aria-hidden="true" /> </div> <div className="ltr:ml-3 rtl:mr-3"> <p className="text-sm text-yellow-700">{t("slots_load_fail")}</p> </div> </div> </div> )} </div> </div> ); }; export default AvailableTimes;