diff --git a/package-lock.json b/package-lock.json
index 6921446..237c5c5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,8 @@
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
+ "@stripe/react-stripe-js": "^2.8.0",
+ "@stripe/stripe-js": "^4.5.0",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0",
"@types/jest": "^29.5.12",
@@ -3184,6 +3186,27 @@
"@sinonjs/commons": "^3.0.0"
}
},
+ "node_modules/@stripe/react-stripe-js": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.8.0.tgz",
+ "integrity": "sha512-Vf1gNEuBxA9EtxiLghm2ZWmgbADNMJw4HW6eolUu0DON/6mZvWZgk0KHolN0sozNJwYp0i/8hBsDBcBUWcvnbw==",
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "@stripe/stripe-js": "^1.44.1 || ^2.0.0 || ^3.0.0 || ^4.0.0",
+ "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": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-4.5.0.tgz",
+ "integrity": "sha512-dMOzc58AOlsF20nYM/avzV8RFhO/vgYTY7ajLMH6mjlnZysnOHZxsECQvjEmL8Q/ukPwHkOnxSPW/QGCCnp7XA==",
+ "engines": {
+ "node": ">=12.16"
+ }
+ },
"node_modules/@testing-library/dom": {
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.0.tgz",
diff --git a/package.json b/package.json
index 70d12b1..2ed23ab 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,8 @@
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
+ "@stripe/react-stripe-js": "^2.8.0",
+ "@stripe/stripe-js": "^4.5.0",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0",
"@types/jest": "^29.5.12",
diff --git a/src/App.jsx b/src/App.jsx
index 57d30ee..824d4fb 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -5,6 +5,7 @@ import 'react-toastify/dist/ReactToastify.css';
import { auth } from './service/firebase';
import styles from './App.module.scss';
import Loading from './pages/Loading/loading';
+import Pricing from './pages/Payement/Pricing';
const LoginPage = lazy(() => import('./pages/LoginPage/LoginPage'));
const ServerDetails = lazy(() => import('./pages/ServerDetails/ServerDetails'));
@@ -55,6 +56,8 @@ const App = () => {
: } />
: } />
: } />
+ : } />
+
} />
: } />
diff --git a/src/pages/Payement/PaymentForm/PaymentForm.jsx b/src/pages/Payement/PaymentForm/PaymentForm.jsx
new file mode 100644
index 0000000..59231c4
--- /dev/null
+++ b/src/pages/Payement/PaymentForm/PaymentForm.jsx
@@ -0,0 +1,49 @@
+import React, { useState } from 'react';
+import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
+import styles from './PaymentForm.module.scss';
+
+const PaymentForm = ({ groups, closeModal }) => {
+ const stripe = useStripe();
+ const elements = useElements();
+ const [errorMessage, setErrorMessage] = useState(null);
+ const [successMessage, setSuccessMessage] = useState(null);
+
+ const handleSubmit = async (event) => {
+ event.preventDefault();
+
+ if (!stripe || !elements) return;
+
+ const cardElement = elements.getElement(CardElement);
+ const { error, paymentMethod } = await stripe.createPaymentMethod({
+ type: 'card',
+ card: cardElement,
+ });
+
+ if (error) {
+ setErrorMessage(error.message);
+ setSuccessMessage(null);
+ } else {
+ setSuccessMessage(`Paiement réussi! Méthode de paiement ID: ${paymentMethod.id}`);
+ setErrorMessage(null);
+ // Ici, vous devriez également envoyer paymentMethod.id à votre serveur
+ // Fermer la modal après un court délai ou après l'envoi à votre serveur
+ setTimeout(() => closeModal(), 2000);
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default PaymentForm;
diff --git a/src/pages/Payement/PaymentForm/PaymentForm.module.scss b/src/pages/Payement/PaymentForm/PaymentForm.module.scss
new file mode 100644
index 0000000..0bbf541
--- /dev/null
+++ b/src/pages/Payement/PaymentForm/PaymentForm.module.scss
@@ -0,0 +1,19 @@
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .modalContent {
+ background: #fff;
+ padding: 20px;
+ border-radius: 8px;
+ width: 300px;
+ }
+
\ No newline at end of file
diff --git a/src/pages/Payement/Pricing.jsx b/src/pages/Payement/Pricing.jsx
new file mode 100644
index 0000000..f82b4df
--- /dev/null
+++ b/src/pages/Payement/Pricing.jsx
@@ -0,0 +1,68 @@
+import React, { useState } from 'react';
+import styles from './Pricing.module.scss';
+import Navbar from '../../components/navbar/Navbar';
+import { useNavigate } from 'react-router-dom';
+import PropTypes from 'prop-types';
+import { loadStripe } from '@stripe/stripe-js';
+import { Elements } from '@stripe/react-stripe-js';
+import PaymentForm from './PaymentForm/PaymentForm';
+
+const stripePromise = loadStripe('pk_test_51PyIYTP3VLLeb9GlXCKgD4ylbemZPx72I3HkEAu0bRtcsfK31nqb3WtUbXKXUcKmyfrxKLfuJzZCPyp7Ymtlq9zy00c7VmkL6G');
+
+const Pricing = ({ user }) => {
+ const navigate = useNavigate();
+ const [selectedPackage, setSelectedPackage] = useState(null);
+ const [isModalOpen, setIsModalOpen] = useState(false);
+
+ const groups = [
+ { title: 'Gratuit', price: '0 €', features: ['Accès limité', 'Support par e-mail'] },
+ { title: 'Standard', price: '2 €', features: ['Accès complet', 'Support prioritaire'] },
+ { title: 'Premium', price: '9 €', features: ['Accès illimité', 'Support 24/7'] },
+ ];
+
+ const handleSubscribe = (pkg) => {
+ setSelectedPackage(pkg);
+ setIsModalOpen(true);
+ };
+
+ return (
+
+
navigate('/Dashboard')}
+ />
+
+ {groups.map((pkg, index) => (
+
+
{pkg.title}
+
{pkg.price}
+
+ {pkg.features.map((feature, idx) => (
+ - {feature}
+ ))}
+
+
+
+ ))}
+
+ {isModalOpen && (
+
+
+
Paiement pour {selectedPackage.title}
+
+ setIsModalOpen(false)} />
+
+
+
+ )}
+
+ );
+};
+
+Pricing.propTypes = {
+ user: PropTypes.object.isRequired,
+};
+
+export default Pricing;
diff --git a/src/pages/Payement/Pricing.module.scss b/src/pages/Payement/Pricing.module.scss
new file mode 100644
index 0000000..b9d81a9
--- /dev/null
+++ b/src/pages/Payement/Pricing.module.scss
@@ -0,0 +1,60 @@
+$primary-color: #000;
+$secondary-color: #fff;
+
+.pricingContainer {
+ display: flex;
+ justify-content: center;
+ gap: 20px;
+ padding: 40px;
+ background-color: $secondary-color;
+}
+
+.packageCard {
+ background-color: $primary-color;
+ color: $secondary-color;
+ border-radius: 8px;
+ padding: 20px;
+ text-align: center;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s;
+
+ &:hover {
+ transform: scale(1.05);
+ }
+}
+
+.title {
+ font-size: 24px;
+ margin-bottom: 10px;
+}
+
+.price {
+ font-size: 32px;
+ margin: 10px 0;
+}
+
+.features {
+ list-style-type: none;
+ padding: 0;
+ margin: 20px 0;
+
+ li {
+ margin: 5px 0;
+ }
+}
+
+.button {
+ background-color: $secondary-color;
+ color: $primary-color;
+ border: none;
+ border-radius: 4px;
+ padding: 10px 20px;
+ cursor: pointer;
+ font-size: 16px;
+ transition: background-color 0.3s;
+
+ &:hover {
+ background-color: $primary-color;
+ color: $secondary-color;
+ }
+}