Files
drone-detector/management/src/pages/System.jsx
2025-09-12 23:16:32 +02:00

197 lines
6.8 KiB
JavaScript

import React, { useState, useEffect } from 'react'
import api from '../services/api'
import toast from 'react-hot-toast'
import {
CogIcon,
ServerIcon,
CircleStackIcon,
ShieldCheckIcon,
ClockIcon
} from '@heroicons/react/24/outline'
const System = () => {
const [systemInfo, setSystemInfo] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
loadSystemInfo()
}, [])
const loadSystemInfo = async () => {
try {
setLoading(true)
// This would be a real API endpoint in production
const response = await api.get('/system/info')
setSystemInfo(response.data.data)
} catch (error) {
// Mock data for development
setSystemInfo({
version: '1.0.0',
environment: 'development',
uptime: '7d 14h 32m',
database: {
status: 'connected',
version: 'PostgreSQL 14.2',
connections: 5,
maxConnections: 100
},
memory: {
used: '256MB',
total: '1GB',
percentage: 25
},
lastBackup: '2024-01-15T10:30:00Z',
ssl: {
status: 'valid',
expiresAt: '2024-03-15T00:00:00Z'
}
})
} finally {
setLoading(false)
}
}
const StatusCard = ({ title, icon: Icon, children }) => (
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center mb-4">
<Icon className="h-6 w-6 text-blue-600 mr-2" />
<h3 className="text-lg font-medium text-gray-900">{title}</h3>
</div>
{children}
</div>
)
const StatusIndicator = ({ status }) => {
const colors = {
connected: 'bg-green-100 text-green-800',
valid: 'bg-green-100 text-green-800',
warning: 'bg-yellow-100 text-yellow-800',
error: 'bg-red-100 text-red-800'
}
return (
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${colors[status] || colors.error}`}>
{status.charAt(0).toUpperCase() + status.slice(1)}
</span>
)
}
if (loading) {
return (
<div className="flex items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
)
}
return (
<div>
<div className="mb-8">
<h1 className="text-2xl font-bold text-gray-900">System</h1>
<p className="text-gray-600">Monitor system health and configuration</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
<StatusCard title="Server Status" icon={ServerIcon}>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-sm text-gray-500">Version</span>
<span className="text-sm font-medium">{systemInfo.version}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-500">Environment</span>
<span className="text-sm font-medium capitalize">{systemInfo.environment}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-500">Uptime</span>
<span className="text-sm font-medium">{systemInfo.uptime}</span>
</div>
</div>
</StatusCard>
<StatusCard title="Database" icon={CircleStackIcon}>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-sm text-gray-500">Status</span>
<StatusIndicator status={systemInfo.database.status} />
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-500">Version</span>
<span className="text-sm font-medium">{systemInfo.database.version}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-500">Connections</span>
<span className="text-sm font-medium">
{systemInfo.database.connections}/{systemInfo.database.maxConnections}
</span>
</div>
</div>
</StatusCard>
<StatusCard title="SSL Certificate" icon={ShieldCheckIcon}>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-sm text-gray-500">Status</span>
<StatusIndicator status={systemInfo.ssl.status} />
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-500">Expires</span>
<span className="text-sm font-medium">
{new Date(systemInfo.ssl.expiresAt).toLocaleDateString()}
</span>
</div>
</div>
</StatusCard>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="bg-white rounded-lg shadow p-6">
<h3 className="text-lg font-medium text-gray-900 mb-4 flex items-center">
<CogIcon className="h-5 w-5 text-blue-600 mr-2" />
Memory Usage
</h3>
<div className="space-y-3">
<div className="flex justify-between text-sm">
<span className="text-gray-500">Used</span>
<span className="font-medium">{systemInfo.memory.used}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-gray-500">Total</span>
<span className="font-medium">{systemInfo.memory.total}</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-blue-600 h-2 rounded-full"
style={{ width: `${systemInfo.memory.percentage}%` }}
></div>
</div>
<div className="text-xs text-gray-500 text-center">
{systemInfo.memory.percentage}% used
</div>
</div>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h3 className="text-lg font-medium text-gray-900 mb-4 flex items-center">
<ClockIcon className="h-5 w-5 text-blue-600 mr-2" />
Last Backup
</h3>
<div className="text-center">
<div className="text-2xl font-bold text-gray-900">
{new Date(systemInfo.lastBackup).toLocaleDateString()}
</div>
<div className="text-sm text-gray-500">
{new Date(systemInfo.lastBackup).toLocaleTimeString()}
</div>
<button className="mt-4 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors">
Run Backup Now
</button>
</div>
</div>
</div>
</div>
)
}
export default System