Merged in feat/sw-2857-refactor-booking-flow-url-updates (pull request #2302)
feat(SW-2857): Refactor booking flow url updates * Add support for removing parameters when using initial values in serializeSearchParams * Don't manually write search params in rate store * Booking is already from live search params so no need * Fix input type in serializeBookingSearchParams Approved-by: Linus Flood
This commit is contained in:
@@ -450,6 +450,53 @@ describe("Serialize search params", () => {
|
||||
"city=stockholm&hotel=456&filter[0]=1831&filter[1]=1383&packages=ABC"
|
||||
)
|
||||
})
|
||||
|
||||
test("with initial search params and removing existing parameter", () => {
|
||||
const initialSearchParams = new URLSearchParams(
|
||||
"city=stockholm&hotel=123&filters=123,456,789"
|
||||
)
|
||||
const obj = {
|
||||
hotel: null,
|
||||
filters: ["123", "789"],
|
||||
}
|
||||
const result = serializeSearchParams(obj, {
|
||||
initialSearchParams,
|
||||
typeHints: {
|
||||
filters: "COMMA_SEPARATED_ARRAY",
|
||||
},
|
||||
})
|
||||
|
||||
expect(decodeURIComponent(result.toString())).toEqual(
|
||||
"city=stockholm&filters=123,789"
|
||||
)
|
||||
})
|
||||
|
||||
test("with initial search params and removing values in array", () => {
|
||||
const initialSearchParams = new URLSearchParams(
|
||||
"room[0].adults=1&room[0].rateCode=ABC&room[1].adults=2&room[2].adults=3&room[3].adults=4"
|
||||
)
|
||||
const obj = {
|
||||
room: [
|
||||
{
|
||||
adults: 1,
|
||||
rateCode: null,
|
||||
},
|
||||
{
|
||||
adults: 3,
|
||||
},
|
||||
{
|
||||
adults: 4,
|
||||
},
|
||||
],
|
||||
}
|
||||
const result = serializeSearchParams(obj, {
|
||||
initialSearchParams,
|
||||
})
|
||||
|
||||
expect(decodeURIComponent(result.toString())).toEqual(
|
||||
"room[0].adults=1&room[1].adults=3&room[2].adults=4"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Parse serialized search params", () => {
|
||||
|
||||
@@ -150,7 +150,11 @@ type SerializeOptions = {
|
||||
* @param obj - The object to serialize
|
||||
* @param options.keyRenameMap - Optional mapping of keys to rename, ie { "oldKey": "newKey" }
|
||||
* @param options.typeHints - Optional type hints to force certain keys to be treated as comma separated arrays
|
||||
* @param options.initialSearchParams - Optional initial URL search parameters to merge with the serialized object
|
||||
* @returns URLSearchParams - The serialized URL search parameters
|
||||
*
|
||||
* To force a key to be removed when merging with initialSearchParams, set its value to `null` in the object.
|
||||
* Arrays are not merged, they will always replace existing values.
|
||||
*/
|
||||
export function serializeSearchParams(
|
||||
obj: Record<string, any>,
|
||||
@@ -173,23 +177,31 @@ export function serializeSearchParams(
|
||||
const value = obj[key]
|
||||
|
||||
const renamedKey = keyRenameMap[key] || key
|
||||
const paramKey = prefix ? `${prefix}.${renamedKey}` : renamedKey
|
||||
|
||||
if (value === null) {
|
||||
params.delete(paramKey)
|
||||
continue
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (typeHints[key] === "COMMA_SEPARATED_ARRAY") {
|
||||
const paramKey = prefix ? `${prefix}.${renamedKey}` : renamedKey
|
||||
params.set(paramKey, value.join(","))
|
||||
continue
|
||||
}
|
||||
|
||||
// If an array value already exists (from initialSearchParams),
|
||||
// we need to first remove it since it can't be merged.
|
||||
deleteAllKeysStartingWith(params, renamedKey)
|
||||
value.forEach((item, index) => {
|
||||
const indexedKey = `${renamedKey}[${index}]`
|
||||
const paramKey = prefix ? `${prefix}.${indexedKey}` : indexedKey
|
||||
buildParams(item, paramKey)
|
||||
const arrayKey = prefix ? `${prefix}.${indexedKey}` : indexedKey
|
||||
|
||||
buildParams(item, arrayKey)
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
const paramKey = prefix ? `${prefix}.${renamedKey}` : renamedKey
|
||||
if (typeof value === "object" && value !== null) {
|
||||
buildParams(value, paramKey)
|
||||
continue
|
||||
@@ -207,3 +219,12 @@ export function serializeSearchParams(
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null
|
||||
}
|
||||
|
||||
function deleteAllKeysStartingWith(searchParams: URLSearchParams, key: string) {
|
||||
const keysToDelete = Array.from(searchParams.keys()).filter(
|
||||
(k) => k.startsWith(key) || k === key
|
||||
)
|
||||
for (const k of keysToDelete) {
|
||||
searchParams.delete(k)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +238,11 @@ const reversedKeyRenameMap = Object.fromEntries(
|
||||
Object.entries(keyRenameMap).map(([key, value]) => [value, key])
|
||||
)
|
||||
export function serializeBookingSearchParams(
|
||||
obj: { [key: string]: any },
|
||||
obj:
|
||||
| BookingWidgetSearchData
|
||||
| SelectHotelBooking
|
||||
| SelectRateBooking
|
||||
| DetailsBooking,
|
||||
{ initialSearchParams }: { initialSearchParams?: URLSearchParams } = {}
|
||||
) {
|
||||
return serializeSearchParams(obj, {
|
||||
|
||||
Reference in New Issue
Block a user