import 'package:flutter/material.dart'; import 'package:superport/screens/common/theme_shadcn.dart'; import 'package:superport/screens/common/components/shadcn_components.dart'; import 'package:superport/screens/overview/controllers/overview_controller.dart'; import 'package:superport/services/mock_data_service.dart'; /// shadcn/ui 스타일로 재설계된 대시보드 화면 class OverviewScreenRedesign extends StatefulWidget { const OverviewScreenRedesign({Key? key}) : super(key: key); @override State createState() => _OverviewScreenRedesignState(); } class _OverviewScreenRedesignState extends State { late final OverviewController _controller; bool _isLoading = true; @override void initState() { super.initState(); _controller = OverviewController(dataService: MockDataService()); _loadData(); } Future _loadData() async { setState(() { _isLoading = true; }); await Future.delayed(const Duration(milliseconds: 800)); _controller.loadData(); setState(() { _isLoading = false; }); } @override Widget build(BuildContext context) { if (_isLoading) { return _buildLoadingState(); } return Container( color: ShadcnTheme.background, child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 환영 섹션 ShadcnCard( padding: const EdgeInsets.all(32), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('안녕하세요, 관리자님! 👋', style: ShadcnTheme.headingH3), const SizedBox(height: 8), Text( '오늘의 포트 운영 현황을 확인해보세요.', style: ShadcnTheme.bodyMuted, ), const SizedBox(height: 16), Row( children: [ ShadcnBadge( text: '실시간 모니터링', variant: ShadcnBadgeVariant.success, ), const SizedBox(width: 8), ShadcnBadge( text: '업데이트됨', variant: ShadcnBadgeVariant.outline, ), ], ), ], ), ), ], ), ), const SizedBox(height: 32), // 통계 카드 그리드 (반응형) LayoutBuilder( builder: (context, constraints) { final crossAxisCount = constraints.maxWidth > 1200 ? 4 : constraints.maxWidth > 800 ? 2 : 1; return GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: crossAxisCount, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 1.5, children: [ _buildStatCard( '총 회사 수', '${_controller.totalCompanies}', Icons.business, ShadcnTheme.gradient1, ), _buildStatCard( '총 사용자 수', '${_controller.totalUsers}', Icons.people, ShadcnTheme.gradient2, ), _buildStatCard( '입고 장비', '${_controller.totalEquipmentIn}', Icons.inventory, ShadcnTheme.success, ), _buildStatCard( '출고 장비', '${_controller.totalEquipmentOut}', Icons.local_shipping, ShadcnTheme.warning, ), ], ); }, ), const SizedBox(height: 32), // 하단 콘텐츠 LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 1000) { // 큰 화면: 가로로 배치 return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(flex: 2, child: _buildLeftColumn()), const SizedBox(width: 24), Expanded(flex: 1, child: _buildRightColumn()), ], ); } else { // 작은 화면: 세로로 배치 return Column( children: [ _buildLeftColumn(), const SizedBox(height: 24), _buildRightColumn(), ], ); } }, ), ], ), ), ); } Widget _buildLoadingState() { return Container( color: ShadcnTheme.background, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(color: ShadcnTheme.primary), const SizedBox(height: ShadcnTheme.spacing4), Text('대시보드를 불러오는 중...', style: ShadcnTheme.bodyMuted), ], ), ), ); } Widget _buildLeftColumn() { return Column( children: [ // 차트 카드 ShadcnCard( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('월별 활동 현황', style: ShadcnTheme.headingH4), Text('최근 6개월 데이터', style: ShadcnTheme.bodyMuted), ], ), ShadcnButton( text: '상세보기', onPressed: () {}, variant: ShadcnButtonVariant.ghost, size: ShadcnButtonSize.small, ), ], ), const SizedBox(height: 24), Container( height: 200, decoration: BoxDecoration( color: ShadcnTheme.muted, borderRadius: BorderRadius.circular(8), ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.analytics, size: 48, color: ShadcnTheme.mutedForeground, ), const SizedBox(height: 12), Text('차트 영역', style: ShadcnTheme.bodyMuted), Text( 'fl_chart 라이브러리로 구현 예정', style: ShadcnTheme.bodySmall, ), ], ), ), ), ], ), ), const SizedBox(height: 24), // 최근 활동 ShadcnCard( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('최근 활동', style: ShadcnTheme.headingH4), ShadcnButton( text: '전체보기', onPressed: () {}, variant: ShadcnButtonVariant.ghost, size: ShadcnButtonSize.small, ), ], ), const SizedBox(height: 16), ...List.generate(5, (index) => _buildActivityItem(index)), ], ), ), ], ); } Widget _buildRightColumn() { return Column( children: [ // 빠른 작업 ShadcnCard( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('빠른 작업', style: ShadcnTheme.headingH4), const SizedBox(height: 16), _buildQuickActionButton(Icons.add_box, '장비 입고', '새 장비 등록'), const SizedBox(height: 12), _buildQuickActionButton( Icons.local_shipping, '장비 출고', '장비 대여 처리', ), const SizedBox(height: 12), _buildQuickActionButton( Icons.business_center, '회사 등록', '새 회사 추가', ), ], ), ), const SizedBox(height: 24), // 시스템 상태 ShadcnCard( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('시스템 상태', style: ShadcnTheme.headingH4), const SizedBox(height: 16), _buildStatusItem('서버 상태', '정상'), _buildStatusItem('데이터베이스', '정상'), _buildStatusItem('네트워크', '정상'), _buildStatusItem('백업', '완료'), ], ), ), ], ); } Widget _buildStatCard( String title, String value, IconData icon, Color color, ) { return ShadcnCard( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(6), ), child: Icon(icon, color: color, size: 20), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: ShadcnTheme.success.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.trending_up, size: 12, color: ShadcnTheme.success, ), const SizedBox(width: 4), Text( '+2.3%', style: ShadcnTheme.labelSmall.copyWith( color: ShadcnTheme.success, ), ), ], ), ), ], ), const SizedBox(height: 16), Text(value, style: ShadcnTheme.headingH2), const SizedBox(height: 4), Text(title, style: ShadcnTheme.bodyMedium), Text('등록된 항목', style: ShadcnTheme.bodySmall), ], ), ); } Widget _buildActivityItem(int index) { final activities = [ { 'icon': Icons.inventory, 'title': '장비 입고 처리', 'subtitle': '크레인 #CR-001 입고 완료', 'time': '2분 전', }, { 'icon': Icons.local_shipping, 'title': '장비 출고 처리', 'subtitle': '포클레인 #FK-005 출고 완료', 'time': '5분 전', }, { 'icon': Icons.business, 'title': '회사 등록', 'subtitle': '새로운 회사 "ABC건설" 등록', 'time': '10분 전', }, { 'icon': Icons.person_add, 'title': '사용자 추가', 'subtitle': '신규 사용자 계정 생성', 'time': '15분 전', }, { 'icon': Icons.settings, 'title': '시스템 점검', 'subtitle': '정기 시스템 점검 완료', 'time': '30분 전', }, ]; final activity = activities[index]; return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: ShadcnTheme.success.withOpacity(0.1), borderRadius: BorderRadius.circular(6), ), child: Icon( activity['icon'] as IconData, color: ShadcnTheme.success, size: 16, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( activity['title'] as String, style: ShadcnTheme.bodyMedium, ), Text( activity['subtitle'] as String, style: ShadcnTheme.bodySmall, ), ], ), ), Text(activity['time'] as String, style: ShadcnTheme.bodySmall), ], ), ); } Widget _buildQuickActionButton(IconData icon, String title, String subtitle) { return GestureDetector( onTap: () { // 실제 기능 구현 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('$title 기능은 개발 중입니다.'), backgroundColor: ShadcnTheme.info, ), ); }, child: Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: ShadcnTheme.border), borderRadius: BorderRadius.circular(6), ), child: Row( children: [ Icon(icon, color: ShadcnTheme.primary), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: ShadcnTheme.bodyMedium), Text(subtitle, style: ShadcnTheme.bodySmall), ], ), ), Icon( Icons.arrow_forward_ios, size: 16, color: ShadcnTheme.mutedForeground, ), ], ), ), ); } Widget _buildStatusItem(String label, String status) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: ShadcnTheme.bodyMedium), ShadcnBadge( text: status, variant: ShadcnBadgeVariant.success, size: ShadcnBadgeSize.small, ), ], ), ); } }