Merged in feat/sw-2879-booking-widget-to-booking-flow-package (pull request #2532)
feat(SW-2879): Move BookingWidget to booking-flow package * Fix lockfile * Fix styling * a tiny little booking widget test * Tiny fixes * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package * Remove unused scripts * lint:fix * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package * Tiny lint fixes * update test * Update Input in booking-flow * Clean up comments etc * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package * Setup tracking context for booking-flow * Add missing use client * Fix temp tracking function * Pass booking to booking-widget * Remove comment * Add use client to booking widget tracking provider * Add use client to tracking functions * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package * Move debug page * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package * Merge branch 'master' into feat/sw-2879-booking-widget-to-booking-flow-package Approved-by: Bianca Widstam
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { logger } from "@scandic-hotels/common/logger"
|
||||
|
||||
import { bookingWidgetErrors } from "../BookingWidget/BookingWidgetForm/schema"
|
||||
|
||||
import type { IntlShape } from "react-intl"
|
||||
|
||||
export function getErrorMessage(intl: IntlShape, errorCode?: string) {
|
||||
switch (errorCode) {
|
||||
case bookingWidgetErrors.BOOKING_CODE_INVALID:
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Booking code is invalid",
|
||||
})
|
||||
case bookingWidgetErrors.AGE_REQUIRED:
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Age is required",
|
||||
})
|
||||
case bookingWidgetErrors.BED_CHOICE_REQUIRED:
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Bed choice is required",
|
||||
})
|
||||
case bookingWidgetErrors.CHILDREN_EXCEEDS_ADULTS:
|
||||
return intl.formatMessage({
|
||||
defaultMessage:
|
||||
"You cannot have more children in adults bed than adults in the room",
|
||||
})
|
||||
case bookingWidgetErrors.REQUIRED:
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Required",
|
||||
})
|
||||
case bookingWidgetErrors.DESTINATION_REQUIRED:
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Destination required",
|
||||
})
|
||||
case bookingWidgetErrors.MULTIROOM_BOOKING_CODE_UNAVAILABLE:
|
||||
return intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Multi-room booking is not available with this booking code.",
|
||||
})
|
||||
case bookingWidgetErrors.MULTIROOM_REWARD_NIGHT_UNAVAILABLE:
|
||||
return intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Multi-room booking is not available with reward night.",
|
||||
})
|
||||
case bookingWidgetErrors.CODE_VOUCHER_REWARD_NIGHT_UNAVAILABLE:
|
||||
return intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Reward nights can't be combined with codes or vouchers.",
|
||||
})
|
||||
default:
|
||||
logger.warn("Error code not supported:", errorCode)
|
||||
return errorCode
|
||||
}
|
||||
}
|
||||
109
packages/booking-flow/lib/components/BookingFlowInput/index.tsx
Normal file
109
packages/booking-flow/lib/components/BookingFlowInput/index.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
"use client"
|
||||
|
||||
// This is almost a copy of the Input in TempDesignSystem, but since it's tightly coupled
|
||||
// to the error messages we need to duplicate it for now. In the future we should
|
||||
// rewrite it to be more reusable.
|
||||
|
||||
import { forwardRef } from "react"
|
||||
import { Text, TextField } from "react-aria-components"
|
||||
import {
|
||||
Controller,
|
||||
type RegisterOptions,
|
||||
useFormContext,
|
||||
} from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Caption from "@scandic-hotels/design-system/Caption"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Input as InputWithLabel } from "@scandic-hotels/design-system/Input"
|
||||
|
||||
import { getErrorMessage } from "./errors"
|
||||
|
||||
import styles from "./input.module.css"
|
||||
|
||||
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
helpText?: string
|
||||
label: string
|
||||
name: string
|
||||
registerOptions?: RegisterOptions
|
||||
hideError?: boolean
|
||||
}
|
||||
|
||||
const BookingFlowInput = forwardRef<HTMLInputElement, InputProps>(
|
||||
function Input(
|
||||
{
|
||||
"aria-label": ariaLabel,
|
||||
autoComplete,
|
||||
className = "",
|
||||
disabled = false,
|
||||
helpText = "",
|
||||
label,
|
||||
maxLength,
|
||||
name,
|
||||
placeholder,
|
||||
readOnly = false,
|
||||
registerOptions = {},
|
||||
type = "text",
|
||||
hideError,
|
||||
inputMode,
|
||||
},
|
||||
ref
|
||||
) {
|
||||
const intl = useIntl()
|
||||
const { control } = useFormContext()
|
||||
|
||||
return (
|
||||
<Controller
|
||||
disabled={disabled}
|
||||
control={control}
|
||||
name={name}
|
||||
rules={registerOptions}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
aria-label={ariaLabel}
|
||||
className={className}
|
||||
isDisabled={field.disabled}
|
||||
isInvalid={fieldState.invalid}
|
||||
isRequired={!!registerOptions.required}
|
||||
name={field.name}
|
||||
onBlur={field.onBlur}
|
||||
onChange={field.onChange}
|
||||
validationBehavior="aria"
|
||||
value={field.value}
|
||||
>
|
||||
<InputWithLabel
|
||||
{...field}
|
||||
ref={ref}
|
||||
aria-labelledby={field.name}
|
||||
autoComplete={autoComplete}
|
||||
id={field.name}
|
||||
label={label}
|
||||
maxLength={maxLength}
|
||||
placeholder={placeholder}
|
||||
readOnly={readOnly}
|
||||
required={!!registerOptions.required}
|
||||
type={type}
|
||||
inputMode={inputMode}
|
||||
/>
|
||||
{helpText && !fieldState.error ? (
|
||||
<Caption asChild color="black">
|
||||
<Text className={styles.helpText} slot="description">
|
||||
<MaterialIcon icon="check" size={20} />
|
||||
{helpText}
|
||||
</Text>
|
||||
</Caption>
|
||||
) : null}
|
||||
{fieldState.error && !hideError ? (
|
||||
<Caption className={styles.error} fontOnly>
|
||||
<MaterialIcon icon="info" color="Icon/Feedback/Error" />
|
||||
{getErrorMessage(intl, fieldState.error.message)}
|
||||
</Caption>
|
||||
) : null}
|
||||
</TextField>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default BookingFlowInput
|
||||
@@ -0,0 +1,17 @@
|
||||
.helpText {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
.error {
|
||||
align-items: center;
|
||||
color: var(--Text-Interactive-Error);
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
margin: var(--Space-x1) 0 0;
|
||||
}
|
||||
|
||||
.error svg {
|
||||
min-width: 20px;
|
||||
}
|
||||
Reference in New Issue
Block a user