No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Componente OrderCard

17/31
Recursos

Aportes 36

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Si quieren agregar un scroll al apartado, agreguen lo siguiente:

file: CheckoutsideMenu.jsx dentro de className del aside, agregar:

scrollable-cards

quedaría así:

className={`${context.isCheckoutSideMenuOpen ? 'flex' : 'hidden'} checkout-side-menu scrollable-cards flex-col fixed right-0 border border-black rounded-lg bg-white`}>

En styles.css agregar lo siguiente:

.scrollable-cards {
	overflow: scroll;
}

/* ===== Scrollbar CSS ===== */
  /* Firefox */
  .scrollable-cards {
    scrollbar-width: auto;
    scrollbar-color: #141414 #ffffff;
		/* overflow-x: hidden; */
  }

  /* Chrome, Edge, and Safari */
  .scrollable-cards::-webkit-scrollbar {
    width: 16px;
		/* overflow-x: hidden; */
  }

  .scrollable-cards::-webkit-scrollbar-track {
    background: #ffffff;
		/* overflow-x: hidden; */
  }

  .scrollable-cards::-webkit-scrollbar-thumb {
    background-color: #141414;
    border-radius: 10px;
    border: 3px solid #000000;
		/* overflow-x: hidden; */
  }

Resultado:

Si quieren agregar el mismo producto varias veces, cuando agregan por primera vez un producto le pueden agregar la propiedad “quantity” con valor 1. Si en cambio el producto ya fue agregado anteriormente, hay que validar que ese producto esté ya en el carrito y aumentarle en uno la propiedad quantity. De esta forma, podemos tambien en nuestro checkout ‘pintar’ la cantidad de productos de un mismo tipo y el valor total. Dejo el código por si les interesa.

const [cartProducts, setCartProducts] = useState([]);
	const onAdd = product => {
		const productExists = cartProducts.some(el => el.id === product.id); // dará true si el producto ya se encuentra en el carrito

		if (productExists) {
			// valida la existencia
			const productCart = cartProducts.find(el => el.id === product.id); // busca el producto
			productCart.quantity += 1; // aumenta la cantidad en 1
		} else {
			product.quantity = 1; // si el producto no está, le agrega la propiedad quantity con valor uno, y luego setea el carrito agregando ese producto
			setCartProducts([...cartProducts, product]);
		}
		setCount(count + 1);
	};

Por acá dejo como quedó el código para pintar la card en el checkout.

import PropTypes from 'prop-types';

export const CheckoutCard = ({ product }) => {
	CheckoutCard.propTypes = {
		product: PropTypes.object.isRequired,
	};
	return (
		<div className='border-y flex w-full p-2 h-20 items-center gap-x-2'>
			<span className='text-sm w-4'>{product.quantity}</span>
			<figure className='w-1/4 gap-3  flex justify-start'>
				<img
					className='w-full h-full object-contain rounded-lg'
					src={product.images && product.images[0]}
					alt={product.title}
				/>
			</figure>
			<span className='text-sm w-1/2'>{product.title}</span>
			<span className='font-medium text-sm'>${product.price * product.quantity}</span>
		</div>
	);
};

Si quieren hacer su propia API con endpoints y todas las configuraciones que deseen, pueden hacerla localmente con json server y hacer el deploy con Render. Es super fácil, les dejo un tutorial, está ingles, pero funciona bien:
https://www.youtube.com/watch?v=EcxYcpF3W7c
Hagan ejemplo del tutorial y luego para actualizarla solo tienen que hacer un commit y push a la misma rama, ya que Render se conecta con github y en pocos minutos su url se actualiza. Sigan la estructura de la Fake API de Platzi para que no tengan errores de undefined en su código o si cambian la estructura, no se olviden de adaptar el código.
En el archivo db.json que creen:

{
  "products": [
  {
    "id": 1,
    "title": "Handmade Fresh Table",
    "price": 687,
    "description": "Andy shoes are designed to keeping in...",
    "category": {
      "id": 5,
      "name": "Others",
      "image": "https://placeimg.com/640/480/any?r=0.591926261873231"
    },
    "images": [
      "https://placeimg.com/640/480/any?r=0.9178516507833767",
      "https://placeimg.com/640/480/any?r=0.9300320592588625",
      "https://placeimg.com/640/480/any?r=0.8807778235430017"
    ]
  },
  {
    "id": 2,
    "title": "Handmade Fresh ",
    "price": 687,
    "description": "Andy shoes",
    "category": {
      "id": 5,
      "name": "Others",
      "image": "https://placeimg.com/640/480/any?r=0.591926261873231"
    },
    "images": [
      "https://placeimg.com/640/480/any?r=0.9178516507833767",
      "https://placeimg.com/640/480/any?r=0.9300320592588625",
      "https://placeimg.com/640/480/any?r=0.8807778235430017"
    ]
  },
  	.
  	. El Resto de Productos
  	.
  ],
  "categories": [
  {
    "id": 1,
    "name": "Clothes",
    "image": "https://api.lorem.space/image/fashion?w=640&h=480&r=4278"
  },
  {
    "id": 2,
    "name": "Electronics",
    "image": "https://api.lorem.space/image/fashion?w=640&h=480&r=4278"
  },
	.
	. El Resto de Categorias
	.
  ]
}

