Merged in chore/upgrade-next (pull request #3124)

Upgrade next@15.5.6

* chore: upgrade next@15.5.6

* chore: upgrade turborepo@2.6.1

* fix typings for scandic-web

* fix: set correct type for pages

* cleanup

* fix more route.ts typing issues

* Merge branch 'master' of bitbucket.org:scandic-swap/web into chore/upgrade-next

* explicitly import the types


Approved-by: Linus Flood
This commit is contained in:
Joakim Jäderberg
2025-11-13 07:33:56 +00:00
parent ce469bc4b4
commit dc53ab9245
64 changed files with 746 additions and 404 deletions

View File

@@ -25,7 +25,7 @@ const tokenResponseSchema = z.object({
export async function GET(
request: NextRequest,
props: { params: Promise<{ lang: string }> }
props: RouteContext<"/[lang]/sas-x-scandic/callback">
) {
const params = await props.params
const { lang } = params

View File

@@ -10,11 +10,8 @@ import { TooManyCodesError } from "../components/TooManyCodesError"
import { TooManyFailedAttemptsError } from "../components/TooManyFailedAttemptsError"
import { UnlinkError } from "../components/UnlinkError"
import type { LangParams, PageArgs, SearchParams } from "@/types/params"
export default async function Page(
props: PageArgs<LangParams> &
SearchParams<{ errorCode?: "dateOfBirthMismatch" }>
props: PageProps<"/[lang]/sas-x-scandic/error">
) {
const searchParams = await props.searchParams
const intl = await getIntl()

View File

@@ -9,14 +9,13 @@ import background from "@/public/_static/img/partner/sas/sas_x_scandic_airplane_
import styles from "./layout.module.css"
import type { PropsWithChildren } from "react"
import type { LangParams, LayoutArgs } from "@/types/params"
import type { Lang } from "@scandic-hotels/common/constants/language"
export default async function SasXScandicLayout(
props: PropsWithChildren<LayoutArgs<LangParams>>
props: LayoutProps<"/[lang]/sas-x-scandic">
) {
const params = await props.params
const lang = params.lang as Lang
const { children } = props
@@ -29,7 +28,7 @@ export default async function SasXScandicLayout(
>
<header className={styles.header}>
{/* TODO should this link to my-pages sas page? */}
<Link className={styles.backLink} href={profileOverview[params.lang]}>
<Link className={styles.backLink} href={profileOverview[lang]}>
<ArrowLeft height={20} width={20} />
<span className={styles.long}>
{intl.formatMessage({

View File

@@ -8,9 +8,9 @@ import { getProfileSafely } from "@/lib/trpc/memoizedRequests"
import { SASModal } from "../components/SASModal"
import { LinkAccountForm } from "./LinkAccountForm"
import type { LangParams, PageArgs } from "@/types/params"
export default async function SASxScandicLinkPage(props: PageArgs<LangParams>) {
export default async function SASxScandicLinkPage(
props: PageProps<"/[lang]/sas-x-scandic/link">
) {
const params = await props.params
const profile = await getProfileSafely()

View File

@@ -9,15 +9,18 @@ import { getIntl } from "@/i18n"
import { SASModal } from "../../components/SASModal"
import type { LangParams, PageArgs } from "@/types/params"
import type { Lang } from "@scandic-hotels/common/constants/language"
export default async function SASxScandicLinkPage(props: PageArgs<LangParams>) {
export default async function SASxScandicLinkPage(
props: PageProps<"/[lang]/sas-x-scandic/link/success">
) {
const params = await props.params
const lang = params.lang as Lang
const intl = await getIntl()
return (
<SASModal>
<Redirect url={partnerSas[params.lang]} timeout={3000} />
<Redirect url={partnerSas[lang]} timeout={3000} />
<MaterialIcon
icon="check_circle"
size={64}

View File

@@ -15,7 +15,6 @@ import { SASModal } from "../components/SASModal"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { LangParams, PageArgs, SearchParams } from "@/types/params"
import type { State } from "../sasUtils"
const searchParamsSchema = z.object({
@@ -25,20 +24,23 @@ const searchParamsSchema = z.object({
type Intent = z.infer<typeof searchParamsSchema>["intent"]
export default async function SASxScandicLoginPage(
props: PageArgs<LangParams> & SearchParams
props: PageProps<"/[lang]/sas-x-scandic/login">
) {
const params = await props.params
const searchParams = await props.searchParams
const result = searchParamsSchema.safeParse(searchParams)
const lang = params.lang as Lang
if (!result.success) {
// TOOD where to redirect?
redirect(`/${params.lang}/sas-x-scandic/link`)
redirect(`/${lang}/sas-x-scandic/link`)
}
const parsedParams = result.data
const intl = await getIntl()
const redirectUri = new URL(
`/${params.lang}/sas-x-scandic/callback`,
`/${lang}/sas-x-scandic/callback`,
env.PUBLIC_URL
).toString()
@@ -49,7 +51,7 @@ export default async function SASxScandicLoginPage(
const audience = "eb-partner-api"
const scope = encodeURIComponent("openid profile email")
const loginLink = `${sasLoginHostname}/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&state=${urlState}&audience=${audience}&ui_locales=${SAS_LANGUAGE_MAP[params.lang]}`
const loginLink = `${sasLoginHostname}/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&state=${urlState}&audience=${audience}&ui_locales=${SAS_LANGUAGE_MAP[lang]}`
const intentDescriptions: Record<Intent, string> = {
link: intl.formatMessage({

View File

@@ -21,8 +21,6 @@ import OneTimePasswordForm, {
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { ReactNode } from "react"
import type { LangParams, PageArgs, SearchParams } from "@/types/params"
const otpError = z.enum(["invalidCode", "expiredCode"])
const intent = z.enum(["link", "unlink", "transfer"])
const searchParamsSchema = z.object({
@@ -35,10 +33,12 @@ export type OtpError = z.infer<typeof otpError>
type Intent = z.infer<typeof intent>
export default async function SASxScandicOneTimePasswordPage(
props: PageArgs<LangParams> & SearchParams
props: PageProps<"/[lang]/sas-x-scandic/otp">
) {
const params = await props.params
const searchParams = await props.searchParams
const lang = params.lang as Lang
const intl = await getIntl()
const cookieStore = await cookies()
const tokenCookie = cookieStore.get(SAS_TOKEN_STORAGE_KEY)
@@ -50,7 +50,7 @@ export default async function SASxScandicOneTimePasswordPage(
const { intent, to, error } = result.data
if (!verifyTokenValidity(tokenCookie?.value)) {
redirect(`/${params.lang}/sas-x-scandic/login?intent=${intent}`)
redirect(`/${lang}/sas-x-scandic/login?intent=${intent}`)
}
const handleOtpVerified: OnSubmitHandler = async ({ otp }) => {
@@ -65,7 +65,7 @@ export default async function SASxScandicOneTimePasswordPage(
switch (data.status) {
case "ABUSED":
return {
url: `/${params.lang}/sas-x-scandic/error?errorCode=tooManyFailedAttempts`,
url: `/${lang}/sas-x-scandic/error?errorCode=tooManyFailedAttempts`,
}
case "EXPIRED": {
const search = new URLSearchParams({
@@ -74,7 +74,7 @@ export default async function SASxScandicOneTimePasswordPage(
}).toString()
return {
url: `/${params.lang}/sas-x-scandic/otp?${search}`,
url: `/${lang}/sas-x-scandic/otp?${search}`,
}
}
case "RETRY": {
@@ -84,7 +84,7 @@ export default async function SASxScandicOneTimePasswordPage(
}).toString()
return {
url: `/${params.lang}/sas-x-scandic/otp?${search}`,
url: `/${lang}/sas-x-scandic/otp?${search}`,
}
}
case "NOTSENT":
@@ -97,11 +97,11 @@ export default async function SASxScandicOneTimePasswordPage(
switch (intent) {
case "link":
return handleLinkAccount({ lang: params.lang })
return handleLinkAccount({ lang: lang })
case "unlink":
return handleUnlinkAccount({ lang: params.lang })
return handleUnlinkAccount({ lang: lang })
case "transfer":
return handleTransferPoints({ lang: params.lang })
return handleTransferPoints({ lang: lang })
}
}

View File

@@ -19,15 +19,13 @@ import styles from "./transferSuccess.module.css"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { LangParams, PageArgs, SearchParams } from "@/types/params"
export default async function SASxScandicTransferSuccessPage(
props: PageArgs<LangParams> & SearchParams<{ p?: string }>
props: PageProps<"/[lang]/sas-x-scandic/transfer/success">
) {
const searchParams = await props.searchParams
const params = await props.params
const intl = await getIntl()
const { lang } = params
const lang = params.lang as Lang
// TODO get from api
const exchangeRate = 2
@@ -61,7 +59,7 @@ export default async function SASxScandicTransferSuccessPage(
fullWidth
className={styles.backButton}
>
<Link href={partnerSas[params.lang]} color="none">
<Link href={partnerSas[lang]} color="none">
{intl.formatMessage({
id: "transferEuroBonusPoints.backToMyPagesButton",
defaultMessage: "Go back to My Pages",

View File

@@ -9,17 +9,18 @@ import { getIntl } from "@/i18n"
import { SASModal } from "../../components/SASModal"
import type { LangParams, PageArgs } from "@/types/params"
import type { Lang } from "@scandic-hotels/common/constants/language"
export default async function SASxScandicUnlinkSuccessPage(
props: PageArgs<LangParams>
props: PageProps<"/[lang]/sas-x-scandic/unlink/success">
) {
const params = await props.params
const lang = params.lang as Lang
const intl = await getIntl()
return (
<SASModal>
<Redirect url={overview[params.lang]} timeout={3000} />
<Redirect url={overview[lang]} timeout={3000} />
<MaterialIcon
icon="check_circle"
size={64}

View File

@@ -25,21 +25,17 @@ import { getMessages } from "@/i18n"
import ClientIntlProvider from "@/i18n/Provider"
import { setLang } from "@/i18n/serverContext"
import type { LangParams, LayoutArgs } from "@/types/params"
export default async function RootLayout(
props: React.PropsWithChildren<LayoutArgs<LangParams>>
) {
export default async function RootLayout(props: LayoutProps<"/[lang]">) {
const params = await props.params
const lang = params.lang as Lang
const { children } = props
setLang(params.lang)
setLang(lang)
const messages = await getMessages(params.lang)
const messages = await getMessages(lang)
return (
<html lang={params.lang}>
<html lang={lang}>
<head>
<FontPreload />
<AdobeSDKScript />
@@ -52,7 +48,7 @@ export default async function RootLayout(
<body className="scandic">
<ClientIntlProvider
defaultLocale={Lang.en}
locale={params.lang}
locale={lang}
messages={messages}
>
<NuqsAdapter>
@@ -72,7 +68,7 @@ export default async function RootLayout(
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
data-culture={lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
async={true}