Almost ready le carosse

This commit is contained in:
DavidBelisle 2022-11-07 23:36:19 -05:00
parent 75ab07a355
commit 48f77de441
6 changed files with 314 additions and 115 deletions

View File

@ -0,0 +1,94 @@
import { createContext, useState } from "react";
export const CartContext = createContext({
items: [],
getProductQuantity: () => { },
addOneToCart: () => { },
removeOneFromCart: () => { },
deleteFromCart: () => { },
getTotalCost: () => { },
addToCart: () => { }
});
export function CartProvider({ children }) {
const [cartProducts, setCartProducts] = useState([]);
function addToCart(product, qty) {
setCartProducts([...cartProducts, {...product, quantity: parseFloat(qty)}]);
}
function getProductQuantity(id) {
const quantity = cartProducts.find(product => product.id === id)?.quantity;
if (quantity === undefined) {
return 0;
}
return quantity;
};
function addOneToCart(id, qty) {
const currentQty = getProductQuantity(id);
if (qty > currentQty) {
setCartProducts(
cartProducts.map(
product => product.id === id
? { ...product, quantity: parseFloat(product.quantity) + 1 }
: product
)
);
}
};
function removeOneFromCart(id) {
const currentQty = getProductQuantity(id);
if (currentQty === 1)
deleteFromCart();
else
setCartProducts(
cartProducts.map(
product => product.id === id
? { ...product, quantity: parseFloat(product.quantity) - 1 }
: product
)
);
};
function deleteFromCart(id) {
setCartProducts(
cartProducts => cartProducts.filter(currentProduct => {
return currentProduct.id != id;
})
);
};
function getTotalCost() {
let totalCost = 0;
cartProducts.map((cartItem) => {
totalCost += (cartItem.Price * cartItem.quantity);
});
return totalCost;
};
const contextValue = {
items: cartProducts,
getProductQuantity,
addOneToCart,
removeOneFromCart,
deleteFromCart,
getTotalCost,
addToCart
};
return (
<CartContext.Provider value={contextValue}>
{children}
</CartContext.Provider>
);
}
export default CartProvider;

View File

