feat(SW-706): make eslint rule 'formatjs/no-literal-string-in-jsx' pass
This commit is contained in:
@@ -73,15 +73,15 @@
|
||||
"ignoreRestSiblings": true
|
||||
}
|
||||
],
|
||||
"formatjs/enforce-description": ["warn", "anything"],
|
||||
"formatjs/enforce-default-message": ["error", "literal"],
|
||||
// "formatjs/enforce-description": ["warn", "anything"],
|
||||
// "formatjs/enforce-default-message": ["error", "literal"],
|
||||
"formatjs/enforce-placeholders": ["error"],
|
||||
"formatjs/enforce-plural-rules": ["error"],
|
||||
"formatjs/no-literal-string-in-jsx": ["error"],
|
||||
"formatjs/no-multiple-whitespaces": ["error"],
|
||||
"formatjs/no-multiple-plurals": ["error"],
|
||||
"formatjs/no-invalid-icu": ["error"],
|
||||
"formatjs/no-id": ["error"],
|
||||
// "formatjs/no-id": ["error"],
|
||||
"formatjs/no-complex-selectors": ["error"],
|
||||
"formatjs/no-useless-message": ["error"],
|
||||
"formatjs/prefer-pound-in-plural": ["error"]
|
||||
|
||||
@@ -61,7 +61,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
message: issue.message,
|
||||
})),
|
||||
message: intl.formatMessage({
|
||||
id: "An error occured when trying to update profile.",
|
||||
defaultMessage: "An error occured when trying to update profile.",
|
||||
}),
|
||||
status: Status.error,
|
||||
}
|
||||
@@ -81,7 +81,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
data: input,
|
||||
issues: [],
|
||||
message: intl.formatMessage({
|
||||
id: "An error occured when trying to update profile.",
|
||||
defaultMessage: "An error occured when trying to update profile.",
|
||||
}),
|
||||
status: Status.error,
|
||||
}
|
||||
@@ -137,7 +137,9 @@ export const editProfile = protectedServerActionProcedure
|
||||
if (Object.keys(body).length === 0) {
|
||||
return {
|
||||
data: input,
|
||||
message: intl.formatMessage({ id: "Successfully updated profile!" }),
|
||||
message: intl.formatMessage({
|
||||
defaultMessage: "Successfully updated profile!",
|
||||
}),
|
||||
status: Status.success,
|
||||
}
|
||||
} else {
|
||||
@@ -172,7 +174,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
data: input,
|
||||
issues: [],
|
||||
message: intl.formatMessage({
|
||||
id: "An error occured when trying to update profile.",
|
||||
defaultMessage: "An error occured when trying to update profile.",
|
||||
}),
|
||||
status: Status.error,
|
||||
}
|
||||
@@ -208,7 +210,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
message: issue.message,
|
||||
})),
|
||||
message: intl.formatMessage({
|
||||
id: "An error occured when trying to update profile.",
|
||||
defaultMessage: "An error occured when trying to update profile.",
|
||||
}),
|
||||
status: Status.error,
|
||||
}
|
||||
@@ -216,7 +218,9 @@ export const editProfile = protectedServerActionProcedure
|
||||
|
||||
return {
|
||||
data: validatedData.data,
|
||||
message: intl.formatMessage({ id: "Successfully updated profile!" }),
|
||||
message: intl.formatMessage({
|
||||
defaultMessage: "Successfully updated profile!",
|
||||
}),
|
||||
status: Status.success,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -22,7 +22,9 @@ export default function Error({
|
||||
<p>
|
||||
<strong>
|
||||
{intl.formatMessage(
|
||||
{ id: "Breadcrumbs failed for this page ({errorId})" },
|
||||
{
|
||||
defaultMessage: "Breadcrumbs failed for this page ({errorId})",
|
||||
},
|
||||
{
|
||||
errorId: `${error.digest}@${Date.now()}`,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ export default function Error({
|
||||
<p>
|
||||
<strong>
|
||||
{intl.formatMessage(
|
||||
{ id: "Error loading this page ({errorId})" },
|
||||
{
|
||||
defaultMessage: "Error loading this page ({errorId})",
|
||||
},
|
||||
{
|
||||
errorId: `${error.digest}@${Date.now()}`,
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ export default async function MyPages({}: PageArgs<
|
||||
{content?.length ? (
|
||||
<Blocks blocks={content} />
|
||||
) : (
|
||||
<p>{intl.formatMessage({ id: "No content published" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No content published",
|
||||
})}
|
||||
</p>
|
||||
)}
|
||||
</main>
|
||||
<TrackingSDK pageData={tracking} />
|
||||
|
||||
@@ -25,7 +25,9 @@ export default function Error({
|
||||
<p>
|
||||
<strong>
|
||||
{intl.formatMessage(
|
||||
{ id: "An error occurred ({errorId})" },
|
||||
{
|
||||
defaultMessage: "An error occurred ({errorId})",
|
||||
},
|
||||
{
|
||||
errorId: `${error.digest}@${Date.now()}`,
|
||||
}
|
||||
|
||||
@@ -128,12 +128,17 @@ export default async function DetailsPage({
|
||||
<Alert
|
||||
type={AlertTypeEnum.Alarm}
|
||||
variant="inline"
|
||||
heading={intl.formatMessage({ id: "Room sold out" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "Room sold out",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
|
||||
defaultMessage:
|
||||
"Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
|
||||
})}
|
||||
link={{
|
||||
title: intl.formatMessage({ id: "Change room" }),
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Change room",
|
||||
}),
|
||||
url: `${selectRate(lang)}?${selectRoomParams.toString()}`,
|
||||
keepSearchParams: true,
|
||||
}}
|
||||
|
||||
@@ -26,6 +26,7 @@ export default function HotelReservationPage({ params }: PageArgs<LangParams>) {
|
||||
}
|
||||
|
||||
return (
|
||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
<div className={styles.page}>
|
||||
<TrackingSDK pageData={pageTrackingData} />
|
||||
</div>
|
||||
|
||||
@@ -61,7 +61,9 @@ export default function Error({
|
||||
return (
|
||||
<section className={styles.layout}>
|
||||
<div className={styles.content}>
|
||||
{intl.formatMessage({ id: "Something went wrong!" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Something went wrong!",
|
||||
})}
|
||||
{env.NEXT_PUBLIC_NODE_ENV === "development" && (
|
||||
<pre>{error.stack || error.message}</pre>
|
||||
)}
|
||||
|
||||
@@ -52,6 +52,7 @@ export default async function RootLayout({
|
||||
id="Cookiebot"
|
||||
src="https://consent.cookiebot.com/uc.js"
|
||||
/>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Script id="ensure-adobeDataLayer">{`
|
||||
window.adobeDataLayer = window.adobeDataLayer || []
|
||||
`}</Script>
|
||||
|
||||
@@ -6,8 +6,9 @@ export default async function MiddlewareError({
|
||||
params,
|
||||
}: LayoutArgs<LangParams & StatusParams>) {
|
||||
return (
|
||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
<div className={styles.layout}>
|
||||
Middleware error {params.lang}: {params.status}
|
||||
Middleware error {params.lang} {params.status}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable formatjs/no-literal-string-in-jsx */
|
||||
|
||||
import "@scandic-hotels/design-system/fonts.css"
|
||||
import "@/app/globals.css"
|
||||
import "@/public/_static/css/design-system-current-deprecated.css"
|
||||
|
||||
@@ -43,6 +43,7 @@ export default async function RootLayout({
|
||||
id="Cookiebot"
|
||||
src="https://consent.cookiebot.com/uc.js"
|
||||
/>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Script id="ensure-adobeDataLayer">{`
|
||||
window.adobeDataLayer = window.adobeDataLayer || []
|
||||
`}</Script>
|
||||
|
||||
@@ -20,18 +20,25 @@ export function AlreadyLinkedError() {
|
||||
<SASModal>
|
||||
<MaterialIcon icon="cancel" isFilled size={64} />
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>{intl.formatMessage({ id: "Accounts are already linked" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Accounts are already linked",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Looks like you’ve already linked your Scandic Friends and SAS EuroBonus accounts!",
|
||||
defaultMessage:
|
||||
"Looks like you’ve already linked your Scandic Friends and SAS EuroBonus accounts!",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" asChild>
|
||||
<Link href={partnerSas[lang]}>
|
||||
{intl.formatMessage({ id: "View your linked accounts" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "View your linked accounts",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
<SASModalDivider />
|
||||
|
||||
@@ -25,18 +25,25 @@ export function DateOfBirthError() {
|
||||
size={64}
|
||||
/>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>{intl.formatMessage({ id: "Date of birth not matching" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Date of birth not matching",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "We couldn’t connect your accounts. Please contact us and we’ll help you resolve this.",
|
||||
defaultMessage:
|
||||
"We couldn’t connect your accounts. Please contact us and we’ll help you resolve this.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" asChild>
|
||||
<Link href={profile[lang]}>
|
||||
{intl.formatMessage({ id: "View your details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "View your details",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
<SASModalDivider />
|
||||
|
||||
@@ -13,18 +13,22 @@ export function FailedAttemptsError() {
|
||||
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({ id: "Too many failed attempts" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Too many failed attempts",
|
||||
})}
|
||||
variant="info"
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Please wait 1 hour before trying again.",
|
||||
defaultMessage: "Please wait 1 hour before trying again.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" disabled>
|
||||
{intl.formatMessage({ id: "Send new code" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Send new code",
|
||||
})}
|
||||
</Button>
|
||||
</GenericError>
|
||||
)
|
||||
|
||||
@@ -18,7 +18,11 @@ export function SASModalDivider() {
|
||||
return (
|
||||
<div className={styles.divider}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span>{intl.formatMessage({ id: "or" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "or",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
@@ -27,13 +31,17 @@ export function SASModalDivider() {
|
||||
export function SASModalContactBlock() {
|
||||
const intl = useIntl()
|
||||
|
||||
const phone = intl.formatMessage({ id: "+46 8 517 517 00" })
|
||||
const phone = intl.formatMessage({
|
||||
defaultMessage: "+46 8 517 517 00",
|
||||
})
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h4 className={styles.contactBlockTitle}>
|
||||
{intl.formatMessage({ id: "Contact us" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Contact us",
|
||||
})}
|
||||
</h4>
|
||||
</Typography>
|
||||
<Link
|
||||
@@ -42,6 +50,7 @@ export function SASModalContactBlock() {
|
||||
>
|
||||
{phone}
|
||||
</Link>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Link href="mailto:member@scandichotels.com" textDecoration="underline">
|
||||
member@scandichotels.com
|
||||
</Link>
|
||||
|
||||
@@ -13,18 +13,22 @@ export function TooManyCodesError() {
|
||||
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({ id: "You’ve requested too many codes" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "You’ve requested too many codes",
|
||||
})}
|
||||
variant="info"
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Please wait 1 hour before trying again.",
|
||||
defaultMessage: "Please wait 1 hour before trying again.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" disabled>
|
||||
{intl.formatMessage({ id: "Send new code" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Send new code",
|
||||
})}
|
||||
</Button>
|
||||
</GenericError>
|
||||
)
|
||||
|
||||
@@ -13,18 +13,22 @@ export function TooManyFailedAttemptsError() {
|
||||
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({ id: "Too many failed attempts." })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Too many failed attempts.",
|
||||
})}
|
||||
variant="info"
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Please wait 1 hour before trying again.",
|
||||
defaultMessage: "Please wait 1 hour before trying again.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" disabled>
|
||||
{intl.formatMessage({ id: "Send new code" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Send new code",
|
||||
})}
|
||||
</Button>
|
||||
</GenericError>
|
||||
)
|
||||
|
||||
@@ -26,13 +26,13 @@ export default function Error({
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "Something went wrong",
|
||||
defaultMessage: "Something went wrong",
|
||||
})}
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Please try again later",
|
||||
defaultMessage: "Please try again later",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -37,13 +37,14 @@ export default async function Page({
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "We could not connect your accounts",
|
||||
defaultMessage: "We could not connect your accounts",
|
||||
})}
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "We couldn’t connect your accounts. Please contact us and we’ll help you resolve this.",
|
||||
defaultMessage:
|
||||
"We couldn’t connect your accounts. Please contact us and we’ll help you resolve this.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -29,10 +29,14 @@ export default async function SasXScandicLayout({
|
||||
<Link className={styles.backLink} href={profileOverview[params.lang]}>
|
||||
<ArrowLeft height={20} width={20} />
|
||||
<span className={styles.long}>
|
||||
{intl.formatMessage({ id: "Back to scandichotels.com" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back to scandichotels.com",
|
||||
})}
|
||||
</span>
|
||||
<span className={styles.short}>
|
||||
{intl.formatMessage({ id: "Back" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</span>
|
||||
</Link>
|
||||
<MainMenuLogo />
|
||||
@@ -45,7 +49,13 @@ export default async function SasXScandicLayout({
|
||||
async function MainMenuLogo() {
|
||||
const intl = await getIntl()
|
||||
|
||||
return <Logo alt={intl.formatMessage({ id: "Back to scandichotels.com" })} />
|
||||
return (
|
||||
<Logo
|
||||
alt={intl.formatMessage({
|
||||
defaultMessage: "Back to scandichotels.com",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function Logo({ alt }: { alt: string }) {
|
||||
|
||||
@@ -61,7 +61,11 @@ export function LinkAccountForm({
|
||||
src="/_static/img/partner/sas/sas-campaign-logo.png"
|
||||
/>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>{intl.formatMessage({ id: "Link your accounts" })}</h3>
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Link your accounts",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.dateOfBirth}>
|
||||
@@ -70,19 +74,23 @@ export function LinkAccountForm({
|
||||
{userDateOfBirth
|
||||
? intl.formatMessage(
|
||||
{
|
||||
id: "Birth date: {dateOfBirth, date, ::MMMM d yyyy}",
|
||||
defaultMessage:
|
||||
"Birth date: {dateOfBirth, date, ::MMMM d yyyy}",
|
||||
},
|
||||
{
|
||||
dateOfBirth: new Date(userDateOfBirth),
|
||||
}
|
||||
)
|
||||
: intl.formatMessage({ id: "Birth date is missing" })}
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Birth date is missing",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Label/xsRegular">
|
||||
<p className={styles.dateOfBirthDescription}>
|
||||
{intl.formatMessage({
|
||||
id: "We require your birth date in order to link your Scandic Friends account with your SAS EuroBonus account. Please check that it is correct.",
|
||||
defaultMessage:
|
||||
"We require your birth date in order to link your Scandic Friends account with your SAS EuroBonus account. Please check that it is correct.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -93,7 +101,7 @@ export function LinkAccountForm({
|
||||
variant="underscored"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "Edit your personal details",
|
||||
defaultMessage: "Edit your personal details",
|
||||
})}
|
||||
|
||||
<MaterialIcon icon="arrow_forward" size={18} color="CurrentColor" />
|
||||
@@ -106,7 +114,7 @@ export function LinkAccountForm({
|
||||
required: {
|
||||
value: true,
|
||||
message: intl.formatMessage({
|
||||
id: "You must accept the terms and conditions",
|
||||
defaultMessage: "You must accept the terms and conditions",
|
||||
}),
|
||||
},
|
||||
disabled: !userDateOfBirth,
|
||||
@@ -115,7 +123,7 @@ export function LinkAccountForm({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "I accept the terms and conditions",
|
||||
defaultMessage: "I accept the terms and conditions",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -124,7 +132,8 @@ export function LinkAccountForm({
|
||||
<p className={styles.termsDescription}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "By linking your accounts you accept the <sasScandicTermsAndConditionsLink>Terms & Conditions for Scandic Friends and SAS EuroBonus Account Linking</sasScandicTermsAndConditionsLink>.",
|
||||
defaultMessage:
|
||||
"By linking your accounts you accept the <sasScandicTermsAndConditionsLink>Terms & Conditions for Scandic Friends and SAS EuroBonus Account Linking</sasScandicTermsAndConditionsLink>.",
|
||||
},
|
||||
{
|
||||
sasScandicTermsAndConditionsLink: (str) => (
|
||||
@@ -150,7 +159,9 @@ export function LinkAccountForm({
|
||||
type="submit"
|
||||
disabled={isPending || disableSubmit}
|
||||
>
|
||||
{intl.formatMessage({ id: "Link my accounts" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Link my accounts",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -26,20 +26,24 @@ export default async function SASxScandicLinkPage({
|
||||
color="Icon/Feedback/Success"
|
||||
/>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>{intl.formatMessage({ id: "Your accounts are linked" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your accounts are linked",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "We successfully connected your accounts!",
|
||||
defaultMessage: "We successfully connected your accounts!",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Redirecting you to my pages.",
|
||||
defaultMessage: "Redirecting you to my pages.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -51,13 +51,16 @@ export default async function SASxScandicLoginPage({
|
||||
|
||||
const intentDescriptions: Record<Intent, string> = {
|
||||
link: intl.formatMessage({
|
||||
id: "Log in to your SAS EuroBonus account to confirm account linking.",
|
||||
defaultMessage:
|
||||
"Log in to your SAS EuroBonus account to confirm account linking.",
|
||||
}),
|
||||
unlink: intl.formatMessage({
|
||||
id: "Log in to your SAS Eurobonus account to confirm account unlinking.",
|
||||
defaultMessage:
|
||||
"Log in to your SAS Eurobonus account to confirm account unlinking.",
|
||||
}),
|
||||
transfer: intl.formatMessage({
|
||||
id: "In order to transfer your points we will ask you to sign in to your SAS EuroBonus account.",
|
||||
defaultMessage:
|
||||
"In order to transfer your points we will ask you to sign in to your SAS EuroBonus account.",
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -72,7 +75,11 @@ export default async function SASxScandicLoginPage({
|
||||
style={{ marginTop: 16 }}
|
||||
/>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>{intl.formatMessage({ id: "Redirecting you to SAS" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Redirecting you to SAS",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p style={{ textAlign: "center" }}>
|
||||
@@ -82,7 +89,8 @@ export default async function SASxScandicLoginPage({
|
||||
<Footnote textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "If you are not redirected automatically, please <loginLink>click here</loginLink>.",
|
||||
defaultMessage:
|
||||
"If you are not redirected automatically, please <loginLink>click here</loginLink>.",
|
||||
},
|
||||
{
|
||||
loginLink: (str) => (
|
||||
|
||||
@@ -56,7 +56,9 @@ export default function OneTimePasswordForm({
|
||||
if (requestOtp.isError) {
|
||||
const cause = requestOtp.error?.data?.cause as RequestOtpError
|
||||
|
||||
const title = intl.formatMessage({ id: "Error requesting OTP" })
|
||||
const title = intl.formatMessage({
|
||||
defaultMessage: "Error requesting OTP",
|
||||
})
|
||||
const body = getRequestErrorBody(intl, cause?.errorCode)
|
||||
|
||||
return (
|
||||
@@ -125,11 +127,12 @@ export default function OneTimePasswordForm({
|
||||
|
||||
const errorMessages: Record<OtpError, ReactNode> = {
|
||||
invalidCode: intl.formatMessage({
|
||||
id: "The code you've entered is incorrect.",
|
||||
defaultMessage: "The code you've entered is incorrect.",
|
||||
}),
|
||||
expiredCode: intl.formatMessage(
|
||||
{
|
||||
id: "This code has expired. <resendOtpLink>Send new code.</resendOtpLink>",
|
||||
defaultMessage:
|
||||
"This code has expired. <resendOtpLink>Send new code.</resendOtpLink>",
|
||||
},
|
||||
{
|
||||
resendOtpLink: getResendOtpLink,
|
||||
@@ -189,7 +192,8 @@ export default function OneTimePasswordForm({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "Didn't receive a code? <resendOtpLink>Resend code</resendOtpLink>",
|
||||
defaultMessage:
|
||||
"Didn't receive a code? <resendOtpLink>Resend code</resendOtpLink>",
|
||||
},
|
||||
{
|
||||
resendOtpLink: getResendOtpLink,
|
||||
@@ -226,11 +230,11 @@ const getRequestErrorBody = (
|
||||
switch (errorCode) {
|
||||
case "TOO_MANY_REQUESTS":
|
||||
return intl.formatMessage({
|
||||
id: "Too many requests. Please try again later.",
|
||||
defaultMessage: "Too many requests. Please try again later.",
|
||||
})
|
||||
default:
|
||||
return intl.formatMessage({
|
||||
id: "An error occurred while requesting a new OTP",
|
||||
defaultMessage: "An error occurred while requesting a new OTP",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function Loading() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Hang tight...",
|
||||
defaultMessage: "Hang tight...",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -110,19 +110,22 @@ export default async function SASxScandicOneTimePasswordPage({
|
||||
const intentDescriptions: Record<Intent, ReactNode> = {
|
||||
link: intl.formatMessage(
|
||||
{
|
||||
id: "Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to confirm your account linking.",
|
||||
defaultMessage:
|
||||
"Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to confirm your account linking.",
|
||||
},
|
||||
{ maskedContactInfo }
|
||||
),
|
||||
unlink: intl.formatMessage(
|
||||
{
|
||||
id: "Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to unlink your accounts.",
|
||||
defaultMessage:
|
||||
"Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to unlink your accounts.",
|
||||
},
|
||||
{ maskedContactInfo }
|
||||
),
|
||||
transfer: intl.formatMessage(
|
||||
{
|
||||
id: "Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to transfer your points.",
|
||||
defaultMessage:
|
||||
"Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to transfer your points.",
|
||||
},
|
||||
{ maskedContactInfo }
|
||||
),
|
||||
@@ -130,10 +133,12 @@ export default async function SASxScandicOneTimePasswordPage({
|
||||
|
||||
return (
|
||||
<OneTimePasswordForm
|
||||
heading={intl.formatMessage({ id: "Verification code" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "Verification code",
|
||||
})}
|
||||
ingress={intentDescriptions[intent]}
|
||||
footnote={intl.formatMessage({
|
||||
id: "This verifcation is needed for additional security.",
|
||||
defaultMessage: "This verifcation is needed for additional security.",
|
||||
})}
|
||||
otpLength={6}
|
||||
onSubmit={handleOtpVerified}
|
||||
|
||||
@@ -40,7 +40,11 @@ export default async function SASxScandicTransferSuccessPage({
|
||||
/>
|
||||
<div className={styles.container}>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>{intl.formatMessage({ id: "Point transfer completed!" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Point transfer completed!",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<TransactionCard addedPoints={addedPoints} lang={lang} />
|
||||
<div className={styles.divider} />
|
||||
@@ -52,7 +56,7 @@ export default async function SASxScandicTransferSuccessPage({
|
||||
>
|
||||
<Link href={partnerSas[params.lang]} color="none">
|
||||
{intl.formatMessage({
|
||||
id: "Go back to My Pages",
|
||||
defaultMessage: "Go back to My Pages",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -80,20 +84,33 @@ async function TransactionCard({
|
||||
return (
|
||||
<div className={styles.transactionBox}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>{intl.formatMessage({ id: "Your transaction" })}</h2>
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your transaction",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<div className={styles.transactionDetails}>
|
||||
<div className={styles.transactionRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h3>{intl.formatMessage({ id: "Points added" })}</h3>
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Points added",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<p>+ {transferredPoints}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.transactionRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h3>{intl.formatMessage({ id: "Your new total" })}</h3>
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your new total",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Suspense fallback={<SkeletonShimmer width="15ch" height="24px" />}>
|
||||
<TotalPoints />
|
||||
@@ -106,14 +123,15 @@ async function TransactionCard({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "You have enough points for a bonus night!",
|
||||
defaultMessage: "You have enough points for a bonus night!",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Bonus Nights range from 10 000 - 80 000 points. Book your next stay with us today!",
|
||||
defaultMessage:
|
||||
"Bonus Nights range from 10 000 - 80 000 points. Book your next stay with us today!",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -128,7 +146,13 @@ async function TransactionCard({
|
||||
>
|
||||
{/* TODO correct link */}
|
||||
<Link href={hotelreservation(lang)} color="none">
|
||||
{intl.formatMessage({ id: "Book now" })}{" "}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Book now",
|
||||
})}
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
}
|
||||
<MaterialIcon
|
||||
icon="calendar_add_on"
|
||||
size={20}
|
||||
@@ -150,9 +174,12 @@ async function TotalPoints() {
|
||||
return (
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
={" "}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{"= "}
|
||||
{intl.formatMessage(
|
||||
{ id: "{points, number} points" },
|
||||
{
|
||||
defaultMessage: "{points, number} points",
|
||||
},
|
||||
{
|
||||
points,
|
||||
}
|
||||
|
||||
@@ -26,13 +26,17 @@ export default async function SASxScandicUnlinkSuccessPage({
|
||||
color="Icon/Feedback/Success"
|
||||
/>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>{intl.formatMessage({ id: "Your accounts are now unlinked" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your accounts are now unlinked",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Redirecting you to My Pages.",
|
||||
defaultMessage: "Redirecting you to My Pages.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -47,6 +47,7 @@ export default async function RootLayout({
|
||||
id="Cookiebot"
|
||||
src="https://consent.cookiebot.com/uc.js"
|
||||
/>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Script id="ensure-adobeDataLayer">{`
|
||||
window.adobeDataLayer = window.adobeDataLayer || []
|
||||
`}</Script>
|
||||
|
||||
@@ -22,7 +22,13 @@ export default async function ContentTypePage({
|
||||
|
||||
if (!user) {
|
||||
console.log(`[webview:page] unable to load user`)
|
||||
return <p>{intl.formatMessage({ id: "Error: No user could be loaded" })}</p>
|
||||
return (
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Error: No user could be loaded",
|
||||
})}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
if ("error" in user) {
|
||||
@@ -36,11 +42,19 @@ export default async function ContentTypePage({
|
||||
console.log(`[webview:page] user error, redirecting to: ${redirectURL}`)
|
||||
redirect(redirectURL)
|
||||
case "notfound":
|
||||
return <p>{intl.formatMessage({ id: "Error: user not found" })}</p>
|
||||
return (
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Error: user not found",
|
||||
})}
|
||||
</p>
|
||||
)
|
||||
case "unknown":
|
||||
return (
|
||||
<p>
|
||||
{intl.formatMessage({ id: "Unknown error occurred loading user" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Unknown error occurred loading user",
|
||||
})}
|
||||
</p>
|
||||
)
|
||||
default:
|
||||
|
||||
@@ -38,6 +38,7 @@ export default async function RootLayout({
|
||||
<head>
|
||||
<AdobeSDKScript />
|
||||
<GTMScript />
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Script id="ensure-adobeDataLayer">{`
|
||||
window.adobeDataLayer = window.adobeDataLayer || []
|
||||
`}</Script>
|
||||
|
||||
@@ -23,7 +23,11 @@ export default function GlobalError({
|
||||
<html>
|
||||
<body>
|
||||
<div className={styles.layout}>
|
||||
<h1>{intl.formatMessage({ id: "Something went really wrong!" })}</h1>
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Something went really wrong!",
|
||||
})}
|
||||
</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -12,7 +12,11 @@ export default async function HowItWorks({ dynamic_content }: HowItWorksProps) {
|
||||
return (
|
||||
<SectionWrapper dynamic_content={dynamic_content}>
|
||||
<section className={styles.container}>
|
||||
<Title level="h3">{intl.formatMessage({ id: "How it works" })}</Title>
|
||||
<Title level="h3">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "How it works",
|
||||
})}
|
||||
</Title>
|
||||
</section>
|
||||
</SectionWrapper>
|
||||
)
|
||||
|
||||
@@ -33,8 +33,12 @@ export default function Filter({
|
||||
<Select
|
||||
items={countryFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({ id: "Country" })}
|
||||
aria-label={intl.formatMessage({ id: "Country" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
name="country"
|
||||
onSelect={(value) => onFilterChange(JobylonFilterKey.country, value)}
|
||||
/>
|
||||
@@ -42,10 +46,10 @@ export default function Filter({
|
||||
items={cityFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({
|
||||
id: "Location (shown in local language)",
|
||||
defaultMessage: "Location (shown in local language)",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "Location (shown in local language)",
|
||||
defaultMessage: "Location (shown in local language)",
|
||||
})}
|
||||
name="city"
|
||||
onSelect={(value) => onFilterChange(JobylonFilterKey.city, value)}
|
||||
@@ -53,16 +57,24 @@ export default function Filter({
|
||||
<Select
|
||||
items={departmentFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({ id: "Hotel or office" })}
|
||||
aria-label={intl.formatMessage({ id: "Hotel or office" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Hotel or office",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Hotel or office",
|
||||
})}
|
||||
name="department"
|
||||
onSelect={(value) => onFilterChange(JobylonFilterKey.department, value)}
|
||||
/>
|
||||
<Select
|
||||
items={categoryFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({ id: "Category" })}
|
||||
aria-label={intl.formatMessage({ id: "Category" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Category",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Category",
|
||||
})}
|
||||
name="category"
|
||||
onSelect={(value) => onFilterChange(JobylonFilterKey.category, value)}
|
||||
/>
|
||||
|
||||
@@ -31,19 +31,39 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
}
|
||||
|
||||
const countryFilters = [
|
||||
{ label: intl.formatMessage({ id: "All countries" }), value: "" },
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "All countries",
|
||||
}),
|
||||
value: "",
|
||||
},
|
||||
...state.countryFilters,
|
||||
]
|
||||
const cityFilters = [
|
||||
{ label: intl.formatMessage({ id: "All locations" }), value: "" },
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "All locations",
|
||||
}),
|
||||
value: "",
|
||||
},
|
||||
...state.cityFilters,
|
||||
]
|
||||
const departmentFilters = [
|
||||
{ label: intl.formatMessage({ id: "All hotels and offices" }), value: "" },
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "All hotels and offices",
|
||||
}),
|
||||
value: "",
|
||||
},
|
||||
...state.departmentFilters,
|
||||
]
|
||||
const categoryFilters = [
|
||||
{ label: intl.formatMessage({ id: "All categories" }), value: "" },
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "All categories",
|
||||
}),
|
||||
value: "",
|
||||
},
|
||||
...state.categoryFilters,
|
||||
]
|
||||
|
||||
@@ -59,7 +79,7 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{count, plural, one {# Result} other {# Results}}",
|
||||
defaultMessage: "{count, plural, one {# Result} other {# Results}}",
|
||||
},
|
||||
{ count: state.jobs.length }
|
||||
)}
|
||||
|
||||
@@ -24,10 +24,14 @@ export default function JobylonCard({ job }: JobylonCardProps) {
|
||||
const lang = useLang()
|
||||
const deadlineText = job.toDate
|
||||
? intl.formatMessage(
|
||||
{ id: "Deadline: {date}" },
|
||||
{
|
||||
defaultMessage: "Deadline: {date}",
|
||||
},
|
||||
{ date: dt(job.toDate).locale(lang).format("Do MMMM") }
|
||||
)
|
||||
: intl.formatMessage({ id: "Open for application" })
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Open for application",
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styles.jobylonCard}>
|
||||
@@ -53,7 +57,9 @@ export default function JobylonCard({ job }: JobylonCardProps) {
|
||||
asChild
|
||||
>
|
||||
<a href={job.url} target="_blank" rel="noopener noreferrer">
|
||||
{intl.formatMessage({ id: "View & apply" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "View & apply",
|
||||
})}
|
||||
<MaterialIcon icon="open_in_new" size={20} />
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
@@ -37,14 +37,17 @@ async function LevelCard({ level }: LevelCardProps) {
|
||||
const intl = await getIntl()
|
||||
|
||||
let pointsMsg: React.ReactNode = intl.formatMessage(
|
||||
{ id: "{pointsAmount, number} points" },
|
||||
{
|
||||
defaultMessage: "{pointsAmount, number} points",
|
||||
},
|
||||
{ pointsAmount: level.required_points }
|
||||
)
|
||||
|
||||
if (level.required_nights) {
|
||||
pointsMsg = intl.formatMessage(
|
||||
{
|
||||
id: "{pointsAmount, number} points <highlight>or {nightsAmount, number} nights</highlight>",
|
||||
defaultMessage:
|
||||
"{pointsAmount, number} points <highlight>or {nightsAmount, number} nights</highlight>",
|
||||
},
|
||||
{
|
||||
pointsAmount: level.required_points,
|
||||
@@ -63,7 +66,9 @@ async function LevelCard({ level }: LevelCardProps) {
|
||||
tilted="large"
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "Level {level}" },
|
||||
{
|
||||
defaultMessage: "Level {level}",
|
||||
},
|
||||
{ level: level.user_facing_tag }
|
||||
)}
|
||||
</BiroScript>
|
||||
|
||||
@@ -18,10 +18,16 @@ export default function CopyButton({ membershipNumber }: CopyButtonProps) {
|
||||
try {
|
||||
navigator.clipboard.writeText(membershipNumber)
|
||||
toast.success(
|
||||
intl.formatMessage({ id: "Membership ID copied to clipboard" })
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Membership ID copied to clipboard",
|
||||
})
|
||||
)
|
||||
} catch {
|
||||
toast.error(intl.formatMessage({ id: "Failed to copy" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to copy",
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,17 @@ export default async function MembershipNumber({
|
||||
return (
|
||||
<div className={classNames}>
|
||||
<Caption color="pale">
|
||||
{intl.formatMessage({ id: "Membership ID:" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Membership ID:",
|
||||
})}
|
||||
</Caption>
|
||||
<span className={styles.icon}>
|
||||
<Caption className={styles.icon} color="pale" asChild>
|
||||
<code data-hj-suppress>
|
||||
{membership?.membershipNumber ?? intl.formatMessage({ id: "N/A" })}
|
||||
{membership?.membershipNumber ??
|
||||
intl.formatMessage({
|
||||
defaultMessage: "N/A",
|
||||
})}
|
||||
</code>
|
||||
</Caption>
|
||||
{membership?.membershipNumber && (
|
||||
|
||||
@@ -24,10 +24,14 @@ export default async function Friend({
|
||||
}
|
||||
const isHighestLevel = isHighestMembership(membership.membershipLevel)
|
||||
|
||||
const lvlMessageHighest = intl.formatMessage({ id: "Highest level" })
|
||||
const lvlMessageHighest = intl.formatMessage({
|
||||
defaultMessage: "Highest level",
|
||||
})
|
||||
|
||||
const lvlMessageLevel = intl.formatMessage(
|
||||
{ id: "Level {level}" },
|
||||
{
|
||||
defaultMessage: "Level {level}",
|
||||
},
|
||||
{ level: membershipLevels[membership.membershipLevel] }
|
||||
)
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ export default async function ExpiringPoints({ user }: UserProps) {
|
||||
<section>
|
||||
<Body color="white" textTransform="bold" textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{ id: "{points} spendable points expiring by {date}" },
|
||||
{
|
||||
defaultMessage: "{points} spendable points expiring by {date}",
|
||||
},
|
||||
{
|
||||
points: intl.formatNumber(membership.pointsToExpire),
|
||||
date: d.format(dateFormat),
|
||||
|
||||
@@ -25,15 +25,23 @@ export default async function Points({ user }: UserProps) {
|
||||
<PointsContainer>
|
||||
<PointsColumn
|
||||
value={membership?.currentPoints}
|
||||
title={intl.formatMessage({ id: "Your points to spend" })}
|
||||
subtitle={intl.formatMessage({ id: "as of today" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Your points to spend",
|
||||
})}
|
||||
subtitle={intl.formatMessage({
|
||||
defaultMessage: "as of today",
|
||||
})}
|
||||
/>
|
||||
{nextLevel && (
|
||||
<PointsColumn
|
||||
value={membership?.pointsRequiredToNextlevel}
|
||||
title={intl.formatMessage({ id: "Points needed to level up" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Points needed to level up",
|
||||
})}
|
||||
subtitle={intl.formatMessage(
|
||||
{ id: "next level: {nextLevel}" },
|
||||
{
|
||||
defaultMessage: "next level: {nextLevel}",
|
||||
},
|
||||
{ nextLevel: nextLevel.name }
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -99,9 +99,13 @@ export default function OverviewTableClient({
|
||||
showDescription={false}
|
||||
/>
|
||||
<Select
|
||||
aria-label={intl.formatMessage({ id: "Level" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
name={`reward` + column}
|
||||
label={intl.formatMessage({ id: "Level" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
items={levelOptions}
|
||||
value={selectedLevelMobile.level_id}
|
||||
onSelect={handleSelectChange(actionEnumMobile)}
|
||||
@@ -134,9 +138,13 @@ export default function OverviewTableClient({
|
||||
}
|
||||
return (
|
||||
<Select
|
||||
aria-label={intl.formatMessage({ id: "Level" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
name={`reward` + column}
|
||||
label={intl.formatMessage({ id: "Level" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
items={levelOptions}
|
||||
value={selectedLevelDesktop.level_id}
|
||||
onSelect={handleSelectChange(actionEnumDesktop)}
|
||||
|
||||
@@ -13,7 +13,8 @@ export default function LevelSummary({
|
||||
const pointsMsg: React.ReactNode = level.required_nights
|
||||
? intl.formatMessage(
|
||||
{
|
||||
id: "{pointsAmount, number} points or {nightsAmount, number} nights",
|
||||
defaultMessage:
|
||||
"{pointsAmount, number} points or {nightsAmount, number} nights",
|
||||
},
|
||||
{
|
||||
pointsAmount: level.required_points,
|
||||
@@ -21,7 +22,9 @@ export default function LevelSummary({
|
||||
}
|
||||
)
|
||||
: intl.formatMessage(
|
||||
{ id: "{pointsAmount, number} points" },
|
||||
{
|
||||
defaultMessage: "{pointsAmount, number} points",
|
||||
},
|
||||
{ pointsAmount: level.required_points }
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@ export default function YourLevel() {
|
||||
type="two"
|
||||
textAlign={"center"}
|
||||
>
|
||||
{intl.formatMessage({ id: "Your level" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your level",
|
||||
})}
|
||||
</BiroScript>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@ export default function AwardPoints({
|
||||
<Body textTransform="bold" className={classNames}>
|
||||
{isCalculated
|
||||
? intl.formatNumber(awardPoints)
|
||||
: intl.formatMessage({ id: "Points being calculated" })}
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Points being calculated",
|
||||
})}
|
||||
</Body>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function Row({ transaction }: RowProps) {
|
||||
|
||||
const nightsMsg = intl.formatMessage(
|
||||
{
|
||||
id: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{
|
||||
totalNights: transaction.nights,
|
||||
@@ -40,28 +40,40 @@ export default function Row({ transaction }: RowProps) {
|
||||
case Transactions.rewardType.stay:
|
||||
case Transactions.rewardType.stayAdj:
|
||||
if (transaction.hotelId === "ORS") {
|
||||
description = intl.formatMessage({ id: "Former Scandic Hotel" })
|
||||
description = intl.formatMessage({
|
||||
defaultMessage: "Former Scandic Hotel",
|
||||
})
|
||||
}
|
||||
if (transaction.confirmationNumber === "BALFWD") {
|
||||
description = intl.formatMessage({
|
||||
id: "Points earned prior to May 1, 2021",
|
||||
defaultMessage: "Points earned prior to May 1, 2021",
|
||||
})
|
||||
}
|
||||
break
|
||||
case Transactions.rewardType.ancillary:
|
||||
description = intl.formatMessage({ id: "Extras to your booking" })
|
||||
description = intl.formatMessage({
|
||||
defaultMessage: "Extras to your booking",
|
||||
})
|
||||
break
|
||||
case Transactions.rewardType.enrollment:
|
||||
description = intl.formatMessage({ id: "Sign up bonus" })
|
||||
description = intl.formatMessage({
|
||||
defaultMessage: "Sign up bonus",
|
||||
})
|
||||
break
|
||||
case Transactions.rewardType.mastercard_points:
|
||||
description = intl.formatMessage({ id: "Scandic Friends Mastercard" })
|
||||
description = intl.formatMessage({
|
||||
defaultMessage: "Scandic Friends Mastercard",
|
||||
})
|
||||
break
|
||||
case Transactions.rewardType.tui_points:
|
||||
description = intl.formatMessage({ id: "TUI Points" })
|
||||
description = intl.formatMessage({
|
||||
defaultMessage: "TUI Points",
|
||||
})
|
||||
|
||||
case Transactions.rewardType.pointShop:
|
||||
description = intl.formatMessage({ id: "Scandic Friends Point Shop" })
|
||||
description = intl.formatMessage({
|
||||
defaultMessage: "Scandic Friends Point Shop",
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,18 @@ export default function ClientTable({ transactions }: ClientTableProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const tableHeadings = [
|
||||
intl.formatMessage({ id: "Points" }),
|
||||
intl.formatMessage({ id: "Description" }),
|
||||
intl.formatMessage({ id: "Booking number" }),
|
||||
intl.formatMessage({ id: "Arrival date" }),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Description",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Booking number",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Arrival date",
|
||||
}),
|
||||
]
|
||||
|
||||
return (
|
||||
@@ -44,7 +52,9 @@ export default function ClientTable({ transactions }: ClientTableProps) {
|
||||
) : (
|
||||
<Table.TR className={styles.placeholder}>
|
||||
<Table.TD colSpan={tableHeadings.length}>
|
||||
{intl.formatMessage({ id: "No transactions available" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No transactions available",
|
||||
})}
|
||||
</Table.TD>
|
||||
</Table.TR>
|
||||
)}
|
||||
|
||||
@@ -22,8 +22,12 @@ export default function ExpiringPointsTable({
|
||||
const expiration = dt(expirationDate).locale(lang).format("DD MMM YYYY")
|
||||
|
||||
const tableHeadings = [
|
||||
intl.formatMessage({ id: "Points" }),
|
||||
intl.formatMessage({ id: "Expiration Date" }),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Expiration Date",
|
||||
}),
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
@@ -47,12 +47,16 @@ export default async function NextLevelRewardsBlock({
|
||||
<article key={reward.reward_id} className={styles.card}>
|
||||
<Chip>
|
||||
<Lock height={16} />
|
||||
{intl.formatMessage({ id: "Level up to unlock" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Level up to unlock",
|
||||
})}
|
||||
</Chip>
|
||||
<div className={styles.textContainer}>
|
||||
<Body color="peach50" textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{ id: "As our {level}" },
|
||||
{
|
||||
defaultMessage: "As our {level}",
|
||||
},
|
||||
{ level: nextLevelRewards.level?.name }
|
||||
)}
|
||||
</Body>
|
||||
|
||||
@@ -26,7 +26,11 @@ export default function ActiveRedeemedBadge() {
|
||||
>
|
||||
<MaterialIcon icon="check_circle" color="Icon/Feedback/Success" />
|
||||
</motion.div>
|
||||
<Caption>{intl.formatMessage({ id: "Active" })}</Caption>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Active",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,17 +17,18 @@ export function ConfirmClose({ close }: { close: VoidFunction }) {
|
||||
<div className={styles.modalContent}>
|
||||
<Title level="h3" textAlign="center" textTransform="regular">
|
||||
{intl.formatMessage({
|
||||
id: "If you close this your benefit will be removed",
|
||||
defaultMessage: "If you close this your benefit will be removed",
|
||||
})}
|
||||
</Title>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "Have you showed this benefit to the hotel staff?",
|
||||
defaultMessage: "Have you showed this benefit to the hotel staff?",
|
||||
})}
|
||||
</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "If not, please go back and do so before you close this. Once you close this your benefit will be void and removed from My Benefits.",
|
||||
defaultMessage:
|
||||
"If not, please go back and do so before you close this. Once you close this your benefit will be void and removed from My Benefits.",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
@@ -37,10 +38,14 @@ export function ConfirmClose({ close }: { close: VoidFunction }) {
|
||||
intent="primary"
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({ id: "No, go back" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No, go back",
|
||||
})}
|
||||
</Button>
|
||||
<Button onClick={close} intent="secondary" theme="base">
|
||||
{intl.formatMessage({ id: "Yes, close and remove benefit" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Yes, close and remove benefit",
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
</>
|
||||
|
||||
@@ -29,7 +29,9 @@ export default function Campaign({ reward }: { reward: Campaign }) {
|
||||
<Body textAlign="center">{reward.description}</Body>
|
||||
<div className={styles.rewardBadge}>
|
||||
<Caption textAlign="center" color="uiTextHighContrast" type="bold">
|
||||
{intl.formatMessage({ id: "Promo code" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Promo code",
|
||||
})}
|
||||
</Caption>
|
||||
<Caption textAlign="center" color="uiTextHighContrast">
|
||||
{reward.operaRewardId}
|
||||
@@ -41,9 +43,17 @@ export default function Campaign({ reward }: { reward: Campaign }) {
|
||||
onClick={() => {
|
||||
try {
|
||||
navigator.clipboard.writeText(reward.operaRewardId)
|
||||
toast.success(intl.formatMessage({ id: "Copied to clipboard" }))
|
||||
toast.success(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Copied to clipboard",
|
||||
})
|
||||
)
|
||||
} catch {
|
||||
toast.error(intl.formatMessage({ id: "Failed to copy" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to copy",
|
||||
})
|
||||
)
|
||||
}
|
||||
}}
|
||||
type="button"
|
||||
@@ -53,7 +63,9 @@ export default function Campaign({ reward }: { reward: Campaign }) {
|
||||
intent="primary"
|
||||
>
|
||||
<MaterialIcon icon="content_copy" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "Copy promotion code" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Copy promotion code",
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
</>
|
||||
|
||||
@@ -86,7 +86,9 @@ export default function Tier({
|
||||
intent="primary"
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({ id: "Redeem benefit" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Redeem benefit",
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
)}
|
||||
@@ -99,14 +101,18 @@ export default function Tier({
|
||||
intent="primary"
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({ id: "Yes, redeem" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Yes, redeem",
|
||||
})}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setRedeemStep("initial")}
|
||||
intent="secondary"
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({ id: "Go back" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Go back",
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
)}
|
||||
|
||||
@@ -15,7 +15,9 @@ export default function MembershipNumberBadge({
|
||||
<div className={styles.rewardBadge}>
|
||||
<Caption textAlign="center" color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Membership ID: {id}" },
|
||||
{
|
||||
defaultMessage: "Membership ID: {id}",
|
||||
},
|
||||
{ id: membershipNumber }
|
||||
)}
|
||||
</Caption>
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function TimedRedeemedBadge() {
|
||||
<MaterialIcon icon="check_circle" color="Icon/Feedback/Success" />
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "Redeemed & valid through:",
|
||||
defaultMessage: "Redeemed & valid through:",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
|
||||
@@ -71,8 +71,12 @@ export default function Redeem({ reward, membershipNumber }: RedeemProps) {
|
||||
>
|
||||
<Button intent="primary" fullWidth>
|
||||
{reward.redeemLocation === "Non-redeemable"
|
||||
? intl.formatMessage({ id: "How to use" })
|
||||
: intl.formatMessage({ id: "Open" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "How to use",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Open",
|
||||
})}
|
||||
</Button>
|
||||
<MotionOverlay
|
||||
className={styles.overlay}
|
||||
|
||||
@@ -21,11 +21,17 @@ export default function ScriptedRewardText({
|
||||
: null
|
||||
}
|
||||
case "Campaign":
|
||||
return intl.formatMessage({ id: "Campaign" })
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Campaign",
|
||||
})
|
||||
case "Surprise":
|
||||
return intl.formatMessage({ id: "Surprise!" })
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Surprise!",
|
||||
})
|
||||
case "Member-voucher":
|
||||
return intl.formatMessage({ id: "Voucher" })
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "Voucher",
|
||||
})
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -17,17 +17,24 @@ export function UnlinkSAS() {
|
||||
return (
|
||||
<Dialog
|
||||
titleText={intl.formatMessage({
|
||||
id: "Are you sure you want to unlink your account?",
|
||||
defaultMessage: "Are you sure you want to unlink your account?",
|
||||
})}
|
||||
bodyText={intl.formatMessage({
|
||||
id: "This will remove any membership level upgrades gained from the linking.",
|
||||
defaultMessage:
|
||||
"This will remove any membership level upgrades gained from the linking.",
|
||||
})}
|
||||
cancelButtonText={intl.formatMessage({
|
||||
defaultMessage: "Go back",
|
||||
})}
|
||||
proceedText={intl.formatMessage({
|
||||
defaultMessage: "Yes, unlink my accounts",
|
||||
})}
|
||||
cancelButtonText={intl.formatMessage({ id: "Go back" })}
|
||||
proceedText={intl.formatMessage({ id: "Yes, unlink my accounts" })}
|
||||
proceedHref={`/${params.lang}/sas-x-scandic/login?intent=unlink`}
|
||||
trigger={
|
||||
<Button intent="text" theme="base">
|
||||
{intl.formatMessage({ id: "Unlink accounts" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Unlink accounts",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Button>
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ export default async function SASLinkedAccount({
|
||||
<p className={styles.caption}>
|
||||
<MaterialIcon icon="info" size={20} />
|
||||
{intl.formatMessage({
|
||||
id: "Changes in your level match can take up to 24 hours to be displayed.",
|
||||
defaultMessage:
|
||||
"Changes in your level match can take up to 24 hours to be displayed.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -96,20 +97,37 @@ async function MatchedAccountInfo() {
|
||||
<section className={styles.matchedAccountSection}>
|
||||
<div className={styles.accountDetails}>
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Linked account" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Linked account",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "SAS EuroBonus" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Level" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{sasLevelName}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={cx(styles.stack, styles.accountMemberNumber)}>
|
||||
<Label>{intl.formatMessage({ id: "Membership number" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Membership number",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<p className={styles.textRight}>EB{sasMembershipNumber}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -137,17 +155,33 @@ async function MatchedAccountInfoSkeleton() {
|
||||
<section className={styles.matchedAccountSection}>
|
||||
<div className={styles.accountDetails}>
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Linked account" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Linked account",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "SAS EuroBonus" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Level" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
</Label>
|
||||
<SkeletonShimmer width="6ch" height="24px" />
|
||||
</div>
|
||||
<div className={cx(styles.stack, styles.accountMemberNumber)}>
|
||||
<Label>{intl.formatMessage({ id: "Membership number" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Membership number",
|
||||
})}
|
||||
</Label>
|
||||
<SkeletonShimmer width="10ch" height="24px" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,19 +222,22 @@ async function TierMatchMessage({
|
||||
const messageMap: Record<MatchState, ReactNode> = {
|
||||
boostedBySAS: intl.formatMessage(
|
||||
{
|
||||
id: "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||
defaultMessage:
|
||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||
},
|
||||
messageValues
|
||||
),
|
||||
boostedByScandic: intl.formatMessage(
|
||||
{
|
||||
id: "Your Scandic Friends level <scandicMark>{scandicLevelName}</scandicMark> has upgraded you to <sasMark>EuroBonus {sasLevelName}</sasMark>.",
|
||||
defaultMessage:
|
||||
"Your Scandic Friends level <scandicMark>{scandicLevelName}</scandicMark> has upgraded you to <sasMark>EuroBonus {sasLevelName}</sasMark>.",
|
||||
},
|
||||
messageValues
|
||||
),
|
||||
noBoost: intl.formatMessage(
|
||||
{
|
||||
id: "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||
defaultMessage:
|
||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||
},
|
||||
messageValues
|
||||
),
|
||||
@@ -214,7 +251,11 @@ async function TierMatchMessage({
|
||||
|
||||
return (
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Level match status" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Level match status",
|
||||
})}
|
||||
</Label>
|
||||
<div className={styles.tierMatchText}>
|
||||
<div className={styles.iconWrapper}>{iconMap[matchState]}</div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
@@ -230,7 +271,11 @@ async function TierMatchMessageSkeleton() {
|
||||
|
||||
return (
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Level match status" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Level match status",
|
||||
})}
|
||||
</Label>
|
||||
<div className={styles.tierMatchText}>
|
||||
<SkeletonShimmer width="250px" height="24px" />
|
||||
</div>
|
||||
@@ -256,7 +301,11 @@ async function TierMatchExpiration({
|
||||
|
||||
return (
|
||||
<div className={styles.stack}>
|
||||
<Label>{intl.formatMessage({ id: "Upgrade valid until" })}</Label>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Upgrade valid until",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{matchState === "boostedBySAS"
|
||||
|
||||
@@ -78,18 +78,28 @@ async function TransferPointsFormContent({
|
||||
<div>
|
||||
<div className={styles.labelWithIcon}>
|
||||
<Typography variant="Tag/sm">
|
||||
<p>{intl.formatMessage({ id: "Transfer from" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Transfer from",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<MaterialIcon icon="upload" />
|
||||
</div>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p>{intl.formatMessage({ id: "SAS EuroBonus" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<Typography variant="Tag/sm">
|
||||
<p className={styles.balanceLabel}>
|
||||
{intl.formatMessage({ id: "Balance" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Balance",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
{sasPoints === null ? (
|
||||
@@ -102,7 +112,9 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "{points, number} p" },
|
||||
{
|
||||
defaultMessage: "{points, number} p",
|
||||
},
|
||||
{ points: sasPoints }
|
||||
)}
|
||||
</p>
|
||||
@@ -115,7 +127,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "You have no points to transfer.",
|
||||
defaultMessage: "You have no points to transfer.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -126,17 +138,27 @@ async function TransferPointsFormContent({
|
||||
<div className={styles.labelWithIcon}>
|
||||
<MaterialIcon icon="download" />
|
||||
<Typography variant="Tag/sm">
|
||||
<p>{intl.formatMessage({ id: "Transfer to" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Transfer to",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p>{intl.formatMessage({ id: "Scandic Friends" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Scandic Friends",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<Typography variant="Tag/sm">
|
||||
<p className={styles.balanceLabel}>
|
||||
{intl.formatMessage({ id: "Balance" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Balance",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
{scandicPoints === null ? (
|
||||
@@ -149,7 +171,9 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "{points, number} p" },
|
||||
{
|
||||
defaultMessage: "{points, number} p",
|
||||
},
|
||||
{ points: scandicPoints }
|
||||
)}
|
||||
</p>
|
||||
@@ -167,7 +191,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p style={{ color: "var(--Text-Tertiary)" }}>
|
||||
{intl.formatMessage({
|
||||
id: "Transferred points will not be level qualifying",
|
||||
defaultMessage: "Transferred points will not be level qualifying",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -66,7 +66,9 @@ export function TransferPointsFormClient({
|
||||
className={styles.slider}
|
||||
// Set max value to 1 if sasPoints is 0 since slider requires a range
|
||||
maxValue={hasNoSasPoints ? 1 : sasPoints}
|
||||
aria-label={intl.formatMessage({ id: "EB points to transfer" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "EB points to transfer",
|
||||
})}
|
||||
formatOptions={{
|
||||
useGrouping: true,
|
||||
maximumFractionDigits: 0,
|
||||
@@ -85,7 +87,9 @@ export function TransferPointsFormClient({
|
||||
<div className={styles.inputsWrapper}>
|
||||
<TextField type="number" isDisabled={disabled}>
|
||||
<AriaInputWithLabel
|
||||
label={intl.formatMessage({ id: "EB points to transfer" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "EB points to transfer",
|
||||
})}
|
||||
type="number"
|
||||
min={0}
|
||||
value={pointState ?? ""}
|
||||
@@ -105,13 +109,17 @@ export function TransferPointsFormClient({
|
||||
<p className={styles.conversionRate}>
|
||||
{/* TODO maybe dynamic string based on exchange rate */}
|
||||
{intl.formatMessage({
|
||||
id: "1 EuroBonus point = 2 Scandic Friends points",
|
||||
defaultMessage: "1 EuroBonus point = 2 Scandic Friends points",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<div className={styles.pointsOutput}>
|
||||
<Typography variant="Label/xsRegular">
|
||||
<p>{intl.formatMessage({ id: "SF points to receive" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "SF points to receive",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{intl.formatNumber(calculatedPoints)}</p>
|
||||
@@ -174,7 +182,9 @@ function ConfirmModal({
|
||||
onClick={() => handleToggle(true)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{intl.formatMessage({ id: "Transfer points" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Transfer points",
|
||||
})}
|
||||
</Button>
|
||||
<Modal isOpen={isOpen} onToggle={handleToggle}>
|
||||
<div className={styles.modalContainer}>
|
||||
@@ -186,18 +196,25 @@ function ConfirmModal({
|
||||
/>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>
|
||||
{intl.formatMessage({ id: "Proceed with point transfer?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Proceed with point transfer?",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{intl.formatMessage({ id: "You are about to exchange:" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "You are about to exchange:",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "<bold>{sasPoints, number} EuroBonus points</bold> to <bold>{scandicPoints, number} Scandic Friends points</bold>",
|
||||
defaultMessage:
|
||||
"<bold>{sasPoints, number} EuroBonus points</bold> to <bold>{scandicPoints, number} Scandic Friends points</bold>",
|
||||
},
|
||||
{
|
||||
sasPoints,
|
||||
@@ -215,7 +232,8 @@ function ConfirmModal({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p className={styles.expiryText}>
|
||||
{intl.formatMessage({
|
||||
id: "Your exchanged points will retain their original expiry date with a maximum validity of 12 months.",
|
||||
defaultMessage:
|
||||
"Your exchanged points will retain their original expiry date with a maximum validity of 12 months.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -227,7 +245,7 @@ function ConfirmModal({
|
||||
color="none"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "Yes, I want to transfer my points",
|
||||
defaultMessage: "Yes, I want to transfer my points",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -237,7 +255,9 @@ function ConfirmModal({
|
||||
theme="base"
|
||||
onClick={() => handleToggle(false)}
|
||||
>
|
||||
{intl.formatMessage({ id: "Cancel" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Cancel",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ export default async function EmptyPreviousStaysBlock() {
|
||||
<section className={styles.container}>
|
||||
<Title as="h4" level="h3" color="red" textAlign="center">
|
||||
{intl.formatMessage({
|
||||
id: "You have no previous stays.",
|
||||
defaultMessage: "You have no previous stays.",
|
||||
})}
|
||||
</Title>
|
||||
</section>
|
||||
|
||||
@@ -30,7 +30,9 @@ export default function ShowMoreButton({
|
||||
size={20}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
{intl.formatMessage({ id: "Show more" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Show more",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -28,14 +28,20 @@ export default async function EmptyUpcomingStaysBlock() {
|
||||
className={styles.title}
|
||||
textAlign="center"
|
||||
>
|
||||
{intl.formatMessage({ id: "You have no upcoming stays." })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "You have no upcoming stays.",
|
||||
})}
|
||||
<span className={styles.burgundyTitle}>
|
||||
{intl.formatMessage({ id: "Where should you go next?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where should you go next?",
|
||||
})}
|
||||
</span>
|
||||
</Title>
|
||||
</div>
|
||||
<Link href={href} className={styles.link} color="peach80">
|
||||
{intl.formatMessage({ id: "Get inspired" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Get inspired",
|
||||
})}
|
||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" />
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
@@ -59,6 +59,7 @@ export default function StayCard({ stay }: StayCardProps) {
|
||||
<Caption asChild>
|
||||
<time dateTime={arrivalDateTime}>{arrivalDate}</time>
|
||||
</Caption>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{" - "}
|
||||
<Caption asChild>
|
||||
<time dateTime={departDateTime}>{departDate}</time>
|
||||
|
||||
@@ -28,14 +28,20 @@ export default async function EmptyUpcomingStaysBlock() {
|
||||
className={styles.title}
|
||||
textAlign="center"
|
||||
>
|
||||
{intl.formatMessage({ id: "You have no upcoming stays." })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "You have no upcoming stays.",
|
||||
})}
|
||||
<span className={styles.burgundyTitle}>
|
||||
{intl.formatMessage({ id: "Where should you go next?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where should you go next?",
|
||||
})}
|
||||
</span>
|
||||
</Title>
|
||||
</div>
|
||||
<Link href={href} className={styles.link} color="peach80">
|
||||
{intl.formatMessage({ id: "Get inspired" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Get inspired",
|
||||
})}
|
||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" />
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
@@ -56,7 +56,9 @@ export default async function HotelListingItem({
|
||||
</div>
|
||||
<Caption color="uiTextPlaceholder">
|
||||
{intl.formatMessage(
|
||||
{ id: "{number} km to city center" },
|
||||
{
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
number: getSingleDecimal(
|
||||
hotel.location.distanceToCentre / 1000
|
||||
|
||||
@@ -21,7 +21,9 @@ export function getTypeSpecificInformation(
|
||||
alt: images.metaData.altText,
|
||||
},
|
||||
cta: {
|
||||
text: intl.formatMessage({ id: "See hotel details" }),
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "See hotel details",
|
||||
}),
|
||||
url,
|
||||
openInNewTab: false,
|
||||
},
|
||||
@@ -41,7 +43,9 @@ export function getTypeSpecificInformation(
|
||||
}
|
||||
if (meetingUrl) {
|
||||
data.cta = {
|
||||
text: intl.formatMessage({ id: "Book a meeting" }),
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Book a meeting",
|
||||
}),
|
||||
url: meetingUrl,
|
||||
openInNewTab: true,
|
||||
}
|
||||
|
||||
@@ -53,22 +53,31 @@ export default function MobileToggleButton({
|
||||
}, 0)
|
||||
|
||||
const totalNightsMsg = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights }
|
||||
)
|
||||
|
||||
const totalAdultsMsg = intl.formatMessage(
|
||||
{ id: "{totalAdults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{ totalAdults }
|
||||
)
|
||||
|
||||
const totalChildrenMsg = intl.formatMessage(
|
||||
{ id: "{totalChildren, plural, one {# child} other {# children}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalChildren, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{ totalChildren }
|
||||
)
|
||||
|
||||
const totalRoomsMsg = intl.formatMessage(
|
||||
{ id: "{totalRooms, plural, one {# room} other {# rooms}}" },
|
||||
{
|
||||
defaultMessage: "{totalRooms, plural, one {# room} other {# rooms}}",
|
||||
},
|
||||
{ totalRooms }
|
||||
)
|
||||
|
||||
@@ -88,14 +97,18 @@ export default function MobileToggleButton({
|
||||
<span className={styles.block}>
|
||||
<Typography variant={"Body/Supporting text (caption)/smBold"}>
|
||||
<span className={styles.blockLabel}>
|
||||
{intl.formatMessage({ id: "Where to?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where to?",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
||||
<span className={styles.placeholder}>
|
||||
{searchTerm
|
||||
? searchTerm
|
||||
: intl.formatMessage({ id: "Destination" })}
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Destination",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</span>
|
||||
@@ -108,7 +121,9 @@ export default function MobileToggleButton({
|
||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{ id: "{selectedFromDate} - {selectedToDate}" },
|
||||
{
|
||||
defaultMessage: "{selectedFromDate} - {selectedToDate}",
|
||||
},
|
||||
{
|
||||
selectedFromDate,
|
||||
selectedToDate,
|
||||
@@ -133,7 +148,8 @@ export default function MobileToggleButton({
|
||||
<span className={styles.locationAndDate}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{selectedFromDate} - {selectedToDate} ({totalNights}) {details}",
|
||||
defaultMessage:
|
||||
"{selectedFromDate} - {selectedToDate} ({totalNights}) {details}",
|
||||
},
|
||||
{
|
||||
selectedFromDate,
|
||||
@@ -162,7 +178,9 @@ export function MobileToggleButtonSkeleton() {
|
||||
<span className={styles.block}>
|
||||
<Typography variant={"Body/Supporting text (caption)/smBold"}>
|
||||
<span className={styles.blockLabel}>
|
||||
{intl.formatMessage({ id: "Where to?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where to?",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
<SkeletonShimmer display={"block"} height="24px" />
|
||||
@@ -172,7 +190,10 @@ export function MobileToggleButtonSkeleton() {
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span className={styles.blockLabel}>
|
||||
{intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: 0 }
|
||||
)}
|
||||
</span>
|
||||
|
||||
@@ -22,7 +22,9 @@ export function CarouselPrevious({ className, ...props }: CarouselButtonProps) {
|
||||
<button
|
||||
className={cx(styles.button, styles.buttonPrev, className)}
|
||||
onClick={scrollPrev}
|
||||
aria-label={intl.formatMessage({ id: "Previous slide" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Previous slide",
|
||||
})}
|
||||
{...props}
|
||||
>
|
||||
<MaterialIcon color="Icon/Interactive/Default" icon="arrow_back" />
|
||||
@@ -41,7 +43,9 @@ export function CarouselNext({ className, ...props }: CarouselButtonProps) {
|
||||
<button
|
||||
className={cx(styles.button, styles.buttonNext, className)}
|
||||
onClick={scrollNext}
|
||||
aria-label={intl.formatMessage({ id: "Next slide" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Next slide",
|
||||
})}
|
||||
{...props}
|
||||
>
|
||||
<MaterialIcon color="Icon/Interactive/Default" icon="arrow_forward" />
|
||||
|
||||
@@ -31,11 +31,18 @@ export default async function CityDataContainer({
|
||||
|
||||
const sortItems: SortItem[] = [
|
||||
{
|
||||
label: intl.formatMessage({ id: "Recommended" }),
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Recommended",
|
||||
}),
|
||||
value: SortOption.Recommended,
|
||||
isDefault: true,
|
||||
},
|
||||
{ label: intl.formatMessage({ id: "Name" }), value: SortOption.Name },
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Name",
|
||||
}),
|
||||
value: SortOption.Name,
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
@@ -31,7 +31,9 @@ export default function CityListingItem({ city }: CityListingItemProps) {
|
||||
images={galleryImages}
|
||||
fill
|
||||
title={intl.formatMessage(
|
||||
{ id: "{title} - Image gallery" },
|
||||
{
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: city.cityName }
|
||||
)}
|
||||
/>
|
||||
@@ -57,7 +59,9 @@ export default function CityListingItem({ city }: CityListingItemProps) {
|
||||
>
|
||||
<Link href={city.url}>
|
||||
{intl.formatMessage(
|
||||
{ id: "Explore {city}" },
|
||||
{
|
||||
defaultMessage: "Explore {city}",
|
||||
},
|
||||
{ city: city.cityName }
|
||||
)}
|
||||
</Link>
|
||||
|
||||
@@ -38,7 +38,8 @@ export default function CityListing() {
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{count, plural, one {# Location} other {# Locations}}",
|
||||
defaultMessage:
|
||||
"{count, plural, one {# Location} other {# Locations}}",
|
||||
},
|
||||
{ count: activeCities.length }
|
||||
)}
|
||||
@@ -48,9 +49,12 @@ export default function CityListing() {
|
||||
{activeCities.length === 0 ? (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No matching locations found" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "No matching locations found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "It looks like no location match your filters. Try adjusting your search to find the perfect stay.",
|
||||
defaultMessage:
|
||||
"It looks like no location match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -63,7 +63,9 @@ export default function HotelList() {
|
||||
<div className={styles.header}>
|
||||
<Body>
|
||||
{intl.formatMessage(
|
||||
{ id: "{count} hotels" },
|
||||
{
|
||||
defaultMessage: "{count} hotels",
|
||||
},
|
||||
{ count: visibleHotels.length }
|
||||
)}
|
||||
</Body>
|
||||
@@ -72,9 +74,12 @@ export default function HotelList() {
|
||||
{activeHotels.length === 0 ? (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No matching hotels found" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "No matching hotels found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
defaultMessage:
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -67,7 +67,9 @@ export default function HotelListItem(data: DestinationPagesHotelData) {
|
||||
fill
|
||||
sizes="(min-width: 768px) 350px, 100vw"
|
||||
title={intl.formatMessage(
|
||||
{ id: "{title} - Image gallery" },
|
||||
{
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: hotel.name }
|
||||
)}
|
||||
/>
|
||||
@@ -93,7 +95,9 @@ export default function HotelListItem(data: DestinationPagesHotelData) {
|
||||
<Divider variant="vertical" color="beige" />
|
||||
<Caption color="uiTextPlaceholder">
|
||||
{intl.formatMessage(
|
||||
{ id: "{number} km to city center" },
|
||||
{
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
number: getSingleDecimal(
|
||||
hotel.location.distanceToCentre / 1000
|
||||
@@ -120,7 +124,9 @@ export default function HotelListItem(data: DestinationPagesHotelData) {
|
||||
<div className={styles.ctaWrapper}>
|
||||
<Button intent="tertiary" theme="base" size="small" asChild>
|
||||
<Link href={url}>
|
||||
{intl.formatMessage({ id: "See hotel details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,9 @@ export default function CityList() {
|
||||
<div className={styles.header}>
|
||||
<Body>
|
||||
{intl.formatMessage(
|
||||
{ id: "{count} destinations" },
|
||||
{
|
||||
defaultMessage: "{count} destinations",
|
||||
},
|
||||
{ count: activeCities.length }
|
||||
)}
|
||||
</Body>
|
||||
@@ -38,9 +40,12 @@ export default function CityList() {
|
||||
{activeCities.length === 0 ? (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No matching locations found" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "No matching locations found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "It looks like no location match your filters. Try adjusting your search to find the perfect stay.",
|
||||
defaultMessage:
|
||||
"It looks like no location match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -29,7 +29,9 @@ export default function CityListItem({ city }: CityListItemProps) {
|
||||
images={galleryImages}
|
||||
fill
|
||||
title={intl.formatMessage(
|
||||
{ id: "{title} - Image gallery" },
|
||||
{
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: city.cityName }
|
||||
)}
|
||||
/>
|
||||
@@ -47,7 +49,9 @@ export default function CityListItem({ city }: CityListItemProps) {
|
||||
<Button intent="tertiary" theme="base" size="small" asChild>
|
||||
<Link href={city.url}>
|
||||
{intl.formatMessage(
|
||||
{ id: "Explore {city}" },
|
||||
{
|
||||
defaultMessage: "Explore {city}",
|
||||
},
|
||||
{ city: city.cityName }
|
||||
)}
|
||||
</Link>
|
||||
|
||||
@@ -18,15 +18,24 @@ export function getHeadingText(
|
||||
|
||||
if (facilityFilter) {
|
||||
return intl.formatMessage(
|
||||
{ id: "Hotels with {filter} in {location}" },
|
||||
{
|
||||
defaultMessage: "Hotels with {filter} in {location}",
|
||||
},
|
||||
{ location, filter: facilityFilter.name }
|
||||
)
|
||||
} else if (surroudingsFilter) {
|
||||
return intl.formatMessage(
|
||||
{ id: "Hotels near {filter} in {location}" },
|
||||
{
|
||||
defaultMessage: "Hotels near {filter} in {location}",
|
||||
},
|
||||
{ location, filter: surroudingsFilter.name }
|
||||
)
|
||||
}
|
||||
}
|
||||
return intl.formatMessage({ id: "Hotels in {location}" }, { location })
|
||||
return intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Hotels in {location}",
|
||||
},
|
||||
{ location }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default async function Destination({
|
||||
const intl = await getIntl()
|
||||
const accordionSubtitle = intl.formatMessage(
|
||||
{
|
||||
id: "{amount, plural, one {# hotel} other {# hotels}}",
|
||||
defaultMessage: "{amount, plural, one {# hotel} other {# hotels}}",
|
||||
},
|
||||
{ amount: numberOfHotels }
|
||||
)
|
||||
@@ -36,10 +36,14 @@ export default async function Destination({
|
||||
color="baseTextMediumContrast"
|
||||
textDecoration="underline"
|
||||
>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${city.name} (${city.hotelCount})`}
|
||||
</Link>
|
||||
) : (
|
||||
<Body>{`${city.name} (${city.hotelCount})`}</Body>
|
||||
<>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Body>{`${city.name} (${city.hotelCount})`}</Body>
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
) : null
|
||||
@@ -49,7 +53,7 @@ export default async function Destination({
|
||||
<Link href={countryUrl} variant="icon" color="burgundy" weight="bold">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "View all hotels in {country}",
|
||||
defaultMessage: "View all hotels in {country}",
|
||||
},
|
||||
{ country: country }
|
||||
)}
|
||||
|
||||
@@ -18,7 +18,9 @@ export default async function HotelsSection() {
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<Title level="h4" as="h2" textAlign="center">
|
||||
{intl.formatMessage({ id: "Explore all our hotels" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Explore all our hotels",
|
||||
})}
|
||||
</Title>
|
||||
<DestinationsList destinations={destinations} />
|
||||
</section>
|
||||
|
||||
@@ -60,14 +60,16 @@ export function ClientInline({
|
||||
<div className={styles.fields}>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<Label className={styles.label}>
|
||||
{intl.formatMessage({ id: "Where to?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where to?",
|
||||
})}
|
||||
</Label>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<Input
|
||||
className={styles.input}
|
||||
placeholder={intl.formatMessage({
|
||||
id: "Hotels & Destinations",
|
||||
defaultMessage: "Hotels & Destinations",
|
||||
})}
|
||||
onChange={(evt) => {
|
||||
startTransition(() => {
|
||||
@@ -83,7 +85,11 @@ export function ClientInline({
|
||||
|
||||
{state.value !== "" && (
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<ButtonRAC className={styles.clearButton}>Clear</ButtonRAC>
|
||||
<ButtonRAC className={styles.clearButton}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Clear",
|
||||
})}
|
||||
</ButtonRAC>
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
@@ -96,7 +102,9 @@ export function ClientInline({
|
||||
type="submit"
|
||||
>
|
||||
<MaterialIcon icon="search" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "Search" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Search",
|
||||
})}
|
||||
</Button>
|
||||
</Typography>
|
||||
</form>
|
||||
@@ -113,7 +121,9 @@ export function ClientInline({
|
||||
>
|
||||
{showResults ? (
|
||||
<ResultsMemo
|
||||
aria-label={intl.formatMessage({ id: "Results" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Results",
|
||||
})}
|
||||
results={results}
|
||||
onAction={onAction}
|
||||
renderEmptyState={true}
|
||||
@@ -122,7 +132,7 @@ export function ClientInline({
|
||||
{showHistory ? (
|
||||
<ResultsMemo
|
||||
aria-label={intl.formatMessage({
|
||||
id: "Latest searches",
|
||||
defaultMessage: "Latest searches",
|
||||
})}
|
||||
results={latest}
|
||||
onAction={onAction}
|
||||
|
||||
@@ -45,12 +45,16 @@ export function ClientModal({
|
||||
<span>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span className={styles.label}>
|
||||
{intl.formatMessage({ id: "Where to?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where to?",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span className={styles.placeholder}>
|
||||
{intl.formatMessage({ id: "Hotels & Destinations" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Hotels & Destinations",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</span>
|
||||
@@ -62,12 +66,16 @@ export function ClientModal({
|
||||
<Modal className={styles.modal}>
|
||||
<Dialog className={styles.dialog}>
|
||||
<Heading level={2} className="sr-only">
|
||||
{intl.formatMessage({ id: "Find a location" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Find a location",
|
||||
})}
|
||||
</Heading>
|
||||
<ButtonRAC
|
||||
className={styles.closeButton}
|
||||
slot="close"
|
||||
aria-label={intl.formatMessage({ id: "Close" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" color="CurrentColor" />
|
||||
</ButtonRAC>
|
||||
@@ -91,14 +99,16 @@ export function ClientModal({
|
||||
>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<Label className={styles.label}>
|
||||
{intl.formatMessage({ id: "Where to?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Where to?",
|
||||
})}
|
||||
</Label>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<Input
|
||||
className={styles.input}
|
||||
placeholder={intl.formatMessage({
|
||||
id: "Hotels & Destinations",
|
||||
defaultMessage: "Hotels & Destinations",
|
||||
})}
|
||||
onChange={(evt) => {
|
||||
startTransition(() => {
|
||||
@@ -115,7 +125,9 @@ export function ClientModal({
|
||||
{state.value !== "" && (
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<ButtonRAC className={styles.clearButton}>
|
||||
Clear
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Clear",
|
||||
})}
|
||||
</ButtonRAC>
|
||||
</Typography>
|
||||
)}
|
||||
@@ -132,7 +144,9 @@ export function ClientModal({
|
||||
>
|
||||
{showResults ? (
|
||||
<ResultsMemo
|
||||
aria-label={intl.formatMessage({ id: "Results" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Results",
|
||||
})}
|
||||
results={results}
|
||||
onAction={onAction}
|
||||
renderEmptyState={true}
|
||||
@@ -141,7 +155,7 @@ export function ClientModal({
|
||||
{showHistory ? (
|
||||
<ResultsMemo
|
||||
aria-label={intl.formatMessage({
|
||||
id: "Latest searches",
|
||||
defaultMessage: "Latest searches",
|
||||
})}
|
||||
results={latest}
|
||||
onAction={onAction}
|
||||
|
||||
@@ -16,7 +16,7 @@ export function ResultsSkeleton() {
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<header className={styles.sectionHeader}>
|
||||
{intl.formatMessage({
|
||||
id: "Loading results",
|
||||
defaultMessage: "Loading results",
|
||||
})}
|
||||
</header>
|
||||
</Typography>
|
||||
|
||||
@@ -45,13 +45,16 @@ export function Results({
|
||||
<>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<Header className={styles.noResultsLabel}>
|
||||
{intl.formatMessage({ id: "No results" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No results",
|
||||
})}
|
||||
</Header>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span className={styles.noResultsDescription}>
|
||||
{intl.formatMessage({
|
||||
id: "We couldn't find a matching location for your search.",
|
||||
defaultMessage:
|
||||
"We couldn't find a matching location for your search.",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
@@ -158,7 +158,9 @@ export function JumpToClient<T extends JumpToData>({
|
||||
type: "clearHistory",
|
||||
closesModal: false,
|
||||
icon: <MaterialIcon icon="delete" color="CurrentColor" />,
|
||||
displayName: intl.formatMessage({ id: "Clear searches" }),
|
||||
displayName: intl.formatMessage({
|
||||
defaultMessage: "Clear searches",
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function InputForm() {
|
||||
<input
|
||||
type="text"
|
||||
placeholder={intl.formatMessage({
|
||||
id: "Find hotels and destinations",
|
||||
defaultMessage: "Find hotels and destinations",
|
||||
})}
|
||||
className={styles.formInput}
|
||||
/>
|
||||
|
||||
@@ -17,49 +17,63 @@ export function mapExperiencesToListData(
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="hiking" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "Hiking" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "Hiking",
|
||||
}),
|
||||
}
|
||||
case "Kayaking":
|
||||
return {
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="kayaking" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "Kayaking" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "Kayaking",
|
||||
}),
|
||||
}
|
||||
case "Bike friendly":
|
||||
return {
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="pedal_bike" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "Bike friendly" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "Bike friendly",
|
||||
}),
|
||||
}
|
||||
case "Museums":
|
||||
return {
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="museum" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "Museums" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "Museums",
|
||||
}),
|
||||
}
|
||||
case "Family friendly":
|
||||
return {
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="family_restroom" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "Family friendly" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "Family friendly",
|
||||
}),
|
||||
}
|
||||
case "City pulse":
|
||||
return {
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="location_city" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "City pulse" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "City pulse",
|
||||
}),
|
||||
}
|
||||
case "Nightlife":
|
||||
return {
|
||||
Icon: (props: MaterialIconSetIconProps) => (
|
||||
<MaterialIcon icon="nightlife" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({ id: "Nightlife" }),
|
||||
name: intl.formatMessage({
|
||||
defaultMessage: "Nightlife",
|
||||
}),
|
||||
}
|
||||
default:
|
||||
return {
|
||||
|
||||
@@ -23,13 +23,22 @@ export default async function HotelDataContainer({
|
||||
|
||||
const sortItems: SortItem[] = [
|
||||
{
|
||||
label: intl.formatMessage({ id: "Distance to city center" }),
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Distance to city center",
|
||||
}),
|
||||
value: SortOption.Distance,
|
||||
isDefault: true,
|
||||
},
|
||||
{ label: intl.formatMessage({ id: "Name" }), value: SortOption.Name },
|
||||
{
|
||||
label: intl.formatMessage({ id: "TripAdvisor rating" }),
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Name",
|
||||
}),
|
||||
value: SortOption.Name,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "TripAdvisor rating",
|
||||
}),
|
||||
value: SortOption.TripAdvisorRating,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -48,7 +48,9 @@ export default function HotelListingItem(data: DestinationPagesHotelData) {
|
||||
fill
|
||||
sizes="(min-width: 768px) 350px, 100vw"
|
||||
title={intl.formatMessage(
|
||||
{ id: "{title} - Image gallery" },
|
||||
{
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: hotel.name }
|
||||
)}
|
||||
/>
|
||||
@@ -72,7 +74,9 @@ export default function HotelListingItem(data: DestinationPagesHotelData) {
|
||||
<Divider variant="vertical" color="beige" />
|
||||
<Caption color="uiTextPlaceholder">
|
||||
{intl.formatMessage(
|
||||
{ id: "{number} km to city center" },
|
||||
{
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
number: getSingleDecimal(
|
||||
hotel.location.distanceToCentre / 1000
|
||||
@@ -107,7 +111,9 @@ export default function HotelListingItem(data: DestinationPagesHotelData) {
|
||||
scroll={true}
|
||||
onClick={() => setActiveMarker(hotel.id)}
|
||||
>
|
||||
{intl.formatMessage({ id: "See on map" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon="chevron_right"
|
||||
size={20}
|
||||
@@ -123,7 +129,9 @@ export default function HotelListingItem(data: DestinationPagesHotelData) {
|
||||
<div className={styles.ctaWrapper}>
|
||||
<Button intent="tertiary" theme="base" size="small" asChild>
|
||||
<Link href={url}>
|
||||
{intl.formatMessage({ id: "See hotel details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ export default function HotelListing() {
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{count, plural, one {# Hotel} other {# Hotels}}",
|
||||
defaultMessage: "{count, plural, one {# Hotel} other {# Hotels}}",
|
||||
},
|
||||
{ count: activeHotels.length }
|
||||
)}
|
||||
@@ -68,7 +68,9 @@ export default function HotelListing() {
|
||||
>
|
||||
<Link href={mapUrl}>
|
||||
<MaterialIcon icon="map" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "See on map" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
@@ -78,9 +80,12 @@ export default function HotelListing() {
|
||||
{activeHotels.length === 0 ? (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No matching hotels found" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "No matching hotels found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
defaultMessage:
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -55,7 +55,9 @@ export default function HotelMapCard({
|
||||
variant="icon"
|
||||
className={styles.closeButton}
|
||||
onClick={handleClose}
|
||||
aria-label={intl.formatMessage({ id: "Close" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
@@ -120,7 +122,9 @@ export default function HotelMapCard({
|
||||
size="small"
|
||||
>
|
||||
<Link href={url}>
|
||||
{intl.formatMessage({ id: "See hotel information" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See hotel information",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -111,7 +111,15 @@ export default function DynamicMap({
|
||||
)}
|
||||
ref={ref}
|
||||
>
|
||||
<ErrorBoundary fallback={<h2>Unable to display map</h2>}>
|
||||
<ErrorBoundary
|
||||
fallback={
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Unable to display map",
|
||||
})}
|
||||
</h2>
|
||||
}
|
||||
>
|
||||
<Map {...mapOptions}>{children}</Map>
|
||||
</ErrorBoundary>
|
||||
<div className={styles.ctaButtons}>
|
||||
@@ -125,7 +133,11 @@ export default function DynamicMap({
|
||||
onClick={onClose}
|
||||
>
|
||||
<MaterialIcon icon="close" color="CurrentColor" />
|
||||
<span>{intl.formatMessage({ id: "Close the map" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Close the map",
|
||||
})}
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
<div className={styles.zoomButtons}>
|
||||
@@ -136,7 +148,9 @@ export default function DynamicMap({
|
||||
size="small"
|
||||
className={styles.zoomButton}
|
||||
onClick={zoomIn}
|
||||
aria-label={intl.formatMessage({ id: "Zoom out" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Zoom out",
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="add" color="CurrentColor" size={20} />
|
||||
</Button>
|
||||
@@ -147,7 +161,9 @@ export default function DynamicMap({
|
||||
size="small"
|
||||
className={styles.zoomButton}
|
||||
onClick={zoomOut}
|
||||
aria-label={intl.formatMessage({ id: "Zoom in" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Zoom in",
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="remove" color="CurrentColor" size={20} />
|
||||
</Button>
|
||||
|
||||
@@ -146,7 +146,9 @@ export default function Map({
|
||||
style={
|
||||
{ "--destination-map-height": mapHeight } as React.CSSProperties
|
||||
}
|
||||
aria-label={intl.formatMessage({ id: "Map view" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Map view",
|
||||
})}
|
||||
>
|
||||
<div className={styles.mobileNavigation}>
|
||||
<Button
|
||||
@@ -160,7 +162,9 @@ export default function Map({
|
||||
size={20}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
{intl.formatMessage({ id: "Back" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</Button>
|
||||
<DestinationFilterAndSort
|
||||
listType={pageType === "city" ? "hotel" : "city"}
|
||||
|
||||
@@ -45,7 +45,10 @@ export default function DestinationPageSidepeek({
|
||||
size="small"
|
||||
wrapping
|
||||
>
|
||||
{buttonText || intl.formatMessage({ id: "Read more" })}
|
||||
{buttonText ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Read more",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Button>
|
||||
<SidePeek
|
||||
|
||||
@@ -39,7 +39,9 @@ export default function MapButton({ className = "" }: MapButtonProps) {
|
||||
>
|
||||
<Link href={mapUrl} scroll={true}>
|
||||
<MaterialIcon icon="map" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "See on map" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -32,8 +32,12 @@ export default async function DestinationStaticMap({
|
||||
}: StaticMapProps) {
|
||||
const intl = await getIntl()
|
||||
const altText = city
|
||||
? intl.formatMessage({ id: "Map of the city" })
|
||||
: intl.formatMessage({ id: "Map of the country" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Map of the city",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Map of the country",
|
||||
})
|
||||
const coordinates = location
|
||||
? { lat: location.latitude, lng: location.longitude }
|
||||
: undefined
|
||||
|
||||
@@ -65,12 +65,16 @@ export default function TopImages({ images, destinationName }: TopImageProps) {
|
||||
onClick={() => setLightboxState({ open: true, activeIndex: 0 })}
|
||||
className={styles.seeAllButton}
|
||||
>
|
||||
{intl.formatMessage({ id: "See all photos" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See all photos",
|
||||
})}
|
||||
</Button>
|
||||
<Lightbox
|
||||
images={lightboxImages}
|
||||
dialogTitle={intl.formatMessage(
|
||||
{ id: "{title} - Image gallery" },
|
||||
{
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: destinationName }
|
||||
)}
|
||||
isOpen={lightboxState.open}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user