Skip to content

Commit

Permalink
More migrating components, filling out the Order Summary and cart ite…
Browse files Browse the repository at this point in the history
…ms display, update API client
  • Loading branch information
jkachel committed Dec 9, 2024
1 parent 9ad5aa1 commit 1ea3dc0
Show file tree
Hide file tree
Showing 11 changed files with 4,105 additions and 3,336 deletions.
165 changes: 134 additions & 31 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
"use client";
import React from "react";
import React, { useEffect, useState } from "react";
import { useSearchParams, useRouter } from "next/navigation";
import { useMetaIntegratedSystemsList } from "@/services/ecommerce/meta/hooks";
import { styled } from "@mitodl/smoot-design";
import { Typography } from "@mui/material";
import { getCurrentSystem } from "@/utils/system";
import { Card } from "@/page-components/Card/Card";
import { createTheme } from "@mitodl/smoot-design"

import {
usePaymentsBasketList,
useDeferredPaymentsBasketRetrieve,
} from "@/services/ecommerce/payments/hooks";
import {
IntegratedSystem,
PaymentsApiPaymentsBasketsListRequest,
} from "@/services/ecommerce/generated/v0";

type CartProps = {
system: string;
}

type CartBodyProps = {
systemId: number;
}

const theme = createTheme();

const CartPageContainer = styled.div`
margin: 64px 108px;
Expand Down Expand Up @@ -52,7 +72,7 @@ const CartBodyContainer = styled.div`
gap: 48px;
`;

const CartHeader = styled.h1`
const CartHeader = styled.div`
width: 100%;
flex-grow: 1;
margin-bottom: 16px;
Expand All @@ -62,42 +82,125 @@ const CartItemsContainer = styled.div`
width: 816px;
`;

const CartSummaryContainer = styled.div`
type CartSummaryItemProps = {
variant?: string;
}

const CartSummaryContainer = styled.div(() => ({
"width": "auto",
"flexGrow": 1,
"borderBottom": "1px solid #DDE1E6",
"padding": "8px 0",
"margin": "8px 0",
}));

const CartSummaryItem = styled.div<CartSummaryItemProps>(({ variant }) => ({
"display": "flex",
"marginTop": (variant === "tax" ? "16px" : ""),
"marginBottom": "8px",
}));

const CartSummaryItemTitle = styled.div`
width: 280px;
margin-right: 16px;
`;

const CartSummaryItemValue = styled.div`
width: auto;
flex-grow: 1;
text-align: right;
`;

