94 lines
3.6 KiB
React
94 lines
3.6 KiB
React
import { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { getClientOrders } from '../../services/api';
|
|
import { AlertCircle, Loader } from 'lucide-react';
|
|
|
|
// Importation des composants isolés
|
|
import DashboardServiceCard from '../../components/dashboard/DashboardServiceCard';
|
|
import NewServiceCard from '../../components/dashboard/NewServiceCard';
|
|
|
|
export default function Dashboard() {
|
|
const navigate = useNavigate();
|
|
const [orders, setOrders] = useState([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [error, setError] = useState(null);
|
|
|
|
// Chargement des données à l'ouverture du Sas
|
|
useEffect(() => {
|
|
const fetchInventory = async () => {
|
|
try {
|
|
const data = await getClientOrders();
|
|
|
|
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);
|
|
}
|
|
};
|
|
|
|
fetchInventory();
|
|
}, []);
|
|
|
|
return (
|
|
<div className="w-full max-w-6xl p-6 mx-auto">
|
|
|
|
<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">Aperçu de vos accréditations réseau et infrastructures.</p>
|
|
</header>
|
|
|
|
{/* GESTION DES ERREURS & CHARGEMENT */}
|
|
{isLoading && (
|
|
<div className="flex items-center space-x-3 text-cyan-400">
|
|
<Loader className="w-6 h-6 animate-spin" />
|
|
<span>Synchronisation avec l'orchestrateur en cours...</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>
|
|
)}
|
|
|
|
{/* GRILLE DES SERVICES */}
|
|
{!isLoading && !error && (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
|
|
|
{/* Boucle sur les composants isolés */}
|
|
{orders.map((order) => (
|
|
<DashboardServiceCard
|
|
key={order.id}
|
|
order={order}
|
|
onClick={() => navigate(`/services/${order.id}`)}
|
|
/>
|
|
))}
|
|
|
|
{/* Le composant carte d'ajout */}
|
|
<NewServiceCard onClick={() => navigate('/store')} />
|
|
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
} |