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 SpecialRequests from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||
@@ -53,6 +54,9 @@ export default function Details() {
|
||||
lastName: initialData.lastName,
|
||||
membershipNo: initialData.membershipNo,
|
||||
phoneNumber: initialData.phoneNumber,
|
||||
specialRequest: {
|
||||
comment: room.specialRequest.comment,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -114,6 +118,7 @@ export default function Details() {
|
||||
type="tel"
|
||||
/>
|
||||
)}
|
||||
<SpecialRequests />
|
||||
</div>
|
||||
<footer className={styles.footer}>
|
||||
<Button
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { specialRequestSchema } from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests/schema"
|
||||
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
||||
|
||||
// stringMatcher regex is copied from current web as specified by requirements.
|
||||
@@ -40,4 +41,5 @@ export const multiroomDetailsSchema = z.object({
|
||||
}
|
||||
return true
|
||||
}, "Invalid membership number format"),
|
||||
specialRequest: specialRequestSchema,
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
|
||||
import SpecialRequests from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||
@@ -17,7 +18,6 @@ import JoinScandicFriendsCard from "./JoinScandicFriendsCard"
|
||||
import MemberPriceModal from "./MemberPriceModal"
|
||||
import { guestDetailsSchema, signedInDetailsSchema } from "./schema"
|
||||
import Signup from "./Signup"
|
||||
import SpecialRequests from "./SpecialRequests"
|
||||
|
||||
import styles from "./details.module.css"
|
||||
|
||||
@@ -64,10 +64,9 @@ export default function Details({ user }: DetailsProps) {
|
||||
membershipNo: initialData.membershipNo,
|
||||
phoneNumber: user?.phoneNumber ?? initialData.phoneNumber,
|
||||
zipCode: "zipCode" in initialData ? initialData.zipCode : undefined,
|
||||
specialRequests:
|
||||
"specialRequests" in initialData
|
||||
? initialData.specialRequests
|
||||
: undefined,
|
||||
specialRequest: {
|
||||
comment: room.specialRequest.comment,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { z } from "zod"
|
||||
|
||||
import { dt } from "@/lib/dt"
|
||||
|
||||
import { specialRequestSchema } from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests/schema"
|
||||
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
||||
|
||||
// stringMatcher regex is copied from current web as specified by requirements.
|
||||
@@ -10,30 +11,6 @@ const stringMatcher =
|
||||
|
||||
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({
|
||||
countryCode: z.string().min(1, { message: "Country 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",
|
||||
}),
|
||||
phoneNumber: phoneValidator(),
|
||||
specialRequests: specialRequestsSchema,
|
||||
specialRequest: specialRequestSchema,
|
||||
})
|
||||
|
||||
export const notJoinDetailsSchema = baseDetailsSchema.merge(
|
||||
@@ -116,5 +93,5 @@ export const signedInDetailsSchema = z.object({
|
||||
.transform((_) => false),
|
||||
dateOfBirth: z.string().default(""),
|
||||
zipCode: z.string().default(""),
|
||||
specialRequests: specialRequestsSchema,
|
||||
specialRequest: specialRequestSchema,
|
||||
})
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function SpecialRequests() {
|
||||
|
||||
<Select
|
||||
label={intl.formatMessage({ id: "Floor preference" })}
|
||||
name="specialRequests.floorPreference"
|
||||
name="specialRequest.floorPreference"
|
||||
items={[
|
||||
noPreferenceItem,
|
||||
{
|
||||
@@ -54,7 +54,7 @@ export default function SpecialRequests() {
|
||||
/>
|
||||
<Select
|
||||
label={intl.formatMessage({ id: "Elevator preference" })}
|
||||
name="specialRequests.elevatorPreference"
|
||||
name="specialRequest.elevatorPreference"
|
||||
items={[
|
||||
noPreferenceItem,
|
||||
{
|
||||
@@ -75,7 +75,7 @@ export default function SpecialRequests() {
|
||||
label={intl.formatMessage({
|
||||
id: "Is there anything else you would like us to know before your arrival?",
|
||||
})}
|
||||
name="specialRequests.comments"
|
||||
name="specialRequest.comment"
|
||||
/>
|
||||
</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 useSavedCard = savedCreditCard
|
||||
? {
|
||||
card: {
|
||||
alias: savedCreditCard.alias,
|
||||
expiryDate: savedCreditCard.expirationDate,
|
||||
cardType: savedCreditCard.cardType,
|
||||
},
|
||||
}
|
||||
card: {
|
||||
alias: savedCreditCard.alias,
|
||||
expiryDate: savedCreditCard.expirationDate,
|
||||
cardType: savedCreditCard.cardType,
|
||||
},
|
||||
}
|
||||
: {}
|
||||
|
||||
const shouldUsePayment = !isFlexRate || guarantee
|
||||
|
||||
const payment = shouldUsePayment
|
||||
? {
|
||||
paymentMethod: paymentMethod,
|
||||
...useSavedCard,
|
||||
success: `${paymentRedirectUrl}/success`,
|
||||
error: `${paymentRedirectUrl}/error`,
|
||||
cancel: `${paymentRedirectUrl}/cancel`,
|
||||
}
|
||||
paymentMethod: paymentMethod,
|
||||
...useSavedCard,
|
||||
success: `${paymentRedirectUrl}/success`,
|
||||
error: `${paymentRedirectUrl}/error`,
|
||||
cancel: `${paymentRedirectUrl}/cancel`,
|
||||
}
|
||||
: undefined
|
||||
|
||||
trackPaymentEvent({
|
||||
@@ -334,7 +334,7 @@ export default function PaymentClient({
|
||||
},
|
||||
rateCode:
|
||||
(room.guest.join || room.guest.membershipNo) &&
|
||||
booking.rooms[idx].counterRateCode
|
||||
booking.rooms[idx].counterRateCode
|
||||
? booking.rooms[idx].counterRateCode
|
||||
: booking.rooms[idx].rateCode,
|
||||
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.
|
||||
smsConfirmationRequested: data.smsConfirmation,
|
||||
specialRequest: {
|
||||
comment: room.specialRequest.comment
|
||||
? room.specialRequest.comment
|
||||
: undefined,
|
||||
},
|
||||
})),
|
||||
})
|
||||
},
|
||||
@@ -445,7 +450,7 @@ export default function PaymentClient({
|
||||
value={paymentMethod}
|
||||
label={
|
||||
PAYMENT_METHOD_TITLES[
|
||||
paymentMethod as PaymentMethodEnum
|
||||
paymentMethod as PaymentMethodEnum
|
||||
]
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -67,6 +67,9 @@ const rooms: RoomState[] = [
|
||||
isAvailable: true,
|
||||
mustBeGuaranteed: false,
|
||||
isFlexRate: false,
|
||||
specialRequest: {
|
||||
comment: "",
|
||||
},
|
||||
},
|
||||
steps: {
|
||||
[StepEnum.selectBed]: {
|
||||
@@ -107,6 +110,9 @@ const rooms: RoomState[] = [
|
||||
isAvailable: true,
|
||||
mustBeGuaranteed: false,
|
||||
isFlexRate: false,
|
||||
specialRequest: {
|
||||
comment: "",
|
||||
},
|
||||
},
|
||||
steps: {
|
||||
[StepEnum.selectBed]: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Label as AriaLabel,
|
||||
Text,
|
||||
@@ -47,12 +48,11 @@ export default function TextArea({
|
||||
validationBehavior="aria"
|
||||
value={field.value}
|
||||
>
|
||||
<AriaLabel className={styles.container} htmlFor={name}>
|
||||
<AriaLabel className={styles.container}>
|
||||
<Body asChild fontOnly>
|
||||
<AriaTextArea
|
||||
{...field}
|
||||
aria-labelledby={field.name}
|
||||
id={name}
|
||||
placeholder={placeholder}
|
||||
readOnly={readOnly}
|
||||
required={!!registerOptions.required}
|
||||
|
||||
@@ -126,7 +126,13 @@ export default function EnterDetailsProvider({
|
||||
storedRoom.room.guest
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
!currentRoom.room.specialRequest.comment &&
|
||||
storedRoom.room.specialRequest.comment
|
||||
) {
|
||||
currentRoom.room.specialRequest.comment =
|
||||
storedRoom.room.specialRequest.comment
|
||||
}
|
||||
const validGuest =
|
||||
idx > 0
|
||||
? multiroomDetailsSchema.safeParse(currentRoom.room.guest)
|
||||
|
||||
@@ -29,6 +29,9 @@ const roomsSchema = z
|
||||
phoneNumber: z.string(),
|
||||
}),
|
||||
smsConfirmationRequested: z.boolean(),
|
||||
specialRequest: z.object({
|
||||
comment: z.string().optional(),
|
||||
}),
|
||||
packages: z.object({
|
||||
breakfast: z.boolean(),
|
||||
allergyFriendly: z.boolean(),
|
||||
|
||||
@@ -111,6 +111,9 @@ export function createDetailsStore(
|
||||
? deepmerge(defaultGuestState, extractGuestFromUser(user))
|
||||
: defaultGuestState,
|
||||
roomPrice: getRoomPrice(room.roomRate, isMember && idx === 0),
|
||||
specialRequest: {
|
||||
comment: "",
|
||||
},
|
||||
},
|
||||
|
||||
currentStep,
|
||||
@@ -377,6 +380,10 @@ export function createDetailsStore(
|
||||
currentRoom.guest.join = data.join
|
||||
currentRoom.guest.lastName = data.lastName
|
||||
|
||||
if (data.specialRequest?.comment) {
|
||||
currentRoom.specialRequest.comment = data.specialRequest.comment
|
||||
}
|
||||
|
||||
if (data.join) {
|
||||
currentRoom.guest.membershipNo = undefined
|
||||
} else {
|
||||
|
||||
@@ -51,6 +51,9 @@ export interface Room extends InitialRoomData {
|
||||
childrenInRoom: Child[] | undefined
|
||||
guest: DetailsSchema | MultiroomDetailsSchema | SignedInDetailsSchema
|
||||
roomPrice: RoomPrice
|
||||
specialRequest: {
|
||||
comment: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface RoomState {
|
||||
|
||||
Reference in New Issue
Block a user