From 235ebc9df430dffaa1502075e1f61c225daffcc2 Mon Sep 17 00:00:00 2001 From: trevor-anderson Date: Tue, 20 Feb 2024 12:40:58 -0500 Subject: [PATCH] feat: impl route-constants, update import paths --- .../MappedRowOfProductBoxes.tsx | 9 ++-- .../ProductSelection/ProductInfoBox.tsx | 49 +++++++++---------- .../ProductSelection/ProductSelection.tsx | 33 +++++++------ .../ProductSelection/SingleProductBox.tsx | 8 +-- .../SingleProductBoxSwitch.tsx | 27 +++++----- .../ProductSelection/classNames.ts | 10 ++++ .../ProductsPage/ProductSelection/index.ts | 2 +- .../ProductSelection/productPricingInfo.ts | 2 +- 8 files changed, 74 insertions(+), 66 deletions(-) create mode 100644 src/pages/ProductsPage/ProductSelection/classNames.ts diff --git a/src/pages/ProductsPage/ProductSelection/MappedRowOfProductBoxes.tsx b/src/pages/ProductsPage/ProductSelection/MappedRowOfProductBoxes.tsx index 446fec2c..a3b6031d 100644 --- a/src/pages/ProductsPage/ProductSelection/MappedRowOfProductBoxes.tsx +++ b/src/pages/ProductsPage/ProductSelection/MappedRowOfProductBoxes.tsx @@ -1,8 +1,9 @@ import { useNavigate } from "react-router-dom"; -import { checkoutValuesStore, type StoredCheckoutValues } from "@cache/checkoutValuesStore"; +import { APP_PATHS } from "@/routes/appPaths"; +import { checkoutValuesStore, type StoredCheckoutValues } from "@/stores/checkoutValuesStore"; import { ProductInfoBox } from "./ProductInfoBox"; import { PRICE_INFO } from "./productPricingInfo"; -import type { SubscriptionPriceLabel } from "@graphql/types"; +import type { SubscriptionPriceLabel } from "@/graphql/types"; /** * Product selection for desktop layout @@ -32,7 +33,7 @@ export const MappedRowOfProductBoxes = ({ selectedSubscription }: StoredCheckout buttonLabel={!isSelected ? "Select" : "Subscribe"} onClickButton={() => { if (!isSelected) handleClickContainer(priceLabel); - else nav("/checkout"); + else nav(APP_PATHS.CHECKOUT); }} onClickContainer={() => handleClickContainer(priceLabel)} sx={({ palette }) => ({ @@ -52,6 +53,6 @@ const PRICE_INFO_ENTRIES = Object.entries(PRICE_INFO) as Array< PRICE_NAME: string; PRICE_AMOUNT: string; PRICE_DESCRIPTION: string; - } + }, ] >; diff --git a/src/pages/ProductsPage/ProductSelection/ProductInfoBox.tsx b/src/pages/ProductsPage/ProductSelection/ProductInfoBox.tsx index 7ac8ae4c..2e85c93b 100644 --- a/src/pages/ProductsPage/ProductSelection/ProductInfoBox.tsx +++ b/src/pages/ProductsPage/ProductSelection/ProductInfoBox.tsx @@ -2,8 +2,9 @@ import { styled } from "@mui/material/styles"; import Button, { buttonClasses } from "@mui/material/Button"; import Paper, { type PaperProps } from "@mui/material/Paper"; import Text, { typographyClasses } from "@mui/material/Typography"; -import { ShimmerBox, shimmerBoxClassNames } from "@components/Containers/ShimmerBox"; +import { ShimmerBox, containerClassNames } from "@/components/Containers"; import { ProductFeatures } from "./ProductFeatures"; +import { productSelectionClassNames } from "./classNames"; export const ProductInfoBox = ({ priceName, @@ -15,12 +16,8 @@ export const ProductInfoBox = ({ onClickContainer, ...paperProps }: ProductInfoBoxProps) => ( - - + + {priceName} {showMostPopularBadge && ( @@ -33,7 +30,7 @@ export const ProductInfoBox = ({ )}
-
+
{priceAmount} ); -export const productInfoBoxClassNames = { - container: "product-info-box-container", - headerContainer: "product-info-box-header-container", - amountAndDescriptionContainer: "product-info-box-amount-and-description-container", -}; - -const StyledPaper = styled(Paper)(({ onClick, theme: { palette, breakpoints } }) => ({ +const StyledPaper = styled(Paper)(({ onClick, theme: { palette, variables } }) => ({ position: "relative", height: "clamp(24rem, 43vh, 25rem)", - width: "clamp(15rem, 100%, 25rem)", - maxWidth: "25rem", display: "flex", flexDirection: "column", flexGrow: 1, - borderWidth: "1px", borderStyle: "solid", borderRadius: "1rem", borderColor: palette.divider, + ...(variables.isMobilePageLayout + ? { + width: "clamp(15rem, 100%, 25rem)", + maxWidth: "25rem", + borderWidth: "1px", + } + : { + width: "clamp(15rem, 30%, 20rem)", + maxWidth: "20rem", + borderWidth: "4px", + }), + "&:hover": { cursor: onClick ? "pointer" : "auto", }, - [`@media (min-width: ${breakpoints.values.md}) or (min-aspect-ratio: 1/1)`]: { - width: "clamp(15rem, 30%, 20rem)", - maxWidth: "20rem", - borderWidth: "4px", - }, - [`& > .${productInfoBoxClassNames.headerContainer}`]: { + [`& > .${productSelectionClassNames.productInfoBoxHeaderRoot}`]: { alignSelf: "center", height: "4rem", width: "100%", @@ -105,7 +100,7 @@ const StyledPaper = styled(Paper)(({ onClick, theme: { palette, breakpoints } }) width: "1rem", }, - [`& > .${shimmerBoxClassNames.root} .${typographyClasses.root}`]: { + [`& > .${containerClassNames.shimmerBoxRoot} .${typographyClasses.root}`]: { fontSize: "0.9rem", paddingTop: "1px", color: palette.getContrastText(palette.grey[900]), @@ -121,14 +116,14 @@ const StyledPaper = styled(Paper)(({ onClick, theme: { palette, breakpoints } }) alignItems: "flex-start", textAlign: "left", - [`& > .${productInfoBoxClassNames.amountAndDescriptionContainer}`]: { + [`& > .${productSelectionClassNames.productInfoBoxPriceInfoRoot}`]: { width: "100%", display: "flex", justifyContent: "center", alignItems: "center", whiteSpace: "pre-line", - // price amount text + // PRICE AMOUNT TEXT [`& > .${typographyClasses.root}.${typographyClasses.h3}`]: { fontSize: "2.25rem", margin: "0.15rem 0 0 0", diff --git a/src/pages/ProductsPage/ProductSelection/ProductSelection.tsx b/src/pages/ProductsPage/ProductSelection/ProductSelection.tsx index c0ac45e3..a8f1b7ba 100644 --- a/src/pages/ProductsPage/ProductSelection/ProductSelection.tsx +++ b/src/pages/ProductsPage/ProductSelection/ProductSelection.tsx @@ -1,9 +1,10 @@ import { useEffect } from "react"; import { styled } from "@mui/material/styles"; -import { checkoutValuesStore } from "@cache/checkoutValuesStore"; +import { checkoutValuesStore } from "@/stores/checkoutValuesStore"; import { USER_SUBSCRIPTION_PRICE_LABELS } from "@/types/UserSubscription"; import { MappedRowOfProductBoxes } from "./MappedRowOfProductBoxes"; import { SingleProductBox } from "./SingleProductBox"; +import type { IsMobilePageLayout } from "@/app/PageLayoutContext"; /** * Notes regarding ProductSelection on **mobile** devices/layouts: @@ -46,22 +47,26 @@ export const ProductSelection = ({ isMobilePageLayout }: ProductSelectionProps) ); }; -const StyledDiv = styled("div")(({ theme }) => ({ +const StyledDiv = styled("div")(({ theme: { variables } }) => ({ width: "100%", display: "flex", - flexDirection: "column", alignItems: "center", - [`@media (min-width: ${theme.breakpoints.values.md}) or (min-aspect-ratio: 1/1)`]: { - // On desktop/large displays, switch container flex-dir to row - flexDirection: "row", - justifyContent: "space-between", - alignSelf: "center", - // Add horizontal margin to middle ProductInfoDisplay container - "&>*:nth-of-type(2)": { - margin: "0 1rem", - }, - }, + ...(variables.isMobilePageLayout + ? { + flexDirection: "column", + gap: "inherit", + justifyContent: "space-between", + } + : { + flexDirection: "row", + justifyContent: "space-between", + // Add horizontal margin to middle ProductInfoDisplay container + "&>*:nth-of-type(2)": { + // TODO use classname/elementIDs here instead of nth-of-type + margin: "0 1rem", + }, + }), })); -export type ProductSelectionProps = { isMobilePageLayout: boolean }; +export type ProductSelectionProps = IsMobilePageLayout; diff --git a/src/pages/ProductsPage/ProductSelection/SingleProductBox.tsx b/src/pages/ProductsPage/ProductSelection/SingleProductBox.tsx index f04f9a69..541fa8e2 100644 --- a/src/pages/ProductsPage/ProductSelection/SingleProductBox.tsx +++ b/src/pages/ProductsPage/ProductSelection/SingleProductBox.tsx @@ -1,11 +1,12 @@ import { useNavigate } from "react-router-dom"; import Box from "@mui/material/Box"; import Tooltip from "@mui/material/Tooltip"; -import { checkoutValuesStore, StoredCheckoutValues } from "@cache/checkoutValuesStore"; +import { APP_PATHS } from "@/routes/appPaths"; +import { checkoutValuesStore, StoredCheckoutValues } from "@/stores/checkoutValuesStore"; import { ProductInfoBox } from "./ProductInfoBox"; import { SingleProductBoxSwitch } from "./SingleProductBoxSwitch"; import { PRICE_INFO } from "./productPricingInfo"; -import type { SubscriptionPriceLabel } from "@graphql/types"; +import type { SubscriptionPriceLabel } from "@/graphql/types"; /** * Product selection for mobile layout @@ -47,7 +48,7 @@ export const SingleProductBox = ({ selectedSubscription }: StoredCheckoutValues) const handleClickButton = () => { const { selectedSubscription: cachedSelectedSub } = checkoutValuesStore.get(); if (!cachedSelectedSub) checkoutValuesStore.mergeUpdate({ selectedSubscription: "TRIAL" }); - nav("/checkout"); + nav(APP_PATHS.CHECKOUT); }; return ( @@ -57,7 +58,6 @@ export const SingleProductBox = ({ selectedSubscription }: StoredCheckoutValues) style={{ width: "clamp(14rem, 66%, 20rem)", height: "4rem", - marginBottom: "1rem", borderRadius: "1rem", backgroundColor: "transparent", }} diff --git a/src/pages/ProductsPage/ProductSelection/SingleProductBoxSwitch.tsx b/src/pages/ProductsPage/ProductSelection/SingleProductBoxSwitch.tsx index fa7d8eec..7418a18e 100644 --- a/src/pages/ProductsPage/ProductSelection/SingleProductBoxSwitch.tsx +++ b/src/pages/ProductsPage/ProductSelection/SingleProductBoxSwitch.tsx @@ -1,8 +1,9 @@ import { styled } from "@mui/material/styles"; import Text, { typographyClasses } from "@mui/material/Typography"; +import { productSelectionClassNames } from "./classNames"; export const SingleProductBoxSwitch = ({ checked, handleChange }: SingleProductBoxSwitchProps) => ( - +
Monthly
@@ -10,18 +11,14 @@ export const SingleProductBoxSwitch = ({ checked, handleChange }: SingleProductB Yearly
- - + + ); -export const singleProductBoxSwitchClassNames = { - sliderThumb: "single-product-box-switch-slider-thumb", -}; - /** * The box around the slider */ -const StyledLabelElement = styled("label")(({ theme }) => ({ +const StyledLabel = styled("label")(({ theme: { palette } }) => ({ position: "relative", display: "flex", flexDirection: "row", @@ -29,8 +26,8 @@ const StyledLabelElement = styled("label")(({ theme }) => ({ width: "clamp(14rem, 100%, 20rem)", height: "100%", padding: "0.25rem 0.1rem", - backgroundColor: theme.palette.background.paper, - border: `1px solid ${theme.palette.divider}`, + backgroundColor: palette.background.paper, + border: `1px solid ${palette.divider}`, borderRadius: "1rem", cursor: "pointer", zIndex: 5, @@ -60,13 +57,13 @@ const StyledLabelElement = styled("label")(({ theme }) => ({ height: 0, // When it's checked, change the span's transition left/right values - [`&:checked + .${singleProductBoxSwitchClassNames.sliderThumb}`]: { + [`&:checked + .${productSelectionClassNames.singleProductBoxSwitchSliderThumb}`]: { transform: "translateX( calc(100% - 8px) )", }, }, // The visible slider thumb - [`& .${singleProductBoxSwitchClassNames.sliderThumb}`]: { + [`& .${productSelectionClassNames.singleProductBoxSwitchSliderThumb}`]: { position: "absolute", top: "4px", bottom: "4px", @@ -78,12 +75,12 @@ const StyledLabelElement = styled("label")(({ theme }) => ({ height: "calc(100% - 8px)", width: "50%", borderRadius: "0.85rem", - backgroundColor: theme.palette.primary.main, - boxShadow: `inset 0rem 0rem 1rem 0.5rem ${theme.palette.primary.dark}`, + backgroundColor: palette.primary.main, + boxShadow: `inset 0rem 0rem 1rem 0.5rem ${palette.primary.dark}`, }, })); export type SingleProductBoxSwitchProps = { checked: boolean; - handleChange: (event: React.ChangeEvent) => void; + handleChange: React.ChangeEventHandler; }; diff --git a/src/pages/ProductsPage/ProductSelection/classNames.ts b/src/pages/ProductsPage/ProductSelection/classNames.ts new file mode 100644 index 00000000..f4653a3a --- /dev/null +++ b/src/pages/ProductsPage/ProductSelection/classNames.ts @@ -0,0 +1,10 @@ + +/** + * Class names for `ProductSelection` components (src/pages/ProductsPage/ProductSelection/). + */ +export const productSelectionClassNames = { + productInfoBoxHeaderRoot: "product-info-box-header-root", + productInfoBoxPriceInfoRoot: "product-info-box-price-info-root", + + singleProductBoxSwitchSliderThumb: "single-product-box-switch-slider-thumb", +} as const; diff --git a/src/pages/ProductsPage/ProductSelection/index.ts b/src/pages/ProductsPage/ProductSelection/index.ts index eb29c172..ae02249b 100644 --- a/src/pages/ProductsPage/ProductSelection/index.ts +++ b/src/pages/ProductsPage/ProductSelection/index.ts @@ -1 +1 @@ -export { ProductSelection } from "./ProductSelection"; +export * from "./ProductSelection"; diff --git a/src/pages/ProductsPage/ProductSelection/productPricingInfo.ts b/src/pages/ProductsPage/ProductSelection/productPricingInfo.ts index 4fa61560..1bd6e15f 100644 --- a/src/pages/ProductsPage/ProductSelection/productPricingInfo.ts +++ b/src/pages/ProductsPage/ProductSelection/productPricingInfo.ts @@ -1,4 +1,4 @@ -import type { SubscriptionPriceLabel } from "@graphql/types"; +import type { SubscriptionPriceLabel } from "@/graphql/types"; export const PRICE_INFO: Record< SubscriptionPriceLabel,