init aegis
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { pb } from '../../config/pocketbase';
|
||||
|
||||
interface InfrastructureNode {
|
||||
id: string;
|
||||
label: string;
|
||||
type: string;
|
||||
status: string;
|
||||
uptime_sla: string;
|
||||
}
|
||||
|
||||
export default function UptimeWidget() {
|
||||
const [nodes, setNodes] = useState<InfrastructureNode[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchNodes = async () => {
|
||||
try {
|
||||
// Récupération sécurisée filtrée automatiquement par le Token JWT de la compagnie
|
||||
const records = await pb.collection('aegis_infrastructure_nodes').getFullList<InfrastructureNode>({
|
||||
sort: 'created',
|
||||
});
|
||||
setNodes(records);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la récupération des nœuds :", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchNodes();
|
||||
}, []);
|
||||
|
||||
// Fonction pour adapter dynamiquement la couleur du badge selon le statut renvoyé par la base
|
||||
const getStatusStyle = (status: string) => {
|
||||
switch (status) {
|
||||
case 'Opérationnel':
|
||||
return {
|
||||
bg: 'bg-emerald-50 text-emerald-600 border-emerald-100',
|
||||
dot: 'bg-emerald-500'
|
||||
};
|
||||
case 'Dégradé':
|
||||
return {
|
||||
bg: 'bg-amber-50 text-amber-600 border-amber-100',
|
||||
dot: 'bg-amber-500'
|
||||
};
|
||||
case 'Hors Ligne':
|
||||
return {
|
||||
bg: 'bg-red-50 text-red-600 border-red-100',
|
||||
dot: 'bg-red-500'
|
||||
};
|
||||
default:
|
||||
return {
|
||||
bg: 'bg-slate-50 text-slate-600 border-slate-100',
|
||||
dot: 'bg-slate-400'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 flex flex-col">
|
||||
<h2 className="text-lg font-semibold text-slate-900 mb-4">État des Services & SLA</h2>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="flex-1 flex justify-center items-center py-8">
|
||||
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-slate-900"></div>
|
||||
</div>
|
||||
) : nodes.length === 0 ? (
|
||||
<div className="flex-1 flex justify-center items-center py-8 text-sm text-slate-500 italic">
|
||||
Aucun équipement enregistré pour ce contrat.
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y divide-slate-100 flex-1">
|
||||
{nodes.map((node) => {
|
||||
const style = getStatusStyle(node.status);
|
||||
return (
|
||||
<div key={node.id} className="py-4 flex items-center justify-between first:pt-0 last:pb-0">
|
||||
<div>
|
||||
<p className="font-medium text-slate-900">{node.label}</p>
|
||||
<p className="text-xs text-slate-500 mt-0.5">{node.type}</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-6">
|
||||
<div className="text-right">
|
||||
<p className="text-xs text-slate-500">SLA</p>
|
||||
<p className="text-sm font-semibold text-slate-900">{node.uptime_sla}%</p>
|
||||
</div>
|
||||
<div className={`${style.bg} px-3 py-1 rounded-full text-xs font-medium flex items-center border`}>
|
||||
<div className={`w-1.5 h-1.5 rounded-full ${style.dot} mr-2`}></div>
|
||||
{node.status}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user