Merged in feature/simple-sas-book-url (pull request #3082)

feature(SAS): add simple url for entering the booking flow /[lang]/book-hotel/[city]

* Merged in fix/book-115-hidden-focus-indicators (pull request #2925)

Fix/book 115 hidden focus indicators

* added focus ring to "how it works" text and close button in modal

* fix(BOOK-115): added focus ring to Hotel Sidepeek close button

* fix(BOOK-115): enabled selecting ancillaries with keyboard nav

* fix(BOOK-115): added focus indicator to "View and print receipt" in Manage Stay

* fix(BOOK-105 & BOOK-115): combined the two radio groups in payment selection to one, fixes focus indicator issue

* fix(BOOK-115): added focus indicator to shortcut links

* fix(BOOK-115): updated ancillaries keyboard selection

* fix(BOOK-115): removed tabIndex from Link component

* fix(BOOK-115): fixed single payment radio button not focusable

* fix(BOOK-115): updated  to onKeyDown

* added id to "credit card"

* removed toUpperCase() on lables

* removed brackets

* moved the focus indicator to the DS Button component

* removed !important from ButtonLink css

* changed <label> to <fieldset> and <legend> and added aria…
* Merged in feat/sw-3596-console (pull request #3100)

feat(SW-3596): added lint rule for no console.log. Use logger instead.

* feat(SW-3596): added lint rule for no console.log. Use logger instead.


Approved-by: Joakim Jäderberg

* Merged in fix/BOOK-457-select-rate-lowestroomprice- (pull request #3061)

* Fix(BOOK-457): Reduced lowestRoomPrice tracking call from multiple times to one

* fix(BOOK-457): feat(SW-3590): Included RoomsLoadedEvent on select-rate page

Approved-by: Linus Flood

* Merged in feature/SW-3506-refresh-tokens (pull request #3064)

feature(SW-3506): refresh-tokens setup for SAS Eurobonus

* feature(SW-3506): refresh-tokens setup for SAS Eurobonus

* Merge branch 'master' of bitbucket.org:scandic-swap/web into feature/SW-3506-refresh-tokens


Approved-by: Anton Gunnarsson

* Merged in feat/BOOK-434-users-should-redirect-to- (pull request #3087)

* feat(BOOK-434): Redirect user to city/country page if wrong filter url
* feat(BOOK-434): Handled map view

Approved-by: Erik Tiekstra

* Merged in fix/SW-3553-logged-in-details- (pull request #3073)

* fix(SW-3553): Fixed screen scolled & locked on click of menu

Approved-by: Joakim Jäderberg

* Merged in feat/book-522-align (pull request #3101)

feat(BOOK-522): align items in topmenu, header and booking widget

* feat(BOOK-522): align items in topmenu, header and booking widget

* Delete old css variable and use new

* Fixed underline on icons


Approved-by: Erik Tiekstra

* Merged in fix/LOY-444-points-to-keep-left-text (pull request #3086)

fix(LOY-444): fix markerLabel text when left aligned

* fix(LOY-444): fix markerLabel text when left aligned


Approved-by: Matilda Landström

* Merged in chore/replace-graphql-tag/loader (pull request #3096)

Use turbopack for dev builds.
Remove graphql-tag/loader, replaced by gql`` tag literals instead.



Approved-by: Linus Flood

* Merged in fix/system-fragment (pull request #3102)

fix: faulty system fragment

* fix: faulty system fragment


Approved-by: Linus Flood

* fix(BOOK-498): removed and changed z-index values to have booking widget overlapping correctly on mobile.

Approved-by: Bianca Widstam
Approved-by: Hrishikesh Vaipurkar

* Merged in revert-gql (pull request #3104)

Revert gql

* Revert "Merged in fix/system-fragment (pull request #3102)"

This reverts commit 0d479eb337.

* Revert "Merged in chore/replace-graphql-tag/loader (pull request #3096)"

This reverts commit e9bd159e98.

* Merged in fix/BOOK-438-breadcrumbs-seo-filter (pull request #3103)

feat(BOOK-438): add breadcrumbs on seofilter pages

* feat(BOOK-438): add breadcrumbs on seofilter pages

* feat(BOOK-438): remove unused function


Approved-by: Hrishikesh Vaipurkar

* Merged in chore/regular-price-tests (pull request #3075)

chore: Add tests for regular price calculations

* Add tests for calculateRegularPrice

* Add tests for getRegularPrice

* Add multiroom test


Approved-by: Joakim Jäderberg
Approved-by: Linus Flood

* Merged in fix/wrap-webviews-with-sessionprovider (pull request #3111)

Wrap webviews with SessionProvider

* wrap webviews with sessionprovider


Approved-by: Linus Flood

* feat(BOOK-488): Trimming booking code before validating

Approved-by: Bianca Widstam

* feat(BOOK-472): Different placement of no availability alert on mobile viewports

Approved-by: Bianca Widstam

* Merged in feat/sw-3601-hookfix (pull request #3113)

Feat(SW-3601): useIsUserLoggedIn needs to check webview token 

* fix(SW-3601): useIsUserLoggedIn needs to check webview token

* Check if we have webview token as well

* .


Approved-by: Joakim Jäderberg

* Merged in fix/add-missing-partner-data (pull request #3116)

fix: Add param to getScandicUser for extended data

* Add param to getScandicUser for extended data


Approved-by: Linus Flood

* Merged in feat/sw-3596-cache (pull request #3106)

feat(SW-3598): Don't call redis api if cachetime=0

* feat(SW-3596): no cache if ttl=0

* Fixed on set as well

* No cache if redemption

* Revert no cache if redemption


Approved-by: Joakim Jäderberg

* feat(BOOK-212): Refactored LoginButton and added successful tracking functionality

Approved-by: Linus Flood

* Merged in fix/document-undefined (pull request #3118)

Fix/document undefined

* fix: check if document is undefined

* fix: check if document is undefined


Approved-by: Linus Flood

* Merged in feat/sw-3604-webviews (pull request #3123)

feat(SW-3604): wrap mystay with bookingflowconfig

* feat(SW-3604): wrap mystay with bookingflowconfig


Approved-by: Joakim Jäderberg

* Merged in feature/turbopack (pull request #3117)

Feature/turbopack

* .

* .

* pin import-in-the-middle

* update marker

* revert back to using *.graphql.ts


Approved-by: Linus Flood

* Merge branch 'master' of bitbucket.org:scandic-swap/web into feature/simple-sas-book-url
This commit is contained in:
Joakim Jäderberg
2025-11-13 13:01:26 +00:00
parent 5eca2e5d20
commit aca2c1d60c

View File

@@ -0,0 +1,102 @@
import { type NextRequest, NextResponse } from "next/server"
import { z } from "zod"
import { serializeBookingSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { Lang } from "@scandic-hotels/common/constants/language"
import { selectHotel } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { dt } from "@scandic-hotels/common/dt"
import { languageSchema } from "@scandic-hotels/common/utils/languages"
import { equalsIgnoreCaseAndAccents } from "@scandic-hotels/common/utils/stringEquals"
import { env } from "@/env/server"
import { serverClient } from "@/lib/trpc"
const schema = z.object({
city: z.string().catch(() => ""),
lang: languageSchema,
adults: z
.number()
.default(1)
.transform((val) => Math.max(1, Math.min(6, val)))
.catch(() => 1),
fromDate: z
.string()
.date()
.transform((val) => {
const dtVal = dt.utc(val)
if (dtVal.isBefore(dt.utc().startOf("day"))) {
return dt.utc().startOf("day")
}
return dtVal
})
.catch(() => dt.utc().startOf("day")),
toDate: z
.string()
.date()
.transform((val) => dt.utc(val))
.optional()
.catch(() => undefined),
})
export async function GET(
request: NextRequest,
{
params,
}: {
params: Promise<{ city: string; lang: string }>
}
) {
const p = await params
const { data: lang } = languageSchema.safeParse(p.lang) // Validate lang param
const { searchParams } = request.nextUrl
const result = schema.safeParse({
city: p.city,
lang: lang ?? Lang.en,
adults: searchParams.get("adults")
? Number(searchParams.get("adults"))
: undefined,
fromDate: searchParams.get("fromDate") || "",
toDate: searchParams.get("toDate") || undefined,
})
if (result.success === false) {
return NextResponse.redirect(new URL(`/${lang || Lang.en}`, env.PUBLIC_URL))
}
if (
!result.data.toDate ||
!result.data.toDate.isAfter(result.data.fromDate)
) {
result.data.toDate = result.data.fromDate.add(1, "day")
}
const client = await serverClient()
const locations = await client.hotel.locations.get({ lang: Lang.en })
const cityData = locations
.filter((loc) => loc.type === "cities")
.find((loc) => equalsIgnoreCaseAndAccents(loc.name, result.data.city))
if (!cityData?.cityIdentifier) {
return NextResponse.redirect(new URL(`/${lang || Lang.en}`, env.PUBLIC_URL))
}
const url = new URL(
`${selectHotel(lang || Lang.en)}?${serializeBookingSearchParams({
city: cityData.cityIdentifier,
fromDate: result.data.fromDate.format("YYYY-MM-DD"),
toDate: result.data.toDate.format("YYYY-MM-DD"),
rooms: [
{
adults: result.data.adults,
},
],
})}`,
env.PUBLIC_URL
)
return NextResponse.redirect(url)
}