Merged in feat/SW-598 (pull request #1554)
feat: pass specialRequest.comment to create booking * feat: pass specialRequest.comment to create booking Approved-by: Simon.Emanuelsson
This commit is contained in:
committed by
Arvid Norlin
parent
fc219aaec0
commit
0e0b065dd9
@@ -5,6 +5,7 @@ import { useIntl } from "react-intl"
|
|||||||
|
|
||||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
|
import SpecialRequests from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
||||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||||
@@ -53,6 +54,9 @@ export default function Details() {
|
|||||||
lastName: initialData.lastName,
|
lastName: initialData.lastName,
|
||||||
membershipNo: initialData.membershipNo,
|
membershipNo: initialData.membershipNo,
|
||||||
phoneNumber: initialData.phoneNumber,
|
phoneNumber: initialData.phoneNumber,
|
||||||
|
specialRequest: {
|
||||||
|
comment: room.specialRequest.comment,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -114,6 +118,7 @@ export default function Details() {
|
|||||||
type="tel"
|
type="tel"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<SpecialRequests />
|
||||||
</div>
|
</div>
|
||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { specialRequestSchema } from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests/schema"
|
||||||
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
||||||
|
|
||||||
// stringMatcher regex is copied from current web as specified by requirements.
|
// stringMatcher regex is copied from current web as specified by requirements.
|
||||||
@@ -40,4 +41,5 @@ export const multiroomDetailsSchema = z.object({
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, "Invalid membership number format"),
|
}, "Invalid membership number format"),
|
||||||
|
specialRequest: specialRequestSchema,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useIntl } from "react-intl"
|
|||||||
|
|
||||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
|
import SpecialRequests from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
||||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||||
@@ -17,7 +18,6 @@ import JoinScandicFriendsCard from "./JoinScandicFriendsCard"
|
|||||||
import MemberPriceModal from "./MemberPriceModal"
|
import MemberPriceModal from "./MemberPriceModal"
|
||||||
import { guestDetailsSchema, signedInDetailsSchema } from "./schema"
|
import { guestDetailsSchema, signedInDetailsSchema } from "./schema"
|
||||||
import Signup from "./Signup"
|
import Signup from "./Signup"
|
||||||
import SpecialRequests from "./SpecialRequests"
|
|
||||||
|
|
||||||
import styles from "./details.module.css"
|
import styles from "./details.module.css"
|
||||||
|
|
||||||
@@ -64,10 +64,9 @@ export default function Details({ user }: DetailsProps) {
|
|||||||
membershipNo: initialData.membershipNo,
|
membershipNo: initialData.membershipNo,
|
||||||
phoneNumber: user?.phoneNumber ?? initialData.phoneNumber,
|
phoneNumber: user?.phoneNumber ?? initialData.phoneNumber,
|
||||||
zipCode: "zipCode" in initialData ? initialData.zipCode : undefined,
|
zipCode: "zipCode" in initialData ? initialData.zipCode : undefined,
|
||||||
specialRequests:
|
specialRequest: {
|
||||||
"specialRequests" in initialData
|
comment: room.specialRequest.comment,
|
||||||
? initialData.specialRequests
|
},
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
|
import { specialRequestSchema } from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests/schema"
|
||||||
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
||||||
|
|
||||||
// stringMatcher regex is copied from current web as specified by requirements.
|
// stringMatcher regex is copied from current web as specified by requirements.
|
||||||
@@ -10,30 +11,6 @@ const stringMatcher =
|
|||||||
|
|
||||||
const isValidString = (key: string) => stringMatcher.test(key)
|
const isValidString = (key: string) => stringMatcher.test(key)
|
||||||
|
|
||||||
export enum FloorPreference {
|
|
||||||
LOW = "Low floor",
|
|
||||||
HIGH = "High floor",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ElevatorPreference {
|
|
||||||
AWAY_FROM_ELEVATOR = "Away from elevator",
|
|
||||||
NEAR_ELEVATOR = "Near elevator",
|
|
||||||
}
|
|
||||||
|
|
||||||
const specialRequestsSchema = z
|
|
||||||
.object({
|
|
||||||
floorPreference: z
|
|
||||||
.nativeEnum(FloorPreference)
|
|
||||||
.or(z.literal("").transform((_) => undefined))
|
|
||||||
.optional(),
|
|
||||||
elevatorPreference: z
|
|
||||||
.nativeEnum(ElevatorPreference)
|
|
||||||
.or(z.literal("").transform((_) => undefined))
|
|
||||||
.optional(),
|
|
||||||
comments: z.string().default(""),
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
|
|
||||||
export const baseDetailsSchema = z.object({
|
export const baseDetailsSchema = z.object({
|
||||||
countryCode: z.string().min(1, { message: "Country is required" }),
|
countryCode: z.string().min(1, { message: "Country is required" }),
|
||||||
email: z.string().email({ message: "Email address is required" }),
|
email: z.string().email({ message: "Email address is required" }),
|
||||||
@@ -50,7 +27,7 @@ export const baseDetailsSchema = z.object({
|
|||||||
message: "Last name can't contain any special characters",
|
message: "Last name can't contain any special characters",
|
||||||
}),
|
}),
|
||||||
phoneNumber: phoneValidator(),
|
phoneNumber: phoneValidator(),
|
||||||
specialRequests: specialRequestsSchema,
|
specialRequest: specialRequestSchema,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const notJoinDetailsSchema = baseDetailsSchema.merge(
|
export const notJoinDetailsSchema = baseDetailsSchema.merge(
|
||||||
@@ -116,5 +93,5 @@ export const signedInDetailsSchema = z.object({
|
|||||||
.transform((_) => false),
|
.transform((_) => false),
|
||||||
dateOfBirth: z.string().default(""),
|
dateOfBirth: z.string().default(""),
|
||||||
zipCode: z.string().default(""),
|
zipCode: z.string().default(""),
|
||||||
specialRequests: specialRequestsSchema,
|
specialRequest: specialRequestSchema,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function SpecialRequests() {
|
|||||||
|
|
||||||
<Select
|
<Select
|
||||||
label={intl.formatMessage({ id: "Floor preference" })}
|
label={intl.formatMessage({ id: "Floor preference" })}
|
||||||
name="specialRequests.floorPreference"
|
name="specialRequest.floorPreference"
|
||||||
items={[
|
items={[
|
||||||
noPreferenceItem,
|
noPreferenceItem,
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ export default function SpecialRequests() {
|
|||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
label={intl.formatMessage({ id: "Elevator preference" })}
|
label={intl.formatMessage({ id: "Elevator preference" })}
|
||||||
name="specialRequests.elevatorPreference"
|
name="specialRequest.elevatorPreference"
|
||||||
items={[
|
items={[
|
||||||
noPreferenceItem,
|
noPreferenceItem,
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ export default function SpecialRequests() {
|
|||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: "Is there anything else you would like us to know before your arrival?",
|
id: "Is there anything else you would like us to know before your arrival?",
|
||||||
})}
|
})}
|
||||||
name="specialRequests.comments"
|
name="specialRequest.comment"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
export enum FloorPreference {
|
||||||
|
LOW = "Low floor",
|
||||||
|
HIGH = "High floor",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ElevatorPreference {
|
||||||
|
AWAY_FROM_ELEVATOR = "Away from elevator",
|
||||||
|
NEAR_ELEVATOR = "Near elevator",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const specialRequestSchema = z
|
||||||
|
.object({
|
||||||
|
floorPreference: z
|
||||||
|
.nativeEnum(FloorPreference)
|
||||||
|
.or(z.literal("").transform((_) => undefined))
|
||||||
|
.optional(),
|
||||||
|
elevatorPreference: z
|
||||||
|
.nativeEnum(ElevatorPreference)
|
||||||
|
.or(z.literal("").transform((_) => undefined))
|
||||||
|
.optional(),
|
||||||
|
comment: z.string().default(""),
|
||||||
|
})
|
||||||
|
.optional()
|
||||||
@@ -255,24 +255,24 @@ export default function PaymentClient({
|
|||||||
const guarantee = data.guarantee
|
const guarantee = data.guarantee
|
||||||
const useSavedCard = savedCreditCard
|
const useSavedCard = savedCreditCard
|
||||||
? {
|
? {
|
||||||
card: {
|
card: {
|
||||||
alias: savedCreditCard.alias,
|
alias: savedCreditCard.alias,
|
||||||
expiryDate: savedCreditCard.expirationDate,
|
expiryDate: savedCreditCard.expirationDate,
|
||||||
cardType: savedCreditCard.cardType,
|
cardType: savedCreditCard.cardType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
|
|
||||||
const shouldUsePayment = !isFlexRate || guarantee
|
const shouldUsePayment = !isFlexRate || guarantee
|
||||||
|
|
||||||
const payment = shouldUsePayment
|
const payment = shouldUsePayment
|
||||||
? {
|
? {
|
||||||
paymentMethod: paymentMethod,
|
paymentMethod: paymentMethod,
|
||||||
...useSavedCard,
|
...useSavedCard,
|
||||||
success: `${paymentRedirectUrl}/success`,
|
success: `${paymentRedirectUrl}/success`,
|
||||||
error: `${paymentRedirectUrl}/error`,
|
error: `${paymentRedirectUrl}/error`,
|
||||||
cancel: `${paymentRedirectUrl}/cancel`,
|
cancel: `${paymentRedirectUrl}/cancel`,
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
trackPaymentEvent({
|
trackPaymentEvent({
|
||||||
@@ -334,7 +334,7 @@ export default function PaymentClient({
|
|||||||
},
|
},
|
||||||
rateCode:
|
rateCode:
|
||||||
(room.guest.join || room.guest.membershipNo) &&
|
(room.guest.join || room.guest.membershipNo) &&
|
||||||
booking.rooms[idx].counterRateCode
|
booking.rooms[idx].counterRateCode
|
||||||
? booking.rooms[idx].counterRateCode
|
? booking.rooms[idx].counterRateCode
|
||||||
: booking.rooms[idx].rateCode,
|
: booking.rooms[idx].rateCode,
|
||||||
roomPrice: {
|
roomPrice: {
|
||||||
@@ -343,6 +343,11 @@ export default function PaymentClient({
|
|||||||
},
|
},
|
||||||
roomTypeCode: room.bedType!.roomTypeCode, // A selection has been made in order to get to this step.
|
roomTypeCode: room.bedType!.roomTypeCode, // A selection has been made in order to get to this step.
|
||||||
smsConfirmationRequested: data.smsConfirmation,
|
smsConfirmationRequested: data.smsConfirmation,
|
||||||
|
specialRequest: {
|
||||||
|
comment: room.specialRequest.comment
|
||||||
|
? room.specialRequest.comment
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -445,7 +450,7 @@ export default function PaymentClient({
|
|||||||
value={paymentMethod}
|
value={paymentMethod}
|
||||||
label={
|
label={
|
||||||
PAYMENT_METHOD_TITLES[
|
PAYMENT_METHOD_TITLES[
|
||||||
paymentMethod as PaymentMethodEnum
|
paymentMethod as PaymentMethodEnum
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ const rooms: RoomState[] = [
|
|||||||
isAvailable: true,
|
isAvailable: true,
|
||||||
mustBeGuaranteed: false,
|
mustBeGuaranteed: false,
|
||||||
isFlexRate: false,
|
isFlexRate: false,
|
||||||
|
specialRequest: {
|
||||||
|
comment: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
steps: {
|
steps: {
|
||||||
[StepEnum.selectBed]: {
|
[StepEnum.selectBed]: {
|
||||||
@@ -107,6 +110,9 @@ const rooms: RoomState[] = [
|
|||||||
isAvailable: true,
|
isAvailable: true,
|
||||||
mustBeGuaranteed: false,
|
mustBeGuaranteed: false,
|
||||||
isFlexRate: false,
|
isFlexRate: false,
|
||||||
|
specialRequest: {
|
||||||
|
comment: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
steps: {
|
steps: {
|
||||||
[StepEnum.selectBed]: {
|
[StepEnum.selectBed]: {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Label as AriaLabel,
|
Label as AriaLabel,
|
||||||
Text,
|
Text,
|
||||||
@@ -47,12 +48,11 @@ export default function TextArea({
|
|||||||
validationBehavior="aria"
|
validationBehavior="aria"
|
||||||
value={field.value}
|
value={field.value}
|
||||||
>
|
>
|
||||||
<AriaLabel className={styles.container} htmlFor={name}>
|
<AriaLabel className={styles.container}>
|
||||||
<Body asChild fontOnly>
|
<Body asChild fontOnly>
|
||||||
<AriaTextArea
|
<AriaTextArea
|
||||||
{...field}
|
{...field}
|
||||||
aria-labelledby={field.name}
|
aria-labelledby={field.name}
|
||||||
id={name}
|
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
required={!!registerOptions.required}
|
required={!!registerOptions.required}
|
||||||
|
|||||||
@@ -126,7 +126,13 @@ export default function EnterDetailsProvider({
|
|||||||
storedRoom.room.guest
|
storedRoom.room.guest
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
!currentRoom.room.specialRequest.comment &&
|
||||||
|
storedRoom.room.specialRequest.comment
|
||||||
|
) {
|
||||||
|
currentRoom.room.specialRequest.comment =
|
||||||
|
storedRoom.room.specialRequest.comment
|
||||||
|
}
|
||||||
const validGuest =
|
const validGuest =
|
||||||
idx > 0
|
idx > 0
|
||||||
? multiroomDetailsSchema.safeParse(currentRoom.room.guest)
|
? multiroomDetailsSchema.safeParse(currentRoom.room.guest)
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ const roomsSchema = z
|
|||||||
phoneNumber: z.string(),
|
phoneNumber: z.string(),
|
||||||
}),
|
}),
|
||||||
smsConfirmationRequested: z.boolean(),
|
smsConfirmationRequested: z.boolean(),
|
||||||
|
specialRequest: z.object({
|
||||||
|
comment: z.string().optional(),
|
||||||
|
}),
|
||||||
packages: z.object({
|
packages: z.object({
|
||||||
breakfast: z.boolean(),
|
breakfast: z.boolean(),
|
||||||
allergyFriendly: z.boolean(),
|
allergyFriendly: z.boolean(),
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ export function createDetailsStore(
|
|||||||
? deepmerge(defaultGuestState, extractGuestFromUser(user))
|
? deepmerge(defaultGuestState, extractGuestFromUser(user))
|
||||||
: defaultGuestState,
|
: defaultGuestState,
|
||||||
roomPrice: getRoomPrice(room.roomRate, isMember && idx === 0),
|
roomPrice: getRoomPrice(room.roomRate, isMember && idx === 0),
|
||||||
|
specialRequest: {
|
||||||
|
comment: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
currentStep,
|
currentStep,
|
||||||
@@ -377,6 +380,10 @@ export function createDetailsStore(
|
|||||||
currentRoom.guest.join = data.join
|
currentRoom.guest.join = data.join
|
||||||
currentRoom.guest.lastName = data.lastName
|
currentRoom.guest.lastName = data.lastName
|
||||||
|
|
||||||
|
if (data.specialRequest?.comment) {
|
||||||
|
currentRoom.specialRequest.comment = data.specialRequest.comment
|
||||||
|
}
|
||||||
|
|
||||||
if (data.join) {
|
if (data.join) {
|
||||||
currentRoom.guest.membershipNo = undefined
|
currentRoom.guest.membershipNo = undefined
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ export interface Room extends InitialRoomData {
|
|||||||
childrenInRoom: Child[] | undefined
|
childrenInRoom: Child[] | undefined
|
||||||
guest: DetailsSchema | MultiroomDetailsSchema | SignedInDetailsSchema
|
guest: DetailsSchema | MultiroomDetailsSchema | SignedInDetailsSchema
|
||||||
roomPrice: RoomPrice
|
roomPrice: RoomPrice
|
||||||
|
specialRequest: {
|
||||||
|
comment: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RoomState {
|
export interface RoomState {
|
||||||
|
|||||||
Reference in New Issue
Block a user