import 'package:flutter/material.dart'; import 'package:superport/screens/common/theme_shadcn.dart'; import 'package:superport/screens/common/components/shadcn_components.dart'; /// 표준 로딩 상태 위젯 class StandardLoadingState extends StatelessWidget { final String message; const StandardLoadingState({ Key? key, this.message = '데이터를 불러오는 중...', }) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator( color: ShadcnTheme.primary, strokeWidth: 3, ), const SizedBox(height: ShadcnTheme.spacing4), Text( message, style: ShadcnTheme.bodyMuted, ), ], ), ); } } /// 표준 에러 상태 위젯 class StandardErrorState extends StatelessWidget { final String title; final String? message; final VoidCallback? onRetry; final IconData icon; const StandardErrorState({ Key? key, this.title = '오류가 발생했습니다', this.message, this.onRetry, this.icon = Icons.error_outline, }) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Container( padding: const EdgeInsets.all(ShadcnTheme.spacing6), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icon, size: 64, color: ShadcnTheme.destructive.withValues(alpha: 0.8), ), const SizedBox(height: ShadcnTheme.spacing4), Text( title, style: ShadcnTheme.headingH4, textAlign: TextAlign.center, ), if (message != null) ...[ const SizedBox(height: ShadcnTheme.spacing2), Text( message!, style: ShadcnTheme.bodyMuted, textAlign: TextAlign.center, ), ], if (onRetry != null) ...[ const SizedBox(height: ShadcnTheme.spacing6), ShadcnButton( text: '다시 시도', onPressed: onRetry, variant: ShadcnButtonVariant.primary, textColor: Colors.white, icon: const Icon(Icons.refresh, size: 16), ), ], ], ), ), ); } } /// 표준 빈 상태 위젯 class StandardEmptyState extends StatelessWidget { final String title; final String? message; final Widget? action; final IconData icon; const StandardEmptyState({ Key? key, this.title = '데이터가 없습니다', this.message, this.action, this.icon = Icons.inbox_outlined, }) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Container( padding: const EdgeInsets.all(ShadcnTheme.spacing8), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icon, size: 64, color: ShadcnTheme.mutedForeground.withValues(alpha: 0.5), ), const SizedBox(height: ShadcnTheme.spacing4), Text( title, style: ShadcnTheme.headingH4.copyWith( color: ShadcnTheme.mutedForeground, ), textAlign: TextAlign.center, ), if (message != null) ...[ const SizedBox(height: ShadcnTheme.spacing2), Text( message!, style: ShadcnTheme.bodyMuted, textAlign: TextAlign.center, ), ], if (action != null) ...[ const SizedBox(height: ShadcnTheme.spacing6), action!, ], ], ), ), ); } } /// 표준 정보 메시지 위젯 class StandardInfoMessage extends StatelessWidget { final String message; final IconData icon; final Color? color; final VoidCallback? onClose; const StandardInfoMessage({ Key? key, required this.message, this.icon = Icons.info_outline, this.color, this.onClose, }) : super(key: key); @override Widget build(BuildContext context) { final displayColor = color ?? ShadcnTheme.primary; return Container( padding: const EdgeInsets.all(ShadcnTheme.spacing3), decoration: BoxDecoration( color: displayColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(ShadcnTheme.radiusMd), border: Border.all( color: displayColor.withValues(alpha: 0.3), ), ), child: Row( children: [ Icon( icon, size: 20, color: displayColor, ), const SizedBox(width: ShadcnTheme.spacing2), Expanded( child: Text( message, style: TextStyle( color: displayColor, fontSize: 14, ), ), ), if (onClose != null) IconButton( icon: Icon( Icons.close, size: 16, color: displayColor, ), onPressed: onClose, padding: EdgeInsets.zero, constraints: const BoxConstraints( maxHeight: 24, maxWidth: 24, ), ), ], ), ); } } /// 표준 통계 카드 위젯 class StandardStatCard extends StatelessWidget { final String title; final String value; final IconData icon; final Color color; final String? subtitle; const StandardStatCard({ Key? key, required this.title, required this.value, required this.icon, required this.color, this.subtitle, }) : super(key: key); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(ShadcnTheme.spacing5), decoration: BoxDecoration( color: ShadcnTheme.card, borderRadius: BorderRadius.circular(ShadcnTheme.radiusMd), border: Border.all(color: Colors.black), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(ShadcnTheme.radiusSm), ), child: Icon( icon, size: 20, color: color, ), ), const SizedBox(width: ShadcnTheme.spacing3), Expanded( child: Text( title, style: ShadcnTheme.bodySmall.copyWith( color: ShadcnTheme.mutedForeground, ), overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: ShadcnTheme.spacing3), Text( value, style: ShadcnTheme.headingH3.copyWith( color: color, fontWeight: FontWeight.bold, ), ), if (subtitle != null) ...[ const SizedBox(height: ShadcnTheme.spacing1), Text( subtitle!, style: ShadcnTheme.bodySmall.copyWith( color: ShadcnTheme.mutedForeground, ), ), ], ], ), ); } }