diff --git a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts index c1b2b432d..cd965398e 100644 --- a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts +++ b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts @@ -78,7 +78,10 @@ export async function GET( httpOnly: true, }) - if (stateResult.data.intent === "link") { + if ( + stateResult.data.intent === "link" || + stateResult.data.intent === "unlink" + ) { const [data, error] = await safeTry( serverClient().partner.sas.requestOtp({}) ) diff --git a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/layout.tsx b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/layout.tsx index 7e7a707e3..eb5cb323d 100644 --- a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/layout.tsx +++ b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/layout.tsx @@ -29,7 +29,7 @@ export default async function SasXScandicLayout({ - {intl.formatMessage({ id: "Back to Scandichotels.com" })} + {intl.formatMessage({ id: "Back to scandichotels.com" })} {intl.formatMessage({ id: "Back" })} diff --git a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/login/page.tsx b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/login/page.tsx index 542be9def..6546c267b 100644 --- a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/login/page.tsx +++ b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/login/page.tsx @@ -18,8 +18,11 @@ import type { LangParams, PageArgs, SearchParams } from "@/types/params" import type { State } from "../sasUtils" const searchParamsSchema = z.object({ - intent: z.enum(["link"]), + intent: z.enum(["link", "unlink"]), }) + +type Intent = z.infer["intent"] + export default async function SASxScandicLoginPage({ searchParams, params, @@ -42,11 +45,19 @@ export default async function SASxScandicLoginPage({ const clientId = env.SAS_AUTH_CLIENTID const sasLoginHostname = env.SAS_AUTH_ENDPOINT const audience = "eb-partner-api" - // TODO check if this is correct scopes 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}` + const intentDescriptions: Record = { + link: intl.formatMessage({ + id: "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.", + }), + unlink: intl.formatMessage({ + id: "Log in to your SAS Eurobonus account to confirm account unlinking.", + }), + } + return ( @@ -60,11 +71,7 @@ export default async function SASxScandicLoginPage({ {intl.formatMessage({ id: "Redirecting you to SAS" })} - - {intl.formatMessage({ - id: "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.", - })} - + {intentDescriptions[parsedParams.intent]} {intl.formatMessage( { diff --git a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx index b107577de..8525f869a 100644 --- a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx +++ b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx @@ -2,6 +2,7 @@ import { cookies } from "next/headers" import { redirect } from "next/navigation" import { z } from "zod" +import { myPages } from "@/constants/routes/myPages" import { serverClient } from "@/lib/trpc/server" import { getIntl } from "@/i18n" @@ -12,17 +13,21 @@ import OneTimePasswordForm, { type OnSubmitHandler, } from "./OneTimePasswordForm" +import type { ReactNode } from "react" + import type { LangParams, PageArgs, SearchParams } from "@/types/params" import type { Lang } from "@/constants/languages" const otpError = z.enum(["invalidCode", "expiredCode"]) +const intent = z.enum(["link", "unlink"]) const searchParamsSchema = z.object({ - intent: z.enum(["link"]), + intent: intent, to: z.string(), error: otpError.optional(), }) export type OtpError = z.infer +type Intent = z.infer export default async function SASxScandicOneTimePasswordPage({ searchParams, @@ -88,26 +93,37 @@ export default async function SASxScandicOneTimePasswordPage({ switch (intent) { case "link": return handleLinkAccount({ lang: params.lang }) + case "unlink": + return handleUnlinkAccount({ lang: params.lang }) } } + const maskedContactInfo = () => ( + <> +
+ {to} +
+ + ) + const intentDescriptions: Record = { + link: intl.formatMessage( + { + id: "Please enter the code sent to in order to confirm your account linking.", + }, + { maskedContactInfo } + ), + unlink: intl.formatMessage( + { + id: "Please enter the code sent to in order to unlink your accounts.", + }, + { maskedContactInfo } + ), + } + return ( ( - { - id: "Please enter the code sent to in order to confirm your account linking.", - }, - { - maskedContactInfo: () => ( - <> -
- {to} -
- - ), - } - )} + ingress={intentDescriptions[intent]} footnote={intl.formatMessage({ id: "This verifcation is needed for additional security.", })} @@ -168,3 +184,34 @@ async function handleLinkAccount({ } } } + +async function handleUnlinkAccount({ + lang, +}: { + lang: Lang +}): ReturnType { + const [res, error] = await safeTry(serverClient().partner.sas.unlinkAccount()) + if (!res || error) { + console.error("[SAS] unlink account error", error) + return { + url: `/${lang}/sas-x-scandic/error`, + } + } + + switch (res.linkingState) { + case "unlinked": + return { + url: `/${lang}/sas-x-scandic/unlink/success`, + type: "replace", + } + case "notLinked": + return { + url: myPages[lang], + } + case "error": + return { + url: `/${lang}/sas-x-scandic/error`, + type: "replace", + } + } +} diff --git a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/sasUtils.ts b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/sasUtils.ts index 383880b80..776941f40 100644 --- a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/sasUtils.ts +++ b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/sasUtils.ts @@ -2,8 +2,7 @@ import { z } from "zod" export const SAS_TOKEN_STORAGE_KEY = "sas-x-scandic-token" -// TODO nonce?? export const stateSchema = z.object({ - intent: z.literal("link"), + intent: z.enum(["link", "unlink"]), }) export type State = z.infer diff --git a/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/unlink/success/page.tsx b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/unlink/success/page.tsx new file mode 100644 index 000000000..3ab8c22c6 --- /dev/null +++ b/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/unlink/success/page.tsx @@ -0,0 +1,36 @@ +import React from "react" + +import { overview } from "@/constants/routes/myPages" + +import CheckCircle from "@/components/Icons/CheckCircle" +import { Redirect } from "@/components/Redirect" +import Body from "@/components/TempDesignSystem/Text/Body" +import Title from "@/components/TempDesignSystem/Text/Title" +import { getIntl } from "@/i18n" + +import { SASModal } from "../../components/SASModal" + +import type { LangParams, PageArgs } from "@/types/params" + +export default async function SASxScandicUnlinkSuccessPage({ + params, +}: PageArgs) { + const intl = await getIntl() + + return ( + + + + + {intl.formatMessage({ id: "Your accounts are now unlinked" })} + +
+ + {intl.formatMessage({ + id: "Redirecting you to My Pages.", + })} + +
+
+ ) +} diff --git a/components/Blocks/DynamicContent/SAS/LinkedAccounts/UnlinkSAS.tsx b/components/Blocks/DynamicContent/SAS/LinkedAccounts/UnlinkSAS.tsx index c1d8a8b6a..42d40841c 100644 --- a/components/Blocks/DynamicContent/SAS/LinkedAccounts/UnlinkSAS.tsx +++ b/components/Blocks/DynamicContent/SAS/LinkedAccounts/UnlinkSAS.tsx @@ -1,47 +1,34 @@ "use client" -import { useRouter } from "next/navigation" +import { useParams } from "next/navigation" import { useIntl } from "react-intl" -import { trpc } from "@/lib/trpc/client" +import Dialog from "@/components/Dialog" +import Button from "@/components/TempDesignSystem/Button" -import { Loading } from "@/components/Loading" -import Link from "@/components/TempDesignSystem/Link" -import { toast } from "@/components/TempDesignSystem/Toasts" +import type { LangParams } from "@/types/params" export function UnlinkSAS() { const intl = useIntl() - const router = useRouter() - - const { mutate, isPending } = trpc.partner.sas.unlinkAccount.useMutation({ - onSuccess() { - toast.success(intl.formatMessage({ id: "Account unlinked, reloading" })) - // TODO: reload page - router.push("/en/scandic-friends/my-pages") - }, - onError() { - toast.error(intl.formatMessage({ id: "Failed to unlink account" })) - }, - }) - - const handleClick = (event: React.MouseEvent) => { - event.preventDefault() - mutate() - } - - if (isPending) { - return - } + const params = useParams() return ( - - {intl.formatMessage({ id: "Unlink accounts" })} - + + {intl.formatMessage({ id: "Unlink accounts" })} + + } + /> ) } diff --git a/components/Blocks/DynamicContent/SAS/LinkedAccounts/index.tsx b/components/Blocks/DynamicContent/SAS/LinkedAccounts/index.tsx index 6be7b3565..d36faa1dc 100644 --- a/components/Blocks/DynamicContent/SAS/LinkedAccounts/index.tsx +++ b/components/Blocks/DynamicContent/SAS/LinkedAccounts/index.tsx @@ -42,8 +42,8 @@ export default async function SASLinkedAccount({
- +
) diff --git a/components/Blocks/DynamicContent/SAS/LinkedAccounts/levelupgradebutton.module.css b/components/Blocks/DynamicContent/SAS/LinkedAccounts/levelupgradebutton.module.css index d6db44998..3f62be530 100644 --- a/components/Blocks/DynamicContent/SAS/LinkedAccounts/levelupgradebutton.module.css +++ b/components/Blocks/DynamicContent/SAS/LinkedAccounts/levelupgradebutton.module.css @@ -3,6 +3,7 @@ display: flex; justify-content: center; align-items: center; + width: 100%; & .textContainer { display: flex; @@ -10,6 +11,10 @@ align-items: center; gap: var(--Spacing-x1); } + + @media screen and (min-width: 768px) { + width: fit-content; + } } .loading { diff --git a/components/Blocks/DynamicContent/SAS/LinkedAccounts/linkedAccounts.module.css b/components/Blocks/DynamicContent/SAS/LinkedAccounts/linkedAccounts.module.css index 5ed1930ba..89fdb0563 100644 --- a/components/Blocks/DynamicContent/SAS/LinkedAccounts/linkedAccounts.module.css +++ b/components/Blocks/DynamicContent/SAS/LinkedAccounts/linkedAccounts.module.css @@ -21,7 +21,7 @@ .mutationSection { display: flex; - flex-direction: column; + flex-direction: column-reverse; gap: var(--Spacing-x2); align-items: center; diff --git a/components/Dialog/index.tsx b/components/Dialog/index.tsx index 3e299e751..ca18d3516 100644 --- a/components/Dialog/index.tsx +++ b/components/Dialog/index.tsx @@ -24,13 +24,11 @@ export default function Dialog({ proceedOnClick = () => {}, proceedText, titleText, - triggerButtonText, + trigger, }: DialogProps) { return ( - + {trigger} diff --git a/components/Forms/Edit/Profile/index.tsx b/components/Forms/Edit/Profile/index.tsx index c588d9d95..bbdc8ef13 100644 --- a/components/Forms/Edit/Profile/index.tsx +++ b/components/Forms/Edit/Profile/index.tsx @@ -133,7 +133,11 @@ export default function Form({ user }: EditFormProps) { proceedHref={profile[lang]} proceedText={intl.formatMessage({ id: "Yes, discard changes" })} titleText={intl.formatMessage({ id: "Discard unsaved changes?" })} - triggerButtonText={intl.formatMessage({ id: "Discard changes" })} + trigger={ + + } /> + } /> ) } diff --git a/i18n/dictionaries/da.json b/i18n/dictionaries/da.json index 949849a86..22dc64cff 100644 --- a/i18n/dictionaries/da.json +++ b/i18n/dictionaries/da.json @@ -319,6 +319,7 @@ "Locations": "Placeringer", "Log in": "Log på", "Log in here": "Log ind her", + "Log in to your SAS Eurobonus account to confirm account unlinking.": "Log in to your SAS Eurobonus account to confirm account unlinking.", "Log in/Join": "Log på/Tilmeld dig", "Log out": "Log ud", "Long {long} ∙ Lat {lat}": "Long {long} ∙ Lat {lat}", @@ -441,6 +442,7 @@ "Phone number": "Telefonnummer", "Please enter a valid phone number": "Indtast venligst et gyldigt telefonnummer", "Please enter the code sent to in order to confirm your account linking.": "Please enter the code sent to in order to confirm your account linking.", + "Please enter the code sent to in order to unlink your accounts.": "Please enter the code sent to in order to unlink your accounts.", "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.": "Vær opmærksom på, at dette er påkrævet, og at dit kort kun vil blive opkrævet i tilfælde af en no-show.", "Please try and change your search for this destination or see alternative hotels.": "Please try and change your search for this destination or see alternative hotels.", "Points": "Point", @@ -674,6 +676,7 @@ "Your Challenges Conquer & Earn!": "Dine udfordringer Overvind og tjen!", "Your SAS level has upgraded your friends level": "Your SAS level has upgraded your friends level", "Your accounts are connected": "Your accounts are connected", + "Your accounts are now unlinked": "Your accounts are now unlinked", "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Din booking er bekræftet, men vi kunne ikke verificere dit medlemskab. Hvis du har booket med et medlemstilbud, skal du enten vise dit eksisterende medlemskab ved check-in, blive medlem eller betale prisdifferencen ved check-in. Tilmelding er foretrukket online før opholdet.", "Your card was successfully removed!": "Dit kort blev fjernet!", "Your card was successfully saved!": "Dit kort blev gemt!", diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json index e7c8abf1d..9f075b3c2 100644 --- a/i18n/dictionaries/de.json +++ b/i18n/dictionaries/de.json @@ -320,6 +320,7 @@ "Locations": "Orte", "Log in": "Anmeldung", "Log in here": "Hier einloggen", + "Log in to your SAS Eurobonus account to confirm account unlinking.": "Log in to your SAS Eurobonus account to confirm account unlinking.", "Log in/Join": "Log in/Anmelden", "Log out": "Ausloggen", "Long {long} ∙ Lat {lat}": "Long {long} ∙ Lat {lat}", @@ -442,6 +443,7 @@ "Phone number": "Telefonnummer", "Please enter a valid phone number": "Bitte geben Sie eine gültige Telefonnummer ein", "Please enter the code sent to in order to confirm your account linking.": "Please enter the code sent to in order to confirm your account linking.", + "Please enter the code sent to in order to unlink your accounts.": "Please enter the code sent to in order to unlink your accounts.", "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.": "Bitte beachten Sie, dass dies erforderlich ist und dass Ihr Kreditkartenkonto nur in einem No-Show-Fall belastet wird.", "Please try and change your search for this destination or see alternative hotels.": "Please try and change your search for this destination or see alternative hotels.", "Points": "Punkte", @@ -674,6 +676,7 @@ "Your Challenges Conquer & Earn!": "Meistern Sie Ihre Herausforderungen und verdienen Sie Geld!", "Your SAS level has upgraded your friends level": "Your SAS level has upgraded your friends level", "Your accounts are connected": "Your accounts are connected", + "Your accounts are now unlinked": "Your accounts are now unlinked", "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Ihre Buchung ist bestätigt, aber wir konnten Ihr Mitglied nicht verifizieren. Wenn Sie mit einem Mitgliederrabatt gebucht haben, müssen Sie entweder Ihr vorhandenes Mitgliedschaftsnummer bei der Anreise präsentieren, ein Mitglied werden oder die Preisdifferenz bei der Anreise bezahlen. Die Anmeldung ist vorzugsweise online vor der Aufenthaltsdauer erfolgreich.", "Your card was successfully removed!": "Ihre Karte wurde erfolgreich entfernt!", "Your card was successfully saved!": "Ihre Karte wurde erfolgreich gespeichert!", diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json index 5f8fd673a..b7b91daa1 100644 --- a/i18n/dictionaries/en.json +++ b/i18n/dictionaries/en.json @@ -323,6 +323,7 @@ "Locations": "Locations", "Log in": "Log in", "Log in here": "Log in here", + "Log in to your SAS Eurobonus account to confirm account unlinking.": "Log in to your SAS Eurobonus account to confirm account unlinking.", "Log in/Join": "Log in/Join", "Log out": "Log out", "Long {long} ∙ Lat {lat}": "Long {long} ∙ Lat {lat}", @@ -446,6 +447,7 @@ "Phone number": "Phone number", "Please enter a valid phone number": "Please enter a valid phone number", "Please enter the code sent to in order to confirm your account linking.": "Please enter the code sent to in order to confirm your account linking.", + "Please enter the code sent to in order to unlink your accounts.": "Please enter the code sent to in order to unlink your accounts.", "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.": "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.", "Please try and change your search for this destination or see alternative hotels.": "Please try and change your search for this destination or see alternative hotels.", "Points": "Points", @@ -680,6 +682,7 @@ "Your Challenges Conquer & Earn!": "Your Challenges Conquer & Earn!", "Your SAS level has upgraded your friends level": "Your SAS level has upgraded your friends level", "Your accounts are connected": "Your accounts are connected", + "Your accounts are now unlinked": "Your accounts are now unlinked", "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.", "Your card was successfully removed!": "Your card was successfully removed!", "Your card was successfully saved!": "Your card was successfully saved!", diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json index 3cb044153..4d3d748a2 100644 --- a/i18n/dictionaries/fi.json +++ b/i18n/dictionaries/fi.json @@ -319,6 +319,7 @@ "Locations": "Sijainnit", "Log in": "Kirjaudu sisään", "Log in here": "Kirjaudu sisään", + "Log in to your SAS Eurobonus account to confirm account unlinking.": "Log in to your SAS Eurobonus account to confirm account unlinking.", "Log in/Join": "Kirjaudu sisään/Liittyä", "Log out": "Kirjaudu ulos", "Long {long} ∙ Lat {lat}": "Long {long} ∙ Lat {lat}", @@ -441,6 +442,7 @@ "Phone number": "Puhelinnumero", "Please enter a valid phone number": "Ole hyvä ja näppäile voimassaoleva puhelinnumero", "Please enter the code sent to in order to confirm your account linking.": "Please enter the code sent to in order to confirm your account linking.", + "Please enter the code sent to in order to unlink your accounts.": "Please enter the code sent to in order to unlink your accounts.", "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.": "Huomaa, että tämä on pakollinen, ja että maksukorttiisi kirjataan vain, jos varausmyyntiä ei tapahtu.", "Please try and change your search for this destination or see alternative hotels.": "Please try and change your search for this destination or see alternative hotels.", "Points": "Pisteet", @@ -674,6 +676,7 @@ "Your Challenges Conquer & Earn!": "Your Challenges Conquer & Earn!", "Your SAS level has upgraded your friends level": "Your SAS level has upgraded your friends level", "Your accounts are connected": "Your accounts are connected", + "Your accounts are now unlinked": "Your accounts are now unlinked", "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Varauksesi on vahvistettu, mutta jäsenyytesi ei voitu vahvistaa. Jos olet bookeutunut jäsenyysalennoilla, sinun on joko esitettävä olemassa olevan jäsenyysnumero tarkistukseen, tulla jäseneksi tai maksamaan hinnan eron hotellissa. Jäsenyyden tilittäminen on suositeltavampaa tehdä verkkoon ennen majoittumista.", "Your card was successfully removed!": "Korttisi poistettiin onnistuneesti!", "Your card was successfully saved!": "Korttisi tallennettu onnistuneesti!", diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json index 6e4a9c15c..50da80774 100644 --- a/i18n/dictionaries/no.json +++ b/i18n/dictionaries/no.json @@ -318,6 +318,7 @@ "Locations": "Steder", "Log in": "Logg Inn", "Log in here": "Logg inn her", + "Log in to your SAS Eurobonus account to confirm account unlinking.": "Log in to your SAS Eurobonus account to confirm account unlinking.", "Log in/Join": "Logg på/Bli med", "Log out": "Logg ut", "Long {long} ∙ Lat {lat}": "Long {long} ∙ Lat {lat}", @@ -440,6 +441,7 @@ "Phone number": "Telefonnummer", "Please enter a valid phone number": "Vennligst oppgi et gyldig telefonnummer", "Please enter the code sent to in order to confirm your account linking.": "Please enter the code sent to in order to confirm your account linking.", + "Please enter the code sent to in order to unlink your accounts.": "Please enter the code sent to in order to unlink your accounts.", "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.": "Vær oppmerksom på at dette er påkrevd, og at ditt kredittkort kun vil bli belastet i tilfelle av en no-show.", "Please try and change your search for this destination or see alternative hotels.": "Please try and change your search for this destination or see alternative hotels.", "Points": "Poeng", @@ -672,6 +674,7 @@ "Your Challenges Conquer & Earn!": "Dine utfordringer Erobre og tjen!", "Your SAS level has upgraded your friends level": "Your SAS level has upgraded your friends level", "Your accounts are connected": "Your accounts are connected", + "Your accounts are now unlinked": "Your accounts are now unlinked", "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Din bestilling er bekreftet, men vi kunne ikke verifisere medlemskapet ditt. Hvis du har booke ut med et medlemsrabatt, må du enten presentere eksisterende medlemsnummer ved check-in, bli medlem eller betale prisdifferansen ved hotellet. Registrering er foretrukket gjort online før oppholdet.", "Your card was successfully removed!": "Kortet ditt ble fjernet!", "Your card was successfully saved!": "Kortet ditt ble lagret!", diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json index a4790b948..925d48adc 100644 --- a/i18n/dictionaries/sv.json +++ b/i18n/dictionaries/sv.json @@ -318,6 +318,7 @@ "Locations": "Platser", "Log in": "Logga in", "Log in here": "Logga in här", + "Log in to your SAS Eurobonus account to confirm account unlinking.": "Log in to your SAS Eurobonus account to confirm account unlinking.", "Log in/Join": "Logga in/Gå med", "Log out": "Logga ut", "Long {long} ∙ Lat {lat}": "Long {long} ∙ Lat {lat}", @@ -440,6 +441,7 @@ "Phone number": "Telefonnummer", "Please enter a valid phone number": "Var vänlig och ange ett giltigt telefonnummer", "Please enter the code sent to in order to confirm your account linking.": "Please enter the code sent to in order to confirm your account linking.", + "Please enter the code sent to in order to unlink your accounts.": "Please enter the code sent to in order to unlink your accounts.", "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.": "Vänligen notera att detta är obligatoriskt, och att ditt kreditkort endast debiteras i händelse av en no-show.", "Please try and change your search for this destination or see alternative hotels.": "Please try and change your search for this destination or see alternative hotels.", "Points": "Poäng", @@ -672,6 +674,7 @@ "Your Challenges Conquer & Earn!": "Dina utmaningar Erövra och tjäna!", "Your SAS level has upgraded your friends level": "Your SAS level has upgraded your friends level", "Your accounts are connected": "Your accounts are connected", + "Your accounts are now unlinked": "Your accounts are now unlinked", "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Din bokning är bekräftad, men vi kunde inte verifiera ditt medlemskap. Om du har bokat med ett medlemsrabatt måste du antingen presentera ditt befintliga medlemsnummer vid check-in, bli medlem eller betala prisdifferensen vid hotell. Registrering är föredragen gjord online före vistelsen.", "Your card was successfully removed!": "Ditt kort har tagits bort!", "Your card was successfully saved!": "Ditt kort har sparats!", diff --git a/lib/api/endpoints.ts b/lib/api/endpoints.ts index 5dc971639..1581b7244 100644 --- a/lib/api/endpoints.ts +++ b/lib/api/endpoints.ts @@ -163,6 +163,8 @@ export namespace endpoints { export const subscriberId = `${base.path.profile}/${version}/${base.enitity.Profile}/SubscriberId` export const link = `${base.path.profile}/${version}/${base.enitity.Profile}/link` + export const unlink = `${base.path.profile}/${version}/${base.enitity.Profile}/Unlink` + // TODO: Remove once new endpoints are out in production. export const reward = `${base.path.profile}/${version}/${base.enitity.Profile}/reward` export const tierRewards = `${base.path.profile}/${version}/${base.enitity.Profile}/tierRewards` diff --git a/server/routers/partners/sas/unlinkAccount.ts b/server/routers/partners/sas/unlinkAccount.ts index 12d0da187..fb0038a8b 100644 --- a/server/routers/partners/sas/unlinkAccount.ts +++ b/server/routers/partners/sas/unlinkAccount.ts @@ -1,27 +1,50 @@ -import { TRPCError } from "@trpc/server" import { z } from "zod" +import * as api from "@/lib/api" import { protectedProcedure } from "@/server/trpc" -import { timeout } from "@/utils/timeout" +import { getSasToken } from "./getSasToken" const outputSchema = z.object({ - // unlinked: z.boolean(), + linkingState: z.enum(["unlinked", "notLinked", "error"]), }) export const unlinkAccount = protectedProcedure .output(outputSchema) - .mutation(async function ({ ctx, input }) { - console.log("[SAS] unlink account") - await timeout(1000) - //TODO: Call actual API here + .mutation(async function ({ ctx }) { + const sasAuthToken = getSasToken() - throw new TRPCError({ - message: "Unable to unlink account", - code: "BAD_REQUEST", + const apiResponse = await api.post(api.endpoints.v1.Profile.unlink, { + headers: { + Authorization: `Bearer ${ctx.session.token.access_token}`, + }, + body: { + partner: "sas_eb", + partnerSpecific: { + eurobonusAccessToken: sasAuthToken, + }, + }, }) - return { - unlinked: true, + if (apiResponse.status === 204) { + console.log("[SAS] unlink account success") + return { linkingState: "unlinked" } } + + if (apiResponse.status === 400) { + const result = await apiResponse.json() + + console.log("[SAS] unlink account error with response", result) + return { linkingState: "error" } + } + + if (apiResponse.status === 404) { + console.log("[SAS] tried unlinking an account that was not linked") + return { linkingState: "notLinked" } + } + + console.log( + `[SAS] unlink account error with status code ${apiResponse.status} and response ${await apiResponse.text()}` + ) + return { linkingState: "error" } }) diff --git a/types/components/dialog.ts b/types/components/dialog.ts index 31680229d..6d809deeb 100644 --- a/types/components/dialog.ts +++ b/types/components/dialog.ts @@ -6,5 +6,5 @@ export interface DialogProps { proceedOnClick?: (close: () => void) => void proceedText: string titleText: string - triggerButtonText: React.ReactNode + trigger: React.ReactNode }