react-version #1

Merged
memartel_loc merged 290 commits from react-version into main 2023-11-04 09:48:15 -04:00
7 changed files with 284 additions and 123 deletions
Showing only changes of commit 5ece2baea9 - Show all commits

View File

@ -11,6 +11,8 @@
"@fortawesome/fontawesome-svg-core": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@stripe/react-stripe-js": "^1.15.0",
"@stripe/stripe-js": "^1.44.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@ -3395,6 +3397,24 @@
"@sinonjs/commons": "^1.7.0"
}
},
"node_modules/@stripe/react-stripe-js": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.15.0.tgz",
"integrity": "sha512-nqIOuAbbAN1p/zj2d2vykMzd097ZiHbu0+EpPRcfiswBRQIQIZaPrUwmj6HGD8BRA6Wp89mZen1UJbqtsfc3ZA==",
"dependencies": {
"prop-types": "^15.7.2"
},
"peerDependencies": {
"@stripe/stripe-js": "^1.44.1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@stripe/stripe-js": {
"version": "1.44.1",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.44.1.tgz",
"integrity": "sha512-DKj3U6tS+sCNsSXsoZbOl5gDrAVD3cAZ9QCiVSykLC3iJo085kkmw/3BAACRH54Bq2bN34yySuH6G1SLh2xHXA=="
},
"node_modules/@surma/rollup-plugin-off-main-thread": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
@ -21007,6 +21027,19 @@
"@sinonjs/commons": "^1.7.0"
}
},
"@stripe/react-stripe-js": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.15.0.tgz",
"integrity": "sha512-nqIOuAbbAN1p/zj2d2vykMzd097ZiHbu0+EpPRcfiswBRQIQIZaPrUwmj6HGD8BRA6Wp89mZen1UJbqtsfc3ZA==",
"requires": {
"prop-types": "^15.7.2"
}
},
"@stripe/stripe-js": {
"version": "1.44.1",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.44.1.tgz",
"integrity": "sha512-DKj3U6tS+sCNsSXsoZbOl5gDrAVD3cAZ9QCiVSykLC3iJo085kkmw/3BAACRH54Bq2bN34yySuH6G1SLh2xHXA=="
},
"@surma/rollup-plugin-off-main-thread": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",

View File

@ -6,6 +6,8 @@
"@fortawesome/fontawesome-svg-core": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@stripe/react-stripe-js": "^1.15.0",
"@stripe/stripe-js": "^1.44.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",

View File

@ -0,0 +1,105 @@
import React, { useState } from "react"
import { CardElement, useElements, useStripe } from "@stripe/react-stripe-js"
import { Button } from "react-bootstrap"
const CARD_OPTIONS = {
iconStyle: "solid",
style: {
base: {
iconColor: "black",
color: "white",
fontWeight: 500,
fontFamily: "Roboto, Open Sans, Segoe UI, sans-serif",
fontSize: "16px",
fontSmoothing: "antialiased",
":-webkit-autofill": { color: "beige" },
"::placeholder": { color: "lightgray" }
},
invalid: {
iconColor: "red",
color: "red"
}
}
}
const PaymentForm = ({ cost }) => {
const [success, setSuccess] = useState(false);
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (e) => {
e.preventDefault();
const { error, paymentMethod } = await stripe.createPaymentMethod({
type: "card",
card: elements.getElement(CardElement)
})
if (cost <= 0) {
console.log("Coût invalide: ", cost);
return;
}
if (!error) {
const { id } = paymentMethod;
const json = JSON.stringify({ amount: cost, stripeId: id });
fetch(`https://localhost:7292/api/Payment`, {
method: 'POST',
credentials: 'include',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: json
}).then((response) => {
if (response.ok) {
console.log("Successful payment");
setSuccess(true);
}
else {
console.log(response);
}
}).catch((error) => {
console.log("Error: ", error);
})
}
else {
console.log(error.message);
}
}
return (
<>
{!success ?
<form onSubmit={handleSubmit}>
<fieldset className="FormGroup">
<div className="FormRow">
<CardElement options={CARD_OPTIONS} />
</div>
</fieldset>
<div className="Payment-btn-container">
<Button className="Payment-btn" type="submit">Payer</Button>
</div>
</form>
:
<div>
<h2>
L'achat s'est déroulé avec succès
</h2>
</div>
}
</>
)
}
export default PaymentForm;

View File

@ -0,0 +1,19 @@
import React from "react";
import { loadStripe } from "@stripe/stripe-js"
import { Elements } from "@stripe/react-stripe-js"
import PaymentForm from "./PaymentForm";
const PUBLIC_KEY = "pk_test_51M8mzOEerenEZcQIUmJIrmsaZeeNlOil2G1JcMvvO68w50MJr8rDwUjVO44a8dDhSlsRH4GdzH9rDqtkg4Rtbzco00NqkHdn3H";
const stripeTestPromise = loadStripe(PUBLIC_KEY);
const StripeContainer = ({cost}) => {
return (
<Elements stripe={stripeTestPromise}>
<PaymentForm cost={cost}/>
</Elements>
)
}
export default StripeContainer;

