Merged in fix/SW-2501-validation-trigger (pull request #1924)
fix(SW-2501): validation trigger * fix(SW-2501): validation trigger On enter details, when submitting we want to trigger the validation for the details forms for each room. This will display error messages for the form fields with errors if they are not already displayed, so the user knows which fields has errors. Approved-by: Tobias Johansson
This commit is contained in:
@@ -24,7 +24,8 @@ const formID = "enter-details"
|
|||||||
export default function Details() {
|
export default function Details() {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
const { rooms } = useEnterDetailsStore((state) => ({
|
const { addPreSubmitCallback, rooms } = useEnterDetailsStore((state) => ({
|
||||||
|
addPreSubmitCallback: state.actions.addPreSubmitCallback,
|
||||||
rooms: state.rooms,
|
rooms: state.rooms,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -71,13 +72,23 @@ export default function Details() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
formState: { isValid },
|
||||||
|
handleSubmit,
|
||||||
|
trigger,
|
||||||
|
} = methods
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
addPreSubmitCallback(`${idx}-details`, trigger)
|
||||||
|
}, [addPreSubmitCallback, idx, trigger])
|
||||||
|
|
||||||
const updateDetailsStore = useCallback(() => {
|
const updateDetailsStore = useCallback(() => {
|
||||||
if (methods.formState.isValid) {
|
if (isValid) {
|
||||||
methods.handleSubmit(updateDetails)()
|
handleSubmit(updateDetails)()
|
||||||
} else {
|
} else {
|
||||||
setIncomplete()
|
setIncomplete()
|
||||||
}
|
}
|
||||||
}, [methods, setIncomplete, updateDetails])
|
}, [handleSubmit, isValid, setIncomplete, updateDetails])
|
||||||
|
|
||||||
useEffect(updateDetailsStore, [methods.formState.isValid, updateDetailsStore])
|
useEffect(updateDetailsStore, [methods.formState.isValid, updateDetailsStore])
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { useCallback, useEffect } from "react"
|
|||||||
import { FormProvider, useForm } from "react-hook-form"
|
import { FormProvider, useForm } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
import SpecialRequests from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests"
|
import SpecialRequests from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests"
|
||||||
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
import CountrySelect from "@/components/TempDesignSystem/Form/Country"
|
||||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||||
@@ -27,10 +29,15 @@ const formID = "enter-details"
|
|||||||
export default function Details({ user }: DetailsProps) {
|
export default function Details({ user }: DetailsProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
|
const { addPreSubmitCallback } = useEnterDetailsStore((state) => ({
|
||||||
|
addPreSubmitCallback: state.actions.addPreSubmitCallback,
|
||||||
|
}))
|
||||||
|
|
||||||
const {
|
const {
|
||||||
actions: { updateDetails, setIncomplete },
|
actions: { updateDetails, setIncomplete },
|
||||||
room,
|
room,
|
||||||
roomNr,
|
roomNr,
|
||||||
|
idx,
|
||||||
} = useRoomContext()
|
} = useRoomContext()
|
||||||
const initialData = room.guest
|
const initialData = room.guest
|
||||||
|
|
||||||
@@ -58,6 +65,16 @@ export default function Details({ user }: DetailsProps) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
formState: { isValid },
|
||||||
|
handleSubmit,
|
||||||
|
trigger,
|
||||||
|
} = methods
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
addPreSubmitCallback(`${idx}-details`, trigger)
|
||||||
|
}, [addPreSubmitCallback, idx, trigger])
|
||||||
|
|
||||||
const onSubmit = useCallback(
|
const onSubmit = useCallback(
|
||||||
(values: DetailsSchema) => {
|
(values: DetailsSchema) => {
|
||||||
updateDetails(values)
|
updateDetails(values)
|
||||||
@@ -66,12 +83,12 @@ export default function Details({ user }: DetailsProps) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const updateDetailsStore = useCallback(() => {
|
const updateDetailsStore = useCallback(() => {
|
||||||
if (methods.formState.isValid) {
|
if (isValid) {
|
||||||
methods.handleSubmit(onSubmit)()
|
handleSubmit(onSubmit)()
|
||||||
} else {
|
} else {
|
||||||
setIncomplete()
|
setIncomplete()
|
||||||
}
|
}
|
||||||
}, [methods, onSubmit, setIncomplete])
|
}, [handleSubmit, isValid, onSubmit, setIncomplete])
|
||||||
|
|
||||||
useEffect(updateDetailsStore, [methods.formState.isValid, updateDetailsStore])
|
useEffect(updateDetailsStore, [methods.formState.isValid, updateDetailsStore])
|
||||||
|
|
||||||
|
|||||||
@@ -76,11 +76,13 @@ export default function PaymentClient({
|
|||||||
|
|
||||||
const [showBookingAlert, setShowBookingAlert] = useState(false)
|
const [showBookingAlert, setShowBookingAlert] = useState(false)
|
||||||
|
|
||||||
const { booking, rooms, totalPrice } = useEnterDetailsStore((state) => ({
|
const { booking, rooms, totalPrice, preSubmitCallbacks } =
|
||||||
booking: state.booking,
|
useEnterDetailsStore((state) => ({
|
||||||
rooms: state.rooms,
|
booking: state.booking,
|
||||||
totalPrice: state.totalPrice,
|
rooms: state.rooms,
|
||||||
}))
|
totalPrice: state.totalPrice,
|
||||||
|
preSubmitCallbacks: state.preSubmitCallbacks,
|
||||||
|
}))
|
||||||
|
|
||||||
const bookingMustBeGuaranteed = rooms.some(({ room }, idx) => {
|
const bookingMustBeGuaranteed = rooms.some(({ room }, idx) => {
|
||||||
if (idx === 0 && isUserLoggedIn && room.memberMustBeGuaranteed) {
|
if (idx === 0 && isUserLoggedIn && room.memberMustBeGuaranteed) {
|
||||||
@@ -282,6 +284,9 @@ export default function PaymentClient({
|
|||||||
|
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(data: PaymentFormData) => {
|
(data: PaymentFormData) => {
|
||||||
|
Object.values(preSubmitCallbacks).forEach((callback) => {
|
||||||
|
callback()
|
||||||
|
})
|
||||||
const firstIncompleteRoomIndex = rooms.findIndex(
|
const firstIncompleteRoomIndex = rooms.findIndex(
|
||||||
(room) => !room.isComplete
|
(room) => !room.isComplete
|
||||||
)
|
)
|
||||||
@@ -445,10 +450,11 @@ export default function PaymentClient({
|
|||||||
fromDate,
|
fromDate,
|
||||||
toDate,
|
toDate,
|
||||||
rooms,
|
rooms,
|
||||||
booking,
|
booking.rooms,
|
||||||
getPaymentMethod,
|
getPaymentMethod,
|
||||||
hasOnlyFlexRates,
|
hasOnlyFlexRates,
|
||||||
bookingMustBeGuaranteed,
|
bookingMustBeGuaranteed,
|
||||||
|
preSubmitCallbacks,
|
||||||
isUserLoggedIn,
|
isUserLoggedIn,
|
||||||
getTopOffset,
|
getTopOffset,
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -355,6 +355,7 @@ export function createDetailsStore(
|
|||||||
searchParamString: searchParams,
|
searchParamString: searchParams,
|
||||||
totalPrice: initialTotalPrice,
|
totalPrice: initialTotalPrice,
|
||||||
vat: initialState.vat,
|
vat: initialState.vat,
|
||||||
|
preSubmitCallbacks: {},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
setIsSubmittingDisabled(isSubmittingDisabled) {
|
setIsSubmittingDisabled(isSubmittingDisabled) {
|
||||||
@@ -386,6 +387,13 @@ export function createDetailsStore(
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
addPreSubmitCallback(name, callback) {
|
||||||
|
return set(
|
||||||
|
produce((state: DetailsState) => {
|
||||||
|
state.preSubmitCallbacks[name] = callback
|
||||||
|
})
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export interface DetailsState {
|
|||||||
setTotalPrice: (totalPrice: Price) => void
|
setTotalPrice: (totalPrice: Price) => void
|
||||||
toggleSummaryOpen: () => void
|
toggleSummaryOpen: () => void
|
||||||
updateSeachParamString: (searchParamString: string) => void
|
updateSeachParamString: (searchParamString: string) => void
|
||||||
|
addPreSubmitCallback: (name: string, callback: () => void) => void
|
||||||
}
|
}
|
||||||
booking: SelectRateSearchParams
|
booking: SelectRateSearchParams
|
||||||
breakfastPackages: BreakfastPackages
|
breakfastPackages: BreakfastPackages
|
||||||
@@ -98,6 +99,7 @@ export interface DetailsState {
|
|||||||
searchParamString: string
|
searchParamString: string
|
||||||
totalPrice: Price
|
totalPrice: Price
|
||||||
vat: number
|
vat: number
|
||||||
|
preSubmitCallbacks: Record<string, () => void>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PersistedState = {
|
export type PersistedState = {
|
||||||
|
|||||||
Reference in New Issue
Block a user