Yo le quise dar la opcion al usuario que pueda subir o bajar la cantidad del producto que desea comprar desde el shopping cart

No sé porque tengo que agregar este detalle de PropTypes en React pero lo tengo así y funciona bien (gracias a un comentario en una clase previa):

Como nota, podemos pasar directamente las props entre llaves en ves de escribir ‘props’ y luego hacer destructuring.

import PropTypes from 'prop-types'

export const OrderCard = ({ title, imageUrl, price }) => {
  OrderCard.propTypes = {
    title: PropTypes.node.isRequired,
    imageUrl: PropTypes.node.isRequired,
    price: PropTypes.node.isRequired,
  }

  return (
    <div className="flex justify-between items-center mb-3">
      <div className="flex items-center gap-2">
        <figure className="w-20 h-20">
          <img className="w-full h-full rounded-lg object-cover" src={imageUrl} alt={title} />
        </figure>
        <p className="text-sm font-light">{title}</p>
      </div>
      <div className="flex items-center gap-2">
        <p className="text-lg font-medium">${price}</p>
        {/* X close icon */}
        <svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6 cursor-pointer">
          <path fillRule="evenodd" d="M5.47 5.47a.75.75 0 011.06 0L12 10.94l5.47-5.47a.75.75 0 111.06 1.06L13.06 12l5.47 5.47a.75.75 0 11-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 01-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 010-1.06z" clipRule="evenodd" />
        </svg>
      </div>
    </div>
  )
}

Siento mucho alivio haber tomado la INCREÍBLE saga de TypeScript de NicoBytes, antes de llegar aquí. 🤧

Para que no se muestre un titulo tan largo y tengamos problemas que se juntal el titulo con el precio, agregue un archivo css en donde tengo una clase con max-width y esta clase la utiliza el p de el titulo, de esta manera permitimos que no quede el titulo encima del precio

poner opción de cantidad en cada producto y multiplicar valor por cantidad:

para poner la opción de elegir la cantidad deseada de cada producto agregué un input en el OrderCard:

<div className='flex justify-between items-center'>
        <div className='flex  items-center gap-2'>
            <figure className='w-20 h-20'>
                <img className='w-full h-full rounded-lg object-fill' src={url} alt={name} />
            </figure>
            <div className='flex flex-col justify-center'>
                <p className='text-sm font-light'> {name} </p>
                <div className='flex items-center gap-2'>
                <label className='text-sm font-thin' htmlFor="quantity"> Qty</label>
                <input 
                className='w-1/2 border border-black rounded-lg text-md' type="number"  
                name='quantity'
                value={quantity}
                onChange={(e) => handleOnChange(e) }/>
                 </div>   
                
            </div>
            
        </div>
        <div className='flex  items-center gap-2'>
            <p className='text-lg font-medium font-mono'>{total} </p>
            <XMarkIcon className='h-6 w-6 text-black hover:cursor-pointer'></XMarkIcon>  
        </div>      
    </div>

adicionalmente una función para hacer el calculo del valor:

const [quantity, setQuantity] = useState(1);
const [total, setTotal] = useState(price);

