Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Práctico de React.js

Curso Práctico de React.js

Oscar Barajas Tavares

Oscar Barajas Tavares

Orden de compra

23/29
Recursos

Aportes 17

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

En la clase agregamos algunos estilos al componente MyOrder. Una de ellas fue:

.MyOrder {
    bottom: 0;
}

Pero al agregar muchos elementos a nuestro carrito y ver la orden no se ve muy bien… Por ende recomiendo modificarlo de la siguiente manera:

.MyOrder {
    bottom: auto;
}

A los estilos de MyOrder.js yo le agregué los siguientes estilos para darle un poquito de animación 😄 al hacer click ahora la barra lateral “crece” de derecha a izquierda.

@keyframes swipeLeft {
  0% {
    width: 0;
  }
  100% {
    width: 360px;
  }
}

.MyOrder {
  ...
  ...
    animation: swipeLeft 0.26s ease;
}

Si no se les ve, ojo cuando escriban en la iteración. Si ponen la arrow function con " { } " tienen que poner el return, y si lo hacen con " ( ) " pos si el return. Lo digo pq me acaba de pasar xd

<code> 
Recomiendo agregar scroll
.MyOrder {
overflow-y: auto;
height: 350px;
}


Claro se ve perfectamente como va cambiando la numeración del carrito. Genial.

En esta clase, implementaremos una manera para poder desplegar nuestro carrito de compras. Para ello, debemos acceder primero a Header.jsx, donde está el ícono del carrito de compras

//Header.jsx
import MyOrder from '@containers/MyOrder';

const Header = () => {
	const { state } = useContext(AppContext);
	const [toggleOrders, setToggleOrders] = useState(false);	

	const handleToggle = () => {
		setToggle(!toggle);
	}

	return (
			<div className="navbar-right">
				<ul>
					<li className="navbar-shopping-cart" onClick={() => setToggleOrders(!toggleOrders)}>
						<img src={shoppingCart} alt="shopping cart" />
						{state.cart.length > 0 ? <div>{state.cart.length}</div> : null}
					</li>
				</ul>
			</div>
			{toggleOrders && <MyOrder />}
		</nav>
	);
}

export default Header;

Ahora, para poder mostrar el carrito de compras, añadimos otra variable de estado en el componente llamada toggleOrders. Esta se inicializa en falso para indicar que no queremos mostrar el carrito. Para ello, añadimos 2 expresiones. Una en donde solamente se añadira el nodo MyOrder si toggleOrders es verdadero. Por eso se inicia en falso. El evento que se ejecuta cuando damos click esta en el carrito de compras. Añadimos un onClick, el cual ejecuta una función anónima en la que cambia el valor booleano de toggleOrders. Así, cada vez que demos click, alterna en visibilidad. Para que se pueda ver bien el elemento, editamos el css.

// MyOrder.scss
.MyOrder {
	top: 60px;
	bottom: auto; // créditos => @Manuel Valencia Londoño
	border-radius: 6px;
	border: 1px solid var(--very-light-pink);
}

Ahora, una vez tenemos la lógica para mostrar el elemento de MyOrder, con todas las ordenes correspondientes, debemos editar este mismo componente, para que se muestren tantos elementos en el carrito como diga el contexto. Es decir, si en el carrito hay 5 productos, después en el menu de MyOrder deberían haber 5 elementos. Para ello, editamos MyOrder.jsx

// MyOrder.jsx
import React, { useContext } from 'react'; // añadimos useContext
import AppContext from '@context/AppContext'; // añadimos AppContext

const MyOrder = () => {
	const { state } = useContext(AppContext);

	return (
			<div className="my-order-content">
				{state.cart.map(product => (
					<OrderItem product={product} key={`orderItem-${product.id}`}/>
				))}
			</div>
		</aside>
	);
}

export default MyOrder;

Ahora, lo que hacemos es traer las herramientas necesarias para poder trabajar con contexto. En el componente, traemos el valor de state y lo guardamos como contexto para poder acceder a dicho estado.

