diff --git a/src/components/room-booking/list/BookingsListPage.tsx b/src/components/room-booking/list/BookingsListPage.tsx index 25a2397..4f135ca 100644 --- a/src/components/room-booking/list/BookingsListPage.tsx +++ b/src/components/room-booking/list/BookingsListPage.tsx @@ -2,10 +2,11 @@ import { useMe } from "@/api/accounts/user.ts"; import { $roomBooking, roomBookingTypes } from "@/api/room-booking"; import { SignInButton } from "@/components/common/SignInButton.tsx"; import Tooltip from "@/components/common/Tooltip.tsx"; +import { DeleteBookingModal } from "@/components/room-booking/list/DeleteBookingModal.tsx"; import { clockTime, durationFormatted, msBetween } from "@/lib/utils/dates.ts"; import { useQueryClient } from "@tanstack/react-query"; import clsx from "clsx"; -import React, { useMemo } from "react"; +import React, { useMemo, useState } from "react"; export function BookingsListPage() { const { me } = useMe(); @@ -61,6 +62,8 @@ export function BookingCard({ const { data: rooms } = $roomBooking.useQuery("get", "/rooms/"); const room = rooms?.find((v) => v.id === booking.room_id); + const [confirmDialogOpen, setConfirmDialogOpen] = useState(false); + const { mutate: deleteBookingMutate, isPending } = $roomBooking.useMutation( "delete", "/bookings/{booking_id}", @@ -82,41 +85,54 @@ export function BookingCard({ const end = useMemo(() => new Date(booking.end), [booking.end]); return ( -
-
-

{booking.title}

-

- {room?.title} - - - {start.toLocaleString("en-US", { day: "numeric", month: "short" })},{" "} - {start.toLocaleString("en-US", { weekday: "short" })} - - - - {`${clockTime(start)}–${clockTime(end)} (${durationFormatted(msBetween(start, end))})`} - -

-
-
- - - + <> +
+
+

{booking.title}

+

+ {room?.title} + + + {start.toLocaleString("en-US", { + day: "numeric", + month: "short", + })} + , {start.toLocaleString("en-US", { weekday: "short" })} + + + + {`${clockTime(start)}–${clockTime(end)} (${durationFormatted(msBetween(start, end))})`} + +

+
+
+ + + +
-
+ { + deleteBooking(); + setConfirmDialogOpen(false); + }} + /> + ); } diff --git a/src/components/room-booking/list/DeleteBookingModal.tsx b/src/components/room-booking/list/DeleteBookingModal.tsx new file mode 100644 index 0000000..ccbae32 --- /dev/null +++ b/src/components/room-booking/list/DeleteBookingModal.tsx @@ -0,0 +1,97 @@ +import { + FloatingFocusManager, + FloatingOverlay, + FloatingPortal, + useDismiss, + useFloating, + useInteractions, + useRole, + useTransitionStyles, +} from "@floating-ui/react"; +import { useRef } from "react"; + +export function DeleteBookingModal({ + open, + onOpenChange, + onConfirm, +}: { + open: boolean; + onOpenChange: (open: boolean) => void; + onConfirm: () => void; +}) { + const { context, refs } = useFloating({ open, onOpenChange }); + + // Transition effect + const { isMounted, styles: transitionStyles } = useTransitionStyles(context); + + // Event listeners to change the open state + const dismiss = useDismiss(context, { capture: true }); + // Role props for screen readers + const role = useRole(context); + + const { getFloatingProps } = useInteractions([dismiss, role]); + + const cancelRef = useRef(null); + + if (!isMounted) { + return null; + } + + return ( + + + +
+
+
+ {/* Heading and description */} +
+
+ Confirm deletion +
+ +
+ +
+
+

+ Are you sure you want to delete this booking? +

+
+ +
+ + +
+
+
+
+
+
+
+
+ ); +}