aboutsummaryrefslogtreecommitdiffstats
path: root/thallium-frontend
diff options
context:
space:
mode:
authorGravatar Joe Banks <[email protected]>2024-09-12 00:54:06 +0100
committerGravatar Joe Banks <[email protected]>2024-09-12 00:54:06 +0100
commit7ec4030f7334143741c5f19b4b57249aacded374 (patch)
tree6d58c34c8099e7ca5f98423f3c0826aaf226e6d6 /thallium-frontend
parentFix margins for small devices (diff)
Add new CartConfirm component for displaying cart contents on checkout
Diffstat (limited to 'thallium-frontend')
-rw-r--r--thallium-frontend/src/components/CartConfirm.tsx114
1 files changed, 114 insertions, 0 deletions
diff --git a/thallium-frontend/src/components/CartConfirm.tsx b/thallium-frontend/src/components/CartConfirm.tsx
new file mode 100644
index 0000000..f154d60
--- /dev/null
+++ b/thallium-frontend/src/components/CartConfirm.tsx
@@ -0,0 +1,114 @@
+import { useDispatch, useSelector } from "react-redux"
+import { RootState } from "../store"
+import { useState, useEffect } from "react";
+import { getTemplates, Template, Variant } from "../api/templates";
+import { APIError, APIMissingTokenError } from "../api/client";
+import LoadingBar from "./LoadingBar";
+import { Link } from "react-router-dom";
+import styled from "styled-components";
+import Button from "./forms/Button";
+import { removeCartItem, CartItem as CartItemType } from "../slices/cart";
+
+interface CartItemProps {
+ product: Template,
+ variant: Variant,
+ quantity: number,
+ cartItem: CartItemType
+}
+
+const CartItemHolder = styled.div`
+display: flex;
+align-items: center;
+
+span {
+ flex-grow: 1;
+}
+
+div {
+ text-align: right;
+ margin-right: 20px;
+}
+
+h3, p {
+ margin: 0;
+}
+
+img {
+ width: 20%;
+ background-color: ${({theme}) => theme.backgroundColor};
+}
+
+margin-bottom: 10px;
+`
+
+const CartItem: React.FC<CartItemProps> = ({ product, variant, quantity, cartItem }: CartItemProps) => {
+ /* return <div>{product.title} - {variant.size} / {variant.colour} - {quantity} unit{quantity === 1 ? "" : "s"}</div> */
+ const dispatch = useDispatch();
+
+ return <CartItemHolder>
+ <img src={product.mockup_file_url}/>
+ <span></span>
+ <div>
+ <h3>{product.title}</h3>
+ <p><strong>Size:</strong> {variant.size}</p>
+ {variant.colour && <p><strong>Colour:</strong> {variant.colour}</p>}
+ <p><strong>Quantity:</strong> {quantity}</p>
+ </div>
+ <Button onClick={() => {
+ dispatch(removeCartItem(cartItem))
+ }}>
+ Remove
+ </Button>
+ </CartItemHolder>
+}
+
+const CartConfirm = () => {
+ const cart = useSelector((state: RootState) => state.cart);
+ /* TODO: Refactor to hook */
+ const voucherToken = useSelector((state: RootState) => state.authorization.voucherToken);
+ const [storeItems, setStoreItems] = useState<Template[] | null>(null);
+ const [permissionDenied, setPermissionDenied] = useState<boolean>(false);
+ const [loading, setLoading] = useState<boolean>(true);
+
+ useEffect(() => {
+ getTemplates(true).then((items) => {
+ setStoreItems(items);
+ setLoading(false);
+ }).catch((err: unknown) => {
+ setStoreItems([]);
+ setLoading(false);
+ if (err instanceof APIMissingTokenError) {
+ setPermissionDenied(true);
+ } else if (err instanceof APIError) {
+ if ([401, 403].includes(err.status)) {
+ setPermissionDenied(true);
+ }
+ }
+ });
+ }, [voucherToken]);
+
+ return <>
+ {loading && <LoadingBar/>}
+ {permissionDenied && (
+ <>
+ <p>You need to have a valid voucher code to access the store.</p>
+ <Link to="/">Redeem a voucher</Link>
+ </>
+ )}
+ {storeItems && cart.cart.map((cartItem) => {
+ const item = storeItems.find((v) => v.template_id === cartItem.product_template_id);
+ const variant = item?.variants?.find((variant) => variant.variant_id === cartItem.variant_id);
+
+ if (item && variant) {
+ return <CartItem key={cartItem.variant_id} product={item} variant={variant} quantity={cartItem.quantity} cartItem={cartItem} />
+ }
+ })}
+
+ {cart.cart.length === 0 && <>
+ <strong>You have no items in your cart!</strong>
+ <p>Return to the store page to add some items</p>
+ </>}
+ </>;
+}
+
+export default CartConfirm;