Merged in feat/SW-1282-list-added-ancillaries (pull request #1416)
Feat/SW-1282 list added ancillaries * feat(sw-1282): add icon to accordionItem * feat(sw-1282): list added ancillaries * Change translation key to already existing * Remove duplicate key * Move new files to the new folder structure Approved-by: Pontus Dreij
This commit is contained in:
@@ -18,7 +18,7 @@ export default async function AccessibilityAmenity({
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Accessibility" })}
|
||||
icon={IconName.Accessibility}
|
||||
iconName={IconName.Accessibility}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:accessibility"
|
||||
>
|
||||
|
||||
@@ -29,7 +29,7 @@ export default async function BreakfastAmenity({
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Breakfast" })}
|
||||
icon={IconName.CoffeeAlt}
|
||||
iconName={IconName.CoffeeAlt}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:breakfast"
|
||||
>
|
||||
|
||||
@@ -13,7 +13,7 @@ export default async function CheckInAmenity({
|
||||
return (
|
||||
<AccordionItem
|
||||
title={`${intl.formatMessage({ id: "Check-in" })}/${intl.formatMessage({ id: "Check-out" })}`}
|
||||
icon={IconName.Business}
|
||||
iconName={IconName.Business}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:check-in"
|
||||
>
|
||||
|
||||
@@ -19,7 +19,7 @@ export default async function ParkingAmenity({
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Parking" })}
|
||||
icon={IconName.Parking}
|
||||
iconName={IconName.Parking}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:parking"
|
||||
>
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x-half);
|
||||
padding: 0 var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
margin-top: var(--Spacing-x5);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
gap: var(--Spacing-x3);
|
||||
}
|
||||
.header {
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.deliveryTime {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.ancillaryMobile {
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.ancillaryDesktop {
|
||||
display: none;
|
||||
padding: var(--Spacing-x2);
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.ancillaryMobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ancillaryDesktop {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.paymentMobileWrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.paymentMobile {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x2);
|
||||
align-items: center;
|
||||
}
|
||||
.commentMobile {
|
||||
margin-bottom: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.footerMobile {
|
||||
display: flex;
|
||||
margin-top: var(--Spacing-x4);
|
||||
}
|
||||
|
||||
.specification {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: var(--Spacing-x1) 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x1);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.payment {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x2);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: var(--Spacing-x1) 0;
|
||||
}
|
||||
|
||||
.comment {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { CheckCircleIcon, DeleteIcon, EditIcon } from "@/components/Icons"
|
||||
import Accordion from "@/components/TempDesignSystem/Accordion"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import styles from "./addedAncillaries.module.css"
|
||||
|
||||
import type { AddedAncillariesProps } from "@/types/components/myPages/myStay/ancillaries"
|
||||
|
||||
export function AddedAncillaries({
|
||||
ancillaries,
|
||||
booking,
|
||||
}: AddedAncillariesProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<Subtitle>{intl.formatMessage({ id: "My Add-on's" })}</Subtitle>
|
||||
|
||||
{booking.ancillary?.deliveryTime && (
|
||||
<div className={styles.deliveryTime}>
|
||||
<Body color="baseTextHighContrast" textTransform="bold">
|
||||
{intl.formatMessage({ id: "Delivered at:" })}
|
||||
</Body>
|
||||
<Body color="baseTextHighContrast" textTransform="bold">
|
||||
{booking.ancillary?.deliveryTime}
|
||||
</Body>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{booking.ancillaries.map((ancillary) => {
|
||||
const ancillaryItem = ancillaries?.find((a) => a.id === ancillary.code)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Accordion className={styles.ancillaryMobile}>
|
||||
<AccordionItem
|
||||
title={ancillaryItem?.title ?? ""}
|
||||
icon={<CheckCircleIcon color="uiSemanticSuccess" />}
|
||||
>
|
||||
<div>
|
||||
{ancillary.comment && (
|
||||
<>
|
||||
<div className={styles.commentMobile}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Other requests" })}:
|
||||
</Body>
|
||||
<Body color="uiTextMediumContrast">
|
||||
{ancillary.comment}
|
||||
</Body>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className={styles.paymentMobileWrapper}>
|
||||
<div className={styles.paymentMobile}>
|
||||
<Body>{intl.formatMessage({ id: "Total" })}</Body>
|
||||
<Body textTransform="bold">
|
||||
{`${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
</Body>
|
||||
<Divider
|
||||
variant="vertical"
|
||||
color="baseSurfaceSubtleNormal"
|
||||
/>
|
||||
<Body textTransform="bold">
|
||||
{`${ancillary.points} ${intl.formatMessage({ id: "Points" })}`}
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.footerMobile}>
|
||||
<div className={styles.actions}>
|
||||
<Button
|
||||
intent="text"
|
||||
size="small"
|
||||
variant="icon"
|
||||
theme="base"
|
||||
>
|
||||
<EditIcon />
|
||||
{intl.formatMessage({ id: "Modify" })}
|
||||
</Button>
|
||||
<Divider
|
||||
variant="vertical"
|
||||
color="baseSurfaceSubtleNormal"
|
||||
/>
|
||||
<Button
|
||||
intent="text"
|
||||
size="small"
|
||||
variant="icon"
|
||||
theme="base"
|
||||
>
|
||||
<DeleteIcon />
|
||||
{intl.formatMessage({ id: "Remove" })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
<div className={styles.ancillaryDesktop}>
|
||||
<div className={styles.specification}>
|
||||
<div className={styles.name}>
|
||||
<CheckCircleIcon color="uiSemanticSuccess" />
|
||||
<Body textTransform="bold">{ancillaryItem?.title}</Body>
|
||||
<Body textTransform="bold">{`X${ancillary.totalUnit}`}</Body>
|
||||
</div>
|
||||
<div className={styles.payment}>
|
||||
<Body>{intl.formatMessage({ id: "Total" })}</Body>
|
||||
<Body textTransform="bold">
|
||||
{`${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
</Body>
|
||||
<Divider variant="vertical" color="baseSurfaceSubtleNormal" />
|
||||
<Body textTransform="bold">
|
||||
{`${ancillary.points} ${intl.formatMessage({ id: "Points" })}`}
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider color="baseSurfaceSubtleHover" />
|
||||
|
||||
<div className={styles.footer}>
|
||||
<div className={styles.comment}>
|
||||
{ancillary.comment && (
|
||||
<>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Other requests" })}:
|
||||
</Body>
|
||||
<Body>{ancillary.comment}</Body>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.actions}>
|
||||
<Button
|
||||
intent="text"
|
||||
size="small"
|
||||
variant="icon"
|
||||
theme="base"
|
||||
>
|
||||
<EditIcon />
|
||||
{intl.formatMessage({ id: "Modify" })}
|
||||
</Button>
|
||||
<Divider variant="vertical" color="baseSurfaceSubtleNormal" />
|
||||
<Button
|
||||
intent="text"
|
||||
size="small"
|
||||
variant="icon"
|
||||
theme="base"
|
||||
>
|
||||
<DeleteIcon />
|
||||
{intl.formatMessage({ id: "Remove" })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { AncillaryCard } from "@/components/TempDesignSystem/AncillaryCard"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
|
||||
import AddAncillaryFlowModal from "./AddAncillaryFlow/AddAncillaryFlowModal"
|
||||
import { AddedAncillaries } from "./AddedAncillaries"
|
||||
import AncillaryGridModal from "./AncillaryGridModal"
|
||||
|
||||
import styles from "./ancillaries.module.css"
|
||||
@@ -115,6 +116,8 @@ export function Ancillaries({ ancillaries, booking, user }: AncillariesProps) {
|
||||
</Carousel>
|
||||
</div>
|
||||
|
||||
<AddedAncillaries booking={booking} ancillaries={allAncillaries} />
|
||||
|
||||
<AddAncillaryFlowModal
|
||||
user={user}
|
||||
isOpen={isModalOpen}
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function Accessibility({
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Accessibility" })}
|
||||
icon={IconName.Accessibility}
|
||||
iconName={IconName.Accessibility}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body>{elevatorPitchText}</Body>
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function CheckinCheckOut({ checkin }: CheckInCheckOutProps) {
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Check-in/Check-out" })}
|
||||
icon={IconName.Calendar}
|
||||
iconName={IconName.Calendar}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body textTransform="bold">{intl.formatMessage({ id: "Hours" })}</Body>
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function MeetingsAndConferences({
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Meetings & Conferences" })}
|
||||
icon={IconName.Business}
|
||||
iconName={IconName.Business}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body>{meetingDescription}</Body>
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function Parking({ parking }: ParkingProps) {
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Parking" })}
|
||||
icon={IconName.Parking}
|
||||
iconName={IconName.Parking}
|
||||
className={styles.parking}
|
||||
variant="sidepeek"
|
||||
>
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function Restaurant({
|
||||
},
|
||||
{ totalRestaurants: 1 }
|
||||
)}
|
||||
icon={IconName.Restaurant}
|
||||
iconName={IconName.Restaurant}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body>{restaurantsContentDescriptionMedium}</Body>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { ReactNode } from "react"
|
||||
|
||||
import type { IconName } from "@/types/components/icon"
|
||||
import type { accordionItemVariants } from "./variants"
|
||||
@@ -7,7 +8,8 @@ export interface AccordionItemProps
|
||||
extends React.HtmlHTMLAttributes<HTMLDetailsElement>,
|
||||
VariantProps<typeof accordionItemVariants> {
|
||||
title: string
|
||||
icon?: IconName
|
||||
iconName?: IconName
|
||||
icon?: ReactNode
|
||||
trackingId?: string
|
||||
subtitle?: string
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { AccordionItemProps } from "./accordionItem"
|
||||
export default function AccordionItem({
|
||||
children,
|
||||
icon,
|
||||
iconName,
|
||||
title,
|
||||
theme,
|
||||
variant,
|
||||
@@ -27,7 +28,10 @@ export default function AccordionItem({
|
||||
const contentRef = useRef<HTMLDivElement>(null)
|
||||
const detailsRef = useRef<HTMLDetailsElement>(null)
|
||||
|
||||
const IconComp = getIconByIconName(icon)
|
||||
const FoundIcon = getIconByIconName(iconName)
|
||||
const IconComp = icon
|
||||
? icon
|
||||
: FoundIcon && <FoundIcon color="baseTextHighcontrast" />
|
||||
|
||||
function toggleAccordion() {
|
||||
const details = detailsRef.current
|
||||
@@ -56,7 +60,7 @@ export default function AccordionItem({
|
||||
<li className={accordionItemVariants({ className, variant, theme })}>
|
||||
<details ref={detailsRef} onToggle={toggleAccordion}>
|
||||
<summary className={styles.summary}>
|
||||
{IconComp && <IconComp color="baseTextHighcontrast" />}
|
||||
{IconComp}
|
||||
{variant === "sidepeek" ? (
|
||||
<Subtitle
|
||||
className={styles.title}
|
||||
|
||||
@@ -390,6 +390,7 @@
|
||||
"Multiroom with voucher error": "Det er ikke muligt at booke flere værelser med gavekort.",
|
||||
"Museum": "Museum",
|
||||
"Museums": "Museer",
|
||||
"My Add-on's": "Mine tilføjelser",
|
||||
"My Benefits": "Mine Fordele",
|
||||
"My Points": "Mine Point",
|
||||
"My Profile": "Min profil",
|
||||
@@ -522,6 +523,7 @@
|
||||
"Reference #{bookingNr}": "Reference #{bookingNr}",
|
||||
"Relax": "Slap af",
|
||||
"Remember code": "Husk kode",
|
||||
"Remove": "Fjerne",
|
||||
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
|
||||
"Request bedtype": "Anmod om sengetype",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
"Date of Birth": "Geburtsdatum",
|
||||
"Date of birth not matching": "Date of birth not matching",
|
||||
"Day": "Tag",
|
||||
"Delivered at": "Geliefert bei:",
|
||||
"Delivered at:": "Geliefert bei:",
|
||||
"Delivery between {deliveryTime}. Payment will be made on check-in": "Lieferung zwischen {deliveryTime}. Die Zahlung erfolgt beim Check-in.",
|
||||
"Description": "Beschreibung",
|
||||
"Destination": "Bestimmungsort",
|
||||
@@ -392,6 +392,7 @@
|
||||
"Multiroom with voucher error": "Die Buchung mehrerer Zimmer ist nicht mit einem Gutschein möglich",
|
||||
"Museum": "Museum",
|
||||
"Museums": "Museen",
|
||||
"My Add-on's": "Meine Add-ons",
|
||||
"My Benefits": "Meine Vorteile",
|
||||
"My Points": "Meine Punkte",
|
||||
"My Profile": "Mein Profil",
|
||||
@@ -524,6 +525,7 @@
|
||||
"Reference #{bookingNr}": "Referenz #{bookingNr}",
|
||||
"Relax": "Entspannen",
|
||||
"Remember code": "Code merken",
|
||||
"Remove": "Entfernen",
|
||||
"Remove card from member profile": "Karte aus dem Mitgliedsprofil entfernen",
|
||||
"Request bedtype": "Bettentyp anfragen",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
|
||||
@@ -394,6 +394,7 @@
|
||||
"Multiroom with voucher error": "Multiroom booking is not compatible with a code or voucher",
|
||||
"Museum": "Museum",
|
||||
"Museums": "Museums",
|
||||
"My Add-on's": "My Add-on's",
|
||||
"My Benefits": "My Benefits",
|
||||
"My Points": "My points",
|
||||
"My Profile": "My Profile",
|
||||
@@ -527,6 +528,7 @@
|
||||
"Reference number": "Reference number",
|
||||
"Relax": "Relax",
|
||||
"Remember code": "Remember code",
|
||||
"Remove": "Remove",
|
||||
"Remove card from member profile": "Remove card from member profile",
|
||||
"Remove room": "Remove room",
|
||||
"Request bedtype": "Request bedtype",
|
||||
|
||||
@@ -391,6 +391,7 @@
|
||||
"Multiroom with voucher error": "Lahjakortilla ei voi varata monta huonetta",
|
||||
"Museum": "Museo",
|
||||
"Museums": "Museot",
|
||||
"My Add-on's": "Omat lisäosat",
|
||||
"My Benefits": "Etuni",
|
||||
"My Points": "Pisteeni",
|
||||
"My Profile": "Profiilini",
|
||||
@@ -523,6 +524,7 @@
|
||||
"Reference #{bookingNr}": "Referenssi #{bookingNr}",
|
||||
"Relax": "Rentoutua",
|
||||
"Remember code": "Muista koodi",
|
||||
"Remove": "Poistaa",
|
||||
"Remove card from member profile": "Poista kortti jäsenprofiilista",
|
||||
"Request bedtype": "Pyydä sänkytyyppiä",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
|
||||
@@ -390,6 +390,7 @@
|
||||
"Multiroom with voucher error": "Bestilling av flere rom er ikke mulig når du bestiller med voucher",
|
||||
"Museum": "Museum",
|
||||
"Museums": "Museums",
|
||||
"My Add-on's": "Mine tillegg",
|
||||
"My Benefits": "Mine fordeler",
|
||||
"My Points": "Mine poeng",
|
||||
"My Profile": "Min profil",
|
||||
@@ -520,6 +521,7 @@
|
||||
"Reference #{bookingNr}": "Referanse #{bookingNr}",
|
||||
"Relax": "Slappe av",
|
||||
"Remember code": "Husk kode",
|
||||
"Remove": "Fjerne",
|
||||
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
|
||||
"Request bedtype": "Be om sengetype",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
|
||||
@@ -390,6 +390,7 @@
|
||||
"Multiroom with voucher error": "Flera rum kan inte bokas samtidigt med presentkort",
|
||||
"Museum": "Museum",
|
||||
"Museums": "Museer",
|
||||
"My Add-on's": "Mina tillägg",
|
||||
"My Benefits": "Mina förmåner",
|
||||
"My Points": "Mina poäng",
|
||||
"My Profile": "Min profil",
|
||||
@@ -520,6 +521,7 @@
|
||||
"Reference #{bookingNr}": "Referens #{bookingNr}",
|
||||
"Relax": "Koppla av",
|
||||
"Remember code": "Kom ihåg kod",
|
||||
"Remove": "Ta bort",
|
||||
"Remove card from member profile": "Ta bort kortet från medlemsprofilen",
|
||||
"Request bedtype": "Request bedtype",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
|
||||
@@ -81,8 +81,8 @@ const guestSchema = z.object({
|
||||
|
||||
const packageSchema = z
|
||||
.object({
|
||||
type: z.string().nullable(),
|
||||
description: z.string().nullable().default(""),
|
||||
type: z.string().nullable().default(""),
|
||||
code: z.string().nullable().default(""),
|
||||
price: z.object({
|
||||
unit: z.number().int().nullable(),
|
||||
@@ -92,11 +92,13 @@ const packageSchema = z
|
||||
currency: z.string().default(""),
|
||||
points: z.number().int().nullable(),
|
||||
}),
|
||||
comment: z.string().nullable().optional(),
|
||||
})
|
||||
.transform((packageData) => ({
|
||||
description: packageData.description,
|
||||
code: packageData.code,
|
||||
type: packageData.type,
|
||||
description: packageData.description,
|
||||
comment: packageData.comment,
|
||||
code: packageData.code,
|
||||
currency: packageData.price.currency,
|
||||
points: packageData.price.points,
|
||||
totalPrice: packageData.price.totalPrice ?? 0,
|
||||
@@ -219,7 +221,13 @@ export const bookingConfirmationSchema = z
|
||||
})
|
||||
.transform(({ data }) => ({
|
||||
...data.attributes,
|
||||
showAncillaries: !!data.links.addAncillary,
|
||||
packages: data.attributes.packages.filter((p) => p.type !== "Ancillary"),
|
||||
ancillaries: data.attributes.packages.filter((p) => p.type === "Ancillary"),
|
||||
extraBedTypes: data.attributes.childBedPreferences,
|
||||
showAncillaries: !!(
|
||||
data.links.addAncillary ||
|
||||
data.attributes.packages.some((p) => p.type === "Ancillary")
|
||||
),
|
||||
isCancelable: !!data.links.cancel,
|
||||
isModifiable: !!data.links.modify,
|
||||
}))
|
||||
|
||||
@@ -12,6 +12,11 @@ export interface AncillariesProps extends Pick<BookingConfirmation, "booking"> {
|
||||
user: User | null
|
||||
}
|
||||
|
||||
export interface AddedAncillariesProps {
|
||||
ancillaries: Ancillary["ancillaryContent"][number][] | null
|
||||
booking: BookingConfirmation["booking"]
|
||||
}
|
||||
|
||||
export interface AncillaryProps {
|
||||
ancillary: Ancillary["ancillaryContent"][number]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user