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:
Linus Flood
2025-03-18 10:43:28 +00:00
committed by Arvid Norlin
parent fc219aaec0
commit 0e0b065dd9
14 changed files with 89 additions and 51 deletions

View File

@@ -1,84 +0,0 @@
import { useState } from "react"
import { useIntl } from "react-intl"
import { ChevronDownIcon } from "@/components/Icons"
import Divider from "@/components/TempDesignSystem/Divider"
import TextArea from "@/components/TempDesignSystem/Form/TextArea"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import styles from "./specialRequests.module.css"
export default function SpecialRequests() {
const [isOpen, setIsOpen] = useState(false)
const intl = useIntl()
function toggleRequests() {
setIsOpen((prevVal) => !prevVal)
}
return (
<div className={styles.requests} data-requests-open={isOpen}>
<button className={styles.toggle} onClick={toggleRequests} type="button">
<Footnote
color="uiTextHighContrast"
textTransform="uppercase"
type="label"
className={styles.header}
textAlign="left"
>
{intl.formatMessage({ id: "Special requests" })}
</Footnote>
<ChevronDownIcon className={styles.chevron} />
<Divider className={styles.divider} color="subtle" />
</button>
<div className={styles.content}>
<div className={styles.contentWrapper}>
{/*
TODO: Hiding because API is not ready for this yet (https://scandichotels.atlassian.net/browse/SW-1497). Add back in when API is ready.
<Select
label={intl.formatMessage({ id: "Floor preference" })}
name="specialRequests.floorPreference"
items={[
noPreferenceItem,
{
value: FloorPreference.HIGH,
label: intl.formatMessage({ id: "High floor" }),
},
{
value: FloorPreference.LOW,
label: intl.formatMessage({ id: "Low floor" }),
},
]}
/>
<Select
label={intl.formatMessage({ id: "Elevator preference" })}
name="specialRequests.elevatorPreference"
items={[
noPreferenceItem,
{
value: ElevatorPreference.AWAY_FROM_ELEVATOR,
label: intl.formatMessage({
id: "Away from elevator",
}),
},
{
value: ElevatorPreference.NEAR_ELEVATOR,
label: intl.formatMessage({
id: "Near elevator",
}),
},
]}
/> */}
<TextArea
label={intl.formatMessage({
id: "Is there anything else you would like us to know before your arrival?",
})}
name="specialRequests.comments"
/>
</div>
</div>
</div>
)
}

View File

@@ -1,55 +0,0 @@
.requests {
--header-height: 50px;
display: grid;
grid-template-rows: var(--header-height) 0fr;
transition: 0.3s ease-out;
grid-column: 1 / -1;
}
.toggle {
display: grid;
grid-template-areas:
"header chevron"
"divider divider";
grid-template-columns: 1fr auto;
background-color: transparent;
gap: var(--Spacing-x1);
border: none;
width: 100%;
cursor: pointer;
margin: var(--Spacing-x2) 0;
}
.header {
grid-area: header;
align-self: flex-start;
}
.chevron {
grid-area: chevron;
}
.divider {
grid-area: divider;
border-top: 1px solid var(--Color-gray-300);
}
.requests[data-requests-open="true"] .chevron {
transform: rotate(180deg);
}
.content {
overflow: hidden;
}
.contentWrapper {
padding-top: var(--Spacing-x3);
display: grid;
gap: var(--Spacing-x2);
width: 100%;
}
.requests[data-requests-open="true"] {
grid-template-rows: var(--header-height) 1fr;
}

View File

@@ -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,
},
},
})

View File

@@ -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,
})