import 'package:flutter/material.dart'; /// Карточка статистики class StatCard extends StatelessWidget { final String title; final String value; final IconData icon; final Color? color; final VoidCallback? onTap; const StatCard({ super.key, required this.title, required this.value, required this.icon, this.color, this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, color: color ?? Colors.blue), const SizedBox(height: 12), Text( value, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: color ?? Colors.blue, ), ), const SizedBox(height: 4), Text( title, style: TextStyle( color: Colors.grey[600], fontSize: 12, ), ), ], ), ), ); } } /// Пустое состояние class EmptyState extends StatelessWidget { final IconData icon; final String title; final String subtitle; final Widget? action; const EmptyState({ super.key, required this.icon, required this.title, required this.subtitle, this.action, }); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, size: 80, color: Colors.grey[400]), const SizedBox(height: 16), Text( title, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.grey[600], ), ), const SizedBox(height: 8), Text( subtitle, textAlign: TextAlign.center, style: TextStyle(color: Colors.grey[500]), ), if (action != null) ...[ const SizedBox(height: 24), action!, ], ], ), ); } } /// Загрузочный экран class LoadingScreen extends StatelessWidget { final String? message; const LoadingScreen({super.key, this.message}); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const CircularProgressIndicator(), if (message != null) ...[ const SizedBox(height: 16), Text( message!, style: TextStyle(color: Colors.grey[600]), ), ], ], ), ); } } /// Экран ошибки class ErrorScreen extends StatelessWidget { final String message; final VoidCallback? onRetry; const ErrorScreen({ super.key, required this.message, this.onRetry, }); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 64, color: Colors.red), const SizedBox(height: 16), Text( 'Ошибка', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Text( message, textAlign: TextAlign.center, style: TextStyle(color: Colors.grey[600]), ), if (onRetry != null) ...[ const SizedBox(height: 24), ElevatedButton.icon( onPressed: onRetry, icon: const Icon(Icons.refresh), label: const Text('Повторить'), ), ], ], ), ); } }