summaryrefslogtreecommitdiff
path: root/src/frontend/components/CartDropdown
diff options
context:
space:
mode:
authorSaumit <justsaumit@protonmail.com>2025-09-27 02:14:26 +0530
committerSaumit <justsaumit@protonmail.com>2025-09-27 02:14:26 +0530
commit82e03978b89938219958032efb1448cc76baa181 (patch)
tree626f3e54d52ecd49be0ed3bee30abacc0453d081 /src/frontend/components/CartDropdown
Initial snapshot - OpenTelemetry demo 2.1.3 -f
Diffstat (limited to 'src/frontend/components/CartDropdown')
-rw-r--r--src/frontend/components/CartDropdown/CartDropdown.styled.ts100
-rw-r--r--src/frontend/components/CartDropdown/CartDropdown.tsx65
-rw-r--r--src/frontend/components/CartDropdown/index.ts4
3 files changed, 169 insertions, 0 deletions
diff --git a/src/frontend/components/CartDropdown/CartDropdown.styled.ts b/src/frontend/components/CartDropdown/CartDropdown.styled.ts
new file mode 100644
index 0000000..8820210
--- /dev/null
+++ b/src/frontend/components/CartDropdown/CartDropdown.styled.ts
@@ -0,0 +1,100 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+import Image from 'next/image';
+import styled from 'styled-components';
+import Button from '../Button';
+
+export const CartDropdown = styled.div`
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ max-height: 100%;
+ padding: 25px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ gap: 24px;
+ background: ${({ theme }) => theme.colors.white};
+ z-index: 1000;
+ border-radius: 5px;
+ box-shadow: 0 2px 2px 0 rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 12%), 0 1px 5px 0 rgb(0 0 0 / 20%);
+
+ ${({ theme }) => theme.breakpoints.desktop} {
+ position: absolute;
+ width: 400px;
+ top: 95px;
+ right: 17px;
+ max-height: 650px;
+ }
+`;
+
+export const Title = styled.h5`
+ margin: 0px;
+ font-size: ${({ theme }) => theme.sizes.mxLarge};
+
+ ${({ theme }) => theme.breakpoints.desktop} {
+ font-size: ${({ theme }) => theme.sizes.dLarge};
+ }
+`;
+
+export const ItemList = styled.div`
+ ${({ theme }) => theme.breakpoints.desktop} {
+ max-height: 450px;
+ overflow-y: scroll;
+ }
+`;
+
+export const Item = styled.div`
+ display: grid;
+ grid-template-columns: 29% 59%;
+ gap: 2%;
+ padding: 25px 0;
+ border-bottom: 1px solid ${({ theme }) => theme.colors.textLightGray};
+`;
+
+export const ItemImage = styled(Image).attrs({
+ width: '80',
+ height: '80',
+})`
+ border-radius: 5px;
+`;
+
+export const ItemName = styled.p`
+ margin: 0px;
+ font-size: ${({ theme }) => theme.sizes.mLarge};
+ font-weight: ${({ theme }) => theme.fonts.regular};
+`;
+
+export const ItemDetails = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+`;
+
+export const ItemQuantity = styled(ItemName)`
+ font-size: ${({ theme }) => theme.sizes.mMedium};
+`;
+
+export const CartButton = styled(Button)``;
+
+export const Header = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ ${({ theme }) => theme.breakpoints.desktop} {
+ span {
+ display: none;
+ }
+ }
+`;
+
+export const EmptyCart = styled.h3`
+ margin: 0;
+ margin-top: 25px;
+ font-size: ${({ theme }) => theme.sizes.mLarge};
+ color: ${({ theme }) => theme.colors.textLightGray};
+`;
diff --git a/src/frontend/components/CartDropdown/CartDropdown.tsx b/src/frontend/components/CartDropdown/CartDropdown.tsx
new file mode 100644
index 0000000..cd0703e
--- /dev/null
+++ b/src/frontend/components/CartDropdown/CartDropdown.tsx
@@ -0,0 +1,65 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+import Link from 'next/link';
+import { useEffect, useRef } from 'react';
+import { CypressFields } from '../../utils/enums/CypressFields';
+import { IProductCartItem } from '../../types/Cart';
+import ProductPrice from '../ProductPrice';
+import * as S from './CartDropdown.styled';
+
+interface IProps {
+ isOpen: boolean;
+ onClose(): void;
+ productList: IProductCartItem[];
+}
+
+const CartDropdown = ({ productList, isOpen, onClose }: IProps) => {
+ const ref = useRef<HTMLDivElement>(null);
+
+ useEffect(() => {
+ const handleClickOutside = (event: Event) => {
+ if (ref.current && !ref.current.contains(event.target as Node)) {
+ onClose();
+ }
+ };
+ // Bind the event listener
+ document.addEventListener('mousedown', handleClickOutside);
+
+ return () => {
+ // Unbind the event listener on clean up
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, [ref, onClose]);
+
+ return isOpen ? (
+ <S.CartDropdown ref={ref} data-cy={CypressFields.CartDropdown}>
+ <div>
+ <S.Header>
+ <S.Title>Shopping Cart</S.Title>
+ <span onClick={onClose}>Close</span>
+ </S.Header>
+ <S.ItemList>
+ {!productList.length && <S.EmptyCart>Your shopping cart is empty</S.EmptyCart>}
+ {productList.map(
+ ({ quantity, product: { name, picture, id, priceUsd = { nanos: 0, currencyCode: 'USD', units: 0 } } }) => (
+ <S.Item key={id} data-cy={CypressFields.CartDropdownItem}>
+ <S.ItemImage src={"/images/products/" + picture} alt={name} />
+ <S.ItemDetails>
+ <S.ItemName>{name}</S.ItemName>
+ <ProductPrice price={priceUsd} />
+ <S.ItemQuantity>Quantity: {quantity}</S.ItemQuantity>
+ </S.ItemDetails>
+ </S.Item>
+ )
+ )}
+ </S.ItemList>
+ </div>
+ <Link href="/cart">
+ <S.CartButton data-cy={CypressFields.CartGoToShopping}>Go to Shopping Cart</S.CartButton>
+ </Link>
+ </S.CartDropdown>
+ ) : null;
+};
+
+export default CartDropdown;
diff --git a/src/frontend/components/CartDropdown/index.ts b/src/frontend/components/CartDropdown/index.ts
new file mode 100644
index 0000000..559fff3
--- /dev/null
+++ b/src/frontend/components/CartDropdown/index.ts
@@ -0,0 +1,4 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+export { default } from './CartDropdown';