@ -1,14 +1,42 @@
import { Button } from "react-bootstrap";
import { faCartShopping } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Modal, ModalBody, ModalHeader } from "react-bootstrap";
import { useState, useContext } from "react";
import { CartCard } from './CartCard';
import { CartContext } from './Cart';
const CartButton = () =>{
const CartButton = () => {
return(
<Button id="cart-button">
<FontAwesomeIcon icon={faCartShopping}/>
<div id="cart-count">3</div>
</Button>
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const cart = useContext(CartContext);
const productsCount = cart.items.reduce((sum, product) => sum + product.quantity, 0)
return (
<>
<Button id="cart-button" onClick={handleShow}>
<FontAwesomeIcon icon={faCartShopping} />
<div id="cart-count">{productsCount}</div>
</Button>
<Modal show={show} onHide={handleClose} className="carosse">
<ModalHeader closeButton>
<Modal.Title>Carosse</Modal.Title>
</ModalHeader>
<ModalBody>
{productsCount > 0 ?
<>
<p></p>
{cart.items.map((item) => <CartCard product={item}></CartCard>)}
</>
:
<h1>C'est vide! Rempli le hi hi!</h1>
}
</ModalBody>
</Modal>
</>
)
}

View File

@ -0,0 +1,43 @@
import { Card, Button, Form, Row, Col } from 'react-bootstrap';
import { useContext, useState, useEffect } from 'react';
import { CartContext } from './Cart';
const CartCard = ({ product }) => {
const cart = useContext(CartContext);
const productQuantity = cart.getProductQuantity(product.id);
const [imageSrc, setImageSrc] = useState(null);
useEffect(() => {
fetch(`https://localhost:7292/api/Image?id=${product.id}&thumbnail=true`)
.then(response => response.blob())
.then(blob => {
const imageUrl = URL.createObjectURL(blob);
setImageSrc(imageUrl);
})
}, []);
return (
<>
<Card>
<Card.Body>
<div className={!imageSrc ? "cat-load" : "d-none cat-load"} />
<Card.Img className="item-img" variant="top" src={imageSrc} />
<Card.Title>{product.Title}</Card.Title>
<Card.Text>{product.Price}$ CA</Card.Text>
<Form as={Row}>
<Form.Label column="true" sm="6">Dans l'carosse: {productQuantity}</Form.Label>
<Col sm="6">
<Button sm="6" className='mx-2' onClick={() => cart.addOneToCart(product.id, product.quantity)}>+</Button>
<Button sm="6" className='mx-2' onClick={() => cart.removeOneFromCart(product.id)}>-</Button>
</Col>
</Form>
<Button variant="danger" className='my-2' onClick={() => cart.deleteFromCart(product.id)}>Supprimer</Button>
</Card.Body>
</Card>
</>
)
}
export default CartCard;

View File

@ -12,6 +12,8 @@ const Topbar = () => {
const [cookies, setCookie, removeCookie] = useCookies(['name']);
const [user, setLogin] = useState(null);
useEffect(() => {
async function reset() {
await setLogin(await cookies.GMGM ?? null);
@ -29,103 +31,103 @@ const Topbar = () => {
}
return (
<Navbar expand="sm" className="topbar-container">
<Container>
<Link className="navbar-brand" to="/">
<img src="/images/LesGrossesMitaines.png" alt="" height="45" />
</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link className="nav-link" to="/" >
Maison
</Link>
<Link className="nav-link" to="/morceaux" >
Morceaux
</Link>
<Link className="nav-link" to="/aboutUs" >
À propos de nous
</Link>
<Link className="nav-link" to="/contactUs" >
Contactez-nous
</Link>
<Link className="nav-link" to="/privacy" >
Vie privée
</Link>
{(user === null || user.LoggedIn === false) &&
<Link className="nav-link" to="/login" >
Connexion
</Link>
}
{(user === null || user.LoggedIn === false) &&
<Link className="nav-link" to="/register">
S'inscrire
</Link>
}
{user !== null && user.LoggedIn &&
<Dropdown className="dropdown-gestion-container">
<Dropdown.Toggle className="dropdown-gestion" >
Bonjour, {user.firstName} {user.lastName}!
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-gestion-menu">
<Dropdown.Item>
<Link className="nav-link" to="/myaccount" >
Mon Compte
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/myaddresses" >
Mes Addresses
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/myinvoices" >
Mes Commandes
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Button className="nav-link" onClick={() => logOut()}>
Déconnexion
</Button>
</Dropdown.Item>
{user.role === "Administrateur" &&
<Container>
<Dropdown.Divider />
<Dropdown.ItemText>
Gestion
</Dropdown.ItemText>
<Dropdown.Item>
<Link className="nav-link" to="/inventaire" >
Inventaire
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/invoices" >
Commandes
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/clients" >
Clients
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/addresses" >
Adresses
</Link>
</Dropdown.Item>
</Container>
}
</Dropdown.Menu>
</Dropdown>
}
</Nav>
<Link className="nav-link" to="/formulaire" >
<CartButton />
<>
<Navbar expand="sm" className="topbar-container">
<Container>
<Link className="navbar-brand" to="/">
<img src="/images/LesGrossesMitaines.png" alt="" height="45" />
</Link>
</Navbar.Collapse>
</Container>
</Navbar>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link className="nav-link" to="/" >
Maison
</Link>
<Link className="nav-link" to="/morceaux" >
Morceaux
</Link>
<Link className="nav-link" to="/aboutUs" >
À propos de nous
</Link>
<Link className="nav-link" to="/contactUs" >
Contactez-nous
</Link>
<Link className="nav-link" to="/privacy" >
Vie privée
</Link>
{(user === null || user.LoggedIn === false) &&
<Link className="nav-link" to="/login" >
Connexion
</Link>
}
{(user === null || user.LoggedIn === false) &&
<Link className="nav-link" to="/register">
S'inscrire
</Link>
}
{user !== null && user.LoggedIn &&
<Dropdown className="dropdown-gestion-container">
<Dropdown.Toggle className="dropdown-gestion" >
Bonjour, {user.firstName} {user.lastName}!
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-gestion-menu">
<Dropdown.Item>
<Link className="nav-link" to="/myaccount" >
Mon Compte
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/myaddresses" >
Mes Addresses
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/myinvoices" >
Mes Commandes
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Button className="nav-link" onClick={() => logOut()}>
Déconnexion
</Button>
</Dropdown.Item>
{user.role === "Administrateur" &&
<Container>
<Dropdown.Divider />
<Dropdown.ItemText>
Gestion
</Dropdown.ItemText>
<Dropdown.Item>
<Link className="nav-link" to="/inventaire" >
Inventaire
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/invoices" >
Commandes
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/clients" >
Clients
</Link>
</Dropdown.Item>
<Dropdown.Item>
<Link className="nav-link" to="/addresses" >
Adresses
</Link>
</Dropdown.Item>
</Container>
}
</Dropdown.Menu>
</Dropdown>
}
</Nav>
<CartButton/>
</Navbar.Collapse>
</Container>
</Navbar>
</>
);
}

View File

@ -2,13 +2,16 @@ import React from "react";
import { Outlet } from "react-router-dom";
import Topbar from "../components/Topbar";
import Footer from "../components/Footer";
import CartProvider from "../components/Cart";
const Layout = () => {
return (
<>
<Topbar />
<Outlet />
<Footer />
<CartProvider>
<Topbar />
<Outlet />
<Footer />
</CartProvider>
</>
);
};

View File

@ -1,8 +1,10 @@
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useState } from "react";
import { Button } from "react-bootstrap";
import { Button, Form, Row} from 'react-bootstrap';
import QtySelect from "../components/QtySelect";
import { CartContext } from "../components/Cart";
import { useContext } from "react";
const MorceauDetail = () => {
@ -12,11 +14,14 @@ const MorceauDetail = () => {
const [itemQty, setItemQty] = useState(0);
const [currentQty, setCurrentQty] = useState(1);
const cart = useContext(CartContext);
const inCartQuantity = cart.getProductQuantity(item.id)
const isNoStock = () => {
return item.status == 1 || item.status == 2 || item.status == 5;
}
const currentQtyChange = (newQty) =>{
const currentQtyChange = (newQty) => {
setCurrentQty(newQty);
}
@ -139,14 +144,38 @@ const MorceauDetail = () => {
<p className="detail-description">{item.description}</p>
</div>
<div className="detail-container-controls">
<QtySelect
qty={isNoStock() ? 0 : itemQty}
onChange={currentQtyChange}
/>
<Button disabled={isNoStock()} className="add-to-cart">
Ajouter au panier
</Button>
{inCartQuantity > 0 ?
<>
<Form as={Row}>
<Form.Label sm="6">Dans l'carosse: {inCartQuantity}</Form.Label>
<Button disabled={isNoStock()} className="add-to-cart"
onClick={() => cart.addOneToCart(item.id, item.quantity)}
sm="6">
+
</Button >
<Button disabled={isNoStock()} className="add-to-cart"
onClick={() => cart.removeOneFromCart(item.id)}
sm="6">
-
</Button >
</Form>
<Button disabled={isNoStock()} className="add-to-cart"
onClick={() => cart.deleteFromCart(item.id)} variant="danger"
column="true" sm="6" >
Sortir du carosse
</Button>
</>
:
<>
<QtySelect
qty={isNoStock() ? 0 : itemQty}
onChange={currentQtyChange}
/>
<Button disabled={isNoStock()} className="add-to-cart" onClick={() => cart.addToCart(item, currentQty)}>
Ajouter au carosse
</Button>
</>
}
</div>
</div>
</>