Merged in feat/sw-1245-bw-button-update (pull request #2262)
Feat/sw 1245 - Booking widget - change button text when new values * feat(sw-1245) - use isDirty to update button text * Change text only in booking flow * Revert test code Approved-by: Michael Zetterberg
This commit is contained in:
@@ -28,10 +28,14 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
|
|||||||
|
|
||||||
const close = useCallback(() => {
|
const close = useCallback(() => {
|
||||||
if (!selectedDate.toDate) {
|
if (!selectedDate.toDate) {
|
||||||
setValue(name, {
|
setValue(
|
||||||
fromDate: selectedDate.fromDate,
|
name,
|
||||||
toDate: dt(selectedDate.fromDate).add(1, "day").format("YYYY-MM-DD"),
|
{
|
||||||
})
|
fromDate: selectedDate.fromDate,
|
||||||
|
toDate: dt(selectedDate.fromDate).add(1, "day").format("YYYY-MM-DD"),
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsOpen(false)
|
setIsOpen(false)
|
||||||
@@ -54,10 +58,14 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
|
|||||||
// Handle form value updates based on the requirements
|
// Handle form value updates based on the requirements
|
||||||
if (selectedDate.fromDate && selectedDate.toDate) {
|
if (selectedDate.fromDate && selectedDate.toDate) {
|
||||||
// Both dates were previously selected, starting fresh with new date
|
// Both dates were previously selected, starting fresh with new date
|
||||||
setValue(name, {
|
setValue(
|
||||||
fromDate: dateClickedFormatted,
|
name,
|
||||||
toDate: undefined,
|
{
|
||||||
})
|
fromDate: dateClickedFormatted,
|
||||||
|
toDate: undefined,
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
)
|
||||||
} else if (selectedDate.fromDate && !selectedDate.toDate) {
|
} else if (selectedDate.fromDate && !selectedDate.toDate) {
|
||||||
// If the selected day is the same as the first date, we don't need to update the form value
|
// If the selected day is the same as the first date, we don't need to update the form value
|
||||||
if (dateClicked.isSame(selectedDate.fromDate)) {
|
if (dateClicked.isSame(selectedDate.fromDate)) {
|
||||||
@@ -66,16 +74,24 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
|
|||||||
// We're selecting the second date
|
// We're selecting the second date
|
||||||
if (dateClicked.isBefore(selectedDate.fromDate)) {
|
if (dateClicked.isBefore(selectedDate.fromDate)) {
|
||||||
// If second selected date is before first date, swap them
|
// If second selected date is before first date, swap them
|
||||||
setValue(name, {
|
setValue(
|
||||||
fromDate: dateClickedFormatted,
|
name,
|
||||||
toDate: selectedDate.fromDate,
|
{
|
||||||
})
|
fromDate: dateClickedFormatted,
|
||||||
|
toDate: selectedDate.fromDate,
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// If second selected date is after first date, keep order
|
// If second selected date is after first date, keep order
|
||||||
setValue(name, {
|
setValue(
|
||||||
fromDate: selectedDate.fromDate,
|
name,
|
||||||
toDate: dateClickedFormatted,
|
{
|
||||||
})
|
fromDate: selectedDate.fromDate,
|
||||||
|
toDate: dateClickedFormatted,
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,13 +60,18 @@ export default function BookingCode() {
|
|||||||
|
|
||||||
function updateBookingCodeFormValue(value: string) {
|
function updateBookingCodeFormValue(value: string) {
|
||||||
// Set value and show error if validation fails
|
// Set value and show error if validation fails
|
||||||
setValue("bookingCode.value", value.toUpperCase(), { shouldValidate: true })
|
setValue("bookingCode.value", value.toUpperCase(), {
|
||||||
|
shouldValidate: true,
|
||||||
|
shouldDirty: true,
|
||||||
|
})
|
||||||
|
|
||||||
if (getValues(REDEMPTION)) {
|
if (getValues(REDEMPTION)) {
|
||||||
// Remove the redemption as user types booking code and show notification for the same
|
// Remove the redemption as user types booking code and show notification for the same
|
||||||
// Add delay to handle table mode rendering
|
// Add delay to handle table mode rendering
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
setValue(REDEMPTION, false)
|
setValue(REDEMPTION, false, {
|
||||||
|
shouldDirty: true,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
// Hide the above notification popup after 5 seconds by re-triggering validation
|
// Hide the above notification popup after 5 seconds by re-triggering validation
|
||||||
// This is kept consistent with location search field error notification timeout
|
// This is kept consistent with location search field error notification timeout
|
||||||
@@ -87,7 +92,10 @@ export default function BookingCode() {
|
|||||||
) {
|
) {
|
||||||
setShowRemember(false)
|
setShowRemember(false)
|
||||||
if (codeError) {
|
if (codeError) {
|
||||||
setValue("bookingCode.value", "", { shouldValidate: true })
|
setValue("bookingCode.value", "", {
|
||||||
|
shouldValidate: true,
|
||||||
|
shouldDirty: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -306,7 +314,7 @@ export function RemoveExtraRooms({ ...props }: ButtonProps) {
|
|||||||
// Timeout to delay the event scheduling issue with touch events on mobile
|
// Timeout to delay the event scheduling issue with touch events on mobile
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
const rooms = getValues("rooms")[0]
|
const rooms = getValues("rooms")[0]
|
||||||
setValue("rooms", [rooms], { shouldValidate: true })
|
setValue("rooms", [rooms], { shouldValidate: true, shouldDirty: true })
|
||||||
trigger("bookingCode.value")
|
trigger("bookingCode.value")
|
||||||
trigger(REDEMPTION)
|
trigger(REDEMPTION)
|
||||||
}, 300)
|
}, 300)
|
||||||
@@ -357,12 +365,12 @@ function TabletBookingCode({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isOpen && !bookingCode?.value) {
|
if (!isOpen && !bookingCode?.value) {
|
||||||
setValue("bookingCode.flag", false)
|
setValue("bookingCode.flag", false, { shouldDirty: true })
|
||||||
setIsOpen(isOpen)
|
setIsOpen(isOpen)
|
||||||
} else if (!codeError || isOpen) {
|
} else if (!codeError || isOpen) {
|
||||||
setIsOpen(isOpen)
|
setIsOpen(isOpen)
|
||||||
if (isOpen || bookingCode?.value) {
|
if (isOpen || bookingCode?.value) {
|
||||||
setValue("bookingCode.flag", true)
|
setValue("bookingCode.flag", true, { shouldDirty: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -378,7 +386,7 @@ function TabletBookingCode({
|
|||||||
{...register("bookingCode.flag", {
|
{...register("bookingCode.flag", {
|
||||||
onChange: function () {
|
onChange: function () {
|
||||||
if (bookingCode?.value || isOpen) {
|
if (bookingCode?.value || isOpen) {
|
||||||
setValue("bookingCode.flag", true)
|
setValue("bookingCode.flag", true, { shouldDirty: true })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { usePathname } from "next/navigation"
|
||||||
import { useFormContext, useWatch } from "react-hook-form"
|
import { useFormContext, useWatch } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
|
import { hotelreservation } from "@/constants/routes/hotelReservation"
|
||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
import DatePicker from "@/components/DatePicker"
|
import DatePicker from "@/components/DatePicker"
|
||||||
import GuestsRoomsPickerForm from "@/components/GuestsRoomsPicker"
|
import GuestsRoomsPickerForm from "@/components/GuestsRoomsPicker"
|
||||||
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
import { RemoveExtraRooms } from "./BookingCode"
|
import { RemoveExtraRooms } from "./BookingCode"
|
||||||
import { Search, SearchSkeleton } from "./Search"
|
import { Search, SearchSkeleton } from "./Search"
|
||||||
@@ -30,9 +33,13 @@ export default function FormContent({
|
|||||||
}: BookingWidgetFormContentProps) {
|
}: BookingWidgetFormContentProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const {
|
const {
|
||||||
formState: { errors },
|
formState: { errors, isDirty },
|
||||||
} = useFormContext<BookingWidgetSchema>()
|
} = useFormContext<BookingWidgetSchema>()
|
||||||
|
|
||||||
|
const lang = useLang()
|
||||||
|
const pathName = usePathname()
|
||||||
|
const isBookingFlow = pathName.includes(hotelreservation(lang))
|
||||||
|
|
||||||
const selectedDate = useWatch<BookingWidgetSchema, "date">({ name: "date" })
|
const selectedDate = useWatch<BookingWidgetSchema, "date">({ name: "date" })
|
||||||
|
|
||||||
const nights = dt(selectedDate.toDate).diff(dt(selectedDate.fromDate), "days")
|
const nights = dt(selectedDate.toDate).diff(dt(selectedDate.fromDate), "days")
|
||||||
@@ -121,9 +128,9 @@ export default function FormContent({
|
|||||||
className={styles.buttonText}
|
className={styles.buttonText}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
{intl.formatMessage({
|
{isDirty && isBookingFlow
|
||||||
defaultMessage: "Search",
|
? intl.formatMessage({ defaultMessage: "Update" })
|
||||||
})}
|
: intl.formatMessage({ defaultMessage: "Search" })}
|
||||||
</span>
|
</span>
|
||||||
</Typography>
|
</Typography>
|
||||||
<span className={styles.icon}>
|
<span className={styles.icon}>
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ export default function Form({ type, onClose }: BookingWidgetFormProps) {
|
|||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { handleSubmit, setValue } = useFormContext<BookingWidgetSchema>()
|
const { handleSubmit, setValue, reset } =
|
||||||
|
useFormContext<BookingWidgetSchema>()
|
||||||
|
|
||||||
function onSubmit(data: BookingWidgetSchema) {
|
function onSubmit(data: BookingWidgetSchema) {
|
||||||
const bookingFlowPage = data.hotel ? selectRate(lang) : selectHotel(lang)
|
const bookingFlowPage = data.hotel ? selectRate(lang) : selectHotel(lang)
|
||||||
@@ -54,11 +55,14 @@ export default function Form({ type, onClose }: BookingWidgetFormProps) {
|
|||||||
router.push(`${bookingFlowPage}?${bookingWidgetParams.toString()}`)
|
router.push(`${bookingFlowPage}?${bookingWidgetParams.toString()}`)
|
||||||
})
|
})
|
||||||
if (!data.bookingCode?.value) {
|
if (!data.bookingCode?.value) {
|
||||||
setValue("bookingCode.remember", false)
|
setValue("bookingCode.remember", false, {
|
||||||
|
shouldDirty: true,
|
||||||
|
})
|
||||||
localStorage.removeItem("bookingCode")
|
localStorage.removeItem("bookingCode")
|
||||||
} else if (data.bookingCode?.remember) {
|
} else if (data.bookingCode?.remember) {
|
||||||
localStorage.setItem("bookingCode", JSON.stringify(data.bookingCode))
|
localStorage.setItem("bookingCode", JSON.stringify(data.bookingCode))
|
||||||
}
|
}
|
||||||
|
reset(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ export default function AdultSelector({
|
|||||||
|
|
||||||
function increaseAdultsCount() {
|
function increaseAdultsCount() {
|
||||||
if (currentAdults < 6) {
|
if (currentAdults < 6) {
|
||||||
setValue(name, currentAdults + 1)
|
setValue(name, currentAdults + 1, { shouldDirty: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decreaseAdultsCount() {
|
function decreaseAdultsCount() {
|
||||||
if (currentAdults > 1) {
|
if (currentAdults > 1) {
|
||||||
setValue(name, currentAdults - 1)
|
setValue(name, currentAdults - 1, { shouldDirty: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,16 +26,22 @@ export default function ChildSelector({
|
|||||||
|
|
||||||
function increaseChildrenCount(roomIndex: number) {
|
function increaseChildrenCount(roomIndex: number) {
|
||||||
if (currentChildren.length < 5) {
|
if (currentChildren.length < 5) {
|
||||||
setValue(`rooms.${roomIndex}.childrenInRoom.${currentChildren.length}`, {
|
setValue(
|
||||||
age: undefined,
|
`rooms.${roomIndex}.childrenInRoom.${currentChildren.length}`,
|
||||||
bed: undefined,
|
{
|
||||||
})
|
age: undefined,
|
||||||
|
bed: undefined,
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function decreaseChildrenCount(roomIndex: number) {
|
function decreaseChildrenCount(roomIndex: number) {
|
||||||
if (currentChildren.length > 0) {
|
if (currentChildren.length > 0) {
|
||||||
currentChildren.pop()
|
currentChildren.pop()
|
||||||
setValue(`rooms.${roomIndex}.childrenInRoom`, currentChildren)
|
setValue(`rooms.${roomIndex}.childrenInRoom`, currentChildren, {
|
||||||
|
shouldDirty: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export default function GuestsRoomsPickerDialog({
|
|||||||
const handleAddRoom = useCallback(() => {
|
const handleAddRoom = useCallback(() => {
|
||||||
setValue("rooms", [...roomsValue, { adults: 1, childrenInRoom: [] }], {
|
setValue("rooms", [...roomsValue, { adults: 1, childrenInRoom: [] }], {
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
|
shouldDirty: true,
|
||||||
})
|
})
|
||||||
}, [roomsValue, setValue])
|
}, [roomsValue, setValue])
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ export default function GuestsRoomsPickerDialog({
|
|||||||
setValue(
|
setValue(
|
||||||
"rooms",
|
"rooms",
|
||||||
roomsValue.filter((_, i) => i !== index),
|
roomsValue.filter((_, i) => i !== index),
|
||||||
{ shouldValidate: true }
|
{ shouldValidate: true, shouldDirty: true }
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[roomsValue, setValue]
|
[roomsValue, setValue]
|
||||||
|
|||||||
Reference in New Issue
Block a user