Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 2 additions & 25 deletions app/components/booking/actions-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { userHasPermission } from "~/utils/permissions/permission.validator.client";
import { tw } from "~/utils/tw";
import { BookingOverviewPDF } from "./booking-overview-pdf";
import { CancelBookingDialog } from "./cancel-booking-dialog";
import { DeleteBooking } from "./delete-booking";

import ExtendBookingDialog from "./extend-booking-dialog";
Expand Down Expand Up @@ -80,31 +81,7 @@ export const ActionsDropdown = ({ fullWidth }: Props) => {
<When
truthy={(isOngoing || isReserved || isOverdue) && canCancelBooking}
>
<DropdownMenuItem asChild>
<Button
variant="link"
className="justify-start text-gray-700 hover:cursor-pointer hover:text-gray-700"
width="full"
name="intent"
value="cancel"
as="span"
/**
* Here we have to deal with a interesting case that is in a way a conflict between how react works and web platform
* So this button within the react code, is inside a form that is in the parent component, however because its a radix dropdown, it gets rendered within a portal
* So the button is actually rendered outside the form, and when you click on it, it does not submit the form
* So we have to manually submit the data here.
*
* Keep in mind that even though its rendered in the DOM within a portal, react will still detect it as being inside the form, so there could be some hydration errors
*/
onClick={() => {
const formData = new FormData();
formData.append("intent", "cancel");
submit(formData, { method: "post" });
}}
>
Cancel
</Button>
</DropdownMenuItem>
<CancelBookingDialog bookingName={booking.name} />
</When>
<When truthy={canExtendBooking}>
<ExtendBookingDialog
Expand Down
75 changes: 75 additions & 0 deletions app/components/booking/cancel-booking-dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Button } from "~/components/shared/button";
import {
AlertDialog,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "~/components/shared/modal";
import { useDisabled } from "~/hooks/use-disabled";
import { tw } from "~/utils/tw";
import { Form } from "../custom-form";
import { AlertIcon } from "../icons/library";

type CancelBookingDialogProps = {
bookingName: string;
};

export function CancelBookingDialog({ bookingName }: CancelBookingDialogProps) {
const disabled = useDisabled();

return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
type="button"
variant="link"
className="justify-start rounded-sm px-2 py-1.5 text-sm font-medium text-gray-700 outline-none hover:bg-slate-100 hover:text-gray-700"
width="full"
>
Cancel
</Button>
</AlertDialogTrigger>

<AlertDialogContent>
<AlertDialogHeader>
<div className="mx-auto md:m-0">
<span className="flex size-12 items-center justify-center rounded-full bg-error-50 p-2 text-error-600">
<AlertIcon />
</span>
</div>
<AlertDialogTitle>Cancel {bookingName}</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to cancel this booking? This action cannot be
undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<div className="flex justify-center gap-2">
<AlertDialogCancel asChild>
<Button variant="secondary" disabled={disabled}>
Go back
</Button>
</AlertDialogCancel>

<Form method="post">
<input type="hidden" name="intent" value="cancel" />
<Button
type="submit"
className={tw(
"border-error-600 bg-error-600 hover:border-error-800 hover:bg-error-800"
)}
disabled={disabled}
>
Cancel booking
</Button>
</Form>
</div>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
Loading