Merged in feat/BOOK-747-alert-extra-cost (pull request #3455)
feat(BOOK-747): show extra cost alert if reward night or voucher * feat(BOOK-747): show extra cost alert if reward night or voucher * feat(BOOK-747): use enum * feat(BOOK-747): refactor * feat(BOOK-747): add underline to trigger text Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -3,7 +3,7 @@ import type {
|
||||
SidepeekContent,
|
||||
} from "@scandic-hotels/common/constants/alert"
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { AriaRole } from "react"
|
||||
import type { AriaRole, ReactNode } from "react"
|
||||
|
||||
import type { alertVariants } from "./variants"
|
||||
|
||||
@@ -27,4 +27,5 @@ export interface AlertProps extends VariantProps<typeof alertVariants> {
|
||||
close?: () => void
|
||||
ariaRole?: AriaRole
|
||||
ariaLive?: "off" | "assertive" | "polite"
|
||||
slot?: ReactNode
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ export function Alert({
|
||||
sidepeekContent,
|
||||
ariaLive,
|
||||
ariaRole,
|
||||
slot,
|
||||
}: AlertProps) {
|
||||
const classNames = alertVariants({
|
||||
className,
|
||||
@@ -93,6 +94,7 @@ export function Alert({
|
||||
sidePeekContent={sidepeekContent}
|
||||
/>
|
||||
) : null}
|
||||
{slot}
|
||||
</div>
|
||||
{close ? (
|
||||
<Button onPress={close} variant="Text" className={styles.closeButton}>
|
||||
|
||||
@@ -4,12 +4,10 @@ import { Typography } from "../../Typography"
|
||||
import { Rate, RateTermDetails } from "../types"
|
||||
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../../IconButton"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import Modal from "../Modal"
|
||||
import styles from "../rate-card.module.css"
|
||||
import { variants } from "../variants"
|
||||
import TermModal from "../TermModal"
|
||||
|
||||
interface CampaignRateCardProps {
|
||||
id: string
|
||||
@@ -51,7 +49,6 @@ export default function CampaignRateCard({
|
||||
variant: "Campaign",
|
||||
})
|
||||
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div
|
||||
className={cx(classNames, {
|
||||
@@ -74,44 +71,11 @@ export default function CampaignRateCard({
|
||||
<div className={styles.container}>
|
||||
<Typography variant="Tag/sm">
|
||||
<h3 className={styles.title}>
|
||||
<Modal
|
||||
title={rateTitle}
|
||||
subtitle={paymentTerm}
|
||||
trigger={
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
size="sm"
|
||||
className={styles.triggerButton}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "selectRate.rateCard.openReservationPolicy",
|
||||
defaultMessage: "Open reservation policy",
|
||||
})}
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
<div key={termGroup.title} className={styles.terms}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{termGroup.title}</p>
|
||||
</Typography>
|
||||
{termGroup.terms.map((term) => (
|
||||
<Typography key={term}>
|
||||
<p className={styles.term}>
|
||||
<MaterialIcon
|
||||
icon="check"
|
||||
color="Icon/Feedback/Success"
|
||||
size={20}
|
||||
className={styles.termsIcon}
|
||||
/>
|
||||
{term}
|
||||
</p>
|
||||
</Typography>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</Modal>
|
||||
<TermModal
|
||||
rateTitle={rateTitle}
|
||||
paymentTerm={paymentTerm}
|
||||
rateTermDetails={rateTermDetails}
|
||||
/>
|
||||
<span id={`${id}-title`}>
|
||||
{rateTitle}
|
||||
<span className={styles.textSecondary}>
|
||||
|
||||
@@ -2,13 +2,11 @@ import { Rate, RateTermDetails } from "../types"
|
||||
|
||||
import { cx } from "class-variance-authority"
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../../IconButton"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { Typography } from "../../Typography"
|
||||
import Modal from "../Modal"
|
||||
import styles from "../rate-card.module.css"
|
||||
import { variants } from "../variants"
|
||||
import TermModal from "../TermModal"
|
||||
|
||||
interface CodeRateCardProps {
|
||||
id: string
|
||||
@@ -43,7 +41,6 @@ export default function CodeRateCard({
|
||||
const classNames = variants({
|
||||
variant: "Code",
|
||||
})
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -64,44 +61,11 @@ export default function CodeRateCard({
|
||||
<div className={styles.container}>
|
||||
<Typography variant="Tag/sm">
|
||||
<h3 className={styles.title}>
|
||||
<Modal
|
||||
title={rateTitle}
|
||||
subtitle={paymentTerm}
|
||||
trigger={
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
size="sm"
|
||||
className={styles.triggerButton}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "selectRate.rateCard.openReservationPolicy",
|
||||
defaultMessage: "Open reservation policy",
|
||||
})}
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
<div key={termGroup.title} className={styles.terms}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{termGroup.title}</p>
|
||||
</Typography>
|
||||
{termGroup.terms.map((term) => (
|
||||
<Typography key={term}>
|
||||
<p className={styles.term}>
|
||||
<MaterialIcon
|
||||
icon="check"
|
||||
color="Icon/Feedback/Success"
|
||||
size={20}
|
||||
className={styles.termsIcon}
|
||||
/>
|
||||
{term}
|
||||
</p>
|
||||
</Typography>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</Modal>
|
||||
<TermModal
|
||||
rateTitle={rateTitle}
|
||||
paymentTerm={paymentTerm}
|
||||
rateTermDetails={rateTermDetails}
|
||||
/>
|
||||
<span id={`${id}-title`}>
|
||||
{rateTitle}
|
||||
<span className={styles.textSecondary}>
|
||||
|
||||
@@ -2,15 +2,14 @@ import { Typography } from "../../Typography"
|
||||
import { RatePointsOption, RateTermDetails } from "../types"
|
||||
|
||||
import { RadioGroup } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../../IconButton"
|
||||
|
||||
import { Radio } from "../../Radio"
|
||||
import Modal from "../Modal"
|
||||
import styles from "../rate-card.module.css"
|
||||
import { variants } from "../variants"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { getCurrencyText } from "../../currency-utils"
|
||||
import TermModal from "../TermModal"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
interface PointsRateCardProps {
|
||||
rateTitle: string
|
||||
@@ -42,6 +41,7 @@ export default function PointsRateCard({
|
||||
const classNames = variants({
|
||||
variant: "Points",
|
||||
})
|
||||
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
@@ -53,43 +53,11 @@ export default function PointsRateCard({
|
||||
<header>
|
||||
<Typography variant="Tag/sm">
|
||||
<h3 className={styles.title}>
|
||||
<Modal
|
||||
title={rateTitle}
|
||||
subtitle={paymentTerm}
|
||||
trigger={
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
size="sm"
|
||||
aria-label={intl.formatMessage({
|
||||
id: "selectRate.rateCard.openReservationPolicy",
|
||||
defaultMessage: "Open reservation policy",
|
||||
})}
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
<div key={termGroup.title} className={styles.terms}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{termGroup.title}</p>
|
||||
</Typography>
|
||||
{termGroup.terms.map((term) => (
|
||||
<Typography key={term}>
|
||||
<p className={styles.term}>
|
||||
<MaterialIcon
|
||||
icon="check"
|
||||
color="Icon/Feedback/Success"
|
||||
size={20}
|
||||
className={styles.termsIcon}
|
||||
/>
|
||||
{term}
|
||||
</p>
|
||||
</Typography>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</Modal>
|
||||
<TermModal
|
||||
rateTitle={rateTitle}
|
||||
paymentTerm={paymentTerm}
|
||||
rateTermDetails={rateTermDetails}
|
||||
/>
|
||||
{rateTitle}
|
||||
<span className={styles.textSecondary}>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
|
||||
@@ -2,13 +2,11 @@ import { Rate, RateTermDetails } from "../types"
|
||||
|
||||
import { cx } from "class-variance-authority"
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../../IconButton"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { Typography } from "../../Typography"
|
||||
import Modal from "../Modal"
|
||||
import styles from "../rate-card.module.css"
|
||||
import { variants } from "../variants"
|
||||
import TermModal from "../TermModal"
|
||||
|
||||
interface RegularRateCardProps {
|
||||
id: string
|
||||
@@ -41,8 +39,6 @@ export default function RegularRateCard({
|
||||
}: RegularRateCardProps) {
|
||||
const classNames = variants({ variant: "Regular" })
|
||||
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(classNames, {
|
||||
@@ -59,44 +55,11 @@ export default function RegularRateCard({
|
||||
<div className={styles.container}>
|
||||
<Typography variant="Tag/sm">
|
||||
<h3 className={styles.title}>
|
||||
<Modal
|
||||
title={rateTitle}
|
||||
subtitle={paymentTerm}
|
||||
trigger={
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
size="sm"
|
||||
className={styles.triggerButton}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "selectRate.rateCard.openReservationPolicy",
|
||||
defaultMessage: "Open reservation policy",
|
||||
})}
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
<div key={termGroup.title} className={styles.terms}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{termGroup.title}</p>
|
||||
</Typography>
|
||||
{termGroup.terms.map((term) => (
|
||||
<Typography key={term}>
|
||||
<p className={styles.term}>
|
||||
<MaterialIcon
|
||||
icon="check"
|
||||
color="Icon/Feedback/Success"
|
||||
size={20}
|
||||
className={styles.termsIcon}
|
||||
/>
|
||||
{term}
|
||||
</p>
|
||||
</Typography>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</Modal>
|
||||
<TermModal
|
||||
rateTitle={rateTitle}
|
||||
paymentTerm={paymentTerm}
|
||||
rateTermDetails={rateTermDetails}
|
||||
/>
|
||||
<span id={`${id}-title`}>
|
||||
{rateTitle}
|
||||
<span className={styles.textSecondary}>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../../IconButton"
|
||||
import Modal from "../Modal"
|
||||
|
||||
import styles from "./termModal.module.css"
|
||||
import { Typography } from "../../Typography"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { RateTermDetails } from "../types"
|
||||
import { Button } from "../../Button"
|
||||
|
||||
interface TermModalProps {
|
||||
rateTitle: string
|
||||
paymentTerm: string
|
||||
rateTermDetails: RateTermDetails[]
|
||||
variant?: "icon" | "text"
|
||||
}
|
||||
|
||||
export default function TermModal({
|
||||
rateTitle,
|
||||
paymentTerm,
|
||||
rateTermDetails,
|
||||
variant = "icon",
|
||||
}: TermModalProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<Modal
|
||||
title={rateTitle}
|
||||
subtitle={paymentTerm}
|
||||
trigger={
|
||||
variant === "text" ? (
|
||||
<Button variant="Text" size="sm" className={styles.triggerText}>
|
||||
{intl.formatMessage({
|
||||
id: "selectRate.alert.reservationPolicies",
|
||||
defaultMessage: "See reservation policies",
|
||||
})}
|
||||
</Button>
|
||||
) : (
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
size="sm"
|
||||
aria-label={intl.formatMessage({
|
||||
id: "selectRate.rateCard.openReservationPolicy",
|
||||
defaultMessage: "Open reservation policy",
|
||||
})}
|
||||
className={styles.triggerButton}
|
||||
iconName="info"
|
||||
/>
|
||||
)
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
<div key={termGroup.title} className={styles.terms}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{termGroup.title}</p>
|
||||
</Typography>
|
||||
{termGroup.terms.map((term) => (
|
||||
<Typography key={term}>
|
||||
<p className={styles.term}>
|
||||
<MaterialIcon
|
||||
icon="check"
|
||||
color="Icon/Feedback/Success"
|
||||
size={20}
|
||||
/>
|
||||
{term}
|
||||
</p>
|
||||
</Typography>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
.terms {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.term {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.triggerButton {
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.triggerText {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -65,10 +65,6 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.triggerButton {
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
.container > * {
|
||||
padding-bottom: var(--Space-x1);
|
||||
border-bottom: 2px solid var(--Neutral-Opacity-Black-5);
|
||||
@@ -147,17 +143,6 @@
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
.terms {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.term {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.variant-campaign .banner {
|
||||
background-color: var(--Surface-Feedback-Succes);
|
||||
display: flex;
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
"./Stepper": "./lib/components/Stepper/index.tsx",
|
||||
"./Switch": "./lib/components/Switch/index.tsx",
|
||||
"./Table": "./lib/components/Table/index.tsx",
|
||||
"./TermModal": "./lib/components/RateCard/TermModal/index.tsx",
|
||||
"./TextArea": "./lib/components/TextArea/index.tsx",
|
||||
"./TextLink": "./lib/components/TextLink/index.tsx",
|
||||
"./TextLinkButton": "./lib/components/TextLinkButton/index.tsx",
|
||||
|
||||
Reference in New Issue
Block a user