const handleOnChange = (event) => {
    setQuantity(event.target.value);
    setTotal(price * event.target.value);
    
}
Si algunas de las imágenes en el carrito no les quedan cuadradas muy seguramente es porque no hay espacio suficiente para que se escriba el título y por eso le roba espacio a la imagen. ![](https://static.platzi.com/media/user_upload/Imagen%20no%20cuadrada-2df6beac-06fa-47ca-8cd6-cd563553620d.jpg) Para solucionar esto, pueden usar la clase `shrink-0` en el `figure` para que este no ceda su espacio. ``` \
... \
``` Resultado final: ![](https://static.platzi.com/media/user_upload/Imagen%20cuadrada-427c6f3c-972e-4ee8-9c97-9cb084c8ea95.jpg)

Dejo mi proyecto hasta ahora:

![](

My orders hasta ahora

Asi vamos compañeros:

Por el momento creo que las cosas pintan bien 😊 ![](https://static.platzi.com/media/user_upload/image-dd039db1-dd56-402f-b323-a3d1c96f1b5f.jpg)
no ![](https://static.platzi.com/media/user_upload/image-430ce733-dc13-459d-b98e-b7b4ce92a9e7.jpg)es mucho pero es trabajo honesto wee =)
Mi resultado:![](https://static.platzi.com/media/user_upload/image-31cc1b5c-e676-493e-bf12-a1806e810722.jpg)
Así va... le cambié el formato porque le agregué cantidades y total por card. Aprendan TypeScript... es muy fastidoso pero útil ![](https://i.imgur.com/mTUtwan.png)
Despues de muchos errores y arreglos finalmente lo logre :,) ![](https://static.platzi.com/media/user_upload/Captura%20de%20pantalla%202024-05-21%20140405-832737d9-c41e-40be-bcf0-2e7b1214a845.jpg)
![](https://static.platzi.com/media/user_upload/image-7d4e66b0-beb3-4477-8479-642944c6969e.jpg)
Asi Va: ![](https://static.platzi.com/media/user_upload/image-76570157-3302-45b4-93f2-dbdb65c2c681.jpg)
También ten un lindo año, personita que subió este producto a la API uwu ![](https://static.platzi.com/media/user_upload/image-e634cfad-cc5b-4f5e-89b5-55d94fd46ac2.jpg)
Hola teff mira mi pagina e-commerce como esta quedadando ![](https://static.platzi.com/media/user_upload/image-17ae0222-d3b7-49a3-84d8-e8f3da3df850.jpg)

Este es mi progreso hasta ahora

![](https://static.platzi.com/media/user_upload/image-269b8a71-142c-40f4-b6da-8b059cc8b970.jpg)

Así vamos 💪🏻:

Podemos agregar un scroll directamente con tailwind utilizando la clase overflow-auto. Desde la documentación podemos ir jugando un poco con esto. doc: <https://tailwindcss.com/docs/overflow> ```js
{ context.cartProducts.map(product => ( <OrderCard key={product.id} title={product.title} imageUrl={product.images} price={product.price} /> )) }
```

Si quieren un scroll en su componente CheckoutSideMenu solo agreguen la clase ```
overflow-y-scroll



Para poder agregar el mismo item al carrito varias veces pueden usar el indice del item en el arreglo como key

          {context.cartProducts.map((product, index) =>
            <OrderCard key={index} product={product} />
          )}

Así me quedo el diseño.
DP: Por ahora xD

Por si alguien le sirve, en vez de no dejar agregar un producto ya existente, hice que se añada “cantidades”

Este es el código en context file

    const incrementShoppingCart = (e, product) => {
        e.stopPropagation();
        setCount(count + 1);
        setIsCheckoutSideMenu(true);
        setIsPorductModalOpened(false);
        const productInCart = cartProducts.filter(
            (cartProduct) => cartProduct.product.id === product.id
        );
        console.info({ cartProducts });
        if (productInCart.length === 0) {
            setCartProducts((prevProducts) => [
                ...prevProducts,
                {
                    product,
                    quantity: 1,
                },
            ]);
        } else {
            setCartProducts((prevProducts) => {
                const productIndex = prevProducts.findIndex(
                    (prod) => prod.product.id === product.id
                );
                prevProducts[productIndex] = {
                    product,
                    quantity: productInCart[0].quantity + 1,
                };

                return prevProducts;
            });
        }
    };

![](

Ya resolví el reto y le cambié el color al div para que cuando esté agregado sea más notorio el cambio en la interfaz del usuario
.

También se pueden instalar la extensión React-Native/React/Redux snippets for es6/es7.
El comando _slr_les autocompleta la misma estructura con todo y el export default

Si desean agregar mas de un producto del mismo tipo,pero tienen conflictos con la ‘key’ que debe ser única en React,pudiera ser tentador usar el índice del elemento como ‘key’. Sin embargo,la propia documentación de React aconseja no hacerlo.

En su lugar decidí descargar una librería generadora de ‘keys’

npm i uuidv

La importo y la uso de la siguiente manera:

import { v4 as uuidv4 } from 'uuid'

return<OrderCard
              key={uuidv4()} 
              indice={index} 
              title={product.title}
              imageUrl={product.images}
              price={product.price}
              handleDelete={handleDelete}

Por supuesto,seguro que hay soluciones mejores para resolver el problema,como hacer que en una sola card se sume el numero de productos del mismo tipo y el precio a cobrar.

Pero para salir del paso y que todavía sea entendible,esta es la solución mas rápida que encontré.

No entiendo por que no permite comprar mas de un elemento de cada producto!!
En un ecommerce entre más se compre, mejor!!