From 24810eaee6ffcb02a59f8f55959b1599d420b520 Mon Sep 17 00:00:00 2001 From: Arvid Norlin Date: Wed, 5 Jun 2024 15:28:51 +0200 Subject: [PATCH] implement logic to select compared levels based on membershipLevel --- .../DynamicContent/OverviewTable/index.tsx | 127 ++++++++++++------ .../Blocks/Overview/Buttons/CopyButton.tsx | 4 +- .../MyPages/Blocks/Overview/Friend/index.tsx | 4 +- .../Blocks/Overview/Stats/Points/index.tsx | 6 +- .../Points/CurrentPointsBalance/index.tsx | 6 +- constants/membershipLevels.ts | 9 ++ server/routers/user/output.ts | 10 +- utils/user.ts | 7 + 8 files changed, 125 insertions(+), 48 deletions(-) create mode 100644 constants/membershipLevels.ts create mode 100644 utils/user.ts diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx index d9b89f31e..8a9a0ee5d 100644 --- a/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx @@ -1,13 +1,16 @@ "use client" -import { Dispatch, SetStateAction, useState } from "react" +import { Dispatch, SetStateAction, useEffect, useState } from "react" import { type Key } from "react-aria-components" import { useIntl } from "react-intl" import { Lang } from "@/constants/languages" +import { membershipLevels } from "@/constants/membershipLevels" +import { trpc } from "@/lib/trpc/client" import Image from "@/components/Image" import Select from "@/components/TempDesignSystem/Form/Select" +import { getMembership } from "@/utils/user" import levelsData from "./data/EN.json" import BenefitList from "./BenefitList" @@ -56,19 +59,59 @@ function getLevelByTier(tier: number) { export default function OverviewTable() { const intl = useIntl() - const [selectedLevelA, setSelectedLevelA] = useState(getLevelByTier(1)) - const [selectedLevelB, setSelectedLevelB] = useState(getLevelByTier(2)) - const [selectedLevelC, setSelectedLevelC] = useState(getLevelByTier(3)) + // TODO: Should isLoading be used for some loader, or is it fine to just use default values and rerender? + // Also, since it's fine to not be authenticated, how should the error be handled? + const { data, isLoading } = trpc.user.get.useQuery() - const defaultLevelA = levelsData.levels.find( - (level) => level.tier === selectedLevelA.tier - ) as ComparisonLevel - const defaultLevelB = levelsData.levels.find( - (level) => level.tier === selectedLevelB.tier - ) as ComparisonLevel - const defaultLevelC = levelsData.levels.find( - (level) => level.tier === selectedLevelC.tier - ) as ComparisonLevel + const [selectedLevelAMobile, setSelectedLevelAMobile] = useState( + getLevelByTier(1) + ) + const [selectedLevelBMobile, setSelectedLevelBMobile] = useState( + getLevelByTier(2) + ) + + const [selectedLevelADesktop, setSelectedLevelADesktop] = useState( + getLevelByTier(1) + ) + const [selectedLevelBDesktop, setSelectedLevelBDesktop] = useState( + getLevelByTier(2) + ) + const [selectedLevelCDesktop, setSelectedLevelCDesktop] = useState( + getLevelByTier(3) + ) + + useEffect(() => { + const membership = data?.memberships + ? getMembership(data.memberships) + : null + if (membership) { + const tier = membershipLevels[membership.membershipLevel] + + // The logic on which levels to display for upper levels is as requested by UI + if (tier === 6) { + setSelectedLevelAMobile(getLevelByTier(6)) + setSelectedLevelBMobile(getLevelByTier(7)) + + setSelectedLevelADesktop(getLevelByTier(5)) + setSelectedLevelBDesktop(getLevelByTier(6)) + setSelectedLevelCDesktop(getLevelByTier(7)) + } else if (tier === 7) { + setSelectedLevelAMobile(getLevelByTier(6)) + setSelectedLevelBMobile(getLevelByTier(7)) + + setSelectedLevelADesktop(getLevelByTier(6)) + setSelectedLevelBDesktop(getLevelByTier(7)) + setSelectedLevelCDesktop(getLevelByTier(1)) + } else { + setSelectedLevelAMobile(getLevelByTier(tier)) + setSelectedLevelBMobile(getLevelByTier(tier + 1)) + + setSelectedLevelADesktop(getLevelByTier(tier)) + setSelectedLevelBDesktop(getLevelByTier(tier + 1)) + setSelectedLevelCDesktop(getLevelByTier(tier + 2)) + } + } + }, [isLoading, data?.memberships]) function handleSelectChange( callback: Dispatch> @@ -105,13 +148,13 @@ export default function OverviewTable() { name="benefitA" label={intl.formatMessage({ id: "Level" })} items={levelOptions} - defaultSelectedKey={selectedLevelA.tier} - onSelect={handleSelectChange(setSelectedLevelA)} + value={selectedLevelAMobile.tier} + onSelect={handleSelectChange(setSelectedLevelAMobile)} /> {defaultLevelA.name} @@ -119,7 +162,7 @@ export default function OverviewTable() { level.tier === selectedLevelA.tier + (level) => level.tier === selectedLevelAMobile.tier ) as ComparisonLevel } /> @@ -129,13 +172,13 @@ export default function OverviewTable() { name="benefitB" label={intl.formatMessage({ id: "Level" })} items={levelOptions} - defaultSelectedKey={selectedLevelB.tier} - onSelect={handleSelectChange(setSelectedLevelB)} + value={selectedLevelBMobile.tier} + onSelect={handleSelectChange(setSelectedLevelBMobile)} /> {defaultLevelB.name} @@ -143,13 +186,13 @@ export default function OverviewTable() { level.tier === selectedLevelB.tier + (level) => level.tier === selectedLevelBMobile.tier ) as ComparisonLevel } /> - +
@@ -158,13 +201,13 @@ export default function OverviewTable() { name="benefitA" label={intl.formatMessage({ id: "Level" })} items={levelOptions} - defaultSelectedKey={selectedLevelA.tier} - onSelect={handleSelectChange(setSelectedLevelA)} + value={selectedLevelADesktop.tier} + onSelect={handleSelectChange(setSelectedLevelADesktop)} /> {defaultLevelA.name} @@ -172,7 +215,7 @@ export default function OverviewTable() { level.tier === selectedLevelA.tier + (level) => level.tier === selectedLevelADesktop.tier ) as ComparisonLevel } /> @@ -182,13 +225,13 @@ export default function OverviewTable() { name="benefitB" label={intl.formatMessage({ id: "Level" })} items={levelOptions} - defaultSelectedKey={selectedLevelB.tier} - onSelect={handleSelectChange(setSelectedLevelB)} + value={selectedLevelBDesktop.tier} + onSelect={handleSelectChange(setSelectedLevelBDesktop)} /> {defaultLevelB.name} @@ -196,7 +239,7 @@ export default function OverviewTable() { level.tier === selectedLevelB.tier + (level) => level.tier === selectedLevelBDesktop.tier ) as ComparisonLevel } /> @@ -206,13 +249,13 @@ export default function OverviewTable() { name="benefitC" label={intl.formatMessage({ id: "Level" })} items={levelOptions} - defaultSelectedKey={selectedLevelC.tier} - onSelect={handleSelectChange(setSelectedLevelC)} + value={selectedLevelCDesktop.tier} + onSelect={handleSelectChange(setSelectedLevelCDesktop)} /> {defaultLevelC.name} @@ -220,14 +263,18 @@ export default function OverviewTable() { level.tier === selectedLevelC.tier + (level) => level.tier === selectedLevelCDesktop.tier ) as ComparisonLevel } />
diff --git a/components/MyPages/Blocks/Overview/Buttons/CopyButton.tsx b/components/MyPages/Blocks/Overview/Buttons/CopyButton.tsx index 2d9ec3942..fac1a8976 100644 --- a/components/MyPages/Blocks/Overview/Buttons/CopyButton.tsx +++ b/components/MyPages/Blocks/Overview/Buttons/CopyButton.tsx @@ -2,11 +2,13 @@ import Image from "@/components/Image" import Button from "@/components/TempDesignSystem/Button" +import { getMembership } from "@/utils/user" import type { User } from "@/types/user" -export default function CopyButton({ membership }: Pick) { +export default function CopyButton({ memberships }: Pick) { function handleCopy() { + const membership = getMembership(memberships) console.log(`COPIED! (${membership ? membership.membershipNumber : "N/A"})`) } diff --git a/components/MyPages/Blocks/Overview/Friend/index.tsx b/components/MyPages/Blocks/Overview/Friend/index.tsx index c804d5ef8..901da620d 100644 --- a/components/MyPages/Blocks/Overview/Friend/index.tsx +++ b/components/MyPages/Blocks/Overview/Friend/index.tsx @@ -2,6 +2,7 @@ import { GoodFriend } from "@/components/Levels" import BiroScript from "@/components/TempDesignSystem/Text/BiroScript" import Title from "@/components/TempDesignSystem/Text/Title" import { getIntl } from "@/i18n" +import { getMembership } from "@/utils/user" import styles from "./friend.module.css" @@ -9,6 +10,7 @@ import type { UserProps } from "@/types/components/myPages/user" export default async function Friend({ user }: UserProps) { const { formatMessage } = await getIntl() + const membership = getMembership(user.memberships) return (
@@ -26,7 +28,7 @@ export default async function Friend({ user }: UserProps) { {formatMessage({ id: "Membership ID" })}:

- {user.membership ? user.membership.membershipNumber : "N/A"} + {membership ? membership.membershipNumber : "N/A"}

diff --git a/components/MyPages/Blocks/Overview/Stats/Points/index.tsx b/components/MyPages/Blocks/Overview/Stats/Points/index.tsx index 9c280edef..3c408d657 100644 --- a/components/MyPages/Blocks/Overview/Stats/Points/index.tsx +++ b/components/MyPages/Blocks/Overview/Stats/Points/index.tsx @@ -1,5 +1,6 @@ import Title from "@/components/TempDesignSystem/Text/Title" import { getIntl } from "@/i18n" +import { getMembership } from "@/utils/user" import Label from "../Label" @@ -9,18 +10,19 @@ import type { UserProps } from "@/types/components/myPages/user" export default async function Points({ user }: UserProps) { const { formatMessage } = await getIntl() + const membership = getMembership(user.memberships) return (
- {user.membership ? user.membership.currentPoints : "N/A"} + {membership ? membership.currentPoints : "N/A"}
- {user.membership ? user.membership.currentPoints : "N/A"} + {membership ? membership.currentPoints : "N/A"}
diff --git a/components/MyPages/Blocks/Points/CurrentPointsBalance/index.tsx b/components/MyPages/Blocks/Points/CurrentPointsBalance/index.tsx index b851b2a72..37f7833ae 100644 --- a/components/MyPages/Blocks/Points/CurrentPointsBalance/index.tsx +++ b/components/MyPages/Blocks/Points/CurrentPointsBalance/index.tsx @@ -1,7 +1,10 @@ +import { get } from "http" + import { serverClient } from "@/lib/trpc/server" import Header from "@/components/MyPages/Blocks/Header" import { getIntl } from "@/i18n" +import { getMembership } from "@/utils/user" import styles from "./currentPointsBalance.module.css" @@ -15,6 +18,7 @@ async function CurrentPointsBalance({ }: AccountPageComponentProps) { const user = await serverClient().user.get() const { formatMessage } = await getIntl() + const membership = getMembership(user.memberships) return (
@@ -23,7 +27,7 @@ async function CurrentPointsBalance({

{`${formatMessage({ id: "Total points" })}*`}

{`${formatMessage({ id: "Points" })}: ${user.membership?.currentPoints || "N/A"}`}

+ >{`${formatMessage({ id: "Points" })}: ${membership?.currentPoints || "N/A"}`}

{`*${formatMessage({ id: "Points may take up to 10 days to be displayed." })}`}

diff --git a/constants/membershipLevels.ts b/constants/membershipLevels.ts new file mode 100644 index 000000000..10ea4337b --- /dev/null +++ b/constants/membershipLevels.ts @@ -0,0 +1,9 @@ +export enum membershipLevels { + L1 = 1, + L2 = 2, + L3 = 3, + L4 = 4, + L5 = 5, + L6 = 6, + L7 = 7, +} diff --git a/server/routers/user/output.ts b/server/routers/user/output.ts index 1769b9e78..05be439e3 100644 --- a/server/routers/user/output.ts +++ b/server/routers/user/output.ts @@ -1,5 +1,7 @@ import { z } from "zod" +import { membershipLevels } from "@/constants/membershipLevels" + import { countriesMap } from "@/components/TempDesignSystem/Form/Country/countries" export const getUserSchema = z.object({ @@ -14,14 +16,16 @@ export const getUserSchema = z.object({ firstName: z.string(), language: z.string(), lastName: z.string(), - membership: z - .object({ + memberships: z.array( + z.object({ currentPoints: z.number(), expirationDate: z.string(), membershipNumber: z.string(), + membershipLevel: z.enum(["L1", "L2", "L3", "L4", "L5", "L6", "L7"]), memberSince: z.string(), + membershipType: z.string(), }) - .optional(), + ), phoneNumber: z.string(), profileId: z.string(), }) diff --git a/utils/user.ts b/utils/user.ts new file mode 100644 index 000000000..104d8e9f2 --- /dev/null +++ b/utils/user.ts @@ -0,0 +1,7 @@ +import { User } from "@/types/user" + +export function getMembership(memberships: User["memberships"]) { + return memberships?.find( + (membership) => membership.membershipType.toLowerCase() === "guestpr" + ) +}