Skip to content

Commit

Permalink
refactor: change api and adjust properties
Browse files Browse the repository at this point in the history
The code changes in this commit update the property names in the productData type. The 'name' property is changed to 'title' and the 'photo' property is changed to 'image'. This change improves the clarity and consistency of the code.
  • Loading branch information
aliine98 committed Jul 30, 2024
1 parent 649b2f3 commit a512240
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 77 deletions.
5 changes: 2 additions & 3 deletions src/api/ProductData.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
export type productData = {
id: number;
name: string;
brand: string;
title: string;
description: string;
price: string;
photo: string;
image: string;
quantity: number;
};
5 changes: 1 addition & 4 deletions src/api/products-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { useQuery } from '@tanstack/react-query';
export function GetProducts() {
const { isPending, error, data } = useQuery({
queryKey: ['productsData'],
queryFn: () =>
fetch('https://mks-frontend-challenge-04811e8151e6.herokuapp.com/api/v1/products/?page=1&rows=20&sortBy=id&orderBy=ASC').then(res =>
res.json()
),
queryFn: () => fetch('https://fakestoreapi.com/products').then(res => res.json()),
});

return { isPending, error, data };
Expand Down
25 changes: 13 additions & 12 deletions src/components/CartItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,32 @@ const QuantityButton = styled.button`
}
`;

export default function CartItem({product}:{product: productData}) {
const {dispatch} = useContext(StoreContext);
export default function CartItem({ product }: { product: productData }) {
const { dispatch } = useContext(StoreContext);
const [productQty, setProductQty] = useState(1);

useEffect(() => dispatch({type:'updateProductsPrices',newPrice:{id:product.id,price:Number(product.price) * productQty}}),[productQty,dispatch,product]);
useEffect(
() => dispatch({ type: 'updateProductsPrices', newPrice: { id: product.id, price: Number(product.price) * productQty } }),
[productQty, dispatch, product]
);

function deleteProduct() {
dispatch({type: 'deleteProduct', product: product});
dispatch({type:'deleteProductPrice', product: product});
dispatch({ type: 'deleteProduct', product: product });
dispatch({ type: 'deleteProductPrice', product: product });
}

return (
<>
<CartProduct>
<DeleteButton onClick={() => deleteProduct()}>X</DeleteButton>
<img src={product.photo} width='90' height='90' alt={product.name} />
<Title>
{product.brand} {product.name}
</Title>
<img src={product.image} width='90' height='90' alt={product.title} />
<Title>{product.title}</Title>
<Wrapper>
<div>
<QuantityButton
className='minus'
onClick={() => {
if(productQty > 1) setProductQty((productQty) => productQty - 1);
if (productQty > 1) setProductQty(productQty => productQty - 1);
}}>
-
</QuantityButton>
Expand All @@ -128,12 +129,12 @@ export default function CartItem({product}:{product: productData}) {
<QuantityButton
className='plus'
onClick={() => {
setProductQty((productQty) => productQty + 1);
setProductQty(productQty => productQty + 1);
}}>
+
</QuantityButton>
</div>
<PriceTag className='checkout-price'>R${Number(product.price) * productQty}</PriceTag>
<PriceTag className='checkout-price'>${Number(product.price) * productQty}</PriceTag>
</Wrapper>
</CartProduct>
</>
Expand Down
14 changes: 7 additions & 7 deletions src/components/Checkout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext, useEffect, useState} from 'react';
import { useContext, useEffect, useState } from 'react';
import { styled } from 'styled-components';

Check failure on line 2 in src/components/Checkout.tsx

View workflow job for this annotation

GitHub Actions / deploy

Could not find a declaration file for module 'styled-components'. '/home/runner/work/react-mks-frontend-challenge/react-mks-frontend-challenge/node_modules/styled-components/dist/styled-components.cjs.js' implicitly has an 'any' type.
import { productData } from '../api/ProductData';
import { StoreContext } from './Store';
Expand Down Expand Up @@ -71,17 +71,17 @@ const CheckoutPurchaseButton = styled.button`

export default function Checkout() {
const { state, dispatch } = useContext(StoreContext);
const [totalPrice,setTotalPrice] = useState(0);
const [totalPrice, setTotalPrice] = useState(0);

useEffect(() => {
setTotalPrice(state.productsPrices.reduce((acc:number,item:{id:number,price:number}) => acc + item?.price,0));
},[state.selectedProducts, state.productsPrices]);
setTotalPrice(state.productsPrices.reduce((acc: number, item: { id: number; price: number }) => acc + item?.price, 0));
}, [state.selectedProducts, state.productsPrices]);

return (
<>
<CheckoutMenu className={state.isOpen ? 'open' : ''}>
<Wrapper>
<CheckoutTitle>Carrinho de compras</CheckoutTitle>
<CheckoutTitle>Cart</CheckoutTitle>
<CloseButton onClick={() => dispatch({ type: 'openCloseCheckout' })}>X</CloseButton>
</Wrapper>
<CartList>
Expand All @@ -91,9 +91,9 @@ export default function Checkout() {
</CartList>
<Wrapper>
<h3>Total:</h3>
<TotalPrice>R${totalPrice}</TotalPrice>
<TotalPrice>${totalPrice}</TotalPrice>
</Wrapper>
<CheckoutPurchaseButton>Finalizar Compra</CheckoutPurchaseButton>
<CheckoutPurchaseButton>Checkout</CheckoutPurchaseButton>
</CheckoutMenu>
</>
);
Expand Down
36 changes: 17 additions & 19 deletions src/components/ProductCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import styled from "styled-components";
import { productData } from "../api/ProductData";
import { BuyButton, Card, PriceTag, Wrapper } from "./shared/styled-components";
import { useContext } from "react";
import { StoreContext } from "./Store";
import styled from 'styled-components';

Check failure on line 1 in src/components/ProductCard.tsx

View workflow job for this annotation

GitHub Actions / deploy

Could not find a declaration file for module 'styled-components'. '/home/runner/work/react-mks-frontend-challenge/react-mks-frontend-challenge/node_modules/styled-components/dist/styled-components.cjs.js' implicitly has an 'any' type.
import { productData } from '../api/ProductData';
import { BuyButton, Card, PriceTag, Wrapper } from './shared/styled-components';
import { useContext } from 'react';
import { StoreContext } from './Store';

const ProductPhoto = styled.img`
place-self: center;
Expand All @@ -20,29 +20,27 @@ const P = styled.p`
margin-bottom: 3.5rem;
`;

export default function ProductCard({product}:{product:productData}) {
const {state,dispatch} = useContext(StoreContext);
export default function ProductCard({ product }: { product: productData }) {
const { state, dispatch } = useContext(StoreContext);
return (
<>
<Card>
<ProductPhoto src={product.photo} alt={product.name} width={160} height={150} />
<ProductPhoto src={product.image} alt={product.title} width={160} height={150} />
<Wrapper>
<ProductTile>
{product.brand} {product.name}
</ProductTile>
<PriceTag>R${Number(product.price)}</PriceTag>
<ProductTile>{product.title}</ProductTile>
<PriceTag>${Number(product.price)}</PriceTag>
</Wrapper>
<P>{product.description}</P>
<BuyButton
onClick={() => {
if (state.selectedProducts.includes(product)) return;
dispatch({type:'addProduct',product:product});
dispatch({type:'updateProductsPrices',newPrice: {id: product.id, price: Number(product.price)}});
}}>
onClick={() => {
if (state.selectedProducts.includes(product)) return;
dispatch({ type: 'addProduct', product: product });
dispatch({ type: 'updateProductsPrices', newPrice: { id: product.id, price: Number(product.price) } });
}}>
<img src='./shopping-bag.svg' alt='shopping bag' />
Comprar
Add to cart
</BuyButton>
</Card>
</>
)
);
}
52 changes: 22 additions & 30 deletions src/components/Store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Checkout from './Checkout';
import { createContext, useReducer } from 'react';
import { productData } from '../api/ProductData';
import Loading from './Loading';
import ProductCard from './ProductCard'
import ProductCard from './ProductCard';

const CartButton = styled.button`
border-radius: 8px;
Expand All @@ -26,8 +26,8 @@ const CartButton = styled.button`
type StoreCtx = {
selectedProducts: productData[];
isOpen: boolean;
productsPrices: {id: number; price: number}[];
}
productsPrices: { id: number; price: number }[];
};

const StoreInitialState: StoreCtx = {
selectedProducts: [],
Expand All @@ -36,53 +36,45 @@ const StoreInitialState: StoreCtx = {
};

type Action =
| {type: 'addProduct', product: productData}
| {type: 'openCloseCheckout'}
| {type: 'deleteProduct', product: productData}
| {type: 'updateProductsPrices', newPrice: {id: number; price: number}}
| {type: 'deleteProductPrice', product: productData};
| { type: 'addProduct'; product: productData }
| { type: 'openCloseCheckout' }
| { type: 'deleteProduct'; product: productData }
| { type: 'updateProductsPrices'; newPrice: { id: number; price: number } }
| { type: 'deleteProductPrice'; product: productData };

export const StoreContext = createContext<{state:StoreCtx,dispatch: React.Dispatch<Action>}>({state:StoreInitialState, dispatch: () => {}});
export const StoreContext = createContext<{ state: StoreCtx; dispatch: React.Dispatch<Action> }>({ state: StoreInitialState, dispatch: () => {} });

function reducer(state: StoreCtx, action: Action): StoreCtx {
switch (action.type) {
case 'addProduct': {
return {...state,
selectedProducts: state.selectedProducts.concat(action.product)
};
return { ...state, selectedProducts: state.selectedProducts.concat(action.product) };
}
case 'openCloseCheckout': {
return {...state,
isOpen: !state.isOpen
};
return { ...state, isOpen: !state.isOpen };
}
case 'deleteProduct': {
return {...state,
selectedProducts: state.selectedProducts.filter((p: productData) => p != action.product)
};
return { ...state, selectedProducts: state.selectedProducts.filter((p: productData) => p != action.product) };
}
case 'updateProductsPrices': {
if(state.productsPrices.every(p => p.id !== action.newPrice.id)) {
return {...state,productsPrices: [...state.productsPrices,action.newPrice]};
if (state.productsPrices.every(p => p.id !== action.newPrice.id)) {
return { ...state, productsPrices: [...state.productsPrices, action.newPrice] };
}
state.productsPrices.map((product:{id:number,price:number}) => {
if(product.id === action.newPrice.id) {
state.productsPrices.map((product: { id: number; price: number }) => {
if (product.id === action.newPrice.id) {
// Object.defineProperty(product,'price',{value:action.newPrice.price});
product.price = action.newPrice.price;
}
});
return {...state, productsPrices: [...state.productsPrices]};
return { ...state, productsPrices: [...state.productsPrices] };
}
case 'deleteProductPrice': {
return {...state,
productsPrices: state.productsPrices.filter((price) => price.id != action.product.id)
};
return { ...state, productsPrices: state.productsPrices.filter(price => price.id != action.product.id) };
}
}
}

export default function Store() {
const [state,dispatch] = useReducer(reducer,StoreInitialState);
const [state, dispatch] = useReducer(reducer, StoreInitialState);
const productsInCart = state.selectedProducts?.length;

const fetchProducts = GetProducts();
Expand All @@ -91,13 +83,13 @@ export default function Store() {

return (
<>
<CartButton onClick={() => dispatch({type: 'openCloseCheckout'})}>
<CartButton onClick={() => dispatch({ type: 'openCloseCheckout' })}>
<img src='./cart.svg' alt='cart' />
{productsInCart}
</CartButton>
<StoreContext.Provider value={{state,dispatch}}>
<StoreContext.Provider value={{ state, dispatch }}>
<Checkout />
{fetchProducts.data?.products.map((product: productData) => (
{fetchProducts.data?.map((product: productData) => (
<ProductCard key={product.id} product={product} />
))}
</StoreContext.Provider>
Expand Down
5 changes: 3 additions & 2 deletions src/components/shared/styled-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ export const ProductsGrid = styled.ul`
display: grid;
gap: 1.5rem;
justify-items: center;
margin: 1.2rem auto;
margin: 1.2rem;
@media screen and (min-width: 630px) {
grid-template-columns: repeat(2, 1fr);
margin: 1.2rem auto;
}
@media screen and (min-width: 1000px) {
Expand All @@ -27,7 +28,7 @@ export const Card = styled.li`
padding: 10px 15px 0;
border-radius: 8px;
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.14);
max-width: 250px;
max-width: fit-content;
display: grid;
position: relative;
`;
Expand Down

0 comments on commit a512240

Please sign in to comment.