Feat/manage webservices #2
@@ -66,16 +66,16 @@ export default function ProductCard({ product, selectedPeriod, categoryName }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="p-8 pt-14 border-b border-gray-800 relative bg-gradient-to-b from-gray-800/30 to-transparent min-h-[190px] flex flex-col">
|
<div className="p-8 pt-14 border-b border-gray-800 relative bg-linear-to-b from-gray-800/30 to-transparent min-h-47.5 flex flex-col">
|
||||||
<h3 className="text-2xl font-bold text-white mb-4 relative z-10">{product.title}</h3>
|
<h3 className="text-2xl font-bold text-white mb-4 relative z-10">{product.title}</h3>
|
||||||
|
|
||||||
{priceData.isAvailable ? (
|
{priceData.isAvailable ? (
|
||||||
<div className="flex-grow flex flex-col justify-end">
|
<div className="grow flex flex-col justify-end">
|
||||||
<div className="flex items-baseline space-x-2">
|
<div className="flex items-baseline space-x-2">
|
||||||
<span className="text-4xl font-black text-cyan-400">{priceData.displayPrice} €</span>
|
<span className="text-4xl font-black text-cyan-400">{priceData.displayPrice} €</span>
|
||||||
<span className="text-gray-500">{priceData.suffix}</span>
|
<span className="text-gray-500">{priceData.suffix}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3 min-h-[44px] flex flex-col justify-end">
|
<div className="mt-3 min-h-11 flex flex-col justify-end">
|
||||||
{!priceData.isOnce && (
|
{!priceData.isOnce && (
|
||||||
<>
|
<>
|
||||||
{priceData.originalPrice ? (
|
{priceData.originalPrice ? (
|
||||||
@@ -96,9 +96,9 @@ export default function ProductCard({ product, selectedPeriod, categoryName }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-8 flex-grow flex flex-col justify-between">
|
<div className="p-8 grow flex flex-col justify-between">
|
||||||
<div className="text-gray-400 text-sm mb-8 space-y-3 prose prose-invert max-w-none">
|
<div className="text-gray-400 text-sm mb-8 space-y-3 prose prose-invert max-w-none">
|
||||||
<ReactMarkdown components={{ ul: ({node, ...props}) => <ul className="space-y-2" {...props} />, li: ({node, ...props}) => <li className="flex items-start space-x-2"><CheckCircle2 className="w-4 h-4 text-cyan-400 mt-0.5 flex-shrink-0"/> <span>{props.children}</span></li>, p: ({node, ...props}) => <p className="mb-2 text-gray-300" {...props} />, strong: ({node, ...props}) => <strong className="text-white font-semibold" {...props} /> }}>
|
<ReactMarkdown components={{ ul: ({node, ...props}) => <ul className="space-y-2" {...props} />, li: ({node, ...props}) => <li className="flex items-start space-x-2"><CheckCircle2 className="w-4 h-4 text-cyan-400 mt-0.5 shrink-0"/> <span>{props.children}</span></li>, p: ({node, ...props}) => <p className="mb-2 text-gray-300" {...props} />, strong: ({node, ...props}) => <strong className="text-white font-semibold" {...props} /> }}>
|
||||||
{product.description || "Aucune description technique."}
|
{product.description || "Aucune description technique."}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useParams, useSearchParams, useNavigate } from 'react-router-dom';
|
import { useParams, useSearchParams, useNavigate } from 'react-router-dom';
|
||||||
import { resetCart, addToCart, checkoutCart, getProductList, getClientProfile } from '../../services/api';
|
import { resetCart, addToCart, checkoutCart, getProductList, getClient } from '../../services/billing_api';
|
||||||
|
|
||||||
export default function Checkout() {
|
export default function Checkout() {
|
||||||
const { productId } = useParams();
|
const { productId } = useParams();
|
||||||
@@ -18,7 +18,7 @@ export default function Checkout() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
// 1. On charge d'abord le produit (Requête Publique)
|
// 1. On charge d'abord le produit
|
||||||
const productData = await getProductList();
|
const productData = await getProductList();
|
||||||
const foundProduct = productData.list?.find(p => p.id === parseInt(productId));
|
const foundProduct = productData.list?.find(p => p.id === parseInt(productId));
|
||||||
|
|
||||||
@@ -29,15 +29,14 @@ export default function Checkout() {
|
|||||||
}
|
}
|
||||||
setProduct(foundProduct);
|
setProduct(foundProduct);
|
||||||
|
|
||||||
// 2. Ensuite, on tente de charger le profil (Requête Privée)
|
// 2. Ensuite, on tente de charger le profil
|
||||||
try {
|
try {
|
||||||
const profileData = await getClientProfile();
|
const profileData = await getClient();
|
||||||
setUserProfile(profileData);
|
setUserProfile(profileData);
|
||||||
} catch (profileErr) {
|
} catch (profileErr) {
|
||||||
// Si on tombe ici, c'est que FOSSBilling refuse l'accès au profil.
|
// Si on tombe ici, c'est que FOSSBilling refuse l'accès au profil.
|
||||||
console.error("Rejet API Profil :", profileErr);
|
console.error("Rejet API Profil :", profileErr);
|
||||||
setError("Accès refusé. Vous devez être connecté à votre compte pour provisionner une instance.");
|
setError("Accès refusé. Vous devez être connecté à votre compte pour provisionner une instance.");
|
||||||
// Tu pourras décommenter la ligne suivante plus tard pour forcer la redirection :
|
|
||||||
// navigate('/login');
|
// navigate('/login');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { getClientOrders } from '../../services/api';
|
import { getOrdersList } from '../../services/billing_api';
|
||||||
import { AlertCircle, Loader, FileText, X } from 'lucide-react';
|
import { AlertCircle, Loader, FileText, X } from 'lucide-react';
|
||||||
|
|
||||||
// Importation des composants
|
// Importation des composants
|
||||||
@@ -23,7 +23,7 @@ export default function Dashboard() {
|
|||||||
const fetchInventory = async () => {
|
const fetchInventory = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const data = await getClientOrders();
|
const data = await getOrdersList();
|
||||||
|
|
||||||
if (data.list) {
|
if (data.list) {
|
||||||
// LE FILTRE CHIRURGICAL PAR PREFIXE
|
// LE FILTRE CHIRURGICAL PAR PREFIXE
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { getClientOrders, getOrderDetails } from '../../services/api';
|
import { getOrdersList, getOrderDetails } from '../../services/billing_api';
|
||||||
import { useVPC } from '../../services/useVPC';
|
import { useVPC } from '../../services/useVPC';
|
||||||
import { Server, Globe, Folder, Trash2, Loader, Plus, AlertCircle } from 'lucide-react';
|
import { Server, Globe, Folder, Trash2, Loader, Plus, AlertCircle } from 'lucide-react';
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export default function Services() {
|
|||||||
|
|
||||||
const fetchServices = useCallback(async () => {
|
const fetchServices = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getClientOrders();
|
const data = await getOrdersList();
|
||||||
if (data.list && data.list.length > 0) {
|
if (data.list && data.list.length > 0) {
|
||||||
const detailedServices = await Promise.all(data.list.map(async (order) => {
|
const detailedServices = await Promise.all(data.list.map(async (order) => {
|
||||||
let hDetails = null;
|
let hDetails = null;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// src/pages/app/Store.jsx
|
// src/pages/app/Store.jsx
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Server, Database, Cloud, Globe, Loader, AlertCircle } from 'lucide-react';
|
import { Server, Database, Cloud, Globe, Loader, AlertCircle } from 'lucide-react';
|
||||||
import { getProductList } from '../../services/api';
|
import { getProductList } from '../../services/billing_api';
|
||||||
import CategorySection from '../../components/store/CategorySection'; // L'import magique
|
import CategorySection from '../../components/store/CategorySection';
|
||||||
|
|
||||||
export default function Store() {
|
export default function Store() {
|
||||||
const [groupedProducts, setGroupedProducts] = useState({});
|
const [groupedProducts, setGroupedProducts] = useState({});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useNavigate, Link } from 'react-router-dom';
|
import { useNavigate, Link } from 'react-router-dom';
|
||||||
import { loginClient } from '../../services/api';
|
import { loginClient } from '../../services/billing_api';
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useNavigate, Link } from 'react-router-dom';
|
import { useNavigate, Link } from 'react-router-dom';
|
||||||
import { registerUnifiedClient } from '../../services/api';
|
import { createNewClient } from '../../services/billing_api';
|
||||||
import NotificationModal from '../../components/ui/NotificationModal';
|
import NotificationModal from '../../components/ui/NotificationModal';
|
||||||
|
|
||||||
export default function Register() {
|
export default function Register() {
|
||||||
@@ -10,7 +10,7 @@ export default function Register() {
|
|||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [confirmPassword, setConfirmPassword] = useState('');
|
const [confirmPassword, setConfirmPassword] = useState('');
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [customAlert, setCustomAlert] = useState(null);
|
const [customAlert, setCustomAlert] = useState(null);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -28,15 +28,15 @@ export default function Register() {
|
|||||||
setCustomAlert({ type: 'error', title: 'Erreur de saisie', message: "Les clés d'accès ne correspondent pas." });
|
setCustomAlert({ type: 'error', title: 'Erreur de saisie', message: "Les clés d'accès ne correspondent pas." });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!/^[a-zA-Z0-9]{3,12}$/.test(username)) {
|
if (!/^[a-zA-Z0-9]{3,20}$/.test(username)) {
|
||||||
setCustomAlert({ type: 'error', title: 'Identifiant invalide', message: "Le nom d'utilisateur doit contenir uniquement des lettres ou chiffres (entre 3 et 12 caractères)." });
|
setCustomAlert({ type: 'error', title: 'Identifiant invalide', message: "Le nom d'utilisateur doit contenir uniquement des lettres ou chiffres (entre 3 et 12 caractères)." });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
await registerUnifiedClient(email, username, password, firstName, lastName);
|
await createNewClient(email, firstName, lastName, password, confirmPassword, "individual", username);
|
||||||
setCustomAlert({ type: 'success', title: 'PROVISIONNEMENT RÉUSSI', message: "Vos comptes FOSSBilling, HestiaCP et Nextcloud ont été initialisés.\n\nVous pouvez maintenant vous connecter." });
|
setCustomAlert({ type: 'success', title: 'PROVISIONNEMENT RÉUSSI', message: "Votre compte a été initialisé.\n\nVous pouvez maintenant vous connecter." });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setCustomAlert({ type: 'error', title: 'Échec du Déploiement', message: err.message || "Échec de l'initialisation." });
|
setCustomAlert({ type: 'error', title: 'Échec du Déploiement', message: err.message || "Échec de l'initialisation." });
|
||||||
} finally {
|
} finally {
|
||||||
@@ -56,7 +56,7 @@ export default function Register() {
|
|||||||
Créer un accès réseau
|
Créer un accès réseau
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-[#888] font-mono text-sm mb-6">
|
<p className="text-[#888] font-mono text-sm mb-6">
|
||||||
[ INITIALISATION DU PROVISIONNEMENT TRIPLE ]
|
[ INITIALISATION DU PROVISIONNEMENT ]
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form onSubmit={handleRegister} className="font-mono">
|
<form onSubmit={handleRegister} className="font-mono">
|
||||||
|
|||||||
+36
-1
@@ -164,6 +164,42 @@ export const logoutClient = () =>
|
|||||||
// GESTION DU CLIENT
|
// GESTION DU CLIENT
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|
||||||
|
// Creer un nouveau profil client
|
||||||
|
export const createClientProfile = (email, last_name, aid, gender, country, city, birthday, company, company_vat, company_number, type, address_1, address_2, postcode, state, phone, phone_cc, document_type, document_nr, notes, lang, custom_1, custom_2, custom_3, custom_4, custom_5, custom_6, custom_7, custom_8, custom_9, custom_10) =>
|
||||||
|
apiCall(`${BASE_URL}/api/guest/profile/create`, {
|
||||||
|
email: email,
|
||||||
|
last_name: last_name,
|
||||||
|
aid: aid,
|
||||||
|
gender: gender,
|
||||||
|
country: country,
|
||||||
|
city: city,
|
||||||
|
birthday: birthday,
|
||||||
|
company: company,
|
||||||
|
company_vat: company_vat,
|
||||||
|
company_number: company_number,
|
||||||
|
type: type,
|
||||||
|
address_1: address_1,
|
||||||
|
address_2: address_2,
|
||||||
|
postcode: postcode,
|
||||||
|
state: state,
|
||||||
|
phone: phone,
|
||||||
|
phone_cc: phone_cc,
|
||||||
|
document_type: document_type,
|
||||||
|
document_nr: document_nr,
|
||||||
|
notes: notes,
|
||||||
|
lang: lang,
|
||||||
|
custom_1: custom_1,
|
||||||
|
custom_2: custom_2,
|
||||||
|
custom_3: custom_3,
|
||||||
|
custom_4: custom_4,
|
||||||
|
custom_5: custom_5,
|
||||||
|
custom_6: custom_6,
|
||||||
|
custom_7: custom_7,
|
||||||
|
custom_8: custom_8,
|
||||||
|
custom_9: custom_9,
|
||||||
|
custom_10: custom_10
|
||||||
|
});
|
||||||
|
|
||||||
// Recuperer les informations du client
|
// Recuperer les informations du client
|
||||||
export const getClientProfile = () =>
|
export const getClientProfile = () =>
|
||||||
apiCall(`${BASE_URL}/api/client/profile/get`, 'GET');
|
apiCall(`${BASE_URL}/api/client/profile/get`, 'GET');
|
||||||
@@ -202,7 +238,6 @@ export const updateClientProfile = (email, last_name, aid, gender, country, city
|
|||||||
custom_8: custom_8,
|
custom_8: custom_8,
|
||||||
custom_9: custom_9,
|
custom_9: custom_9,
|
||||||
custom_10: custom_10
|
custom_10: custom_10
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Changer le mot de passe
|
// Changer le mot de passe
|
||||||
|
|||||||
@@ -0,0 +1,345 @@
|
|||||||
|
const BASE_URL = import.meta.env.VITE_API_BASE_URL || '';
|
||||||
|
const CUSTOM_API_BASE_URL = import.meta.env.VITE_CUSTOM_API_BASE_URL || '';
|
||||||
|
|
||||||
|
// Le moteur de requête
|
||||||
|
const apiCall = async (endpoint, param2 = 'GET', param3 = null) => {
|
||||||
|
let method = 'GET';
|
||||||
|
let body = null;
|
||||||
|
|
||||||
|
// DÉTECTION DE SIGNATURE (Le bouclier anti-crash)
|
||||||
|
if (typeof param2 === 'string') {
|
||||||
|
// Cas 1 : On a bien envoyé (URL, "POST", {données})
|
||||||
|
method = param2.toUpperCase();
|
||||||
|
body = param3;
|
||||||
|
} else if (typeof param2 === 'object' && param2 !== null) {
|
||||||
|
// Cas 2 : L'ancienne méthode a envoyé (URL, {données})
|
||||||
|
// On redirige l'objet vers le body, et on force en POST
|
||||||
|
body = param2;
|
||||||
|
method = (typeof param3 === 'string') ? param3.toUpperCase() : 'POST';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Récupération du sésame
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
|
||||||
|
// 2. Préparation de l'enveloppe
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
headers['Authorization'] = `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Configuration finale garantie sans objets égarés
|
||||||
|
const options = {
|
||||||
|
method: method,
|
||||||
|
headers: headers,
|
||||||
|
credentials: 'include'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (body) {
|
||||||
|
options.body = JSON.stringify(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(endpoint, options);
|
||||||
|
|
||||||
|
if (response.status === 401 || response.status === 403) {
|
||||||
|
throw new Error("Accès refusé. Session expirée ou non valide.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Gestion des erreurs internes de l'API
|
||||||
|
if (data.error) {
|
||||||
|
throw new Error(data.error.message || "Erreur renvoyée par le serveur de facturation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.result || data;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[API FAIL] ${method} ${endpoint} :`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Vide le panier (Action PUBLIQUE : on passe par l'API Guest)
|
||||||
|
export const resetCart = async () => {
|
||||||
|
try {
|
||||||
|
const cart = await apiCall(`${BASE_URL}/api/guest/cart/get`);
|
||||||
|
|
||||||
|
if (cart && cart.items && cart.items.length > 0) {
|
||||||
|
for (const item of cart.items) {
|
||||||
|
await apiCall(`${BASE_URL}/api/guest/cart/remove_item`, { id: item.id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Nettoyage du panier ignoré :", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// ROUTES PERSONNALISÉES (CUSTOM API)
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
export const registerUnifiedClient = async (email, username, password, firstName, lastName) => {
|
||||||
|
try {
|
||||||
|
// Utilisation des backticks ici aussi !
|
||||||
|
const response = await fetch(`${CUSTOM_API_BASE_URL}/custom_api/signup.php`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
email: email,
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
first_name: firstName,
|
||||||
|
last_name: lastName
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.error) throw new Error(data.error.message);
|
||||||
|
return data.result;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Erreur lors de l'inscription unifiée :", err);
|
||||||
|
throw new Error("Échec de l'inscription. Veuillez réessayer plus tard.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #######################################################################################
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DES ACCES
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Connexion
|
||||||
|
export const loginClient = (email, password) =>
|
||||||
|
apiCall(`${BASE_URL}/api/guest/client/login`, { email, password });
|
||||||
|
|
||||||
|
// Deconnexion
|
||||||
|
export const logoutClient = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/profile/logout`);
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DU CLIENT
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Creer un nouveau profil client
|
||||||
|
export const createNewClient = (
|
||||||
|
email,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
password,
|
||||||
|
password_confirm,
|
||||||
|
type,
|
||||||
|
custom_1) =>
|
||||||
|
apiCall(`${BASE_URL}/api/guest/client/create`, {
|
||||||
|
email: email,
|
||||||
|
first_name: first_name,
|
||||||
|
password: password,
|
||||||
|
password_confirm: password_confirm,
|
||||||
|
last_name: last_name,
|
||||||
|
type: type,
|
||||||
|
custom_1: custom_1
|
||||||
|
});
|
||||||
|
|
||||||
|
// Recuperer les informations du client
|
||||||
|
export const getClient = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/profile/get`);
|
||||||
|
|
||||||
|
// Update les informations du client
|
||||||
|
export const updateClient = (email, last_name, aid, gender, country, city, birthday, company, company_vat, company_number, type, address_1, address_2, postcode, state, phone, phone_cc, document_type, document_nr, notes, lang, custom_1, custom_2, custom_3, custom_4, custom_5, custom_6, custom_7, custom_8, custom_9, custom_10) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/profile/update`, {
|
||||||
|
email: email,
|
||||||
|
last_name: last_name,
|
||||||
|
aid: aid,
|
||||||
|
gender: gender,
|
||||||
|
country: country,
|
||||||
|
city: city,
|
||||||
|
birthday: birthday,
|
||||||
|
company: company,
|
||||||
|
company_vat: company_vat,
|
||||||
|
company_number: company_number,
|
||||||
|
type: type,
|
||||||
|
address_1: address_1,
|
||||||
|
address_2: address_2,
|
||||||
|
postcode: postcode,
|
||||||
|
state: state,
|
||||||
|
phone: phone,
|
||||||
|
phone_cc: phone_cc,
|
||||||
|
document_type: document_type,
|
||||||
|
document_nr: document_nr,
|
||||||
|
notes: notes,
|
||||||
|
lang: lang,
|
||||||
|
custom_1: custom_1,
|
||||||
|
custom_2: custom_2,
|
||||||
|
custom_3: custom_3,
|
||||||
|
custom_4: custom_4,
|
||||||
|
custom_5: custom_5,
|
||||||
|
custom_6: custom_6,
|
||||||
|
custom_7: custom_7,
|
||||||
|
custom_8: custom_8,
|
||||||
|
custom_9: custom_9,
|
||||||
|
custom_10: custom_10
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Changer le mot de passe
|
||||||
|
export const changeClientPassword = (current_password, new_password) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/profile/change_password`, {
|
||||||
|
current_password: current_password,
|
||||||
|
new_password: new_password,
|
||||||
|
confirm_password: new_password
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DES ABONNEMENTS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Souscription
|
||||||
|
|
||||||
|
// Resiliation (après 14 jours)
|
||||||
|
export const cancelRenewal = (order_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/admin/order/update`, {
|
||||||
|
id: order_id,
|
||||||
|
cancel_at_expiration: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// Suppression
|
||||||
|
export const cancelOrder = (order_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/order/delete`, { id: order_id });
|
||||||
|
|
||||||
|
// Promotion (Surclassement)
|
||||||
|
// Lister
|
||||||
|
export const getUpgrades = (order_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/order/upgradables`, { id: order_id });
|
||||||
|
|
||||||
|
// Demotion (Declassement)
|
||||||
|
|
||||||
|
// Lister les abonnements du client
|
||||||
|
export const getOrdersList = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/order/get_list`);
|
||||||
|
|
||||||
|
// Lister les produits disponibles
|
||||||
|
export const getProductList = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/guest/product/get_list`);
|
||||||
|
|
||||||
|
// Recuperer les details d'un abonnement
|
||||||
|
export const getOrderDetails = (order_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/order/service`, { id: order_id });
|
||||||
|
|
||||||
|
// Recuperer les details secrets d'un abonnement
|
||||||
|
export const getServiceDetails = (orderId) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/order/get`, { id: orderId });
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DU PANIER
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Ajouter au panier
|
||||||
|
export const addToCart = (productId, period, additionalData = {}) =>
|
||||||
|
apiCall(`${BASE_URL}/api/guest/cart/add_item`, {
|
||||||
|
id: productId,
|
||||||
|
period: period,
|
||||||
|
...additionalData // Les 3 petits points "étalent" le contenu de l'objet
|
||||||
|
});
|
||||||
|
|
||||||
|
// Checkout
|
||||||
|
export const checkoutCart = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/cart/checkout`, 'POST');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DES SERVICES D'HEBERGEMENT
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Modification du username
|
||||||
|
export const updateHostingUsername = (order_id, username) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/servicehosting/change_username`, {
|
||||||
|
order_id: order_id,
|
||||||
|
username: username
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modification du mot de passe
|
||||||
|
export const updateHostingPassword = (order_id, new_password) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/servicehosting/change_password`, {
|
||||||
|
order_id: order_id,
|
||||||
|
password: new_password,
|
||||||
|
password_confirm: new_password
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modification du domaine principal
|
||||||
|
export const updateHostingDomain = (order_id, new_domain) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/servicehosting/change_domain`, {
|
||||||
|
order_id: order_id,
|
||||||
|
domain: new_domain
|
||||||
|
});
|
||||||
|
|
||||||
|
// Login URL (SSO)
|
||||||
|
export const getHostingLoginUrl = (order_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/servicehosting/get_login_url`, {
|
||||||
|
order_id: order_id
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modification du plan d'hébergement
|
||||||
|
export const updateHostingPlan = (order_id, new_plan_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/admin/servicehosting/change_plan`, {
|
||||||
|
order_id: order_id,
|
||||||
|
plan_id: new_plan_id
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DES FACTURES
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Creation
|
||||||
|
// Suppression
|
||||||
|
// Modification
|
||||||
|
// Lister
|
||||||
|
export const getInvoiceList = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/invoice/get_list`);
|
||||||
|
|
||||||
|
// Lire
|
||||||
|
export const getInvoiceDetails = (InvoiceHash) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/invoice/get`);
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// GESTION DES TICKETS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// Creation
|
||||||
|
export const createTicket = (subject, message, helpdesk_id) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/support/ticket_create`, {
|
||||||
|
support_helpdesk_id: helpdesk_id,
|
||||||
|
subject: subject,
|
||||||
|
content: message
|
||||||
|
});
|
||||||
|
// Suppression
|
||||||
|
|
||||||
|
// Lister les tickets
|
||||||
|
export const getClientTickets = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/support/ticket_get_list`);
|
||||||
|
|
||||||
|
// Lister les helpdesks
|
||||||
|
export const getHelpdesks = () =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/support/helpdesk_get_pairs`);
|
||||||
|
|
||||||
|
// Lire
|
||||||
|
export const getTicketDetails = (ticketId) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/support/ticket_get`, { id: ticketId });
|
||||||
|
|
||||||
|
// Repondre
|
||||||
|
export const replyTicket = (ticketId, message) =>
|
||||||
|
apiCall(`${BASE_URL}/api/client/support/ticket_reply`, {
|
||||||
|
id: ticketId,
|
||||||
|
content: message
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user