navigate('/Pricing')}>
S'abonner
@@ -101,7 +101,7 @@ Navbar.propTypes = {
showBackButton: PropTypes.bool,
onBackClick: PropTypes.func,
backButtonText: PropTypes.string,
- Subsribebtn: PropTypes.bool // Updated: Prop type corrected
+ Subsribebtn: PropTypes.bool
};
export default Navbar;
diff --git a/src/pages/DashboardPage/DashboardPage.jsx b/src/pages/DashboardPage/DashboardPage.jsx
index bec1a02..2b030cc 100644
--- a/src/pages/DashboardPage/DashboardPage.jsx
+++ b/src/pages/DashboardPage/DashboardPage.jsx
@@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
import ServerCard from '../../components/serverCards/DefaultServerCard';
import Navbar from '../../components/navbar/Navbar';
import Loading from '../Loading/loading';
-import { getUserSubdomain } from "../../service/firebase";
+import { getUserSubdomain, getUserSubscription } from "../../service/firebase";
import serviiApi from "../../service/api.tsx";
import PropTypes from "prop-types";
import styles from './DashboardPage.module.scss';
@@ -21,6 +21,7 @@ const DashboardPage = ({ user }) => {
});
const [subdomain, setSubdomain] = useState(' ');
+ const [subscription, setSubscription] = useState(0);
const [loading, setLoading] = useState(servers.length === 0);
const [searchTerm, setSearchTerm] = useState('');
const [newSubdomain, setNewSubdomain] = useState(' ');
@@ -33,6 +34,8 @@ const DashboardPage = ({ user }) => {
if (user?.uid) {
const userSubdomain = await getUserSubdomain(user.uid);
setSubdomain(userSubdomain || null);
+ const userSubscription = await getUserSubscription(user.uid);
+ setSubscription(userSubscription || 0);
}
const ApiResponse = await serviiApi.fetchServers();
@@ -55,14 +58,44 @@ const DashboardPage = ({ user }) => {
const handleCreateServer = () => navigate('/CreateServer');
- const handleRunServer = async (serverName) => {
+ const handleRunServer = async (serverName, framework) => {
try {
- await serviiApi.serverRun(serverName);
- updateServersFromApi();
+ if (subscription === 0) {
+ if (framework === "paper") {
+ navigate('/payement?package=Gratuit');
+ } if (framework === "Bedrock") {
+ navigate('/payement?package=Standard');
+ }
+ else {
+ navigate('/payement?package=Standard');
+ }
+ }
+
+ else if (subscription === 1) {
+ if (framework === "paper") {
+ await serviiApi.serverRun(serverName);
+ updateServersFromApi();
+ } else {
+ navigate('/payement?package=Standard');
+ }
+ }
+ else if (subscription === 2) {
+ if (framework === "paper" || framework === "Bedrock") {
+ await serviiApi.serverRun(serverName);
+ updateServersFromApi();
+ } else {
+ navigate('/payement?package=Premium');
+ }
+ }
+ else if (subscription === 3) {
+ await serviiApi.serverRun(serverName);
+ updateServersFromApi();
+ }
} catch (error) {
console.error('Error starting server:', error);
}
};
+
const handleStopServer = async (serverName) => {
try {
@@ -193,7 +226,7 @@ const DashboardPage = ({ user }) => {
framework={favoriteServer.framework}
maxPlayers={favoriteServer.maxPlayers}
countPlayers={favoriteServer.onlinePlayers}
- onRunClick={() => handleRunServer(favoriteServer.name)}
+ onRunClick={() => handleRunServer(favoriteServer.name , favoriteServer.framework)}
onStopClick={() => handleStopServer(favoriteServer.name)}
onDeleteClick={() => {
setServerToDelete(favoriteServer.name);
@@ -219,7 +252,7 @@ const DashboardPage = ({ user }) => {
framework={server.framework}
maxPlayers={server.maxPlayers}
countPlayers={server.onlinePlayers}
- onRunClick={() => handleRunServer(server.name)}
+ onRunClick={() => handleRunServer(server.name , server.framework)}
onStopClick={() => handleStopServer(server.name)}
onDeleteClick={() => {
setServerToDelete(server.name);
diff --git a/src/pages/Payement/Checkout.jsx b/src/pages/Payement/Checkout.jsx
new file mode 100644
index 0000000..120c0a6
--- /dev/null
+++ b/src/pages/Payement/Checkout.jsx
@@ -0,0 +1,51 @@
+import { useState, useEffect } from 'react';
+
+const Checkout = () => {
+ const [sessionStatus, setSessionStatus] = useState(null);
+
+ useEffect(() => {
+ const params = new URLSearchParams(window.location.search);
+ const session_id = params.get('session_id');
+
+ console.log('session_id:', session_id);
+
+ if (session_id) {
+ const fetchSessionStatus = async () => {
+ try {
+ const response = await fetch(`http://192.168.68.114:3000/get-session-status?session_id=${session_id}`);
+ const data = await response.json();
+ setSessionStatus(data);
+ } catch (error) {
+ console.error('Error fetching session status:', error);
+ }
+ };
+
+ fetchSessionStatus();
+ } else {
+ console.error('No session_id found in URL');
+ }
+ }, []);
+
+ if (!sessionStatus) {
+ return
Loading...
;
+ }
+
+ return (
+
+ {sessionStatus.status === 'open' && (
+
+
Checkout is still open
+
+ )}
+ {sessionStatus.status === 'complete' && (
+
+
Success!
+
Payment Status: {sessionStatus.payment_status}
+
Customer Email: {sessionStatus.customer_email}
+
+ )}
+
+ );
+};
+
+export default Checkout;
diff --git a/src/pages/Payement/PaymentForm/PaymentForm.jsx b/src/pages/Payement/PaymentForm/PaymentForm.jsx
index 59231c4..628ba22 100644
--- a/src/pages/Payement/PaymentForm/PaymentForm.jsx
+++ b/src/pages/Payement/PaymentForm/PaymentForm.jsx
@@ -1,49 +1,97 @@
-import React, { useState } from 'react';
-import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
+import { useCallback, useState, useEffect } from 'react';
+import { useLocation, useNavigate } from 'react-router-dom';
+import Navbar from '../../../components/navbar/Navbar';
+import PropTypes from 'prop-types';
+import { loadStripe } from '@stripe/stripe-js';
+import { EmbeddedCheckoutProvider, EmbeddedCheckout } 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 stripePromise = loadStripe("pk_test_51PyIYTP3VLLeb9GlXCKgD4ylbemZPx72I3HkEAu0bRtcsfK31nqb3WtUbXKXUcKmyfrxKLfuJzZCPyp7Ymtlq9zy00c7VmkL6G");
- const handleSubmit = async (event) => {
- event.preventDefault();
+const PackageNumber = (selectedPackage) => {
+ switch (selectedPackage) {
+ case 'Gratuit':
+ return 1;
+ case 'Standard':
+ return 2;
+ case 'Premium':
+ return 3;
+ default:
+ return 1;
+ }
+};
- if (!stripe || !elements) return;
+const CheckoutForm = ({ email }) => {
+ const location = useLocation();
+ const [clientSecret, setClientSecret] = useState('');
+ const queryParams = new URLSearchParams(location.search);
+ const selectedPackage = queryParams.get('package');
+
+ const fetchClientSecret = useCallback(() => {
+ return fetch('http://192.168.68.114:3000/get-checkout-session', {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'permission': PackageNumber(selectedPackage),
+ 'email': email,
+ },
+ })
+ .then((res) => res.json())
+ .then((data) => {
+ if (data && data.clientSecret) {
+ setClientSecret(data.clientSecret);
+ }
+ })
+ .catch((error) => {
+ console.error('Error fetching client secret:', error);
+ });
+ }, [selectedPackage, email]);
+
+ useEffect(() => {
+ fetchClientSecret();
+
+
+ }, [fetchClientSecret]);
+
+
+
+ return { clientSecret };
+};
+
+
+
+const PaymentForm = ({ user }) => {
+ const navigate = useNavigate();
+ const { clientSecret } = CheckoutForm({ email: user.email });
+
+ const options = { clientSecret };
- 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 (
-
+
+
navigate('/Pricing')}
+ backButtonText="Retour"
+ />
+
+
+
+
+
+
);
};
-export default PaymentForm;
+PaymentForm.propTypes = {
+ user: PropTypes.shape({
+ uid: PropTypes.string.isRequired,
+ email: PropTypes.string,
+ photoURL: PropTypes.string,
+ }).isRequired,
+};
+
+export default PaymentForm;
\ No newline at end of file
diff --git a/src/pages/Payement/PaymentForm/PaymentForm.module.scss b/src/pages/Payement/PaymentForm/PaymentForm.module.scss
index 0bbf541..95748db 100644
--- a/src/pages/Payement/PaymentForm/PaymentForm.module.scss
+++ b/src/pages/Payement/PaymentForm/PaymentForm.module.scss
@@ -1,19 +1,7 @@
-.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
+.container{
+ margin-top: 5.5rem;
+}
+
+.Footer-PoweredBy-Text{
+ display: none;
+}
\ No newline at end of file
diff --git a/src/pages/Payement/Pricing.jsx b/src/pages/Payement/Pricing.jsx
deleted file mode 100644
index f82b4df..0000000
--- a/src/pages/Payement/Pricing.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-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/Pricing.jsx b/src/pages/Payement/Pricing/Pricing.jsx
new file mode 100644
index 0000000..7f025c3
--- /dev/null
+++ b/src/pages/Payement/Pricing/Pricing.jsx
@@ -0,0 +1,52 @@
+import styles from './Pricing.module.scss';
+import Navbar from '../../../components/navbar/Navbar';
+import { useNavigate } from 'react-router-dom';
+import PropTypes from 'prop-types';
+
+const Pricing = ({ user }) => {
+ const navigate = useNavigate();
+
+ 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) => {
+ navigate(`/payement?package=${pkg.title}`);
+ };
+
+ return (
+
+
navigate('/Dashboard')}
+ />
+
+
+ {groups.map((pkg, index) => (
+
+
{pkg.title}
+
{pkg.price}
+
+ {pkg.features.map((feature, idx) => (
+ - {feature}
+ ))}
+
+
+
+ ))}
+
+
+ );
+};
+
+Pricing.propTypes = {
+ user: PropTypes.object.isRequired,
+};
+
+export default Pricing;
diff --git a/src/pages/Payement/Pricing.module.scss b/src/pages/Payement/Pricing/Pricing.module.scss
similarity index 70%
rename from src/pages/Payement/Pricing.module.scss
rename to src/pages/Payement/Pricing/Pricing.module.scss
index b9d81a9..259d960 100644
--- a/src/pages/Payement/Pricing.module.scss
+++ b/src/pages/Payement/Pricing/Pricing.module.scss
@@ -2,35 +2,43 @@ $primary-color: #000;
$secondary-color: #fff;
.pricingContainer {
+ margin-top: 5rem;
display: flex;
justify-content: center;
- gap: 20px;
- padding: 40px;
+ flex-direction: row;
+ gap: 2rem;
+ padding: 4rem;
background-color: $secondary-color;
}
+.packageList{
+ display: flex;
+ flex-direction: row;
+ gap: 2rem;
+}
+
.packageCard {
background-color: $primary-color;
color: $secondary-color;
- border-radius: 8px;
- padding: 20px;
+ border-radius: .8rem;
+ padding: 5rem;
text-align: center;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
transition: transform 0.3s;
&:hover {
- transform: scale(1.05);
+ transform: scale(1.01);
}
}
.title {
- font-size: 24px;
- margin-bottom: 10px;
+ font-size: 2rem;
+ margin-bottom: .6rem;
}
.price {
- font-size: 32px;
- margin: 10px 0;
+ font-size: 2.5rem;
+ margin: 1rem 0;
}
.features {
@@ -52,9 +60,4 @@ $secondary-color: #fff;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
-
- &:hover {
- background-color: $primary-color;
- color: $secondary-color;
- }
-}
+}
\ No newline at end of file
diff --git a/src/service/firebase.jsx b/src/service/firebase.jsx
index 5f84bdd..d8245a1 100644
--- a/src/service/firebase.jsx
+++ b/src/service/firebase.jsx
@@ -37,4 +37,16 @@ const getUserSubdomain = async (userId) => {
}
};
-export { auth, googleProvider, signInWithPopup, getUserSubdomain, app };
+
+const getUserSubscription = async (userId) => {
+ const userDocRef = doc(db, 'users', userId);
+ const userDocSnap = await getDoc(userDocRef);
+ if (userDocSnap.exists()) {
+ const userData = userDocSnap.data();
+ return userData.subscription;
+ } else {
+ throw new Error("No such document!");
+ }
+};
+
+export { auth, googleProvider, signInWithPopup, getUserSubdomain, getUserSubscription, app };