From 632f37cb1671d54a6776ea13c5a2d48e789b322a Mon Sep 17 00:00:00 2001 From: Rajesh Jonnalagadda Date: Tue, 28 May 2024 15:48:50 +0530 Subject: [PATCH 01/24] feat:Generating a PDF with booking overview #942 --- app/components/booking/actions-dropdown.tsx | 6 +- .../booking/generate-booking-pdf.tsx | 125 +++ app/modules/qr/service.server.ts | 39 + ...bookingId.generate-pdf.$fileName[.pdf].tsx | 275 +++++++ app/views/booking-assets-template.ejs | 218 +++++ package-lock.json | 776 +++++++++++++++++- package.json | 3 + 7 files changed, 1406 insertions(+), 36 deletions(-) create mode 100644 app/components/booking/generate-booking-pdf.tsx create mode 100644 app/routes/_layout+/bookings.$bookingId.generate-pdf.$fileName[.pdf].tsx create mode 100644 app/views/booking-assets-template.ejs diff --git a/app/components/booking/actions-dropdown.tsx b/app/components/booking/actions-dropdown.tsx index 541eaa3e5..281857ba2 100644 --- a/app/components/booking/actions-dropdown.tsx +++ b/app/components/booking/actions-dropdown.tsx @@ -1,4 +1,5 @@ -import { useLoaderData, useSubmit } from "@remix-run/react"; +import { useLoaderData, useSubmit, useLocation } from "@remix-run/react"; +import { Divider } from "@tremor/react"; import { ChevronRight } from "~/components/icons/library"; import { DropdownMenu, @@ -12,6 +13,7 @@ import { useUserIsSelfService } from "~/hooks/user-user-is-self-service"; import type { loader } from "~/routes/_layout+/bookings.$bookingId"; import { tw } from "~/utils/tw"; import { DeleteBooking } from "./delete-booking"; +import { GenerateBookingPdf } from "./generate-booking-pdf"; import { Button } from "../shared/button"; interface Props { @@ -104,6 +106,8 @@ export const ActionsDropdown = ({ fullWidth }: Props) => { {(isSelfService && isDraft) || !isSelfService ? ( ) : null} + + {} diff --git a/app/components/booking/generate-booking-pdf.tsx b/app/components/booking/generate-booking-pdf.tsx new file mode 100644 index 000000000..98b26ec87 --- /dev/null +++ b/app/components/booking/generate-booking-pdf.tsx @@ -0,0 +1,125 @@ +import { useEffect, useState } from "react"; +import { Button } from "~/components/shared/button"; +import { + AlertDialog, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from "~/components/shared/modal"; +import { Spinner } from "../shared/spinner"; + +export const GenerateBookingPdf = ({ booking }: { booking: any }) => { + const [url, setUrl] = useState(""); + const [iframeLoaded, setIframeLoaded] = useState(false); + const [errorMessage, setErrorMessage] = useState(""); + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + setIframeLoaded(false); + if (booking && booking?.assets?.length) { + const timestamp = new Date().getTime(); + setUrl( + `/bookings/${booking.id}/generate-pdf/${ + booking.name || "booking-assets" + }-${new Date().toISOString().slice(0, 10)}.pdf?timeStamp=${timestamp}` + ); + } else { + setErrorMessage("No assets available to generate PDF."); + } + }, [booking, booking?.assets]); + + useEffect(() => { + const isMobileDevice = /Mobi/.test(navigator.userAgent); + setIsMobile(isMobileDevice); + }, []); + + const handleIframeLoad = () => { + setIframeLoaded(true); + }; + + const handleMobileView = () => { + window.location.href = url; + }; + + return ( + <> + {!isMobile ? ( + + + + + + + {/* {icon changes} */} + {/*
+ + + +
*/} + + Generate Booking Checklist PDF for {booking?.name} + + + {errorMessage || + "You can either preview the PDF or download it."} + {!iframeLoaded && ( +
+ +

Generating PDF...

+
+ )} + {booking?.assets?.length && ( +
+