Merge branch 'react-version' of https://github.com/MarcEricMartel/420-5DW-HY-TP into react-version
This commit is contained in:
commit
fba4921a56
94
GrossesMitaines/grosses-mitaines-ui/src/components/Cart.js
Normal file
94
GrossesMitaines/grosses-mitaines-ui/src/components/Cart.js
Normal 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;
|
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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;
|
@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -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>
|
||||
</>
|
||||
|
Loading…
Reference in New Issue
Block a user