Files
web/components/Forms/BookingWidget/FormContent/index.tsx
Linus Flood ebb007b7f0 Merged in feat/booking-flow-performance (pull request #1282)
feat: booking flow performance

* feat: booking flow performance

* Cleanup


Approved-by: Michael Zetterberg
Approved-by: Pontus Dreij
2025-02-08 10:40:42 +00:00

160 lines
4.7 KiB
TypeScript

"use client"
import { useWatch } from "react-hook-form"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import DatePicker from "@/components/DatePicker"
import GuestsRoomsPickerForm from "@/components/GuestsRoomsPicker"
import { SearchIcon } from "@/components/Icons"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import Button from "@/components/TempDesignSystem/Button"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Search, { SearchSkeleton } from "./Search"
import Voucher, { VoucherSkeleton } from "./Voucher"
import styles from "./formContent.module.css"
import type { BookingWidgetFormContentProps } from "@/types/components/form/bookingwidget"
export default function FormContent({
locations,
formId,
onSubmit,
isSearching,
}: BookingWidgetFormContentProps) {
const intl = useIntl()
const selectedDate = useWatch({ name: "date" })
const roomsLabel = intl.formatMessage({ id: "Rooms & Guests" })
const nights = dt(selectedDate.toDate).diff(dt(selectedDate.fromDate), "days")
return (
<>
<div className={styles.input}>
<div className={styles.inputContainer}>
<div className={styles.where}>
<Search locations={locations} handlePressEnter={onSubmit} />
</div>
<div className={styles.when}>
<Caption color="red" type="bold">
{nights > 0
? intl.formatMessage(
{
id: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights: nights }
)
: intl.formatMessage({
id: "Check in",
})}
</Caption>
<DatePicker />
</div>
<div className={styles.rooms}>
<label>
<Caption color="red" type="bold" asChild>
<span>{roomsLabel}</span>
</Caption>
</label>
<GuestsRoomsPickerForm />
</div>
</div>
<div className={`${styles.buttonContainer} ${styles.showOnTablet}`}>
<Button
className={styles.button}
form={formId}
intent="primary"
theme="base"
type="submit"
>
<span className={styles.icon}>
<SearchIcon color="white" width={28} height={28} />
</span>
</Button>
</div>
<div className={`${styles.voucherContainer} ${styles.voucherRow}`}>
<Voucher />
</div>
<div className={`${styles.buttonContainer} ${styles.hideOnTablet}`}>
<Button
className={styles.button}
form={formId}
intent="primary"
theme="base"
type="submit"
disabled={isSearching}
>
<Caption
color="white"
type="bold"
className={styles.buttonText}
asChild
>
<span>{intl.formatMessage({ id: "Search" })}</span>
</Caption>
<span className={styles.icon}>
<SearchIcon color="white" width={28} height={28} />
</span>
</Button>
</div>
</div>
</>
)
}
export function BookingWidgetFormContentSkeleton() {
const intl = useIntl()
return (
<div className={styles.input}>
<div className={styles.inputContainer}>
<div className={styles.where}>
<SearchSkeleton />
</div>
<div className={styles.when}>
<Caption color="red" type="bold">
{intl.formatMessage(
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
{ totalNights: 0 }
)}
</Caption>
<SkeletonShimmer width={"100%"} />
</div>
<div className={styles.rooms}>
<Caption color="red" type="bold" asChild>
<span>{intl.formatMessage({ id: "Rooms & Guests" })}</span>
</Caption>
<SkeletonShimmer width={"100%"} />
</div>
</div>
<div className={styles.voucherContainer}>
<VoucherSkeleton />
</div>
<div className={styles.buttonContainer}>
<Button
className={styles.button}
intent="primary"
theme="base"
type="submit"
disabled
>
<Caption
color="white"
type="bold"
className={styles.buttonText}
asChild
>
<span>{intl.formatMessage({ id: "Search" })}</span>
</Caption>
<span className={styles.icon}>
<SearchIcon color="white" width={28} height={28} />
</span>
</Button>
</div>
</div>
)
}