Este es un ejemplo perfecto del uso de context, donde simplemente cada componente accede a las variables si es necesario o no. No hay que trasladar estos datos de manera tediosa y repetitiva

Como en state tenemos un array, por ello creamos una lógica con map. Al ejecutar state.cart.map estaremos recorriendo cada elemento de state (es decir, del array de los elementos del carrito) Y regresamos un nodo llamado OrderItem. En orderItem le pasamos un valor product y key, en el cual podrán guardar cada componente un elemento product y un key identificador único. Simplemente editamos de tal manera que el key sea totalmente único, por ello usamos templateliterals.

Con relación al error del setToggleOrders con ( ) => o sin el, encontré un enlace muy bueno que lo explica (Está en inglés) Aquí

Seguro que a más de una persona le parece muy fea la barra de scroll.
Aquí dejo como lo he quitado de mi MyOrders mediante CSS.

estas ultimas clases con Oscar han sido un deleite, hasta cuando el se equivoca te deja JOYITAS de experiencia!!!

Le agregué una validación extra para mostrar un mensaje si no tienes ningun producto en el carrito:

{state.cart.length > 0 ? (
          state.cart.map((product) => (
            <OrderItem product={product} key={`orderItem-${product.id}`} />
          ))
        ) : (
          <div className="cart-empty"> No tienes productos Agregados :( </div>
        )}

css:

.cart-empty {
  color: var(--hospital-green);
  text-align: center;
  font-weight: bold;
}

Para que quede más conciso se pueden agregar los siguientes estilos:

/*Header.scss*/

nav {
	position: sticky;
	top: 0;
	background-color: white;
}
/*MyOrder.scss*/

.MyOrder {
	position: fixed;
	top: 60px;
	bottom: 0;
	overflow-y: auto;
	background-color: white;
}

hola que tal, se me a presentado un error y no se como poder resolverlo
al presionar el carrito, se rompe

//Header.jsx
import React, { useState, useContext } from 'react';
import '@styles/Header.scss';
import Menu from '@components/Menu';
import MyOrder from '@containers/MyOrder';
import menu from '@icons/icon_menu.svg';
import logo from '@logos/logo_yard_sale.svg';
import AppContext from '@context/AppContext';
import shoppingCart from '@icons/icon_shopping_cart.svg';

const Header = () => {
  const [toggle, setToggle] = useState (false);
  const [toggleOrders, setToggleOrders] = useState(false);
  const { state } = useContext(AppContext);

const handleToggle = () => {
  setToggle(!toggle);
}

    return (
  <nav>
  <img src={menu} alt="menu" className="menu" />
  <div className="navbar-left">
    <img src={logo} alt="logo" className="nav-logo" />
    <ul>
      <li>
        <a href="/">All</a>
      </li>
      <li>
        <a href="/">Clothes</a>
      </li>
      <li>
        <a href="/">Electronics</a>
      </li>
      <li>
        <a href="/">Furnitures</a>
      </li>
      <li>
        <a href="/">Toys</a>
      </li>
      <li>
        <a href="/">Others</a>
      </li>
    </ul>
  </div>
  <div className="navbar-right">
    <ul>
      <li className="navbar-email" onClick={handleToggle}>
        [email protected]
        </li>
      <li
      className="navbar-shopping-cart"
      onClick={() => setToggleOrders(!toggleOrders)}
      >
        <img src={shoppingCart} alt="shopping cart" />
        {state.cart.length > 0 ? <div>{state.cart.length} </div> : null }
      </li>
    </ul>
  </div>
{toggle &&  <Menu />}
{toggleOrders && <MyOrder />}
</nav>


    );
}

export default Header;
//MyOrder.jsx
import React, { useContext } from 'react';
import OrderItem from '@components/OrderItem';
import AppContext from '@context/AppContext';
import '@styles/MyOrder.scss';
import arrow from '@icons/flechita.svg';

const MyOrder = () => {
	const { state } = useContext (AppContext);
	return (
		<aside className="MyOrder">
			<div className="title-container">
				<img src= {arrow} alt="arrow" />
				<p className="title">My order</p>
			</div>
			<div className="my-order-content">
				{state.cart.map(pruduct=> (
					<OrderItem product ={product} key={`orderItem-${product.id}`} />
				))}
				<div className="order">
					<p>
						<span>Total</span>
					</p>
					<p>$560.00</p>
				</div>
				<button className="primary-button">
					Checkout
				</button>
			</div>
		</aside>
	);
}

export default MyOrder;
//MyOrder.scss
@import 'vars';

.MyOrder {
	width: 360px;
	padding: 24px;
	box-sizing: border-box;
	position: absolute;
	right: 0;
	background-color: white;
	top : 60px;
	bottom: auto;
	border-radius: 6px;
	border: 1px solid var(--very-light-pink);

}
.title-container {
	display: flex;
}
.title-container img {
	transform: rotate(180deg);
	margin-right: 14px;
}
.title {
	font-size: var(--lg);
	font-weight: bold;
}
.order {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 16px;
	align-items: center;
	background-color: var(--text-input-field);
	margin-bottom: 24px;
	border-radius: 8px;
	padding: 0 24px;
}
.order p:nth-child(1) {
	display: flex;
	flex-direction: column;
}
.order p span:nth-child(1) {
	font-size: var(--md);
	font-weight: bold;
}
.order p:nth-child(2) {
	text-align: end;
	font-weight: bold;
}

.primary-button {
	background-color: var(--hospital-green);
	border-radius: 8px;
	border: none;
	color: var(--white);
	width: 100%;
	cursor: pointer;
	font-size: var(--md);
	font-weight: bold;
	height: 50px;
}
@media (max-width: 640px) {
	.MyOrder {
		width: 100%;
	}
}

Siento que se ve un poco fea la sección de MyOrder con todo amontonado sin un scroll escribí este código, espero les sea de utilidad

jsx:

<div className="seccion-scroll">
					{
						estadoApp.cart.map( product => (
							<OrderItem 
								key={ `orderItem-${ product.id }` } 
								product={ product } 
							/>
						) )
					}
				</div>

css:

.seccion-scroll::-webkit-scrollbar {
	width: 0.8rem;
}
.seccion-scroll::-webkit-scrollbar-track {
background: var( --very-light-pink );
border-radius: 1rem;
}
.seccion-scroll::-webkit-scrollbar-thumb {
background-color: var( --hospital-green );
border-radius: 20px;
}
.seccion-scroll {
	height: 300px;
	overflow-y: scroll !important;
	overflow-x:hidden !important;
}

obteniendo como resultado algo asi:

Si al darle click al icono del carrito y se les rompe la aplicación es decir se pone todo en blanco es porq en el archivo MyOrder.jsx les falta importar este componente q estamos utlizando mas no importando :

import OrderItem from “…/components/OrderItem”

Wenas wenas, si han notado, la estilización del componente de “MyOrder.jsx” no se termina de ver del todo bien, Asi que agregué una clase y le hice unas modificaciones a un par de clases.

Aqui tienen el codigo:

Clase agregada en el documento de MyOrder.jsx:

<div className="container-total">
	<div className="order">
		<p>
			<span>Total</span>
		</p>
		<p>$560.00</p>
	</div>
	<button className="primary-button">
		Checkout
	</button>
</div>

Clases Modificadas y agregadas al My Order.scss:

.MyOrder {
	width: 360px;
	padding: 24px;
	box-sizing: border-box;
	position: absolute;
	right: 0;
	top: 60px;
	background-color: var(--white);
	border-radius: 6px;
	bottom: 0;
	overflow: auto;
}

.my-order-content{
	max-height: 60%;
	overflow: auto;
}


.container-total{
	width: 85%;
	position: absolute;
	top: 75%;
}

Respecto al **key **igual habrá un warning usando el nombre sugerido. Recuerden que el id es el mismo si agregas al carrito un mismo producto más de una vez. No soy fan de usar el index pero en este caso lo usé para evitar el error/warning.

{state.cart.map((product, index) => (
	<OrderItem
		key={`orderItem-${index}-${product.id}`}
		product={product}
	/>
))}