// TODO: replace headlessui with radix-ui import { BanIcon, CalendarIcon, CheckIcon, ClockIcon, XIcon } from "@heroicons/react/outline"; import { BookingStatus } from "@prisma/client"; import dayjs from "dayjs"; import { useRouter } from "next/router"; import { useMutation } from "react-query"; import { HttpError } from "@lib/core/http/error"; import { inferQueryOutput, trpc } from "@lib/trpc"; import BookingsShell from "@components/BookingsShell"; import EmptyScreen from "@components/EmptyScreen"; import Loader from "@components/Loader"; import Shell from "@components/Shell"; import { Alert } from "@components/ui/Alert"; import TableActions from "@components/ui/TableActions"; type BookingItem = inferQueryOutput<"viewer.bookings">[number]; function BookingListItem(booking: BookingItem) { const utils = trpc.useContext(); const mutation = useMutation( async (confirm: boolean) => { const res = await fetch("/api/book/confirm", { method: "PATCH", body: JSON.stringify({ id: booking.id, confirmed: confirm }), headers: { "Content-Type": "application/json", }, }); if (!res.ok) { throw new HttpError({ statusCode: res.status }); } }, { async onSettled() { await utils.invalidateQuery(["viewer.bookings"]); }, } ); const isUpcoming = new Date(booking.endTime) >= new Date(); const isCancelled = booking.status === BookingStatus.CANCELLED; const pendingActions = [ { id: "confirm", label: "Confirm", onClick: () => mutation.mutate(true), icon: CheckIcon, disabled: mutation.isLoading, }, { id: "reject", label: "Reject", onClick: () => mutation.mutate(false), icon: BanIcon, disabled: mutation.isLoading, }, ]; const bookedActions = [ { id: "cancel", label: "Cancel", href: `/cancel/${booking.uid}`, icon: XIcon, }, { id: "reschedule", label: "Reschedule", href: `/reschedule/${booking.uid}`, icon: ClockIcon, }, ]; return ( {!booking.confirmed && !booking.rejected && ( Unconfirmed )}
{booking.eventType?.team && {booking.eventType.team.name}: } {booking.title}
{dayjs(booking.startTime).format("D MMMM YYYY")}:{" "} {dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
{booking.description && (
"{booking.description}"
)} {booking.attendees.length !== 0 && (
{booking.attendees[0].email}
)}
{dayjs(booking.startTime).format("D MMMM YYYY")}
{dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
{isUpcoming && !isCancelled ? ( <> {!booking.confirmed && !booking.rejected && } {booking.confirmed && !booking.rejected && } {!booking.confirmed && booking.rejected &&
Rejected
} ) : null} ); } export default function Bookings() { const router = useRouter(); const query = trpc.useQuery(["viewer.bookings"]); const filtersByStatus = { upcoming: (booking: BookingItem) => new Date(booking.endTime) >= new Date() && booking.status !== BookingStatus.CANCELLED, past: (booking: BookingItem) => new Date(booking.endTime) < new Date(), cancelled: (booking: BookingItem) => booking.status === BookingStatus.CANCELLED, } as const; const filterKey = (router.query?.status as string as keyof typeof filtersByStatus) || "upcoming"; const appliedFilter = filtersByStatus[filterKey]; const bookings = query.data?.filter(appliedFilter); return (
{query.status === "error" && ( )} {query.status === "loading" && } {bookings && (bookings.length === 0 ? ( ) : (
{bookings.map((booking) => ( ))}
))}
); }