From 09b1d322a7c1741a974d7fd51648cad0a60211cf Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Tue, 16 Jul 2024 15:50:26 +0200 Subject: [PATCH] feat: list credit card according to design --- .../profile/@creditCards/page.module.css | 26 +++++--- .../my-pages/profile/@creditCards/page.tsx | 59 +++++++++++-------- .../my-pages/profile/@profile/page.module.css | 13 +++- .../my-pages/profile/profileLayout.css | 8 ++- components/Icons/CreditCard.tsx | 40 +++++++++++++ components/Icons/Delete.tsx | 36 +++++++++++ components/Icons/index.tsx | 2 + .../Profile/AddCreditCardButton/index.tsx | 31 ++++++++++ .../TempDesignSystem/Button/button.module.css | 9 ++- components/TempDesignSystem/Button/index.tsx | 2 + .../TempDesignSystem/Button/variants.ts | 3 + .../Text/Subtitle/variants.ts | 2 +- 12 files changed, 195 insertions(+), 36 deletions(-) create mode 100644 components/Icons/CreditCard.tsx create mode 100644 components/Icons/Delete.tsx create mode 100644 components/Profile/AddCreditCardButton/index.tsx diff --git a/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.module.css b/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.module.css index 3b9f6e70a..22f01c255 100644 --- a/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.module.css +++ b/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.module.css @@ -1,6 +1,6 @@ .container { display: grid; - gap: var(--Spacing-x3); + gap: var(--Spacing-x2); max-width: 510px; } @@ -9,14 +9,24 @@ gap: var(--Spacing-x1); } -.card { - margin-top: 2rem; +.cardContainer { display: grid; - grid-template-columns: repeat(2, 1fr); - grid-template-rows: repeat(3, auto); - gap: 0.5rem; + gap: var(--Spacing-x1); } -.subTitle { - grid-column: span 2; +.card { + display: grid; + align-items: center; + column-gap: var(--Spacing-x1); + grid-template-columns: auto auto auto 1fr; + justify-items: flex-end; + padding: var(--Spacing-x1) var(--Spacing-x-one-and-half,); + border-radius: var(--Corner-radius-Small); + background-color: var(--Base-Background-Primary-Normal); +} + +@media screen and (min-width: 768px) { + .container { + gap: var(--Spacing-x2); + } } diff --git a/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.tsx b/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.tsx index ce1152f73..c30661d9e 100644 --- a/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/profile/@creditCards/page.tsx @@ -1,8 +1,10 @@ import { serverClient } from "@/lib/trpc/server" -import { PlusCircleIcon } from "@/components/Icons" -import Link from "@/components/TempDesignSystem/Link" +import { CreditCard, Delete } from "@/components/Icons" +import AddCreditCardButton from "@/components/Profile/AddCreditCardButton" +import Button from "@/components/TempDesignSystem/Button" import Body from "@/components/TempDesignSystem/Text/Body" +import Caption from "@/components/TempDesignSystem/Text/Caption" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import { getIntl } from "@/i18n" @@ -24,27 +26,38 @@ export default async function CreditCardSlot() { })} - {creditCards && - creditCards.length > 0 && - creditCards.map((card, idx) => ( -
- - Name: {card.attribute.cardName} - - Type: {card.attribute.cardType} - Alias: {card.attribute.alias} - Number: {card.attribute.truncatedNumber} - - Expiration Date: {card.attribute.expirationDate.split("T")[0]} - -
- ))} - - - - {formatMessage({ id: "Add new card" })} - - + {creditCards?.length ? ( +
+ {creditCards.map((card, idx) => ( + + ))} +
+ ) : null} + ) } + +function CreditCardRow({ + truncatedNumber, + cardType, +}: { + truncatedNumber: string + cardType: string +}) { + const maskedCardNumber = `**** ${truncatedNumber.slice(12, 16)}` + return ( +
+ + {cardType} + {maskedCardNumber} + +
+ ) +} diff --git a/app/[lang]/(live)/(protected)/my-pages/profile/@profile/page.module.css b/app/[lang]/(live)/(protected)/my-pages/profile/@profile/page.module.css index 8af872e91..64091c9ba 100644 --- a/app/[lang]/(live)/(protected)/my-pages/profile/@profile/page.module.css +++ b/app/[lang]/(live)/(protected)/my-pages/profile/@profile/page.module.css @@ -7,7 +7,7 @@ .info { display: grid; gap: var(--Spacing-x-one-and-half) var(--Spacing-x7); - grid-template-columns: repeat(3, auto); + width: 100%; justify-items: flex-start; } @@ -16,4 +16,15 @@ display: grid; gap: var(--Spacing-x1); grid-template-columns: auto auto 1fr; + justify-items: flex-end; + width: 100%; +} + +@media screen and (min-width: 768px) { + .info { + grid-template-columns: repeat(3, auto); + } + .item { + justify-items: flex-start; + } } diff --git a/app/[lang]/(live)/(protected)/my-pages/profile/profileLayout.css b/app/[lang]/(live)/(protected)/my-pages/profile/profileLayout.css index d4ab39c54..891598b37 100644 --- a/app/[lang]/(live)/(protected)/my-pages/profile/profileLayout.css +++ b/app/[lang]/(live)/(protected)/my-pages/profile/profileLayout.css @@ -7,5 +7,11 @@ border-radius: var(--Corner-radius-xLarge); display: grid; gap: var(--Spacing-x4); - padding: var(--Spacing-x3) var(--Spacing-x3) var(--Spacing-x4); + padding: var(--Spacing-x2) var(--Spacing-x2) var(--Spacing-x4); +} + +@media screen and (min-width: 768px) { + .profile-layout { + padding: var(--Spacing-x3) var(--Spacing-x3) var(--Spacing-x4); + } } diff --git a/components/Icons/CreditCard.tsx b/components/Icons/CreditCard.tsx new file mode 100644 index 000000000..ae74314bb --- /dev/null +++ b/components/Icons/CreditCard.tsx @@ -0,0 +1,40 @@ +import * as variants from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function CreditCardIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = variants.iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Delete.tsx b/components/Icons/Delete.tsx new file mode 100644 index 000000000..c91d632a8 --- /dev/null +++ b/components/Icons/Delete.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function DeleteIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index 07c9b7016..848e701fe 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -13,6 +13,8 @@ export { default as ChevronRightIcon } from "./ChevronRight" export { default as CloseIcon } from "./Close" export { default as CoffeeIcon } from "./Coffee" export { default as ConciergeIcon } from "./Concierge" +export { default as CreditCard } from "./CreditCard" +export { default as Delete } from "./Delete" export { default as DoorOpenIcon } from "./DoorOpen" export { default as ElectricBikeIcon } from "./ElectricBike" export { default as EmailIcon } from "./Email" diff --git a/components/Profile/AddCreditCardButton/index.tsx b/components/Profile/AddCreditCardButton/index.tsx new file mode 100644 index 000000000..a85ef1cf6 --- /dev/null +++ b/components/Profile/AddCreditCardButton/index.tsx @@ -0,0 +1,31 @@ +"use client" + +import { useIntl } from "react-intl" + +import { trpc } from "@/lib/trpc/client" + +import { PlusCircleIcon } from "@/components/Icons" +import Button from "@/components/TempDesignSystem/Button" + +export default function AddCreditCardButton() { + const { formatMessage } = useIntl() + + async function handleAddCreditCard() { + // TODO: initiate add credit card flow and redirect user to planet: + // const { url } = trpc.user.creditCard.add.useMutation() + // router.redirect(url) + console.log("Credit card added!") + } + return ( + + ) +} diff --git a/components/TempDesignSystem/Button/button.module.css b/components/TempDesignSystem/Button/button.module.css index db14f131a..9dc82ae2d 100644 --- a/components/TempDesignSystem/Button/button.module.css +++ b/components/TempDesignSystem/Button/button.module.css @@ -13,11 +13,16 @@ /* TODO: Waiting for variables for buttons from Design team */ font-family: var(--typography-Body-Bold-fontFamily); font-size: var(--typography-Body-Bold-fontSize); - font-weight: var(--typography-Body-Bold-fontWeight); + font-weight: 500; line-height: 24px; letter-spacing: 0.6%; } +.wrapping { + padding-left: 0 !important; + padding-right: 0 !important; +} + /* INTENT */ .primary, a.primary { @@ -69,7 +74,7 @@ a.default { } .medium { - gap: var(--Spacing-x-quarter); + gap: var(--Spacing-x-half); height: 48px; padding: var(--Spacing-x-one-and-half) var(--Spacing-x2); } diff --git a/components/TempDesignSystem/Button/index.tsx b/components/TempDesignSystem/Button/index.tsx index be0185016..5acb884b1 100644 --- a/components/TempDesignSystem/Button/index.tsx +++ b/components/TempDesignSystem/Button/index.tsx @@ -14,6 +14,7 @@ export default function Button({ intent, size, variant, + wrapping, ...props }: ButtonProps) { const Comp = asChild ? Slot : "button" @@ -22,6 +23,7 @@ export default function Button({ intent, size, theme, + wrapping, variant, }) return diff --git a/components/TempDesignSystem/Button/variants.ts b/components/TempDesignSystem/Button/variants.ts index 217d14b51..301613544 100644 --- a/components/TempDesignSystem/Button/variants.ts +++ b/components/TempDesignSystem/Button/variants.ts @@ -30,6 +30,9 @@ export const buttonVariants = cva(styles.btn, { default: styles.default, icon: styles.icon, }, + wrapping: { + true: styles.wrapping, + }, }, defaultVariants: { intent: "primary", diff --git a/components/TempDesignSystem/Text/Subtitle/variants.ts b/components/TempDesignSystem/Text/Subtitle/variants.ts index da1985669..a4cfb6095 100644 --- a/components/TempDesignSystem/Text/Subtitle/variants.ts +++ b/components/TempDesignSystem/Text/Subtitle/variants.ts @@ -26,7 +26,7 @@ const config = { defaultVariants: { color: "burgundy", textAlign: "left", - textTransform: "capitalize", + textTransform: "regular", type: "one", }, } as const