feat(BOOK-212): Refactored LoginButton and added successful tracking functionality
Approved-by: Linus Flood
This commit is contained in:
@@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { login } from "@scandic-hotels/common/constants/routes/handleAuth"
|
|
||||||
import { useLazyPathname } from "@scandic-hotels/common/hooks/useLazyPathname"
|
import { useLazyPathname } from "@scandic-hotels/common/hooks/useLazyPathname"
|
||||||
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
|
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
||||||
import { trackEvent } from "@scandic-hotels/tracking/base"
|
import { trackEvent } from "@scandic-hotels/tracking/base"
|
||||||
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
@@ -12,13 +11,13 @@ import useLang from "@/hooks/useLang"
|
|||||||
export default function PromoLoginButton() {
|
export default function PromoLoginButton() {
|
||||||
const lang = useLang()
|
const lang = useLang()
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const pathname = useLazyPathname()
|
const loginPathname = useLazyPathname({ includeSearchParams: true })
|
||||||
const loginHref = pathname
|
|
||||||
? `${login[lang]}?redirectTo=${encodeURIComponent(pathname)}`
|
|
||||||
: login[lang]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ButtonLink
|
<LoginButton
|
||||||
|
lang={lang}
|
||||||
|
redirectTo={loginPathname}
|
||||||
|
loginPosition="promo-campaign"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
trackEvent({
|
trackEvent({
|
||||||
event: "loginStart",
|
event: "loginStart",
|
||||||
@@ -29,16 +28,14 @@ export default function PromoLoginButton() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
href={loginHref}
|
|
||||||
variant="Primary"
|
variant="Primary"
|
||||||
color="Inverted"
|
color="Inverted"
|
||||||
size="Medium"
|
size="Medium"
|
||||||
prefetch={false}
|
|
||||||
>
|
>
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
id: "promoCampaign.logIn",
|
id: "promoCampaign.logIn",
|
||||||
defaultMessage: "Log in",
|
defaultMessage: "Log in",
|
||||||
})}
|
})}
|
||||||
</ButtonLink>
|
</LoginButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membership
|
|||||||
import { useLazyPathname } from "@scandic-hotels/common/hooks/useLazyPathname"
|
import { useLazyPathname } from "@scandic-hotels/common/hooks/useLazyPathname"
|
||||||
import { Avatar } from "@scandic-hotels/design-system/Avatar"
|
import { Avatar } from "@scandic-hotels/design-system/Avatar"
|
||||||
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
||||||
|
|
||||||
@@ -75,17 +74,18 @@ export default function MyPagesMenuWrapper() {
|
|||||||
trackLoginClick("top menu")
|
trackLoginClick("top menu")
|
||||||
}}
|
}}
|
||||||
redirectTo={loginPathname}
|
redirectTo={loginPathname}
|
||||||
trackingId="loginStartNewTopMenu"
|
loginPosition="top-menu"
|
||||||
|
variant="Text"
|
||||||
|
typography="Body/Paragraph/mdBold"
|
||||||
|
wrapping={false}
|
||||||
>
|
>
|
||||||
<Avatar />
|
<Avatar />
|
||||||
<Typography variant={"Body/Paragraph/mdBold"}>
|
<span className={styles.loginText}>
|
||||||
<span className={styles.loginText}>
|
{intl.formatMessage({
|
||||||
{intl.formatMessage({
|
id: "header.logInJoin",
|
||||||
id: "header.logInJoin",
|
defaultMessage: "Log in/Join",
|
||||||
defaultMessage: "Log in/Join",
|
})}
|
||||||
})}
|
</span>
|
||||||
</span>
|
|
||||||
</Typography>
|
|
||||||
</LoginButton>
|
</LoginButton>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
.loginLink {
|
.loginLink:hover {
|
||||||
display: flex;
|
text-decoration: none !important; /* Special case for the login link inside the header */
|
||||||
align-items: center;
|
|
||||||
gap: var(--Spacing-x1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
@media screen and (max-width: 767px) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { startTransition, useEffect } from "react"
|
|||||||
import { isSameBookingWidgetParams } from "@scandic-hotels/booking-flow/utils/isSameBooking"
|
import { isSameBookingWidgetParams } from "@scandic-hotels/booking-flow/utils/isSameBooking"
|
||||||
import useRouterTransitionStore from "@scandic-hotels/common/stores/router-transition"
|
import useRouterTransitionStore from "@scandic-hotels/common/stores/router-transition"
|
||||||
import useTrackingStore from "@scandic-hotels/common/stores/tracking"
|
import useTrackingStore from "@scandic-hotels/common/stores/tracking"
|
||||||
|
import { trackEvent } from "@scandic-hotels/tracking/base"
|
||||||
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
import { trackPageViewStart } from "@/utils/tracking"
|
import { trackPageViewStart } from "@/utils/tracking"
|
||||||
@@ -57,5 +58,26 @@ export default function RouteChange() {
|
|||||||
startRouterTransition,
|
startRouterTransition,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Track login success if loginPosition param is present. The LoginButton component has a
|
||||||
|
// loginPosition prop that adds this param to the URL upon successful login.
|
||||||
|
useEffect(() => {
|
||||||
|
const loginPosition = searchParams.get("loginPosition")
|
||||||
|
if (loginPosition) {
|
||||||
|
const position = `${loginPosition}, ${pathName}`
|
||||||
|
trackEvent({
|
||||||
|
event: "loginSuccess",
|
||||||
|
login: {
|
||||||
|
position,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const params = new URLSearchParams(searchParams)
|
||||||
|
params.delete("loginPosition")
|
||||||
|
const search = params.toString()
|
||||||
|
const newUrl = search ? `${pathName}?${search}` : pathName
|
||||||
|
window.history.replaceState(null, "", newUrl)
|
||||||
|
}
|
||||||
|
}, [pathName, searchParams])
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { useIntl } from "react-intl"
|
|||||||
import { useLazyPathname } from "@scandic-hotels/common/hooks/useLazyPathname"
|
import { useLazyPathname } from "@scandic-hotels/common/hooks/useLazyPathname"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
|
||||||
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
import { trackLoginClick } from "@/utils/tracking"
|
import { trackLoginClick } from "@/utils/tracking"
|
||||||
@@ -22,17 +21,18 @@ export function LoyaltyLoginButton() {
|
|||||||
trackLoginClick("join scandic friends sidebar")
|
trackLoginClick("join scandic friends sidebar")
|
||||||
}}
|
}}
|
||||||
redirectTo={loginPathname}
|
redirectTo={loginPathname}
|
||||||
trackingId="loginJoinLoyalty"
|
loginPosition="scandic-friends-sidebar"
|
||||||
|
variant="Text"
|
||||||
|
typography="Body/Supporting text (caption)/smBold"
|
||||||
|
wrapping={false}
|
||||||
>
|
>
|
||||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" size={20} />
|
<MaterialIcon icon="arrow_forward" color="CurrentColor" size={20} />
|
||||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
<span>
|
||||||
<span>
|
{intl.formatMessage({
|
||||||
{intl.formatMessage({
|
id: "loyalty.loginButton",
|
||||||
id: "loyalty.loginButton",
|
defaultMessage: "Log in here",
|
||||||
defaultMessage: "Log in here",
|
})}
|
||||||
})}
|
</span>
|
||||||
</span>
|
|
||||||
</Typography>
|
|
||||||
</LoginButton>
|
</LoginButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ article.wrapper .preamble {
|
|||||||
.loginContainer {
|
.loginContainer {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--Spacing-x2);
|
gap: var(--Spacing-x2);
|
||||||
|
justify-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
|||||||
import Footnote from "@scandic-hotels/design-system/Footnote"
|
import Footnote from "@scandic-hotels/design-system/Footnote"
|
||||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||||
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
import { LoginButton } from "@scandic-hotels/design-system/LoginButton"
|
||||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
|
||||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
import { trackLoginClick } from "@scandic-hotels/tracking/navigation"
|
import { trackLoginClick } from "@scandic-hotels/tracking/navigation"
|
||||||
@@ -74,23 +73,23 @@ export function JoinScandicFriendsCard({ name = "join" }: Props) {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
|
||||||
<Button size="small" color="Primary" asChild>
|
<LoginButton
|
||||||
<LoginButton
|
color="Primary"
|
||||||
lang={lang}
|
variant="Tertiary"
|
||||||
className={styles.login}
|
size="Small"
|
||||||
color="white"
|
lang={lang}
|
||||||
trackingId="join-scandic-friends-enter-details"
|
className={styles.login}
|
||||||
onClick={() => {
|
loginPosition="enter-details"
|
||||||
trackLoginClick("enter details")
|
onClick={() => {
|
||||||
}}
|
trackLoginClick("enter details")
|
||||||
redirectTo={loginPathname}
|
}}
|
||||||
>
|
redirectTo={loginPathname}
|
||||||
{intl.formatMessage({
|
>
|
||||||
id: "enterDetails.joinScandicFriendsCard.loginButtonText",
|
{intl.formatMessage({
|
||||||
defaultMessage: "Log in",
|
id: "enterDetails.joinScandicFriendsCard.loginButtonText",
|
||||||
})}
|
defaultMessage: "Log in",
|
||||||
</LoginButton>
|
})}
|
||||||
</Button>
|
</LoginButton>
|
||||||
|
|
||||||
<div className={styles.terms}>
|
<div className={styles.terms}>
|
||||||
<Footnote color="uiTextPlaceholder">
|
<Footnote color="uiTextPlaceholder">
|
||||||
|
|||||||
@@ -1,31 +1,34 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { login } from '@scandic-hotels/common/constants/routes/handleAuth'
|
import { login } from '@scandic-hotels/common/constants/routes/handleAuth'
|
||||||
import Link, { type LinkProps } from '../OldDSLink'
|
|
||||||
|
|
||||||
import type { Lang } from '@scandic-hotels/common/constants/language'
|
import type { Lang } from '@scandic-hotels/common/constants/language'
|
||||||
import type { PropsWithChildren } from 'react'
|
import ButtonLink, { ButtonLinkProps } from '../ButtonLink'
|
||||||
|
|
||||||
|
interface LoginButtonProps
|
||||||
|
extends React.PropsWithChildren<Omit<ButtonLinkProps, 'href'>> {
|
||||||
|
lang: Lang
|
||||||
|
redirectTo: string | null
|
||||||
|
loginPosition: string
|
||||||
|
}
|
||||||
|
|
||||||
export function LoginButton({
|
export function LoginButton({
|
||||||
lang,
|
lang,
|
||||||
redirectTo,
|
redirectTo,
|
||||||
trackingId,
|
loginPosition,
|
||||||
children,
|
|
||||||
...props
|
...props
|
||||||
}: PropsWithChildren<
|
}: LoginButtonProps) {
|
||||||
{
|
let href = login[lang]
|
||||||
lang: Lang
|
|
||||||
redirectTo: string | null
|
|
||||||
trackingId: string
|
|
||||||
} & Omit<LinkProps, 'href'>
|
|
||||||
>) {
|
|
||||||
const href = redirectTo
|
|
||||||
? `${login[lang]}?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
||||||
: login[lang]
|
|
||||||
|
|
||||||
return (
|
if (redirectTo) {
|
||||||
<Link id={trackingId} href={href} prefetch={false} {...props}>
|
const [pathname, existingQuery] = redirectTo.split('?')
|
||||||
{children}
|
const searchParams = new URLSearchParams(existingQuery)
|
||||||
</Link>
|
|
||||||
)
|
searchParams.set('loginPosition', loginPosition)
|
||||||
|
const redirectUrl = `${pathname}?${searchParams.toString()}`
|
||||||
|
|
||||||
|
href = `${href}?redirectTo=${encodeURIComponent(redirectUrl)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ButtonLink href={href} prefetch={false} {...props} />
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user