Merged in feat/sw-3514-join-card-membership-id (pull request #2967)
feat(SW-3514): Add variant of join friends card with membership id input * Move membershipId input in enter details to join card Add booking flow feature flag to move membershipId into join card and hide login button. Currently only applies to first room. * Add sas join card to multiroom Approved-by: Hrishikesh Vaipurkar
This commit is contained in:
@@ -61,6 +61,7 @@ export default async function RootLayout(props: RootLayoutProps) {
|
|||||||
|
|
||||||
const bookingFlowConfig: BookingFlowConfig = {
|
const bookingFlowConfig: BookingFlowConfig = {
|
||||||
bookingCodeEnabled: false,
|
bookingCodeEnabled: false,
|
||||||
|
enterDetailsMembershipIdInputLocation: "join-card",
|
||||||
variant: "partner-sas",
|
variant: "partner-sas",
|
||||||
routes: {
|
routes: {
|
||||||
myStay: routeToScandicWeb(myStay),
|
myStay: routeToScandicWeb(myStay),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlow
|
|||||||
|
|
||||||
export const bookingFlowConfig: BookingFlowConfig = {
|
export const bookingFlowConfig: BookingFlowConfig = {
|
||||||
bookingCodeEnabled: true,
|
bookingCodeEnabled: true,
|
||||||
|
enterDetailsMembershipIdInputLocation: "form",
|
||||||
variant: "scandic",
|
variant: "scandic",
|
||||||
routes: {
|
routes: {
|
||||||
myStay,
|
myStay,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import type { BookingFlowVariant } from "./bookingFlowVariants"
|
|||||||
|
|
||||||
export type BookingFlowConfig = {
|
export type BookingFlowConfig = {
|
||||||
bookingCodeEnabled: boolean
|
bookingCodeEnabled: boolean
|
||||||
|
enterDetailsMembershipIdInputLocation: "form" | "join-card"
|
||||||
variant: BookingFlowVariant
|
variant: BookingFlowVariant
|
||||||
routes: {
|
routes: {
|
||||||
myStay: LangRoute
|
myStay: LangRoute
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
"use client"
|
||||||
|
import { useWatch } from "react-hook-form"
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
|
import { membershipTermsAndConditions } from "@scandic-hotels/common/constants/routes/membershipTermsAndConditions"
|
||||||
|
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||||
|
import Footnote from "@scandic-hotels/design-system/Footnote"
|
||||||
|
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||||
|
import Link from "@scandic-hotels/design-system/Link"
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
|
import { useRoomContext } from "../../../../../contexts/EnterDetails/RoomContext"
|
||||||
|
import useLang from "../../../../../hooks/useLang"
|
||||||
|
import { MembershipNumberInput } from "../../RoomOne/Signup/MembershipNumberInput"
|
||||||
|
|
||||||
|
import styles from "./partnerSASJoinScandicFriendsCard.module.css"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
name?: string
|
||||||
|
updateDetailsStore?: () => void
|
||||||
|
}
|
||||||
|
export function PartnerSASJoinScandicFriendsCard({
|
||||||
|
name = "join",
|
||||||
|
updateDetailsStore,
|
||||||
|
}: Props) {
|
||||||
|
const lang = useLang()
|
||||||
|
const intl = useIntl()
|
||||||
|
const { data: euroBonusProfile } =
|
||||||
|
trpc.partner.sas.getEuroBonusProfile.useQuery()
|
||||||
|
|
||||||
|
const {
|
||||||
|
room,
|
||||||
|
roomNr,
|
||||||
|
actions: { updateJoin },
|
||||||
|
} = useRoomContext()
|
||||||
|
|
||||||
|
const joinValue = useWatch({ name: "join" })
|
||||||
|
|
||||||
|
function onChange(event: { target: { value: boolean } }) {
|
||||||
|
updateJoin(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (euroBonusProfile && euroBonusProfile.linkStatus !== "UNLINKED") {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!("member" in room.roomRate) || !room.roomRate.member) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.cardContainer}>
|
||||||
|
<Typography variant="Title/Subtitle/md">
|
||||||
|
<h2 className={styles.priceContainer}>
|
||||||
|
<span>
|
||||||
|
{intl.formatMessage({
|
||||||
|
defaultMessage: "Get the member room price",
|
||||||
|
})}
|
||||||
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
|
{`: `}
|
||||||
|
</span>
|
||||||
|
<span className={styles.price}>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{
|
||||||
|
defaultMessage: "{amount} for room {roomNr}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
amount: formatPrice(
|
||||||
|
intl,
|
||||||
|
room.roomRate.member.localPrice.pricePerStay ?? 0,
|
||||||
|
room.roomRate.member.localPrice.currency ??
|
||||||
|
CurrencyEnum.Unknown
|
||||||
|
),
|
||||||
|
roomNr,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
</Typography>
|
||||||
|
<div className={styles.checkBox}>
|
||||||
|
<Checkbox name={name} registerOptions={{ onChange }}>
|
||||||
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
|
<div>
|
||||||
|
{intl.formatMessage({
|
||||||
|
defaultMessage: "Join Scandic Friends before check-in",
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Typography>
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<MembershipNumberInput
|
||||||
|
className={styles.membershipInput}
|
||||||
|
registerOptions={{ onBlur: updateDetailsStore }}
|
||||||
|
disabled={Boolean(joinValue)}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
defaultMessage: "Already a member? Membership ID",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.terms}>
|
||||||
|
<Footnote color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage(
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
termsAndConditionsLink: (str) => (
|
||||||
|
<Link
|
||||||
|
textDecoration="underline"
|
||||||
|
size="tiny"
|
||||||
|
target="_blank"
|
||||||
|
href={membershipTermsAndConditions[lang]}
|
||||||
|
>
|
||||||
|
{str}
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</Footnote>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
.cardContainer {
|
||||||
|
align-self: flex-start;
|
||||||
|
background-color: var(--Surface-Primary-Hover-Accent);
|
||||||
|
border-radius: var(--Corner-radius-lg);
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Space-x2);
|
||||||
|
padding: var(--Space-x2);
|
||||||
|
grid-template-areas:
|
||||||
|
"price"
|
||||||
|
"checkbox"
|
||||||
|
"terms";
|
||||||
|
width: min(100%, 696px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceContainer {
|
||||||
|
grid-area: price;
|
||||||
|
margin-bottom: var(--Space-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
color: var(--Text-Accent-Primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkBox {
|
||||||
|
align-self: center;
|
||||||
|
grid-area: checkbox;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--Space-x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.terms {
|
||||||
|
grid-area: terms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
.cardContainer {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
gap: var(--Space-x3);
|
||||||
|
grid-template-areas:
|
||||||
|
"price checkbox"
|
||||||
|
"terms terms";
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceContainer {
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import { getErrorMessage } from "../../../BookingFlowInput/errors"
|
|||||||
import MemberPriceModal from "../MemberPriceModal"
|
import MemberPriceModal from "../MemberPriceModal"
|
||||||
import { SpecialRequests } from "../SpecialRequests"
|
import { SpecialRequests } from "../SpecialRequests"
|
||||||
import JoinScandicFriendsCard from "./JoinScandicFriendsCard"
|
import JoinScandicFriendsCard from "./JoinScandicFriendsCard"
|
||||||
|
import { PartnerSASJoinScandicFriendsCard } from "./PartnerSASJoinScandicFriendsCard"
|
||||||
import { getMultiroomDetailsSchema } from "./schema"
|
import { getMultiroomDetailsSchema } from "./schema"
|
||||||
|
|
||||||
import styles from "./details.module.css"
|
import styles from "./details.module.css"
|
||||||
@@ -161,6 +162,10 @@ export default function Details() {
|
|||||||
const guestIsGoingToJoin = methods.watch("join")
|
const guestIsGoingToJoin = methods.watch("join")
|
||||||
const guestIsMember = methods.watch("membershipNo")
|
const guestIsMember = methods.watch("membershipNo")
|
||||||
|
|
||||||
|
const showMembershipIdInput =
|
||||||
|
config.enterDetailsMembershipIdInputLocation === "form" &&
|
||||||
|
!guestIsGoingToJoin
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<form
|
<form
|
||||||
@@ -168,7 +173,9 @@ export default function Details() {
|
|||||||
id={`${formID}-room-${roomNr}`}
|
id={`${formID}-room-${roomNr}`}
|
||||||
onSubmit={methods.handleSubmit(updateDetails)}
|
onSubmit={methods.handleSubmit(updateDetails)}
|
||||||
>
|
>
|
||||||
{guestIsMember ? null : <JoinScandicFriendsCard />}
|
{guestIsMember ? null : (
|
||||||
|
<JoinScandicCard updateDetailsStore={updateDetailsStore} />
|
||||||
|
)}
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<Footnote
|
<Footnote
|
||||||
color="uiTextHighContrast"
|
color="uiTextHighContrast"
|
||||||
@@ -245,7 +252,7 @@ export default function Details() {
|
|||||||
name="phoneNumber"
|
name="phoneNumber"
|
||||||
registerOptions={{ required: true, onBlur: updateDetailsStore }}
|
registerOptions={{ required: true, onBlur: updateDetailsStore }}
|
||||||
/>
|
/>
|
||||||
{guestIsGoingToJoin ? null : (
|
{showMembershipIdInput ? (
|
||||||
<BookingFlowInput
|
<BookingFlowInput
|
||||||
className={styles.fullWidth}
|
className={styles.fullWidth}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
@@ -255,7 +262,7 @@ export default function Details() {
|
|||||||
type="tel"
|
type="tel"
|
||||||
registerOptions={{ onBlur: updateDetailsStore }}
|
registerOptions={{ onBlur: updateDetailsStore }}
|
||||||
/>
|
/>
|
||||||
)}
|
) : null}
|
||||||
<SpecialRequests registerOptions={{ onBlur: updateDetailsStore }} />
|
<SpecialRequests registerOptions={{ onBlur: updateDetailsStore }} />
|
||||||
</div>
|
</div>
|
||||||
<MemberPriceModal />
|
<MemberPriceModal />
|
||||||
@@ -263,3 +270,26 @@ export default function Details() {
|
|||||||
</FormProvider>
|
</FormProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function JoinScandicCard({
|
||||||
|
updateDetailsStore,
|
||||||
|
}: {
|
||||||
|
updateDetailsStore: () => void
|
||||||
|
}) {
|
||||||
|
const config = useBookingFlowConfig()
|
||||||
|
|
||||||
|
switch (config.enterDetailsMembershipIdInputLocation) {
|
||||||
|
case "form":
|
||||||
|
return <JoinScandicFriendsCard />
|
||||||
|
case "join-card":
|
||||||
|
return (
|
||||||
|
<PartnerSASJoinScandicFriendsCard
|
||||||
|
updateDetailsStore={updateDetailsStore}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
const _exhaustiveCheck: never =
|
||||||
|
config.enterDetailsMembershipIdInputLocation
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import { useWatch } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { membershipTermsAndConditions } from "@scandic-hotels/common/constants/routes/membershipTermsAndConditions"
|
import { membershipTermsAndConditions } from "@scandic-hotels/common/constants/routes/membershipTermsAndConditions"
|
||||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
|
||||||
import Footnote from "@scandic-hotels/design-system/Footnote"
|
import Footnote from "@scandic-hotels/design-system/Footnote"
|
||||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||||
import Link from "@scandic-hotels/design-system/Link"
|
import Link from "@scandic-hotels/design-system/Link"
|
||||||
import { toast } from "@scandic-hotels/design-system/Toast"
|
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
import { useRoomContext } from "../../../../../contexts/EnterDetails/RoomContext"
|
import { useRoomContext } from "../../../../../contexts/EnterDetails/RoomContext"
|
||||||
import useLang from "../../../../../hooks/useLang"
|
import useLang from "../../../../../hooks/useLang"
|
||||||
|
import { MembershipNumberInput } from "../Signup/MembershipNumberInput"
|
||||||
|
|
||||||
import styles from "./partnerSASJoinScandicFriendsCard.module.css"
|
import styles from "./partnerSASJoinScandicFriendsCard.module.css"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
name?: string
|
name?: string
|
||||||
|
updateDetailsStore?: () => void
|
||||||
}
|
}
|
||||||
export function PartnerSASJoinScandicFriendsCard({ name = "join" }: Props) {
|
export function PartnerSASJoinScandicFriendsCard({
|
||||||
|
name = "join",
|
||||||
|
updateDetailsStore,
|
||||||
|
}: Props) {
|
||||||
const lang = useLang()
|
const lang = useLang()
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const { data: euroBonusProfile } =
|
const { data: euroBonusProfile } =
|
||||||
@@ -31,11 +35,13 @@ export function PartnerSASJoinScandicFriendsCard({ name = "join" }: Props) {
|
|||||||
actions: { updateJoin },
|
actions: { updateJoin },
|
||||||
} = useRoomContext()
|
} = useRoomContext()
|
||||||
|
|
||||||
|
const joinValue = useWatch({ name: "join" })
|
||||||
|
|
||||||
function onChange(event: { target: { value: boolean } }) {
|
function onChange(event: { target: { value: boolean } }) {
|
||||||
updateJoin(event.target.value)
|
updateJoin(event.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!euroBonusProfile || euroBonusProfile.linkStatus !== "UNLINKED") {
|
if (euroBonusProfile && euroBonusProfile.linkStatus !== "UNLINKED") {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,14 +54,9 @@ export function PartnerSASJoinScandicFriendsCard({ name = "join" }: Props) {
|
|||||||
<Typography variant="Title/Subtitle/md">
|
<Typography variant="Title/Subtitle/md">
|
||||||
<h2 className={styles.priceContainer}>
|
<h2 className={styles.priceContainer}>
|
||||||
<span>
|
<span>
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
{intl.formatMessage({
|
||||||
<>
|
defaultMessage: "Get the member room price",
|
||||||
NOT IMPLEMENTED
|
})}
|
||||||
<br />
|
|
||||||
{intl.formatMessage({
|
|
||||||
defaultMessage: "Get the Scandic Friends room price",
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
{`: `}
|
{`: `}
|
||||||
</span>
|
</span>
|
||||||
@@ -68,32 +69,26 @@ export function PartnerSASJoinScandicFriendsCard({ name = "join" }: Props) {
|
|||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Checkbox
|
<div className={styles.checkBox}>
|
||||||
name={name}
|
<Checkbox name={name} registerOptions={{ onChange }}>
|
||||||
className={styles.checkBox}
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
registerOptions={{ onChange }}
|
<div>
|
||||||
>
|
{intl.formatMessage({
|
||||||
<Typography variant="Body/Paragraph/mdRegular">
|
defaultMessage: "Join Scandic Friends now",
|
||||||
<div>
|
})}
|
||||||
{intl.formatMessage({
|
</div>
|
||||||
defaultMessage: "Join Scandic Friends now",
|
</Typography>
|
||||||
})}
|
</Checkbox>
|
||||||
</div>
|
|
||||||
</Typography>
|
|
||||||
</Checkbox>
|
|
||||||
|
|
||||||
<Button
|
<MembershipNumberInput
|
||||||
variant={"Tertiary"}
|
className={styles.membershipInput}
|
||||||
size={"Small"}
|
registerOptions={{ onBlur: updateDetailsStore }}
|
||||||
typography={"Body/Paragraph/mdBold"}
|
disabled={Boolean(joinValue)}
|
||||||
color="Inverted"
|
label={intl.formatMessage({
|
||||||
className={styles.login}
|
defaultMessage: "Already a member? Membership ID",
|
||||||
onClick={() => toast.error("TODO: Not implemented")}
|
})}
|
||||||
>
|
/>
|
||||||
{intl.formatMessage({
|
</div>
|
||||||
defaultMessage: "Link",
|
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<div className={styles.terms}>
|
<div className={styles.terms}>
|
||||||
<Footnote color="uiTextPlaceholder">
|
<Footnote color="uiTextPlaceholder">
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
.cardContainer {
|
.cardContainer {
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
background-color: orchid;
|
background-color: var(--Surface-Primary-Hover-Accent);
|
||||||
color: white;
|
|
||||||
border-radius: var(--Corner-radius-lg);
|
border-radius: var(--Corner-radius-lg);
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--Space-x2);
|
gap: var(--Space-x2);
|
||||||
padding: var(--Space-x2);
|
padding: var(--Space-x2);
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"price login"
|
"price"
|
||||||
"checkbox checkbox"
|
"checkbox"
|
||||||
"terms terms";
|
"terms";
|
||||||
width: min(100%, 696px);
|
width: min(100%, 696px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,15 +21,12 @@
|
|||||||
color: var(--Text-Accent-Primary);
|
color: var(--Text-Accent-Primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login {
|
|
||||||
grid-area: login;
|
|
||||||
align-self: center;
|
|
||||||
justify-self: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkBox {
|
.checkBox {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
grid-area: checkbox;
|
grid-area: checkbox;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--Space-x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.terms {
|
.terms {
|
||||||
@@ -39,12 +35,12 @@
|
|||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
.cardContainer {
|
.cardContainer {
|
||||||
grid-template-columns: 1fr auto auto;
|
grid-template-columns: 1fr 1fr;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: auto auto;
|
||||||
gap: var(--Space-x3);
|
gap: var(--Space-x3);
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"price checkbox login"
|
"price checkbox"
|
||||||
"terms terms terms";
|
"terms terms";
|
||||||
}
|
}
|
||||||
|
|
||||||
.priceContainer {
|
.priceContainer {
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import BookingFlowInput from "../../../../BookingFlowInput"
|
||||||
|
|
||||||
|
import type { RegisterOptions } from "react-hook-form"
|
||||||
|
|
||||||
|
export function MembershipNumberInput({
|
||||||
|
registerOptions,
|
||||||
|
label,
|
||||||
|
className,
|
||||||
|
disabled,
|
||||||
|
}: {
|
||||||
|
registerOptions?: RegisterOptions
|
||||||
|
label?: string
|
||||||
|
className?: string
|
||||||
|
disabled?: boolean
|
||||||
|
}) {
|
||||||
|
const intl = useIntl()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BookingFlowInput
|
||||||
|
label={
|
||||||
|
label ||
|
||||||
|
intl.formatMessage({
|
||||||
|
defaultMessage: "Membership ID",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
name="membershipNo"
|
||||||
|
type="tel"
|
||||||
|
registerOptions={registerOptions}
|
||||||
|
className={className}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ import { useBookingFlowConfig } from "../../../../../bookingFlowConfig/bookingFl
|
|||||||
import useLang from "../../../../../hooks/useLang"
|
import useLang from "../../../../../hooks/useLang"
|
||||||
import BookingFlowInput from "../../../../BookingFlowInput"
|
import BookingFlowInput from "../../../../BookingFlowInput"
|
||||||
import { getErrorMessage } from "../../../../BookingFlowInput/errors"
|
import { getErrorMessage } from "../../../../BookingFlowInput/errors"
|
||||||
|
import { MembershipNumberInput } from "./MembershipNumberInput"
|
||||||
|
|
||||||
import styles from "./signup.module.css"
|
import styles from "./signup.module.css"
|
||||||
|
|
||||||
@@ -41,50 +42,46 @@ export default function Signup({
|
|||||||
setIsJoinChecked(joinValue)
|
setIsJoinChecked(joinValue)
|
||||||
}, [joinValue])
|
}, [joinValue])
|
||||||
|
|
||||||
return isJoinChecked ? (
|
if (isJoinChecked)
|
||||||
<div className={styles.additionalFormData}>
|
return (
|
||||||
<BookingFlowInput
|
<div className={styles.additionalFormData}>
|
||||||
name="zipCode"
|
<BookingFlowInput
|
||||||
label={intl.formatMessage({
|
name="zipCode"
|
||||||
defaultMessage: "Zip code",
|
label={intl.formatMessage({
|
||||||
})}
|
defaultMessage: "Zip code",
|
||||||
registerOptions={{ required: true, ...registerOptions }}
|
})}
|
||||||
/>
|
|
||||||
<div className={styles.dateField}>
|
|
||||||
<header>
|
|
||||||
<Caption type="bold">
|
|
||||||
<span className={styles.required}>
|
|
||||||
{intl.formatMessage({
|
|
||||||
defaultMessage: "Birth date",
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
</Caption>
|
|
||||||
</header>
|
|
||||||
<DateSelect
|
|
||||||
labels={{
|
|
||||||
day: intl.formatMessage({ defaultMessage: "Day" }),
|
|
||||||
month: intl.formatMessage({ defaultMessage: "Month" }),
|
|
||||||
year: intl.formatMessage({ defaultMessage: "Year" }),
|
|
||||||
errorMessage: getErrorMessage(
|
|
||||||
intl,
|
|
||||||
config.variant,
|
|
||||||
errors["dateOfBirth"]?.message?.toString()
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
lang={lang}
|
|
||||||
name="dateOfBirth"
|
|
||||||
registerOptions={{ required: true, ...registerOptions }}
|
registerOptions={{ required: true, ...registerOptions }}
|
||||||
/>
|
/>
|
||||||
|
<div className={styles.dateField}>
|
||||||
|
<header>
|
||||||
|
<Caption type="bold">
|
||||||
|
<span className={styles.required}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
defaultMessage: "Birth date",
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</Caption>
|
||||||
|
</header>
|
||||||
|
<DateSelect
|
||||||
|
labels={{
|
||||||
|
day: intl.formatMessage({ defaultMessage: "Day" }),
|
||||||
|
month: intl.formatMessage({ defaultMessage: "Month" }),
|
||||||
|
year: intl.formatMessage({ defaultMessage: "Year" }),
|
||||||
|
errorMessage: getErrorMessage(
|
||||||
|
intl,
|
||||||
|
config.variant,
|
||||||
|
errors["dateOfBirth"]?.message?.toString()
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
lang={lang}
|
||||||
|
name="dateOfBirth"
|
||||||
|
registerOptions={{ required: true, ...registerOptions }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
) : (
|
|
||||||
<BookingFlowInput
|
if (config.enterDetailsMembershipIdInputLocation === "join-card") return null
|
||||||
label={intl.formatMessage({
|
|
||||||
defaultMessage: "Membership ID",
|
return <MembershipNumberInput registerOptions={registerOptions} />
|
||||||
})}
|
|
||||||
name="membershipNo"
|
|
||||||
type="tel"
|
|
||||||
registerOptions={registerOptions}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,9 @@ export default function Details({ user }: DetailsProps) {
|
|||||||
setValue("phoneNumberCC", countryCode.toLowerCase())
|
setValue("phoneNumberCC", countryCode.toLowerCase())
|
||||||
}
|
}
|
||||||
}, [countryCode, setValue])
|
}, [countryCode, setValue])
|
||||||
|
|
||||||
|
const showJoinCard = memberRate && !user
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<form
|
<form
|
||||||
@@ -156,15 +159,9 @@ export default function Details({ user }: DetailsProps) {
|
|||||||
id={`${formID}-room-${roomNr}`}
|
id={`${formID}-room-${roomNr}`}
|
||||||
onSubmit={methods.handleSubmit(onSubmit)}
|
onSubmit={methods.handleSubmit(onSubmit)}
|
||||||
>
|
>
|
||||||
{config.variant === "scandic" && (
|
{showJoinCard ? (
|
||||||
<>{user || !memberRate ? null : <JoinScandicFriendsCard />}</>
|
<JoinScandicCard updateDetailsStore={updateDetailsStore} />
|
||||||
)}
|
) : null}
|
||||||
|
|
||||||
{config.variant === "partner-sas" && (
|
|
||||||
<>
|
|
||||||
{user || !memberRate ? null : <PartnerSASJoinScandicFriendsCard />}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<Footnote
|
<Footnote
|
||||||
color="uiTextHighContrast"
|
color="uiTextHighContrast"
|
||||||
@@ -257,3 +254,26 @@ export default function Details({ user }: DetailsProps) {
|
|||||||
</FormProvider>
|
</FormProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function JoinScandicCard({
|
||||||
|
updateDetailsStore,
|
||||||
|
}: {
|
||||||
|
updateDetailsStore: () => void
|
||||||
|
}) {
|
||||||
|
const config = useBookingFlowConfig()
|
||||||
|
|
||||||
|
switch (config.enterDetailsMembershipIdInputLocation) {
|
||||||
|
case "form":
|
||||||
|
return <JoinScandicFriendsCard />
|
||||||
|
case "join-card":
|
||||||
|
return (
|
||||||
|
<PartnerSASJoinScandicFriendsCard
|
||||||
|
updateDetailsStore={updateDetailsStore}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
const _exhaustiveCheck: never =
|
||||||
|
config.enterDetailsMembershipIdInputLocation
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user