feat: add communication preferences
feat: add generatePreferencesLink feat: add subscriberId endpoint
This commit is contained in:
@@ -19,6 +19,8 @@ DESIGN_SYSTEM_ACCESS_TOKEN=""
|
||||
NEXTAUTH_REDIRECT_PROXY_URL="http://localhost:3000/api/web/auth"
|
||||
NEXTAUTH_SECRET=""
|
||||
REVALIDATE_SECRET=""
|
||||
SALESFORCE_PREFRENCE_BASE_URL="https://mc31njyvc80x-2b9wg-24jxcj5yq.pub.sfmc-content.com/disfelgm4fv"
|
||||
|
||||
SEAMLESS_LOGIN_DA="http://www.example.dk/updatelogin"
|
||||
SEAMLESS_LOGIN_DE="http://www.example.de/updatelogin"
|
||||
SEAMLESS_LOGIN_EN="http://www.example.com/updatelogin"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ArrowRightIcon } from "@/components/Icons"
|
||||
import ManagePreferencesButton from "@/components/Profile/ManagePreferencesButton"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
@@ -27,12 +28,7 @@ export default async function CommunicationSlot({
|
||||
})}
|
||||
</Body>
|
||||
</article>
|
||||
<Link href="#" variant="icon">
|
||||
<ArrowRightIcon color="burgundy" />
|
||||
<Body color="burgundy" textTransform="underlined">
|
||||
{formatMessage({ id: "Manage preferences" })}
|
||||
</Body>
|
||||
</Link>
|
||||
<ManagePreferencesButton />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { env } from "@/env/server"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import AddCreditCardButton from "@/components/Profile/AddCreditCardButton"
|
||||
@@ -17,8 +16,6 @@ export default async function CreditCardSlot({ params }: PageArgs<LangParams>) {
|
||||
const { formatMessage } = await getIntl()
|
||||
const creditCards = await serverClient().user.creditCards()
|
||||
|
||||
const { lang } = params
|
||||
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<article className={styles.content}>
|
||||
|
||||
@@ -15,8 +15,7 @@ export default function ProfileLayout({
|
||||
{profile}
|
||||
<Divider color="burgundy" opacity={8} />
|
||||
{creditCards}
|
||||
{/* TODO: Implement communication preferences flow. Hidden until decided on where to send user. */}
|
||||
{/* {communication} */}
|
||||
{communication}
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
|
||||
51
components/Profile/ManagePreferencesButton/index.tsx
Normal file
51
components/Profile/ManagePreferencesButton/index.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
|
||||
import ArrowRight from "@/components/Icons/ArrowRight"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import { toast } from "@/components/TempDesignSystem/Toasts"
|
||||
|
||||
import styles from "./managePreferencesButton.module.css"
|
||||
|
||||
export default function ManagePreferencesButton() {
|
||||
const intl = useIntl()
|
||||
const generatePreferencesLink = trpc.user.generatePreferencesLink.useMutation(
|
||||
{
|
||||
onSuccess: (preferencesLink) => {
|
||||
if (preferencesLink) {
|
||||
window.open(preferencesLink, "_blank")
|
||||
} else {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.",
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
onError: (e) => {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "An error occurred trying to manage your preferences, please try again later.",
|
||||
})
|
||||
)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={styles.managePreferencesButton}
|
||||
variant="icon"
|
||||
theme="base"
|
||||
intent="text"
|
||||
onClick={() => generatePreferencesLink.mutate()}
|
||||
wrapping
|
||||
>
|
||||
<ArrowRight color="burgundy" />
|
||||
{intl.formatMessage({ id: "Manage preferences" })}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.managePreferencesButton {
|
||||
justify-self: flex-start;
|
||||
}
|
||||
2
env/server.ts
vendored
2
env/server.ts
vendored
@@ -47,6 +47,7 @@ export const env = createEnv({
|
||||
.default("false"),
|
||||
PUBLIC_URL: z.string().optional(),
|
||||
REVALIDATE_SECRET: z.string(),
|
||||
SALESFORCE_PREFRENCE_BASE_URL: z.string(),
|
||||
SEAMLESS_LOGIN_DA: z.string(),
|
||||
SEAMLESS_LOGIN_DE: z.string(),
|
||||
SEAMLESS_LOGIN_EN: z.string(),
|
||||
@@ -104,6 +105,7 @@ export const env = createEnv({
|
||||
PRINT_QUERY: process.env.PRINT_QUERY,
|
||||
PUBLIC_URL: process.env.PUBLIC_URL,
|
||||
REVALIDATE_SECRET: process.env.REVALIDATE_SECRET,
|
||||
SALESFORCE_PREFRENCE_BASE_URL: process.env.SALESFORCE_PREFRENCE_BASE_URL,
|
||||
SEAMLESS_LOGIN_DA: process.env.SEAMLESS_LOGIN_DA,
|
||||
SEAMLESS_LOGIN_DE: process.env.SEAMLESS_LOGIN_DE,
|
||||
SEAMLESS_LOGIN_EN: process.env.SEAMLESS_LOGIN_EN,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"Amenities": "Faciliteter",
|
||||
"Amusement park": "Forlystelsespark",
|
||||
"An error occurred when adding a credit card, please try again later.": "Der opstod en fejl under tilføjelse af et kreditkort. Prøv venligst igen senere.",
|
||||
"An error occurred trying to manage your preferences, please try again later.": "Der opstod en fejl under forsøget på at administrere dine præferencer. Prøv venligst igen senere.",
|
||||
"An error occurred when trying to update profile.": "Der opstod en fejl under forsøg på at opdatere profilen.",
|
||||
"Any changes you've made will be lost.": "Alle ændringer, du har foretaget, går tabt.",
|
||||
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Er du sikker på, at du vil fjerne kortet, der slutter me {lastFourDigits} fra din medlemsprofil?",
|
||||
@@ -99,6 +100,7 @@
|
||||
"How do you want to sleep?": "Hvordan vil du sove?",
|
||||
"How it works": "Hvordan det virker",
|
||||
"Image gallery": "Billedgalleri",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det er ikke muligt at administrere dine kommunikationspræferencer lige nu, prøv venligst igen senere eller kontakt support, hvis problemet fortsætter.",
|
||||
"Join Scandic Friends": "Tilmeld dig Scandic Friends",
|
||||
"Join at no cost": "Tilmeld dig uden omkostninger",
|
||||
"Language": "Sprog",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"Amenities": "Annehmlichkeiten",
|
||||
"Amusement park": "Vergnügungspark",
|
||||
"An error occurred when adding a credit card, please try again later.": "Beim Hinzufügen einer Kreditkarte ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.",
|
||||
"An error occurred trying to manage your preferences, please try again later.": "Beim Versuch, Ihre Einstellungen zu verwalten, ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.",
|
||||
"An error occurred when trying to update profile.": "Beim Versuch, das Profil zu aktualisieren, ist ein Fehler aufgetreten.",
|
||||
"Any changes you've made will be lost.": "Alle Änderungen, die Sie vorgenommen haben, gehen verloren.",
|
||||
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Möchten Sie die Karte mit der Endung {lastFourDigits} wirklich aus Ihrem Mitgliedsprofil entfernen?",
|
||||
@@ -104,6 +105,7 @@
|
||||
"How do you want to sleep?": "Wie möchtest du schlafen?",
|
||||
"How it works": "Wie es funktioniert",
|
||||
"Image gallery": "Bildergalerie",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Es ist derzeit nicht möglich, Ihre Kommunikationseinstellungen zu verwalten. Bitte versuchen Sie es später erneut oder wenden Sie sich an den Support, wenn das Problem weiterhin besteht.",
|
||||
"Join Scandic Friends": "Treten Sie Scandic Friends bei",
|
||||
"km to city center": "km bis zum Stadtzentrum",
|
||||
"Language": "Sprache",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"Amenities": "Amenities",
|
||||
"Amusement park": "Amusement park",
|
||||
"An error occurred when adding a credit card, please try again later.": "An error occurred when adding a credit card, please try again later.",
|
||||
"An error occurred trying to manage your preferences, please try again later.": "An error occurred trying to manage your preferences, please try again later.",
|
||||
"An error occurred when trying to update profile.": "An error occurred when trying to update profile.",
|
||||
"Any changes you've made will be lost.": "Any changes you've made will be lost.",
|
||||
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?",
|
||||
@@ -103,6 +104,7 @@
|
||||
"How do you want to sleep?": "How do you want to sleep?",
|
||||
"How it works": "How it works",
|
||||
"Image gallery": "Image gallery",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.",
|
||||
"Join Scandic Friends": "Join Scandic Friends",
|
||||
"Join at no cost": "Join at no cost",
|
||||
"Language": "Language",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"Amenities": "Mukavuudet",
|
||||
"Amusement park": "Huvipuisto",
|
||||
"An error occurred when adding a credit card, please try again later.": "Luottokorttia lisättäessä tapahtui virhe. Yritä myöhemmin uudelleen.",
|
||||
"An error occurred trying to manage your preferences, please try again later.": "Asetusten hallinnassa tapahtui virhe. Yritä myöhemmin uudelleen.",
|
||||
"An error occurred when trying to update profile.": "Profiilia päivitettäessä tapahtui virhe.",
|
||||
"Any changes you've made will be lost.": "Kaikki tekemäsi muutokset menetetään.",
|
||||
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Haluatko varmasti poistaa kortin, joka päättyy numeroon {lastFourDigits} jäsenprofiilistasi?",
|
||||
@@ -99,6 +100,7 @@
|
||||
"How do you want to sleep?": "Kuinka haluat nukkua?",
|
||||
"How it works": "Kuinka se toimii",
|
||||
"Image gallery": "Kuvagalleria",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Viestintäasetuksiasi ei voi hallita juuri nyt. Yritä myöhemmin uudelleen tai ota yhteyttä tukeen, jos ongelma jatkuu.",
|
||||
"Join Scandic Friends": "Liity jäseneksi",
|
||||
"Join at no cost": "Liity maksutta",
|
||||
"Language": "Kieli",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"Amenities": "Fasiliteter",
|
||||
"Amusement park": "Tivoli",
|
||||
"An error occurred when adding a credit card, please try again later.": "Det oppstod en feil ved å legge til et kredittkort. Prøv igjen senere.",
|
||||
"An error occurred trying to manage your preferences, please try again later.": "Det oppstod en feil under forsøket på å administrere innstillingene dine. Prøv igjen senere.",
|
||||
"An error occurred when trying to update profile.": "Det oppstod en feil under forsøk på å oppdatere profilen.",
|
||||
"Any changes you've made will be lost.": "Eventuelle endringer du har gjort, går tapt.",
|
||||
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Er du sikker på at du vil fjerne kortet som slutter på {lastFourDigits} fra medlemsprofilen din?",
|
||||
@@ -99,6 +100,7 @@
|
||||
"How do you want to sleep?": "Hvordan vil du sove?",
|
||||
"How it works": "Hvordan det fungerer",
|
||||
"Image gallery": "Bildegalleri",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det er ikke mulig å administrere kommunikasjonspreferansene dine akkurat nå, prøv igjen senere eller kontakt support hvis problemet vedvarer.",
|
||||
"Join Scandic Friends": "Bli med i Scandic Friends",
|
||||
"Join at no cost": "Bli med uten kostnad",
|
||||
"Language": "Språk",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"Amenities": "Bekvämligheter",
|
||||
"Amusement park": "Nöjespark",
|
||||
"An error occurred when adding a credit card, please try again later.": "Ett fel uppstod när ett kreditkort lades till, försök igen senare.",
|
||||
"An error occurred trying to manage your preferences, please try again later.": "Ett fel uppstod när du försökte hantera dina inställningar, försök igen senare.",
|
||||
"An error occurred when trying to update profile.": "Ett fel uppstod när du försökte uppdatera profilen.",
|
||||
"Any changes you've made will be lost.": "Alla ändringar du har gjort kommer att gå förlorade.",
|
||||
"Are you sure you want to remove the card ending with {lastFourDigits} from your member profile?": "Är du säker på att du vill ta bort kortet som slutar med {lastFourDigits} från din medlemsprofil?",
|
||||
@@ -99,6 +100,8 @@
|
||||
"How do you want to sleep?": "Hur vill du sova?",
|
||||
"How it works": "Hur det fungerar",
|
||||
"Image gallery": "Bildgalleri",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det gick inte att hantera dina kommunikationsinställningar just nu, försök igen senare eller kontakta supporten om problemet kvarstår.",
|
||||
|
||||
"Join Scandic Friends": "Gå med i Scandic Friends",
|
||||
"Join at no cost": "Gå med utan kostnad",
|
||||
"Language": "Språk",
|
||||
|
||||
@@ -21,6 +21,9 @@ export namespace endpoints {
|
||||
upcomingStays = "booking/v1/Stays/future",
|
||||
rewards = `${profile}/reward`,
|
||||
tierRewards = `${profile}/TierRewards`,
|
||||
intiateSaveCard = `${creditCards}/initiateSaveCard`,
|
||||
deleteCreditCard = `${profile}/creditCards`,
|
||||
subscriberId = `${profile}/SubscriberId`,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { metrics } from "@opentelemetry/api"
|
||||
|
||||
import { env } from "@/env/server"
|
||||
import * as api from "@/lib/api"
|
||||
import { initiateSaveCardSchema } from "@/server/routers/user/output"
|
||||
import {
|
||||
initiateSaveCardSchema,
|
||||
subscriberIdSchema,
|
||||
} from "@/server/routers/user/output"
|
||||
import { protectedProcedure, router } from "@/server/trpc"
|
||||
|
||||
import {
|
||||
@@ -8,6 +14,17 @@ import {
|
||||
saveCreditCardInput,
|
||||
} from "./input"
|
||||
|
||||
const meter = metrics.getMeter("trpc.user")
|
||||
const generatePreferencesLinkCounter = meter.createCounter(
|
||||
"trpc.user.generatePreferencesLink"
|
||||
)
|
||||
const generatePreferencesLinkSuccessCounter = meter.createCounter(
|
||||
"trpc.user.generatePreferencesLink-success"
|
||||
)
|
||||
const generatePreferencesLinkFailCounter = meter.createCounter(
|
||||
"trpc.user.generatePreferencesLink-fail"
|
||||
)
|
||||
|
||||
export const userMutationRouter = router({
|
||||
creditCard: router({
|
||||
add: protectedProcedure.input(addCreditCardInput).mutation(async function ({
|
||||
@@ -128,4 +145,62 @@ export const userMutationRouter = router({
|
||||
return true
|
||||
}),
|
||||
}),
|
||||
generatePreferencesLink: protectedProcedure.mutation(async function ({
|
||||
ctx,
|
||||
}) {
|
||||
generatePreferencesLinkCounter.add(1)
|
||||
const apiResponse = await api.get(api.endpoints.v1.subscriberId, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
generatePreferencesLinkFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.user.subscriberId error ",
|
||||
JSON.stringify({
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
const data = await apiResponse.json()
|
||||
|
||||
const validatedData = subscriberIdSchema.safeParse(data)
|
||||
|
||||
if (!validatedData.success) {
|
||||
generatePreferencesLinkSuccessCounter.add(1, {
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.user.generatePreferencesLink validation error",
|
||||
JSON.stringify({
|
||||
error: validatedData.error,
|
||||
})
|
||||
)
|
||||
console.error(validatedData.error.format())
|
||||
|
||||
return null
|
||||
}
|
||||
const preferencesLink = new URL(env.SALESFORCE_PREFRENCE_BASE_URL)
|
||||
preferencesLink.searchParams.set("subKey", validatedData.data.subscriberId)
|
||||
|
||||
generatePreferencesLinkSuccessCounter.add(1)
|
||||
return preferencesLink.toString()
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -234,3 +234,7 @@ export const initiateSaveCardSchema = z.object({
|
||||
type: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const subscriberIdSchema = z.object({
|
||||
subscriberId: z.string(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user