Skip to content

Commit

Permalink
feat: impl route-constants, update import paths
Browse files Browse the repository at this point in the history
  • Loading branch information
trevor-anderson committed Feb 20, 2024
1 parent 2ea4b90 commit 235ebc9
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 }) => ({
Expand All @@ -52,6 +53,6 @@ const PRICE_INFO_ENTRIES = Object.entries(PRICE_INFO) as Array<
PRICE_NAME: string;
PRICE_AMOUNT: string;
PRICE_DESCRIPTION: string;
}
},
]
>;
49 changes: 22 additions & 27 deletions src/pages/ProductsPage/ProductSelection/ProductInfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -15,12 +16,8 @@ export const ProductInfoBox = ({
onClickContainer,
...paperProps
}: ProductInfoBoxProps) => (
<StyledPaper
onClick={onClickContainer}
className={productInfoBoxClassNames.container}
{...paperProps}
>
<Paper elevation={2} className={productInfoBoxClassNames.headerContainer}>
<StyledPaper onClick={onClickContainer} {...paperProps}>
<Paper elevation={2} className={productSelectionClassNames.productInfoBoxHeaderRoot}>
<Text>{priceName}</Text>

{showMostPopularBadge && (
Expand All @@ -33,7 +30,7 @@ export const ProductInfoBox = ({
)}
</Paper>
<div>
<div className={productInfoBoxClassNames.amountAndDescriptionContainer}>
<div className={productSelectionClassNames.productInfoBoxPriceInfoRoot}>
<Text variant="h3">{priceAmount}</Text>
<span>
<Text
Expand All @@ -54,35 +51,33 @@ export const ProductInfoBox = ({
</StyledPaper>
);

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%",
Expand All @@ -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]),
Expand All @@ -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",
Expand Down
33 changes: 19 additions & 14 deletions src/pages/ProductsPage/ProductSelection/ProductSelection.tsx
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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;
8 changes: 4 additions & 4 deletions src/pages/ProductsPage/ProductSelection/SingleProductBox.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 (
Expand All @@ -57,7 +58,6 @@ export const SingleProductBox = ({ selectedSubscription }: StoredCheckoutValues)
style={{
width: "clamp(14rem, 66%, 20rem)",
height: "4rem",
marginBottom: "1rem",
borderRadius: "1rem",
backgroundColor: "transparent",
}}
Expand Down
27 changes: 12 additions & 15 deletions src/pages/ProductsPage/ProductSelection/SingleProductBoxSwitch.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
import { styled } from "@mui/material/styles";
import Text, { typographyClasses } from "@mui/material/Typography";
import { productSelectionClassNames } from "./classNames";

export const SingleProductBoxSwitch = ({ checked, handleChange }: SingleProductBoxSwitchProps) => (
<StyledLabelElement>
<StyledLabel>
<div style={{ left: 4 }}>
<Text>Monthly</Text>
</div>
<div style={{ right: 4 }}>
<Text>Yearly</Text>
</div>
<input type="checkbox" onChange={handleChange} checked={checked} aria-label="controlled" />
<span className={singleProductBoxSwitchClassNames.sliderThumb} />
</StyledLabelElement>
<span className={productSelectionClassNames.singleProductBoxSwitchSliderThumb} />
</StyledLabel>
);

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",
alignItems: "center",
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,
Expand Down Expand Up @@ -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",
Expand All @@ -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<HTMLInputElement>) => void;
handleChange: React.ChangeEventHandler<HTMLInputElement>;
};
10 changes: 10 additions & 0 deletions src/pages/ProductsPage/ProductSelection/classNames.ts
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion src/pages/ProductsPage/ProductSelection/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { ProductSelection } from "./ProductSelection";
export * from "./ProductSelection";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SubscriptionPriceLabel } from "@graphql/types";
import type { SubscriptionPriceLabel } from "@/graphql/types";

export const PRICE_INFO: Record<
SubscriptionPriceLabel,
Expand Down

0 comments on commit 235ebc9

Please sign in to comment.