separate components
This commit is contained in:
+12
-64
@@ -1,7 +1,11 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { getClientOrders } from '../../services/api';
|
||||
import { Server, Database, Cloud, Globe, Plus, AlertCircle, Loader } from 'lucide-react';
|
||||
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();
|
||||
@@ -21,16 +25,12 @@ export default function Dashboard() {
|
||||
const title = (order.title || '').toLowerCase();
|
||||
const type = (order.type || '').toLowerCase();
|
||||
|
||||
// On masque la commande SI :
|
||||
// 1. Le type technique est "domain"
|
||||
// 2. OU le titre COMMENCE par "domain", "domaine" ou "enregistrement"
|
||||
const isGhostProduct =
|
||||
type === 'domain' ||
|
||||
title.startsWith('domain ') ||
|
||||
title.startsWith('domaine ') ||
|
||||
title.startsWith('enregistrement ');
|
||||
|
||||
// On retourne true (on affiche) uniquement si ce n'est pas un produit fantôme
|
||||
return !isGhostProduct;
|
||||
});
|
||||
|
||||
@@ -48,25 +48,6 @@ export default function Dashboard() {
|
||||
fetchInventory();
|
||||
}, []);
|
||||
|
||||
// Fonction Radar : Détecte le type de service selon son nom pour afficher la bonne icône
|
||||
const getServiceIcon = (title) => {
|
||||
const t = title.toLowerCase();
|
||||
if (t.includes('vps') || t.includes('serveur')) return <Server className="w-10 h-10 text-cyan-400" />;
|
||||
if (t.includes('cloud') || t.includes('nextcloud')) return <Cloud className="w-10 h-10 text-blue-400" />;
|
||||
if (t.includes('db') || t.includes('base') || t.includes('sql')) return <Database className="w-10 h-10 text-purple-400" />;
|
||||
return <Globe className="w-10 h-10 text-emerald-400" />; // Par défaut : Web / Hestia
|
||||
};
|
||||
|
||||
// Fonction d'état : Formate le statut du service
|
||||
const getStatusBadge = (status) => {
|
||||
switch (status) {
|
||||
case 'active': return <span className="px-2 py-1 text-xs text-green-400 bg-green-400/10 border border-green-400/20 rounded">ACTIF</span>;
|
||||
case 'pending_setup': return <span className="px-2 py-1 text-xs text-orange-400 bg-orange-400/10 border border-orange-400/20 rounded">EN PRÉPARATION</span>;
|
||||
case 'suspended': return <span className="px-2 py-1 text-xs text-red-400 bg-red-400/10 border border-red-400/20 rounded">SUSPENDU</span>;
|
||||
default: return <span className="px-2 py-1 text-xs text-gray-400 bg-gray-400/10 border border-gray-400/20 rounded">{status.toUpperCase()}</span>;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-6xl p-6 mx-auto">
|
||||
|
||||
@@ -94,50 +75,17 @@ export default function Dashboard() {
|
||||
{!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 services FOSSBilling */}
|
||||
{/* Boucle sur les composants isolés */}
|
||||
{orders.map((order) => (
|
||||
<div
|
||||
<DashboardServiceCard
|
||||
key={order.id}
|
||||
className="bg-gray-900 border border-gray-800 p-6 rounded-xl hover:border-cyan-400/50 transition-colors group cursor-pointer flex flex-col justify-between"
|
||||
onClick={() => navigate(`/services/${order.id}`)} // Redirection future vers les détails
|
||||
>
|
||||
<div>
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<div className="p-3 bg-black/50 rounded-lg group-hover:scale-110 transition-transform">
|
||||
{getServiceIcon(order.title)}
|
||||
</div>
|
||||
{getStatusBadge(order.status)}
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-white truncate" title={order.title}>
|
||||
{order.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
Facturation : {order.period}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 pt-4 border-t border-gray-800 flex justify-between items-center text-sm">
|
||||
<span className="text-gray-400">ID Réseau: #{order.id}</span>
|
||||
<span className="text-cyan-400 group-hover:underline">Gérer ></span>
|
||||
</div>
|
||||
</div>
|
||||
order={order}
|
||||
onClick={() => navigate(`/services/${order.id}`)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* LA CARTE : OBTENIR UN NOUVEAU PRODUIT */}
|
||||
<div
|
||||
onClick={() => navigate('/store')} // Remplace /store par l'URL de ton catalogue
|
||||
className="bg-transparent border-2 border-dashed border-gray-700 hover:border-cyan-400 p-6 rounded-xl transition-colors cursor-pointer flex flex-col items-center justify-center text-center group min-h-[200px]"
|
||||
>
|
||||
<div className="p-3 bg-gray-800/50 rounded-full group-hover:bg-cyan-400/20 transition-colors mb-4">
|
||||
<Plus className="w-8 h-8 text-gray-400 group-hover:text-cyan-400" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-white group-hover:text-cyan-400">
|
||||
Demander une accréditation
|
||||
</h3>
|
||||
<p className="text-sm text-gray-500 mt-2">
|
||||
Déployer un nouveau serveur Web, VPS ou Cloud.
|
||||
</p>
|
||||
</div>
|
||||
{/* Le composant carte d'ajout */}
|
||||
<NewServiceCard onClick={() => navigate('/store')} />
|
||||
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user