const Cart = () => {
return <CartContainer>
<CartHeader>You are about to purchase the following:</CartHeader>
<CartBodyContainer>
<CartItemsContainer>
<StyledCard>
<Card.Content>
<p>This is an item that's in the cart..</p>
</Card.Content>
</StyledCard>
const CartSummaryTotalContainer = styled.div`
${{ ...theme.typography.h5 }}
`;

<StyledCard>
<Card.Content>
<p>This is an item that's in the cart..</p>
</Card.Content>
</StyledCard>
</CartItemsContainer>
<CartSummaryContainer>
<StyledCard>
const CartBody: React.FC<CartBodyProps> = ({ systemId }) => {
const basket = usePaymentsBasketList({ integrated_system: systemId });
const basketDetails = useDeferredPaymentsBasketRetrieve(
basket.data?.results[0]?.id || 0,
!!basket.data?.count,
);

return basketDetails.isFetched && basketDetails?.data?.basket_items && basketDetails.data.basket_items.length > 0 ? <CartBodyContainer>
<CartItemsContainer>
{ basketDetails.data.basket_items.map((item) => (
<StyledCard key={`ue-basket-item-${item.id}`}>
<Card.Content>
<Typography variant="h3">Order Summary</Typography>

<p>This is an item that's in the cart..</p>
</Card.Content>
<Card.Footer>
By placing my order I agree to the Terms of Service and Privacy Policy.
</Card.Footer>
</StyledCard>
<Typography variant="h5">{item.product.sku}</Typography>
<Typography variant="h3">{item.product.name}</Typography>

</CartSummaryContainer>
<div>
{item.product.description}
</div>
</Card.Content>
</StyledCard>)) }

</CartItemsContainer>
<CartSummaryContainer>
<StyledCard>
<Card.Content>
<Typography variant="h3">Order Summary</Typography>

<CartSummaryContainer>
{ basketDetails.data.basket_items.map((item) => (
<CartSummaryItem key={`ue-basket-item-${item.id}`}>
<CartSummaryItemTitle>{item.product.name}</CartSummaryItemTitle>
<CartSummaryItemValue>{item.discounted_price.toLocaleString("en-US", { style: "currency", currency: "USD"})}</CartSummaryItemValue>
</CartSummaryItem>)) }


{ basketDetails.data.tax_rate ? <CartSummaryItem variant="tax">
<CartSummaryItemTitle>{basketDetails.data.tax_rate.tax_rate_name}</CartSummaryItemTitle>
<CartSummaryItemValue>{basketDetails.data.tax.toLocaleString("en-US", { style: "currency", currency: "USD" })}</CartSummaryItemValue>
</CartSummaryItem> : null }
</CartSummaryContainer>

<CartSummaryTotalContainer>
<CartSummaryItem>
<CartSummaryItemTitle>Total</CartSummaryItemTitle>
<CartSummaryItemValue>{basketDetails.data.total_price.toLocaleString("en-US", { style: "currency", currency: "USD" })}</CartSummaryItemValue>
</CartSummaryItem>
</CartSummaryTotalContainer>

By placing my order, I agree to the Terms of Service and Privacy Policy.

</Card.Content>
</StyledCard>

</CartSummaryContainer>
</CartBodyContainer> : <CartBodyContainer>
<StyledCard>
<Card.Content>
<p>Your cart is empty.</p>
</Card.Content>
</StyledCard>
</CartBodyContainer>
}

const Cart: React.FC<CartProps> = ({ system }) => {
const systems = useMetaIntegratedSystemsList();
const [ selectedSystem, setSelectedSystem ] = useState<number | null>(null);

useEffect(() => {
if (system && systems.data) {
const foundSystem = systems.data.results.find(
(integratedSystem: IntegratedSystem) =>
integratedSystem.slug === system,
);

if (foundSystem) {
console.log("we found a system", foundSystem);
setSelectedSystem(foundSystem.id);
}
}
}, [ system, systems, selectedSystem ]);

return <CartContainer>
<CartHeader>
<Typography variant="h3">You are about to purchase the following:</Typography>
</CartHeader>
{selectedSystem && <CartBody systemId={selectedSystem} />}
</CartContainer>
}

Expand All @@ -113,7 +216,7 @@ const Home = () => {
<SelectSystem />
</Card.Content>
</StyledCard>}
{specifiedSystem !== "" && <Cart />
{specifiedSystem !== "" && <Cart system={specifiedSystem} />
}
</CartPageContainer>;
};
Expand Down
9 changes: 6 additions & 3 deletions src/page-components/Card/ListCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import React, {
ImgHTMLAttributes,
isValidElement,
} from "react"
import { Link } from "react-router-dom"
import { createTheme } from "@mitodl/smoot-design"
import styled from "@emotion/styled"
import { RiDraggable } from "@remixicon/react"
import { theme } from "../ThemeProvider/ThemeProvider"
import { Wrapper, containerStyles } from "./Card"
import { TruncateText } from "../TruncateText/TruncateText"
import { ActionButton, ActionButtonProps } from "../Button/Button"
import { ActionButton } from "@mitodl/smoot-design"
import Link from "next/link"
import type { ActionButtonProps } from "@mitodl/smoot-design"

const theme = createTheme();

export const LinkContainer = styled(Link)`
${containerStyles}
Expand Down
10 changes: 6 additions & 4 deletions src/page-components/Card/ListCardCondensed.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { FC, ReactNode, Children, isValidElement } from "react"
import styled from "@emotion/styled"
import { RiDraggable } from "@remixicon/react"
import { theme } from "../ThemeProvider/ThemeProvider"
import { Wrapper } from "./Card"
import { TruncateText } from "../TruncateText/TruncateText"
import { createTheme } from "@mitodl/smoot-design"
import {
ListCard,
Body as BaseBody,
Expand All @@ -17,8 +16,11 @@ import {
Actions as BaseActions,
Bottom as BaseBottom,
} from "./ListCard"
import { TruncateText } from "../TruncateText/TruncateText"
import type { Card as BaseCard } from "./ListCard"

const theme = createTheme();

const DragArea = styled(BaseDragArea)`
padding-right: 4px;
margin-right: -4px;
Expand Down Expand Up @@ -97,15 +99,15 @@ const ListCardCondensed: Card = ({ children, className, href, draggable }) => {

if (content) {
return (
<_Container className={className} to={href!}>
<_Container className={className} href={href!}>
{content}
</_Container>
)
}

return (
<Wrapper className={className}>
<_Container to={href!}>
<_Container href={href!}>
{draggable && (
<DragArea>
<RiDraggable />
Expand Down
21 changes: 21 additions & 0 deletions src/page-components/TruncateText/TruncateText.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Canvas, Meta } from "@storybook/blocks"

import * as TruncateTextStories from "./TruncateText.stories"

<Meta of={TruncateTextStories} />

# TruncateText

Use `lineClamp` to truncate text after a certain number of lines:

`lineClamp={1}`

<Canvas of={TruncateTextStories.One} />

`lineClamp={3}`

<Canvas of={TruncateTextStories.Three} />

`lineClamp={"none"}`

<Canvas of={TruncateTextStories.None} />
42 changes: 42 additions & 0 deletions src/page-components/TruncateText/TruncateText.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { Meta, StoryObj } from "@storybook/react"
import { TruncateText } from "./TruncateText"

const meta: Meta<typeof TruncateText> = {
title: "smoot-design/TruncateText",
component: TruncateText,
argTypes: {
lineClamp: {
options: ["none", 1, 2, 3, 4, 5],
control: {
type: "select",
},
},
},
args: {
lineClamp: 1,
children:
"This is a long text that should be truncated after a few lines. ".repeat(
30,
),
},
}

export default meta

type Story = StoryObj<typeof TruncateText>

export const None: Story = {
args: {
lineClamp: "none",
},
}
export const One: Story = {
args: {
lineClamp: 1,
},
}
export const Three: Story = {
args: {
lineClamp: 3,
},
}
34 changes: 34 additions & 0 deletions src/page-components/TruncateText/TruncateText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { css } from "@emotion/react"
import styled from "@emotion/styled"

type TruncateTextProps = {
/**
* Number of lines to display before truncating text.
*/
lineClamp?: number | "none"
}

const truncateText = (lines?: number | "none") =>
css({
display: "-webkit-box",
WebkitBoxOrient: "vertical",
overflow: "hidden",
textOverflow: "ellipsis",
WebkitLineClamp: lines,
[`@supports (-webkit-line-clamp: ${lines})`]: {
whiteSpace: "initial",
display: "-webkit-box",
WebkitLineClamp: `${lines}`, // cast to any to avoid typechecking error in lines,
WebkitBoxOrient: "vertical",
},
})

/**
* Truncate the content after specified number of lines.
*/
const TruncateText = styled.div<TruncateTextProps>(({ lineClamp: lines }) =>
truncateText(lines),
)

export { TruncateText, truncateText }
export type { TruncateTextProps }
Loading

0 comments on commit 1ea3dc0

Please sign in to comment.