import 'package:flutter/material.dart'; import 'package:playmaker/classe/home.config.dart'; import 'package:playmaker/grafico%20de%20pizza/grafico.dart'; import 'package:playmaker/pages/gamePage.dart'; import 'package:playmaker/pages/teamPage.dart'; import 'package:playmaker/controllers/team_controller.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'dart:math' as math; import 'package:playmaker/grafico%20de%20pizza/controllers/contollers_grafico.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { int _selectedIndex = 0; final TeamController _teamController = TeamController(); String? _selectedTeamId; String _selectedTeamName = "Selecionar Equipa"; int _teamWins = 0; int _teamLosses = 0; int _teamDraws = 0; final _supabase = Supabase.instance.client; @override Widget build(BuildContext context) { final double wScreen = MediaQuery.of(context).size.width; final double hScreen = MediaQuery.of(context).size.height; final double sf = math.min(wScreen, hScreen) / 400; final List pages = [ _buildHomeContent(sf, wScreen), const GamePage(), const TeamsPage(), const Center(child: Text('Tela de Status')), ]; return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: Text('PlayMaker', style: TextStyle(fontSize: 20 * sf)), backgroundColor: HomeConfig.primaryColor, foregroundColor: Colors.white, leading: IconButton( icon: Icon(Icons.person, size: 24 * sf), onPressed: () {}, ), ), body: IndexedStack( index: _selectedIndex, children: pages, ), bottomNavigationBar: NavigationBar( selectedIndex: _selectedIndex, onDestinationSelected: (index) => setState(() => _selectedIndex = index), backgroundColor: Theme.of(context).colorScheme.surface, surfaceTintColor: Theme.of(context).colorScheme.surfaceTint, elevation: 1, height: 70 * math.min(sf, 1.2), destinations: const [ NavigationDestination(icon: Icon(Icons.home_outlined), selectedIcon: Icon(Icons.home_filled), label: 'Home'), NavigationDestination(icon: Icon(Icons.sports_soccer_outlined), selectedIcon: Icon(Icons.sports_soccer), label: 'Jogo'), NavigationDestination(icon: Icon(Icons.people_outline), selectedIcon: Icon(Icons.people), label: 'Equipas'), NavigationDestination(icon: Icon(Icons.insights_outlined), selectedIcon: Icon(Icons.insights), label: 'Status'), ], ), ); } void _showTeamSelector(BuildContext context, double sf) { showModalBottomSheet( context: context, shape: RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20 * sf))), builder: (context) { return StreamBuilder>>( stream: _teamController.teamsStream, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator())); if (!snapshot.hasData || snapshot.data!.isEmpty) return SizedBox(height: 200 * sf, child: const Center(child: Text("Nenhuma equipa criada."))); final teams = snapshot.data!; return ListView.builder( shrinkWrap: true, itemCount: teams.length, itemBuilder: (context, index) { final team = teams[index]; return ListTile( title: Text(team['name']), onTap: () { setState(() { _selectedTeamId = team['id']; _selectedTeamName = team['name']; _teamWins = team['wins'] != null ? int.tryParse(team['wins'].toString()) ?? 0 : 0; _teamLosses = team['losses'] != null ? int.tryParse(team['losses'].toString()) ?? 0 : 0; _teamDraws = team['draws'] != null ? int.tryParse(team['draws'].toString()) ?? 0 : 0; }); Navigator.pop(context); }, ); }, ); }, ); }, ); } Widget _buildHomeContent(double sf, double wScreen) { final double cardHeight = (wScreen / 2) * 1.0; return StreamBuilder>>( stream: _selectedTeamId != null ? _supabase.from('player_stats_with_names').stream(primaryKey: ['id']).eq('team_id', _selectedTeamId!) : const Stream.empty(), builder: (context, snapshot) { Map leaders = _calculateLeaders(snapshot.data ?? []); return SingleChildScrollView( child: Padding( padding: EdgeInsets.symmetric(horizontal: 22.0 * sf, vertical: 16.0 * sf), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ InkWell( onTap: () => _showTeamSelector(context, sf), child: Container( padding: EdgeInsets.all(12 * sf), decoration: BoxDecoration(color: Colors.grey.shade100, borderRadius: BorderRadius.circular(15 * sf), border: Border.all(color: Colors.grey.shade300)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row(children: [Icon(Icons.shield, color: HomeConfig.primaryColor, size: 24 * sf), SizedBox(width: 10 * sf), Text(_selectedTeamName, style: TextStyle(fontSize: 16 * sf, fontWeight: FontWeight.bold))]), const Icon(Icons.arrow_drop_down), ], ), ), ), SizedBox(height: 20 * sf), SizedBox( height: cardHeight, child: Row( children: [ Expanded(child: _buildStatCard(title: 'Mais Pontos', playerName: leaders['pts_name'], statValue: leaders['pts_val'].toString(), statLabel: 'TOTAL', color: const Color(0xFF1565C0), isHighlighted: true)), SizedBox(width: 12 * sf), Expanded(child: _buildStatCard(title: 'Assistências', playerName: leaders['ast_name'], statValue: leaders['ast_val'].toString(), statLabel: 'TOTAL', color: const Color(0xFF2E7D32))), ], ), ), SizedBox(height: 12 * sf), SizedBox( height: cardHeight, child: Row( children: [ Expanded(child: _buildStatCard(title: 'Rebotes', playerName: leaders['rbs_name'], statValue: leaders['rbs_val'].toString(), statLabel: 'TOTAL', color: const Color(0xFF6A1B9A))), SizedBox(width: 12 * sf), Expanded( child: PieChartCard( victories: _teamWins, defeats: _teamLosses, draws: _teamDraws, title: 'DESEMPENHO', subtitle: 'Temporada', backgroundColor: const Color(0xFFC62828), sf: sf ), ), ], ), ), SizedBox(height: 40 * sf), Text('Histórico de Jogos', style: TextStyle(fontSize: 20 * sf, fontWeight: FontWeight.bold, color: Colors.grey[800])), SizedBox(height: 16 * sf), // 👇 MAGIA ACONTECE AQUI: Ligação à Base de Dados para os Jogos 👇 _selectedTeamId == null ? Container( padding: EdgeInsets.all(20 * sf), alignment: Alignment.center, child: Text("Seleciona uma equipa para ver os jogos.", style: TextStyle(color: Colors.grey, fontSize: 14 * sf)), ) : StreamBuilder>>( // ⚠️ ATENÇÃO: Substitui 'games' pelo nome real da tua tabela de jogos na Supabase stream: _supabase.from('games').stream(primaryKey: ['id']) .eq('team_id', _selectedTeamId!) // ⚠️ ATENÇÃO: Substitui 'date' pelo nome da coluna da data do jogo .order('date', ascending: false) .limit(3), // Mostra só os 3 últimos jogos builder: (context, gameSnapshot) { if (gameSnapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (!gameSnapshot.hasData || gameSnapshot.data!.isEmpty) { return Container( padding: EdgeInsets.all(20 * sf), decoration: BoxDecoration(color: Colors.grey.shade50, borderRadius: BorderRadius.circular(14)), alignment: Alignment.center, child: Column( children: [ Icon(Icons.sports_basketball, size: 40 * sf, color: Colors.grey.shade300), SizedBox(height: 10 * sf), Text("Ainda não há jogos registados.", style: TextStyle(color: Colors.grey.shade600, fontSize: 14 * sf, fontWeight: FontWeight.bold)), ], ), ); } final gamesList = gameSnapshot.data!; return Column( children: gamesList.map((game) { // ⚠️ ATENÇÃO: Confirma se os nomes entre parênteses retos [ ] // batem certo com as tuas colunas na tabela Supabase! String opponent = game['opponent_name']?.toString() ?? 'Adversário'; int myScore = game['my_score'] != null ? int.tryParse(game['my_score'].toString()) ?? 0 : 0; int oppScore = game['opponent_score'] != null ? int.tryParse(game['opponent_score'].toString()) ?? 0 : 0; String date = game['date']?.toString() ?? 'Sem Data'; // Calcula Vitória (V), Derrota (D) ou Empate (E) automaticamente String result = 'E'; if (myScore > oppScore) result = 'V'; if (myScore < oppScore) result = 'D'; // ⚠️ Destaques da Partida. Se ainda não tiveres estas colunas na tabela 'games', // podes deixar assim e ele mostra '---' sem dar erro. String topPts = game['top_pts']?.toString() ?? '---'; String topAst = game['top_ast']?.toString() ?? '---'; String topRbs = game['top_rbs']?.toString() ?? '---'; String topDef = game['top_def']?.toString() ?? '---'; String mvp = game['mvp']?.toString() ?? '---'; return _buildGameHistoryCard( opponent: opponent, result: result, myScore: myScore, oppScore: oppScore, date: date, sf: sf, topPts: topPts, topAst: topAst, topRbs: topRbs, topDef: topDef, mvp: mvp ); }).toList(), ); }, ), SizedBox(height: 20 * sf), ], ), ), ); }, ); } Map _calculateLeaders(List> data) { Map ptsMap = {}; Map astMap = {}; Map rbsMap = {}; Map namesMap = {}; for (var row in data) { String pid = row['member_id'].toString(); namesMap[pid] = row['player_name']?.toString() ?? "Desconhecido"; ptsMap[pid] = (ptsMap[pid] ?? 0) + (row['pts'] as int? ?? 0); astMap[pid] = (astMap[pid] ?? 0) + (row['ast'] as int? ?? 0); rbsMap[pid] = (rbsMap[pid] ?? 0) + (row['rbs'] as int? ?? 0); } if (ptsMap.isEmpty) return {'pts_name': '---', 'pts_val': 0, 'ast_name': '---', 'ast_val': 0, 'rbs_name': '---', 'rbs_val': 0}; String getBest(Map map) { var bestId = map.entries.reduce((a, b) => a.value > b.value ? a : b).key; return namesMap[bestId]!; } int getBestVal(Map map) => map.values.reduce((a, b) => a > b ? a : b); return {'pts_name': getBest(ptsMap), 'pts_val': getBestVal(ptsMap), 'ast_name': getBest(astMap), 'ast_val': getBestVal(astMap), 'rbs_name': getBest(rbsMap), 'rbs_val': getBestVal(rbsMap)}; } Widget _buildStatCard({required String title, required String playerName, required String statValue, required String statLabel, required Color color, bool isHighlighted = false}) { return Card( elevation: 4, margin: EdgeInsets.zero, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14), side: isHighlighted ? const BorderSide(color: Colors.amber, width: 2) : BorderSide.none), child: Container( decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [color.withOpacity(0.9), color])), child: LayoutBuilder( builder: (context, constraints) { final double ch = constraints.maxHeight; final double cw = constraints.maxWidth; return Padding( padding: EdgeInsets.all(cw * 0.06), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title.toUpperCase(), style: TextStyle(fontSize: ch * 0.06, fontWeight: FontWeight.bold, color: Colors.white70), maxLines: 1, overflow: TextOverflow.ellipsis), SizedBox(height: ch * 0.011), SizedBox( width: double.infinity, child: FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(playerName, style: TextStyle(fontSize: ch * 0.08, fontWeight: FontWeight.bold, color: Colors.white)), ), ), const Spacer(), Center(child: FittedBox(fit: BoxFit.scaleDown, child: Text(statValue, style: TextStyle(fontSize: ch * 0.18, fontWeight: FontWeight.bold, color: Colors.white, height: 1.0)))), SizedBox(height: ch * 0.015), Center(child: Text(statLabel, style: TextStyle(fontSize: ch * 0.05, color: Colors.white70))), const Spacer(), Container( width: double.infinity, padding: EdgeInsets.symmetric(vertical: ch * 0.035), decoration: BoxDecoration(color: Colors.white24, borderRadius: BorderRadius.circular(ch * 0.03)), child: Center(child: Text('DETALHES', style: TextStyle(color: Colors.white, fontSize: ch * 0.05, fontWeight: FontWeight.bold))) ), ], ), ); } ), ), ); } Widget _buildGameHistoryCard({ required String opponent, required String result, required int myScore, required int oppScore, required String date, required double sf, required String topPts, required String topAst, required String topRbs, required String topDef, required String mvp }) { bool isWin = result == 'V'; bool isDraw = result == 'E'; Color statusColor = isWin ? Colors.green : (isDraw ? Colors.yellow.shade700 : Colors.red); return Container( margin: EdgeInsets.only(bottom: 14 * sf), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey.shade200), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.04), blurRadius: 8, offset: const Offset(0, 4))], ), child: Column( children: [ Padding( padding: EdgeInsets.all(14 * sf), child: Row( children: [ Container( width: 36 * sf, height: 36 * sf, decoration: BoxDecoration(color: statusColor.withOpacity(0.15), shape: BoxShape.circle), child: Center(child: Text(result, style: TextStyle(color: statusColor, fontWeight: FontWeight.bold, fontSize: 16 * sf))), ), SizedBox(width: 14 * sf), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(date, style: TextStyle(fontSize: 11 * sf, color: Colors.grey, fontWeight: FontWeight.w600)), SizedBox(height: 6 * sf), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(child: Text(_selectedTeamName == "Selecionar Equipa" ? "Minha Equipa" : _selectedTeamName, style: TextStyle(fontSize: 14 * sf, fontWeight: FontWeight.bold), maxLines: 1, overflow: TextOverflow.ellipsis)), Padding( padding: EdgeInsets.symmetric(horizontal: 8 * sf), child: Container( padding: EdgeInsets.symmetric(horizontal: 8 * sf, vertical: 4 * sf), decoration: BoxDecoration(color: Colors.grey.shade100, borderRadius: BorderRadius.circular(8)), child: Text('$myScore - $oppScore', style: TextStyle(fontSize: 15 * sf, fontWeight: FontWeight.w900, letterSpacing: 1.5, color: Colors.black87)), ), ), Expanded(child: Text(opponent, style: TextStyle(fontSize: 14 * sf, fontWeight: FontWeight.bold), textAlign: TextAlign.right, maxLines: 1, overflow: TextOverflow.ellipsis)), ], ), ], ), ), ], ), ), Divider(height: 1, color: Colors.grey.shade100, thickness: 1.5), Container( width: double.infinity, padding: EdgeInsets.symmetric(horizontal: 16 * sf, vertical: 12 * sf), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(16), bottomRight: Radius.circular(16)), ), child: Column( children: [ Row( children: [ Expanded(child: _buildGridStatRow(Icons.workspace_premium, Colors.amber.shade700, "MVP", mvp, sf, isMvp: true)), Expanded(child: _buildGridStatRow(Icons.shield, Colors.deepOrange.shade700, "Defesa", topDef, sf)), ], ), SizedBox(height: 8 * sf), Row( children: [ Expanded(child: _buildGridStatRow(Icons.bolt, Colors.blue.shade700, "Pontos", topPts, sf)), Expanded(child: _buildGridStatRow(Icons.trending_up, Colors.purple.shade700, "Rebotes", topRbs, sf)), ], ), SizedBox(height: 8 * sf), Row( children: [ Expanded(child: _buildGridStatRow(Icons.star, Colors.green.shade700, "Assists", topAst, sf)), const Expanded(child: SizedBox()), ], ), ], ), ) ], ), ); } Widget _buildGridStatRow(IconData icon, Color color, String label, String value, double sf, {bool isMvp = false}) { return Row( children: [ Icon(icon, size: 14 * sf, color: color), SizedBox(width: 4 * sf), Text('$label: ', style: TextStyle(fontSize: 11 * sf, color: Colors.grey.shade600, fontWeight: FontWeight.bold)), Expanded( child: Text( value, style: TextStyle( fontSize: 11 * sf, color: isMvp ? Colors.amber.shade900 : Colors.black87, fontWeight: FontWeight.bold ), maxLines: 1, overflow: TextOverflow.ellipsis ) ), ], ); } }