Skip to content

Commit

Permalink
Client update, add discount functionality
Browse files Browse the repository at this point in the history
- Update the axios config to includ CSRF stuff
- Update the generated API client
- Add logic to apply the discount code
- Add discount code display in the cart summary
  • Loading branch information
jkachel committed Dec 11, 2024
1 parent 86fe9b3 commit 29a0a81
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 27 deletions.
46 changes: 33 additions & 13 deletions src/page-components/CartSummary/CartSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ import CartSummaryItem, { CartSummaryItemContainer, CartSummaryItemTitle, CartSu

import {
usePaymentsBasketRetrieve,
usePaymentsBasketAddDiscount,
} from "@/services/ecommerce/payments/hooks";

type CartSummaryProps = {
cartId: number;
}


type CartSummaryDiscountProps = {
systemSlug: string;
}

const theme = createTheme();

const CartSummaryContainer = styled.div(() => ({
Expand Down Expand Up @@ -54,7 +59,32 @@ const CartSummaryDiscountContainer = styled.div`
const CartPayButton = styled(Button)`
width: 100%;
`;


const CartSummaryDiscount: React.FC<CartSummaryDiscountProps> = ({ systemSlug }) => {
const discountMutation = usePaymentsBasketAddDiscount();
const [ discountCode, setDiscountCode ] = React.useState<string>("");

const hndUpdateCode = (ev: React.ChangeEvent<HTMLInputElement>) => {
setDiscountCode(ev.target.value);
}

const hndApplyDiscount = () => {
discountMutation.mutate({ system_slug: systemSlug, discount_code: discountCode });
}

return <CartSummaryDiscountContainer>
<label htmlFor="discountcode">Coupon Code</label>
<CartSummaryItemContainer>
<CartSummaryItemTitle>
<Input size="small" name="discountcode" type="text" onChange={hndUpdateCode} />
</CartSummaryItemTitle>
<CartSummaryItemValue>
<Button variant="unstable_inverted" onClick={hndApplyDiscount}>Apply</Button>
</CartSummaryItemValue>
</CartSummaryItemContainer>
</CartSummaryDiscountContainer>;
}

const CartSummary: React.FC<CartSummaryProps> = (props) => {
const { cartId } = props;
const basket = usePaymentsBasketRetrieve(cartId);
Expand All @@ -79,17 +109,7 @@ const CartSummary: React.FC<CartSummaryProps> = (props) => {
</CartSummaryItemContainer>
</CartSummaryTotalContainer>

<CartSummaryDiscountContainer>
<label htmlFor="discountcode">Coupon Code</label>
<CartSummaryItemContainer>
<CartSummaryItemTitle>
<Input size="small" name="discountcode" type="text" />
</CartSummaryItemTitle>
<CartSummaryItemValue>
<Button variant="unstable_inverted">Apply</Button>
</CartSummaryItemValue>
</CartSummaryItemContainer>
</CartSummaryDiscountContainer>
{ basket.data.integrated_system.slug && <CartSummaryDiscount systemSlug={basket.data.integrated_system.slug} /> }

<CartSummaryActionContainer>
<CartPayButton size="large">Place Order</CartPayButton>
Expand Down
30 changes: 21 additions & 9 deletions src/page-components/CartSummaryItem/CartSummaryItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { styled } from "@mitodl/smoot-design";
import { BasketItemWithProduct, BasketWithProduct } from "@/services/ecommerce/generated/v0";

type CartSummaryItemVariant = "tax" | "item";
type CartSummaryItemTitleVariant = "" | "discount";

type CartSummaryItemProps = {
item: BasketItemWithProduct | BasketWithProduct;
Expand All @@ -12,18 +13,23 @@ type CartSummaryItemProps = {

type CartSummaryItemContainerProps = {
variant?: CartSummaryItemVariant;
}
}

type CartSummaryItemTitleProps = {
variant?: CartSummaryItemTitleVariant;
}

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

const CartSummaryItemTitle = styled.div`
width: 280px;
margin-right: 16px;
`;
const CartSummaryItemTitle = styled.div<CartSummaryItemTitleProps>(({ variant }) => ({
"width": "280px",
"marginRight": "16px",
"fontStyle": (variant === "discount" ? "italic" : ""),
}));

const CartSummaryItemValue = styled.div`
width: auto;
Expand All @@ -36,16 +42,22 @@ const isBasketWithProduct = (item: BasketItemWithProduct | BasketWithProduct): i
};

const CartSummaryItem: React.FC<CartSummaryItemProps> = ({ item, variant }) => {
return <CartSummaryItemContainer variant={variant || "item"}>
{isBasketWithProduct(item) ? <>
return <>
{isBasketWithProduct(item) && <CartSummaryItemContainer variant={variant || "item"}>
<CartSummaryItemTitle>{item.tax_rate.tax_rate_name}</CartSummaryItemTitle>
<CartSummaryItemValue>{item.tax.toLocaleString("en-US", { style: "currency", currency: "USD" })}</CartSummaryItemValue>
</> : null}
</CartSummaryItemContainer>}
{!isBasketWithProduct(item) && <>
<CartSummaryItemContainer variant={variant || "item"}>
<CartSummaryItemTitle>{item.product.name}</CartSummaryItemTitle>
<CartSummaryItemValue>{item.discounted_price.toLocaleString("en-US", { style: "currency", currency: "USD"})}</CartSummaryItemValue>
</CartSummaryItemContainer>
{item.discount_applied && <CartSummaryItemContainer>
<CartSummaryItemTitle variant="discount">Discount Applied: {item.discount_applied.discount_code}</CartSummaryItemTitle>
<CartSummaryItemValue>-{(parseFloat(item.product.price) - item.discounted_price).toLocaleString("en-US", { style: "currency", currency: "USD"})}</CartSummaryItemValue>
</CartSummaryItemContainer>}
</>}
</CartSummaryItemContainer>
</>;
};

export default CartSummaryItem;
Expand Down
3 changes: 3 additions & 0 deletions src/services/ecommerce/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ invariant(BASE_PATH, "NEXT_PUBLIC_UE_API_BASE_URL is required.");

const instance = axios.create({
withCredentials: true,
withXSRFToken: true,
xsrfCookieName: "csrftoken",
xsrfHeaderName: "X-CSRFTOKEN",
});

const paymentsApi = new PaymentsApi(undefined, BASE_PATH, instance);
Expand Down
Loading

0 comments on commit 29a0a81

Please sign in to comment.