fix: cleanup profile pages in renaming to follow naming convention
cleanup profile page html to be valid replace old temp design system components with new ones divider is now correctly an hr element less section elements to be valid html
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
.container {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
max-width: 510px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import ManagePreferencesButton from "@/components/Profile/ManagePreferencesButton"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./communication.module.css"
|
||||
|
||||
export default async function CommunicationSlot() {
|
||||
const intl = await getIntl()
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "My communication preferences",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<ManagePreferencesButton />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
.container {
|
||||
display: grid;
|
||||
gap: var(--Space-x2);
|
||||
justify-items: flex-start;
|
||||
max-width: 510px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.cardContainer {
|
||||
display: grid;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.container {
|
||||
gap: var(--Space-x3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import AddCreditCardButton from "@/components/Profile/AddCreditCardButton"
|
||||
import CreditCardList from "@/components/Profile/CreditCardList"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./creditCards.module.css"
|
||||
|
||||
export default async function CreditCardSlot() {
|
||||
const intl = await getIntl()
|
||||
const creditCards = await serverClient().user.creditCards()
|
||||
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "My payment cards",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<CreditCardList initialData={creditCards} />
|
||||
<AddCreditCardButton />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { getMembershipCards } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./membershipcards.module.css"
|
||||
|
||||
export default async function MembershipCardSlot() {
|
||||
const intl = await getIntl()
|
||||
const membershipCards = await getMembershipCards()
|
||||
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "My membership cards",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
</div>
|
||||
{(membershipCards || []).map((card, idx) => (
|
||||
<div className={styles.card} key={idx}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h4 className={styles.subTitle}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Name: {cardMembershipType}",
|
||||
},
|
||||
{
|
||||
cardMembershipType: card.membershipType,
|
||||
}
|
||||
)}
|
||||
</h4>
|
||||
</Typography>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Current Points: {points, number}",
|
||||
},
|
||||
{ points: card.currentPoints }
|
||||
)}
|
||||
</span>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Member Since: {value}",
|
||||
},
|
||||
{
|
||||
value: card.memberSince,
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Number: {membershipNumber}",
|
||||
},
|
||||
{
|
||||
membershipNumber: card.membershipNumber,
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Expiration Date: {expirationDate}",
|
||||
},
|
||||
{
|
||||
expirationDate: card.expirationDate?.split("T")[0],
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
<Link href="#" variant="icon">
|
||||
<MaterialIcon icon="add_circle" color="CurrentColor" />
|
||||
<Body color="burgundy" textTransform="underlined">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Add new card",
|
||||
})}
|
||||
</Body>
|
||||
</Link>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
.container {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
max-width: 510px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-top: var(--Space-x4);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-rows: repeat(3, auto);
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
grid-column: span 2;
|
||||
}
|
||||
182
apps/scandic-web/components/MyPages/Profile/index.tsx
Normal file
182
apps/scandic-web/components/MyPages/Profile/index.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { countriesMap } from "@/constants/countries"
|
||||
import { Lang, languages } from "@/constants/languages"
|
||||
import { profileEdit } from "@/constants/routes/myPages"
|
||||
import { getProfile } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import ButtonLink from "@/components/ButtonLink"
|
||||
import CommunicationSlot from "@/components/MyPages/Profile/Communication"
|
||||
import CreditCardSlot from "@/components/MyPages/Profile/CreditCards"
|
||||
import Header from "@/components/Profile/Header"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { getLang } from "@/i18n/serverContext"
|
||||
import { isValidCountry } from "@/utils/countries"
|
||||
import { isValidLang } from "@/utils/languages"
|
||||
|
||||
import styles from "./profile.module.css"
|
||||
|
||||
export default async function Profile() {
|
||||
const user = await getProfile()
|
||||
if (!user || "error" in user) {
|
||||
return null
|
||||
}
|
||||
|
||||
const intl = await getIntl()
|
||||
const lang = getLang()
|
||||
|
||||
const addressParts = []
|
||||
if (user.address.streetAddress) {
|
||||
addressParts.push(user.address.streetAddress)
|
||||
}
|
||||
|
||||
if (user.address.city) {
|
||||
addressParts.push(user.address.city)
|
||||
}
|
||||
|
||||
const displayNames = {
|
||||
language: new Intl.DisplayNames([lang], { type: "language" }),
|
||||
region: new Intl.DisplayNames([lang], { type: "region" }),
|
||||
}
|
||||
|
||||
if (user.address.country) {
|
||||
const countryCode = isValidCountry(user.address.country)
|
||||
? countriesMap[user.address.country]
|
||||
: null
|
||||
const localizedCountry = countryCode
|
||||
? displayNames.region.of(countryCode)
|
||||
: user.address.country
|
||||
addressParts.push(localizedCountry)
|
||||
}
|
||||
|
||||
const addressOutput =
|
||||
addressParts.length > 0
|
||||
? addressParts.join(", ")
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "N/A",
|
||||
})
|
||||
|
||||
const userLang = isValidLang(user.language) ? user.language : Lang.en
|
||||
const localizedLanguage = displayNames.language.of(userLang)
|
||||
const normalizedLanguage = localizedLanguage
|
||||
? localizedLanguage.charAt(0).toUpperCase() + localizedLanguage.slice(1)
|
||||
: languages[userLang]
|
||||
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<Header>
|
||||
<Typography variant="Title/xs">
|
||||
<h2 className={styles.title}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Welcome",
|
||||
})}
|
||||
<br />
|
||||
<span data-hj-suppress className={styles.titleName}>
|
||||
{user.name}
|
||||
</span>
|
||||
</h2>
|
||||
</Typography>
|
||||
<ButtonLink
|
||||
size="Small"
|
||||
prefetch={false}
|
||||
href={profileEdit[lang]}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Edit profile",
|
||||
})}
|
||||
</ButtonLink>
|
||||
</Header>
|
||||
<div className={styles.info}>
|
||||
<div className={styles.item}>
|
||||
<MaterialIcon
|
||||
icon="calendar_month"
|
||||
color="Icon/Interactive/Default"
|
||||
/>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Date of Birth",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{user.dateOfBirth}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<MaterialIcon icon="phone" color="Icon/Interactive/Default" />
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Phone number",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{user.phoneNumber}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<MaterialIcon icon="globe" color="Icon/Interactive/Default" />
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Language",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{normalizedLanguage}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<MaterialIcon icon="mail" color="Icon/Interactive/Default" />
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{user.email}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<MaterialIcon icon="location_on" color="Icon/Interactive/Default" />
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Address",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{addressOutput}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<MaterialIcon icon="lock" color="Icon/Interactive/Default" />
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Password",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<p>**********</p>
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<Divider color="burgundy" opacity={8} />
|
||||
<CreditCardSlot />
|
||||
{/* <MembershipCardSlot /> */}
|
||||
<CommunicationSlot />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
.container {
|
||||
background-color: var(--Main-Grey-White);
|
||||
border-radius: var(--Corner-radius-lg);
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
padding: var(--Space-x2) var(--Space-x2) var(--Space-x4);
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--Text-Accent-Primary);
|
||||
}
|
||||
|
||||
.titleName {
|
||||
color: var(--Text-Interactive-Default);
|
||||
}
|
||||
|
||||
.info {
|
||||
display: grid;
|
||||
gap: var(--Space-x15) var(--Space-x7);
|
||||
width: 100%;
|
||||
justify-items: flex-start;
|
||||
}
|
||||
|
||||
.item {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
gap: var(--Space-x1);
|
||||
grid-template-columns: auto auto 1fr;
|
||||
justify-items: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
padding-bottom: var(--Space-x8);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.info {
|
||||
grid-template-columns: repeat(3, auto);
|
||||
}
|
||||
|
||||
.item {
|
||||
justify-items: flex-start;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: var(--Space-x3) var(--Space-x3) var(--Space-x4);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.content {
|
||||
gap: var(--Space-x5);
|
||||
grid-template-columns: max(340px) 1fr;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user