From 17df6d6c47347bd4a005bae1ae103c27e41b4c52 Mon Sep 17 00:00:00 2001 From: Arvid Norlin Date: Wed, 6 Nov 2024 16:14:57 +0100 Subject: [PATCH] feat(SW-612): Add popover component --- .../(standard)/step/@summary/page.tsx | 2 + .../EnterDetails/Summary/index.tsx | 21 ++++++-- .../EnterDetails/Summary/summary.module.css | 8 +++ .../Popover/Arrow/arrow.module.css | 22 ++++++++ .../TempDesignSystem/Popover/Arrow/index.tsx | 19 +++++++ components/TempDesignSystem/Popover/index.tsx | 50 +++++++++++++++++++ .../Popover/popover.module.css | 27 ++++++++++ .../TempDesignSystem/Popover/popover.ts | 6 +++ server/routers/hotels/query.ts | 5 ++ .../enterDetails/bookingData.ts | 1 + 10 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 components/TempDesignSystem/Popover/Arrow/arrow.module.css create mode 100644 components/TempDesignSystem/Popover/Arrow/index.tsx create mode 100644 components/TempDesignSystem/Popover/index.tsx create mode 100644 components/TempDesignSystem/Popover/popover.module.css create mode 100644 components/TempDesignSystem/Popover/popover.ts diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/@summary/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/@summary/page.tsx index da3554f50..337d501b3 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/@summary/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/@summary/page.tsx @@ -104,6 +104,7 @@ export default async function SummaryPage({ euroPrice: prices.euro, adults, children, + rateDetails: availability.rateDetails, cancellationText: availability.cancellationText, packages, }} @@ -122,6 +123,7 @@ export default async function SummaryPage({ euroPrice: prices.euro, adults, children, + rateDetails: availability.rateDetails, cancellationText: availability.cancellationText, packages, }} diff --git a/components/HotelReservation/EnterDetails/Summary/index.tsx b/components/HotelReservation/EnterDetails/Summary/index.tsx index c447c7f75..2e0bdb2cd 100644 --- a/components/HotelReservation/EnterDetails/Summary/index.tsx +++ b/components/HotelReservation/EnterDetails/Summary/index.tsx @@ -11,6 +11,7 @@ import { ArrowRightIcon } from "@/components/Icons" import Button from "@/components/TempDesignSystem/Button" import Divider from "@/components/TempDesignSystem/Divider" import Link from "@/components/TempDesignSystem/Link" +import Popover from "@/components/TempDesignSystem/Popover" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" @@ -178,9 +179,23 @@ export default function Summary({ showMemberPrice, room }: SummaryProps) { {room.cancellationText} - - {intl.formatMessage({ id: "Rate details" })} - + + {intl.formatMessage({ id: "Rate details" })} + + } + > + + {room.packages ? room.packages.map((roomPackage) => ( diff --git a/components/HotelReservation/EnterDetails/Summary/summary.module.css b/components/HotelReservation/EnterDetails/Summary/summary.module.css index 426afbc7d..e4ee465a8 100644 --- a/components/HotelReservation/EnterDetails/Summary/summary.module.css +++ b/components/HotelReservation/EnterDetails/Summary/summary.module.css @@ -41,6 +41,13 @@ gap: var(--Spacing-x-one-and-half); } +.rateDetailsPopover { + display: flex; + flex-direction: column; + gap: var(--Spacing-x-half); + max-width: 360px; +} + .entry { display: flex; gap: var(--Spacing-x-half); @@ -50,6 +57,7 @@ .entry > :last-child { justify-items: flex-end; } + .total { display: flex; flex-direction: column; diff --git a/components/TempDesignSystem/Popover/Arrow/arrow.module.css b/components/TempDesignSystem/Popover/Arrow/arrow.module.css new file mode 100644 index 000000000..522b5aff8 --- /dev/null +++ b/components/TempDesignSystem/Popover/Arrow/arrow.module.css @@ -0,0 +1,22 @@ +.arrow { + transform-origin: center; + transform: translateY(-2px); +} + +[data-placement="left"] .arrow, +[data-placement="left top"] .arrow, +[data-placement="left bottom"] .arrow { + transform: rotate(270deg) translateY(-6px); +} + +[data-placement="right"] .arrow, +[data-placement="right top"] .arrow, +[data-placement="right bottom"] .arrow { + transform: rotate(90deg) translateY(-6px); +} + +[data-placement="bottom"] .arrow, +[data-placement="bottom left"] .arrow, +[data-placement="bottom right"] .arrow { + transform: rotate(180deg) translateY(-2px); +} diff --git a/components/TempDesignSystem/Popover/Arrow/index.tsx b/components/TempDesignSystem/Popover/Arrow/index.tsx new file mode 100644 index 000000000..4c67b059b --- /dev/null +++ b/components/TempDesignSystem/Popover/Arrow/index.tsx @@ -0,0 +1,19 @@ +import styles from "./arrow.module.css" + +export function Arrow() { + return ( +
+ + + +
+ ) +} diff --git a/components/TempDesignSystem/Popover/index.tsx b/components/TempDesignSystem/Popover/index.tsx new file mode 100644 index 000000000..1d389c648 --- /dev/null +++ b/components/TempDesignSystem/Popover/index.tsx @@ -0,0 +1,50 @@ +import { useRef } from "react" +import { + Button, + Dialog, + DialogTrigger, + OverlayArrow, + Popover as RAPopover, +} from "react-aria-components" + +import { CloseLargeIcon } from "@/components/Icons" + +import { Arrow } from "./Arrow" +import { PopoverProps } from "./popover" + +import styles from "./popover.module.css" + +export default function Popover({ + triggerContent, + children, + ...props +}: PopoverProps) { + let triggerRef = useRef(null) + + return ( + + + + + + + + + {({ close }) => ( + <> + + {children} + + )} + + + + ) +} diff --git a/components/TempDesignSystem/Popover/popover.module.css b/components/TempDesignSystem/Popover/popover.module.css new file mode 100644 index 000000000..242bd5072 --- /dev/null +++ b/components/TempDesignSystem/Popover/popover.module.css @@ -0,0 +1,27 @@ +.root { + background-color: var(--Base-Surface-Primary-light-Normal); + border-radius: var(--Corner-radius-Medium); + box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); + padding: var(--Spacing-x2); + max-width: calc(360px + var(--Spacing-x2) * 2); +} + +.root section:focus-visible { + outline: none; +} + +.trigger { + background: none; + border: none; + padding: 0; + cursor: pointer; +} +.closeButton { + position: absolute; + top: 8px; + right: 8px; + background: none; + border: none; + cursor: pointer; + padding: 0; +} diff --git a/components/TempDesignSystem/Popover/popover.ts b/components/TempDesignSystem/Popover/popover.ts new file mode 100644 index 000000000..c774ca398 --- /dev/null +++ b/components/TempDesignSystem/Popover/popover.ts @@ -0,0 +1,6 @@ +import type { PopoverProps as RAPopoverProps } from "react-aria-components" + +export interface PopoverProps extends Omit { + triggerContent: React.ReactNode + children: React.ReactNode +} diff --git a/server/routers/hotels/query.ts b/server/routers/hotels/query.ts index af9460b7c..7f2ef84c0 100644 --- a/server/routers/hotels/query.ts +++ b/server/routers/hotels/query.ts @@ -725,6 +725,10 @@ export const hotelQueryRouter = router({ return null } + const rateDetails = validateAvailabilityData.data.rateDefinitions.find( + (rateDef) => rateDef.rateCode === rateCode + )?.generalTerms + const rateTypes = selectedRoom.products.find( (rate) => rate.productType.public.rateCode === rateCode || @@ -782,6 +786,7 @@ export const hotelQueryRouter = router({ return { selectedRoom, + rateDetails, mustBeGuaranteed, cancellationText, memberRate: rates?.member, diff --git a/types/components/hotelReservation/enterDetails/bookingData.ts b/types/components/hotelReservation/enterDetails/bookingData.ts index 628fa3f8b..0afabf91a 100644 --- a/types/components/hotelReservation/enterDetails/bookingData.ts +++ b/types/components/hotelReservation/enterDetails/bookingData.ts @@ -28,6 +28,7 @@ export type RoomsData = { euroPrice: Price | undefined adults: number children?: Child[] + rateDetails?: string[] cancellationText: string packages: Packages | null }