diff --git a/src/components/Cart/Cart.jsx b/src/components/Cart/Cart.jsx index c924e2a..eccedea 100644 --- a/src/components/Cart/Cart.jsx +++ b/src/components/Cart/Cart.jsx @@ -1,50 +1,50 @@ -import React from 'react'; - -import { Divider, Grid } from '@mui/material'; +import { Grid, Box, Divider } from '@mui/material'; import { + GridContainer, EmptyCartContainer, CartContainer, - CartItemWrapper, - RemoveButtonWrapper, + CartItemCard, + ProductImage, + ProductContent, + SummaryCard, + SummaryRowWrapper, + StyledDivider, } from './Cart.styles'; +import { SharedImage } from '../../components/shared/Image/SharedImage.jsx'; import { CART_TEXT } from '../../constants/hardText.js'; import { TEXT_VARIANTS, BUTTON_VARIANTS } from '../../constants/types.js'; import { addSignShekel } from '../../utils/converting.js'; import { LOCKER_LOCATION } from '../../utils/textTemplates.js'; -import ProductCard from '../Product/ProductCard'; import ActionButton from '../shared/Button/ActionButton.jsx'; import SharedTypography from '../shared/Text/SharedTypography.jsx'; const Cart = ({ - items, - total, - onContinue, - handleItemRemove, - isLoading = false, - isError = false, - isLoggedIn = true, - }) => { + items, + total, + onContinue, + handleItemRemove, + isLoading = false, + isError = false, +}) => { const validItems = Array.isArray(items) ? items : []; const isCartEmpty = validItems.length === 0; const canPurchase = !isCartEmpty && total > 0; - const statusText = isLoading - ? CART_TEXT.CART_LOADING - : isError - ? CART_TEXT.CART_ERROR - : isCartEmpty - ? CART_TEXT.CART_EMPTY - : null; + if (isLoading || isError || isCartEmpty) { + const status = isLoading + ? CART_TEXT.CART_LOADING + : isError + ? CART_TEXT.CART_ERROR + : CART_TEXT.CART_EMPTY; - if (statusText) { return ( - + {CART_TEXT.CART_TITLE} - - {statusText} + + {status} ); @@ -52,67 +52,81 @@ const Cart = ({ return ( - - {CART_TEXT.CART_TITLE} - - - - {validItems.map(({ id, images, name, price, rating, lockerId }) => ( - - - {}} - disabled - /> - - {LOCKER_LOCATION.LOCKER_LABEL( - lockerId?.lockerNumber ?? '', - lockerId?.location ?? '', - )} - - + + + + {CART_TEXT.CART_TITLE} + + + {validItems.map(({ id, images, name, price, lockerId }) => ( + + + + + + {name} + + + + {addSignShekel(price)} + + + + {LOCKER_LOCATION.LOCKER_LABEL( + lockerId?.lockerNumber ?? '', + lockerId?.location ?? '', + )} + + handleItemRemove(id)} styleType={BUTTON_VARIANTS.OUTLINED} - fullWidth > {CART_TEXT.REMOVE_BUTTON} - - - - ))} - + + + ))} + - + + + + {CART_TEXT.ORDER_SUMMARY} + - - - {CART_TEXT.CART_TOTAL} - - - {addSignShekel(total)} - - - - - {CART_TEXT.CART_CONTINUE} - - - {!isLoggedIn && ( - - {CART_TEXT.CART_LOGIN_REQUIRED} - - )} + + + {CART_TEXT.SUBTOTAL} + + + {addSignShekel(total)} + + + + + + + + {CART_TEXT.CART_TOTAL} + + + {addSignShekel(total)} + + + + + {CART_TEXT.CONTINUE_TO_PURCHASE} + + + + ); }; diff --git a/src/components/Cart/Cart.styles.js b/src/components/Cart/Cart.styles.js index 49982b6..f021fbb 100644 --- a/src/components/Cart/Cart.styles.js +++ b/src/components/Cart/Cart.styles.js @@ -1,6 +1,22 @@ -import { Paper, Box } from '@mui/material'; +import { Paper, Box , Grid, Divider} from '@mui/material'; import { styled } from '@mui/material/styles'; +import SharedTypography from '../shared/Text/SharedTypography.jsx'; + +export const GridContainer = styled(Grid)(({ theme }) => ({ + width: '100vw', + paddingLeft: theme.spacing(10), + paddingRight: theme.spacing(10), + paddingTop: theme.spacing(6), + paddingBottom: theme.spacing(6), +})); + +export const CartTitle = styled(SharedTypography)({ + marginBottom: '32px', + fontSize: '1.7rem', + fontWeight: 800, +}); + export const EmptyCartContainer = styled(Box)(({ theme }) => ({ maxWidth: '30rem', marginInline: 'auto', @@ -14,33 +30,97 @@ export const EmptyCartContainer = styled(Box)(({ theme }) => ({ gap: '2rem', })); -export const CartContainer = styled(Box)(({ theme }) => ({ - padding: '2rem', - backgroundColor: theme.palette.background.paper, - borderRadius: theme.shape.custom?.roundedLg || '0.75rem', - boxShadow: theme.shadows[2], - margin: '2rem auto', - maxWidth: '62.5rem', - width: '100%', - display: 'flex', - flexDirection: 'column', - gap: '2rem', +export const CartContainer = styled('div')(() => ({ + width: '100vw', + minHeight: '100vh', + paddingTop: '1rem', + paddingBottom: '3rem', + paddingLeft: '6vw', + paddingRight: '6vw', + backgroundColor: '#f9f9f9', + boxSizing: 'border-box', })); -export const CartItemWrapper = styled(Paper)(({ theme }) => ({ - padding: '1rem', - borderRadius: '0.75rem', +export const CartItemCard = styled(Paper)(() => ({ display: 'flex', - flexDirection: 'column', - alignItems: 'center', - boxShadow: theme.shadows[1], - width: '80%', - margin: '0 auto', + flexDirection: 'row', + alignItems: 'flex-start', + padding: '2.5rem', + marginBottom: '3rem', + borderRadius: '1.5rem', + boxShadow: '0 6px 25px rgba(0, 0, 0, 0.08)', + width: '100%', + minHeight: '200px', +})); +export const ProductImage = { + width: '150px', + height: '150px', + objectFit: 'cover', + borderRadius: '14px', + marginRight: '2rem', +}; +export const ProductContent = styled('div')(() => ({ + flex: 1, })); -export const RemoveButtonWrapper = styled(Box)(() => ({ - width: '100%', - marginTop: '1rem', +export const ProductName = styled('div')(() => ({ + fontWeight: 800, + fontSize: '1.6rem', + marginBottom: '1rem', + textTransform: 'capitalize', })); + +export const ProductPrice = styled('div')(() => ({ + fontWeight: 700, + fontSize: '1.4rem', + color: '#111', + marginBottom: '1rem', +})); + +export const ProductLocation = styled('div')(() => ({ + fontSize: '1.1rem', + color: 'gray', + marginBottom: '2rem', +})); + +export const SummaryCard = styled(Paper)(() => ({ + padding: '2.5rem', + borderRadius: '1rem', + boxShadow: '0 6px 25px rgba(0, 0, 0, 0.08)', + backgroundColor: '#fff', + position: 'sticky', + top: 30, + minWidth: '320px', +})); + +export const SummaryTitle = styled('div')(() => ({ + fontWeight: 800, + fontSize: '1.5rem', + marginBottom: '2rem', +})); + +export const SummaryRow = styled('div')(() => ({ + display: 'flex', + justifyContent: 'space-between', + fontSize: '1.2rem', + marginBottom: '1.2rem', +})); + +export const SummaryTotal = styled('div')(() => ({ + display: 'flex', + justifyContent: 'space-between', + fontWeight: 800, + fontSize: '1.4rem', +})); + +export const SummaryRowWrapper = styled(Box)({ + display: 'flex', + justifyContent: 'space-between', +}); + +export const StyledDivider = styled(Divider)(({ theme }) => ({ + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), +})); \ No newline at end of file diff --git a/src/components/Product/Product.styles.js b/src/components/Product/Product.styles.js index d2ab7d5..93b906c 100644 --- a/src/components/Product/Product.styles.js +++ b/src/components/Product/Product.styles.js @@ -1,6 +1,10 @@ import { Card, Box } from '@mui/material'; import { styled } from '@mui/material/styles'; +import { getTextStyles } from '../shared/Text/textVariants'; + +const defaultTextColor = getTextStyles().DEFAULT.color; + export const StyledCard = styled(Card)(({ theme, unavailable }) => ({ width: '15rem', height: '17rem', @@ -17,7 +21,7 @@ export const StyledCard = styled(Card)(({ theme, unavailable }) => ({ }, })); -export const UnavailableOverlay = styled(Box)(({ theme }) => ({ +export const UnavailableOverlay = styled(Box)(() => ({ position: 'absolute', inset: 0, zIndex: 2, @@ -30,7 +34,7 @@ export const UnavailableOverlay = styled(Box)(({ theme }) => ({ export const NotAvailableBadge = styled(Box)(({ theme }) => ({ backgroundColor: theme.palette.disabledCard.background, - color: theme.palette.disabledCard.text, + color: defaultTextColor, padding: `${theme.spacing(1 / 2)} ${theme.spacing(1)}`, borderRadius: '1.25rem', fontWeight: theme.typography.fontWeightBold, diff --git a/src/components/Product/ProductCard.jsx b/src/components/Product/ProductCard.jsx index faa2e85..497f186 100644 --- a/src/components/Product/ProductCard.jsx +++ b/src/components/Product/ProductCard.jsx @@ -1,5 +1,3 @@ -import React from 'react'; - import { CardContent, CardActionArea } from '@mui/material'; import { @@ -13,39 +11,28 @@ import { addSignShekel } from '../../utils/converting.js'; import { SharedImage } from '../shared/Image/SharedImage.jsx'; import SharedTypography from '../shared/Text/SharedTypography.jsx'; -const ProductCard = ({ - id, - images, - name, - price, - status, - onSelect, - disabled, - }) => { - const isUnavailable = status === 'unavailable'; +const ProductCard = ({ id, images, name, price, status, onSelect }) => { + const isUnavailable = status === STATUSES.UNAVAILABLE; return ( - - {isUnavailable && ( - - {STATUSES.NOT_AVAILABLE} - - )} + + {isUnavailable && ( + + {STATUSES.NOT_AVAILABLE} + + )} - !isUnavailable && onSelect(id)}> - - - - {name} - - - {addSignShekel(price)} - - - + !isUnavailable && onSelect(id)}> + + + + {name} + + + {addSignShekel(price)} + + + ); }; diff --git a/src/components/shared/Text/textVariants.js b/src/components/shared/Text/textVariants.js index c79d330..b89ddad 100644 --- a/src/components/shared/Text/textVariants.js +++ b/src/components/shared/Text/textVariants.js @@ -21,4 +21,51 @@ export const getTextStyles = () => ({ fontWeight: 'bold', fontSize: '1rem', }, + + PAGE_TITLE: { + fontSize: '1.7rem', + fontWeight: 800, + marginBottom: '32px', + }, + STATUS_TEXT: { + fontSize: '1rem', + color: '#777', + fontWeight: 500, + marginTop: '0.5rem', + textAlign: 'center', + }, + PRODUCT_TITLE: { + fontSize: '1.2rem', + fontWeight: 700, + color: '#222', + marginBottom: '0.25rem', + }, + PRODUCT_PRICE: { + fontSize: '1.1rem', + fontWeight: 600, + marginBottom: '0.25rem', + }, + PRODUCT_LOCATION: { + fontSize: '1rem', + color: '#888', + marginBottom: '0.5rem', + }, + SECTION_TITLE: { + fontSize: '1.4rem', + fontWeight: 700, + color: '#111', + marginBottom: '1rem', + }, + SUMMARY_ROW: { + fontSize: '1rem', + fontWeight: 500, + display: 'flex', + justifyContent: 'space-between', + }, + SECTION_TOTAL: { + fontSize: '1.2rem', + fontWeight: 700, + display: 'flex', + justifyContent: 'space-between', + }, }); diff --git a/src/constants/hardText.js b/src/constants/hardText.js index 17ce6c6..13b3757 100644 --- a/src/constants/hardText.js +++ b/src/constants/hardText.js @@ -32,12 +32,15 @@ export const CART_TEXT = { CART_TITLE: 'Shopping Cart', CART_EMPTY: 'Your cart is empty', CART_TOTAL: 'Total', + SUBTOTAL: 'Subtotal', CART_CONTINUE: 'Continue to Purchase', ADD_TO_CART: 'Add to Cart', CART_LOADING: 'Loading...', CART_LOGIN_REQUIRED: 'Please log in to continue your purchase.', CART_ERROR: 'Error loading cart. Please try again.', CART_REMOVE: 'Remove from Cart', + ORDER_SUMMARY: 'Order Summary', + CONTINUE_TO_PURCHASE: 'CONTINUE TO PURCHASE', }; export const PLACEHOLDERS = { @@ -60,4 +63,5 @@ export const TIMER = { export const STATUSES = { NOT_AVAILABLE: 'Not Available', + UNAVAILABLE: 'unavailable', }; diff --git a/src/constants/types.js b/src/constants/types.js index 743be17..a7cbce0 100644 --- a/src/constants/types.js +++ b/src/constants/types.js @@ -19,6 +19,14 @@ export const TEXT_VARIANTS = { WHITE_TITLE: 'WHITE_TITLE', GREY_TITLE: 'GREY_TITLE', DEFAULT: 'DEFAULT', + PAGE_TITLE: 'PAGE_TITLE', + STATUS_TEXT: 'STATUS_TEXT', + PRODUCT_TITLE: 'PRODUCT_TITLE', + PRODUCT_PRICE: 'PRODUCT_PRICE', + PRODUCT_LOCATION: 'PRODUCT_LOCATION', + SECTION_TITLE: 'SECTION_TITLE', + SUMMARY_ROW: 'SUMMARY_ROW', + SECTION_TOTAL: 'SECTION_TOTAL', }; export const BUTTON_VARIANTS = { FILLED: 'filled', @@ -48,5 +56,4 @@ export const MODAL_TYPES = { LOGOUT_SUCCESS_MESSAGE: 'Hope to see you again soon!', PRODUCT_ADDED: 'Product Added successfully', PRODUCT_ADDED_MESSAGE: 'The product has been saved to the system.', - };