View File

@ -5,9 +5,6 @@ export function TotalProductsPrice(/*{ products }*/) {
const cart = useContext(CartContext);
// const productTotal = (p) => {
// return (p.quantity * (p.product.status == 3 || p.product.status == 4 ? p.product.promoPrice : p.product.price))
// }
const getPriceHTML = (/*prods*/) => {
@ -19,9 +16,6 @@ export function TotalProductsPrice(/*{ products }*/) {
var tvq = 0;
var total;
// prods.map((p) => {
// price += productTotal(p);
// });
tps = price * (tpsRate / 100);
tvq = price * (tvqRate / 100);

View File

@ -7,6 +7,7 @@ import { useNavigate } from "react-router-dom";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { CartContext } from "../components/Cart";
import StripeContainer from "../components/StripeContainer"
const ReviewInvoice = () => {
@ -28,26 +29,38 @@ const ReviewInvoice = () => {
province: "",
country: "",
postalCode: "",
prodQuant: []
prodQuant: [],
});
const [total, setTotal] = useState(-1);
useEffect(() => {
const cookies = new Cookies();
const thisInvoice = cookies.get('invoice');
if (thisInvoice != null) {
var dic = {};
if (cart.items.length > 0) {
cart.items.forEach((item) =>
dic[item.id] = item.quantity
cart.items.forEach((item) => {
dic[item.id] = item.quantity;
}
)
}
async function test() {
const tpsRate = 5;
const tvqRate = 9.975;
const json = JSON.stringify(dic);
console.log(await json);
}
test();
var price = cart.getTotalCost();
var tps = 0;
var tvq = 0;
var totalCost;
tps = price * (tpsRate / 100);
tvq = price * (tvqRate / 100);
totalCost = price + tps + tvq;
totalCost = totalCost * 100;
totalCost = totalCost.toFixed(0);
setTotal(totalCost);
setThisInvoice((e) => {
@ -73,65 +86,12 @@ const ReviewInvoice = () => {
}
}, [cart]);
// const handleAddOne = (id) => {
// var modifiedPQ = prodQuant.filter((pq) => pq.id == id);
// var modifiedProd = prodQuant.filter((pq) => pq.product.id == id);
// modifiedPQ.quantity++;
// modifiedProd.quantity = modifiedPQ.quantity;
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id)), { ...modifiedPQ }].sort((a, b) => a.id - b.id));
// setProducts([...(products.filter((pq) => pq.product.id !== id)), { ...modifiedProd }].sort((a, b) => a.product.id - b.product.id));
// }
// const handleRemoveOne = (id) => {
// var modifiedPQ = prodQuant.filter((pq) => pq.id == id);
// var modifiedProd = prodQuant.filter((pq) => pq.product.id == id);
// if (modifiedPQ.quantity - 1 <= 0) {
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id))].sort((a, b) => a.id - b.id));
// setProducts([...(products.filter((pq) => pq.product.id !== id))].sort((a, b) => a.product.id - b.product.id));
// }
// else {
// modifiedPQ.quantity--;
// modifiedProd.quantity = modifiedPQ.quantity;
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id)), { ...modifiedPQ }].sort((a, b) => a.id - b.id));
// setProducts([...(products.filter((pq) => pq.product.id !== id)), { ...modifiedProd }].sort((a, b) => a.product.id - b.product.id));
// }
// }
// const handleRemoveProduct = (id) => {
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id))].sort((a, b) => a.id - b.id));
// setProducts([...(products.filter((pq) => pq.product.id !== id))].sort((a, b) => a.product.id - b.product.id));
// }
const handleModify = () => {
navigate("/formulaire")
}
const handleConfirmer = async () => {
// var dic = {};
// if (cart.items.length > 0) {
// cart.items.forEach((item) =>
// dic[item.id] = item.quantity
// )
// }
// const json = JSON.stringify(dic);
// console.log(await json);
// const json1 = JSON.stringify(cart.items);
// console.log(await json1);
//setThisInvoice({ ...thisInvoice, prodQuant: dic });
const json = JSON.stringify(thisInvoice);
console.log(json);
const response = await fetch(`https://localhost:7292/api/Invoice`, {
method: 'POST',
@ -167,69 +127,73 @@ const ReviewInvoice = () => {
}
return (
<Row>
<h2 className="confirmer-infos">Veuillez confirmer les informations ci-dessous!</h2>
<Col xs={6} md={4}>
<>
<Row>
<h2 className="confirmer-infos">Veuillez confirmer les informations ci-dessous!</h2>
<Col xs={6} md={4}>
<div className="review-invoice-info">
<div>
<label className="bold">Prénom: </label> <label>{thisInvoice.firstName}</label>
</div>
<div>
<label className="bold">Nom: </label> <label>{thisInvoice.lastName}</label>
</div>
<div>
<label className="bold">Téléphone: </label> <label>{thisInvoice.phoneNumber}</label>
</div>
<div>
<label className="bold">Courriel: </label> <label>{thisInvoice.emailAddress}</label>
</div>
</div>
<div className="review-invoice-address-container">
<div>
<label className="bold">Numéro civique: </label> <label>{thisInvoice.civicNumber}</label>
</div>
{thisInvoice.appartment != null ?
<div className="review-invoice-info">
<div>
<label className="bold">Numéro d'appartement: </label> <label>{thisInvoice.appartment}</label>
<label className="bold">Prénom: </label> <label>{thisInvoice.firstName}</label>
</div>
<div>
<label className="bold">Nom: </label> <label>{thisInvoice.lastName}</label>
</div>
<div>
<label className="bold">Téléphone: </label> <label>{thisInvoice.phoneNumber}</label>
</div>
<div>
<label className="bold">Courriel: </label> <label>{thisInvoice.emailAddress}</label>
</div>
: null
}
<div>
<label className="bold">Rue: </label> <label>{thisInvoice.street}</label>
</div>
<div>
<label className="bold">Ville: </label> <label>{thisInvoice.city}</label>
<div className="review-invoice-address-container">
<div>
<label className="bold">Numéro civique: </label> <label>{thisInvoice.civicNumber}</label>
</div>
{thisInvoice.appartment != null ?
<div>
<label className="bold">Numéro d'appartement: </label> <label>{thisInvoice.appartment}</label>
</div>
: null
}
<div>
<label className="bold">Rue: </label> <label>{thisInvoice.street}</label>
</div>
<div>
<label className="bold">Ville: </label> <label>{thisInvoice.city}</label>
</div>
<div>
<label className="bold">Province (abréviation): </label> <label>{thisInvoice.province}</label>
</div>
<div>
<label className="bold">Pays: </label> <label>{thisInvoice.country}</label>
</div>
<div>
<label className="bold">Code postal: </label> <label>{thisInvoice.postalCode}</label>
</div>
</div>
<div>
<label className="bold">Province (abréviation): </label> <label>{thisInvoice.province}</label>
<div className="review-invoice-info">
<TotalProductsPrice
/>
</div>
<div>
<label className="bold">Pays: </label> <label>{thisInvoice.country}</label>
</div>
<div>
<label className="bold">Code postal: </label> <label>{thisInvoice.postalCode}</label>
</div>
</div>
<div className="review-invoice-info">
<TotalProductsPrice
/>
</div>
<Row className="invoice-buttons">
{/* <Row className="invoice-buttons">
<Col xs={6}>
<Button className="invoice-button confirmer" onClick={handleConfirmer}>Confirmer</Button>
</Col>
<Col xs={6}>
<Button className="invoice-button modifier" onClick={handleModify}>Modifier</Button>
</Col>
</Row>
</Col>
<Col xs={6} md={8}>
<ReviewProdList
/>
</Col>
</Row>
</Row> */}
</Col>
<Col xs={6} md={8}>
<ReviewProdList
/>
</Col>
</Row>
<StripeContainer cost={total} />
</>
);
}

View File

@ -20,6 +20,44 @@ a {
text-decoration: none;
}
.Payment-btn-container {
display: flex;
}
.Payment-btn {
margin: auto;
width: 20%;
}
.FormGroup {
margin: 20px 15px 20px;
padding: 0;
border-style: none;
color: beige !important;
background-color: purple;
will-change: opacity, transform;
border-radius: 4px;
}
.FormRow {
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
align-items: center;
margin-left: 15px;
}
.StripeElement--webkit-autofill {
background: transparent !important;
}
.StripeElement {
width: 100%;
padding: 11px 15px 11px 0;
}
.Contact {
background-color: beige;
text-align: center;
@ -770,7 +808,7 @@ a {
.invoice-item-products h3 {
text-align: center !important;
color:purple;
color: purple;
font-weight: bold;
background-color: beige;
width: auto;
@ -831,12 +869,12 @@ a {
}
.invoice-buttons {
display:flex;
margin:5%;
display: flex;
margin: 5%;
}
.invoice-button {
margin:2%;
margin: 2%;
width: 100%;
align-content: center;
}
@ -851,7 +889,7 @@ a {
.confirmer-infos {
text-align: center;
color:white;
color: white;
font-weight: bold;
}
@ -861,6 +899,12 @@ a {
/* -------------------------------------------------------- */
@media(max-width:900px) {
.Payment-btn {
margin-top: 10px;
height: 70px;
width: 80%;
}
.invoice-item-container {
display: block;
}