diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx index d72832e35..de46ee3d5 100644 --- a/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx @@ -73,6 +73,7 @@ function getInitialState(user?: User) { selectedLevelCDesktop: getLevelByTier(3), } } + if (!membership.membershipLevel) return null const tier = membershipLevels[membership.membershipLevel] switch (tier) { diff --git a/components/MyProfile/CreditCards/creditCards.module.css b/components/MyProfile/CreditCards/creditCards.module.css index fd51a93d0..c74e5b2db 100644 --- a/components/MyProfile/CreditCards/creditCards.module.css +++ b/components/MyProfile/CreditCards/creditCards.module.css @@ -1,5 +1,18 @@ .container { align-items: center; display: flex; + flex-direction: column; justify-content: center; -} \ No newline at end of file +} + +.card { + margin-top: 2rem; + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(3, auto); + gap: 0.5rem; +} + +.subTitle { + grid-column: span 2; +} diff --git a/components/MyProfile/CreditCards/index.tsx b/components/MyProfile/CreditCards/index.tsx index e9a71b870..26cc42c53 100644 --- a/components/MyProfile/CreditCards/index.tsx +++ b/components/MyProfile/CreditCards/index.tsx @@ -1,14 +1,34 @@ +import { serverClient } from "@/lib/trpc/server" + import Card from "@/components/MyProfile/Card" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import Title from "@/components/TempDesignSystem/Text/Title" import { getIntl } from "@/i18n" import styles from "./creditCards.module.css" export default async function CreditCards() { + const creditCards = await serverClient().user.creditCards() + if (!creditCards) { + return null + } const { formatMessage } = await getIntl() return ( {formatMessage({ id: "My credit cards" })} + {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]} + +
+ ))}
) } diff --git a/lib/api/endpoints.ts b/lib/api/endpoints.ts index 2dd4f268c..d683e7896 100644 --- a/lib/api/endpoints.ts +++ b/lib/api/endpoints.ts @@ -7,9 +7,10 @@ export namespace endpoints { } export const enum v1 { profile = "profile/v1/Profile", + creditCards = `${profile}/creditCards`, + friendTransactions = "profile/v1/Transaction/friendTransactions", upcomingStays = "booking/v1/Stays/future", previousStays = "booking/v1/Stays/past", - friendTransactions = "profile/v1/Transaction/friendTransactions", } } diff --git a/server/routers/user/output.ts b/server/routers/user/output.ts index 535dec547..b7043781a 100644 --- a/server/routers/user/output.ts +++ b/server/routers/user/output.ts @@ -166,3 +166,17 @@ export const getFriendTransactionsSchema = z.object({ }) .nullable(), }) + +export const getCreditCardsSchema = z.object({ + data: z.array( + z.object({ + attribute: z.object({ + cardName: z.string().optional(), + alias: z.string(), + truncatedNumber: z.string(), + expirationDate: z.string(), + cardType: z.string(), + }), + }) + ), +}) diff --git a/server/routers/user/query.ts b/server/routers/user/query.ts index f57c4539d..4d7c57149 100644 --- a/server/routers/user/query.ts +++ b/server/routers/user/query.ts @@ -3,6 +3,7 @@ import { protectedProcedure, router } from "@/server/trpc" import { friendTransactionsInput, staysInput } from "./input" import { + getCreditCardsSchema, getFriendTransactionsSchema, getStaysSchema, getUserSchema, @@ -270,4 +271,31 @@ export const userQueryRouter = router({ } }), }), + + creditCards: protectedProcedure.query(async function ({ ctx }) { + const apiResponse = await api.get(api.endpoints.v1.creditCards, { + cache: "no-store", + headers: { + Authorization: `Bearer ${ctx.session.token.access_token}`, + }, + }) + + if (!apiResponse.ok) { + console.info(`API Response Failed - Getting Creadit Cards`) + console.info(`User: (${JSON.stringify(ctx.session.user)})`) + console.error(apiResponse) + return null + } + + const apiJson = await apiResponse.json() + const verifiedData = getCreditCardsSchema.safeParse(apiJson) + if (!verifiedData.success) { + console.info(`Failed to validate Credit Cards Data`) + console.info(`User: (${JSON.stringify(ctx.session.user)})`) + console.error(verifiedData.error) + return null + } + + return verifiedData.data.data + }), })