import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; class MonitoringPanel extends StatelessWidget { const MonitoringPanel({super.key}); @override Widget build(BuildContext context) { final theme = Theme.of(context); return Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '시스템 모니터링', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const Gap(16), _MonitoringItem( label: 'CPU 사용률', value: 0.45, displayValue: '45%', color: Colors.blue, ), const Gap(12), _MonitoringItem( label: '메모리 사용률', value: 0.62, displayValue: '62%', color: Colors.orange, ), const Gap(12), _MonitoringItem( label: '디스크 사용률', value: 0.35, displayValue: '35%', color: Colors.green, ), const Gap(12), _MonitoringItem( label: '네트워크 I/O', value: 0.78, displayValue: '78 Mbps', color: Colors.purple, ), const Gap(16), const Divider(), const Gap(12), // 서비스 상태 Text( '서비스 상태', style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, ), ), const Gap(12), const _ServiceStatus( name: 'API 서버', status: ServiceState.running, ), const _ServiceStatus( name: 'WebSocket', status: ServiceState.running, ), const _ServiceStatus( name: '데이터베이스', status: ServiceState.running, ), const _ServiceStatus( name: '캐시 서버', status: ServiceState.warning, ), ], ), ), ); } } class _MonitoringItem extends StatelessWidget { const _MonitoringItem({ required this.label, required this.value, required this.displayValue, required this.color, }); final String label; final double value; final String displayValue; final Color color; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: theme.textTheme.bodyMedium), Text( displayValue, style: theme.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w600, ), ), ], ), const Gap(6), ClipRRect( borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: value, backgroundColor: color.withValues(alpha: 0.1), valueColor: AlwaysStoppedAnimation(color), minHeight: 8, ), ), ], ); } } enum ServiceState { running, stopped, warning } class _ServiceStatus extends StatelessWidget { const _ServiceStatus({ required this.name, required this.status, }); final String name; final ServiceState status; @override Widget build(BuildContext context) { final theme = Theme.of(context); final (color, label) = switch (status) { ServiceState.running => (Colors.green, '정상'), ServiceState.stopped => (Colors.red, '중지'), ServiceState.warning => (Colors.orange, '경고'), }; return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( children: [ Container( width: 10, height: 10, decoration: BoxDecoration( color: color, shape: BoxShape.circle, ), ), const Gap(10), Expanded( child: Text(name, style: theme.textTheme.bodyMedium), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(4), ), child: Text( label, style: theme.textTheme.bodySmall?.copyWith( color: color, fontWeight: FontWeight.w600, ), ), ), ], ), ); } }