Files
portail-gise/src/pages/app/Dashboard.jsx
T
LathanDevers 15213bba21 change api
2026-07-16 14:51:57 +02:00

144 lines
6.4 KiB
React

import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { getOrdersList } from '../../services/billing_api';
import { AlertCircle, Loader, FileText, X } from 'lucide-react';
// Importation des composants
import DashboardServiceCard from '../../components/dashboard/DashboardServiceCard';
import NewServiceCard from '../../components/dashboard/NewServiceCard';
import NotificationModal from '../../components/ui/NotificationModal';
import WebServiceSubscriptionManager from '../../components/dashboard/WebServiceSubscriptionManager';
export default function Dashboard() {
const navigate = useNavigate();
const [orders, setOrders] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [activeSubscriptionModal, setActiveSubscriptionModal] = useState(null);
const [customAlert, setCustomAlert] = useState(null);
const triggerAlert = (title, message, type = "info") => setCustomAlert({ title, message, type });
const fetchInventory = async () => {
setIsLoading(true);
try {
const data = await getOrdersList();
if (data.list) {
// LE FILTRE CHIRURGICAL PAR PREFIXE
const filteredOrders = data.list.filter(order => {
const title = (order.title || '').toLowerCase();
const type = (order.type || '').toLowerCase();
const isGhostProduct =
type === 'domain' ||
title.startsWith('domain ') ||
title.startsWith('domaine ') ||
title.startsWith('enregistrement ');
return !isGhostProduct;
});
setOrders(filteredOrders);
} else {
setOrders([]);
}
} catch (err) {
setError(err.message || "Impossible de récupérer la télémétrie des services.");
} finally {
setIsLoading(false);
}
};
useEffect(() => {
fetchInventory();
}, []);
// 🌟 Plus besoin de charger les IPs, on ouvre juste la modale comptable !
const handleManageSubscription = (order) => {
// 1. Détection du type de service
const titleLower = (order.title || '').toLowerCase();
const isVPS = titleLower.includes('vps') || titleLower.includes('compute');
const isCloud = titleLower.includes('cloud') || titleLower.includes('nextcloud');
const isDB = titleLower.includes('db') || titleLower.includes('base') || titleLower.includes('sql');
// C'est un hébergement web s'il ne correspond à aucun des cas ci-dessus
const isWeb = !isVPS && !isCloud && !isDB;
// 2. Logique de blocage
if (isWeb) {
// On ouvre la modale comptable uniquement pour le WEB
setActiveSubscriptionModal(order);
} else {
// On affiche une notification pour les autres types d'instances
triggerAlert(
"Action non disponible",
"La modification autonome d'abonnement est actuellement exclusive aux Hébergements Web. Pour restructurer cette instance, veuillez contacter les ingénieurs via le Centre de Support.",
"info"
);
}
};
return (
<div className="w-full max-w-6xl p-6 mx-auto relative">
<header className="mb-8">
<h1 className="text-3xl font-black text-white tracking-wider">TABLEAU DE <span className="text-cyan-400">BORD</span></h1>
<p className="text-gray-400 mt-2">Gestion financière et accréditations de vos infrastructures.</p>
</header>
{isLoading && (
<div className="flex items-center space-x-3 text-cyan-400">
<Loader className="w-6 h-6 animate-spin" />
<span>Synchronisation avec le registre comptable...</span>
</div>
)}
{error && (
<div className="flex items-center space-x-3 text-red-400 bg-red-400/10 border border-red-400 p-4 rounded-lg">
<AlertCircle className="w-6 h-6" />
<span>{error}</span>
</div>
)}
{!isLoading && !error && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{orders.map((order) => (
<DashboardServiceCard
key={order.id}
order={order}
onClick={() => handleManageSubscription(order)}
/>
))}
<NewServiceCard onClick={() => navigate('/store')} />
</div>
)}
{/* 🌟 LA MODALE DE GESTION D'ABONNEMENT */}
{activeSubscriptionModal && (
<div className="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="bg-gray-900 border border-cyan-500/50 shadow-2xl shadow-cyan-500/10 rounded-lg max-w-xxl w-full p-6 text-gray-200">
<div className="flex justify-between items-center mb-6 border-b border-gray-800 pb-4">
<h3 className="text-xl font-bold text-white tracking-wider flex items-center gap-3">
<FileText className="w-6 h-6 text-cyan-400" />
GESTION DE L'ABONNEMENT
</h3>
<button onClick={() => setActiveSubscriptionModal(null)} className="p-2 text-gray-500 hover:text-white bg-gray-900 hover:bg-gray-800 rounded-lg transition-colors">
<X className="w-5 h-5" />
</button>
</div>
<WebServiceSubscriptionManager
order={activeSubscriptionModal}
onClose={() => setActiveSubscriptionModal(null)}
onRefresh={fetchInventory}
onAlert={triggerAlert}
/>
</div>
</div>
)}
<NotificationModal notification={customAlert} onClose={() => setCustomAlert(null)} />
</div>
);
}