diff --git a/assets/campo.png b/assets/campo.png new file mode 100644 index 0000000..0a226fa Binary files /dev/null and b/assets/campo.png differ diff --git a/lib/pages/PlacarPage.dart b/lib/pages/PlacarPage.dart index 0c29afd..8fa5c9e 100644 --- a/lib/pages/PlacarPage.dart +++ b/lib/pages/PlacarPage.dart @@ -1,18 +1,10 @@ -import 'dart:async'; +/*import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class PlacarPage extends StatefulWidget { - final String gameId; - final String myTeam; - final String opponentTeam; - - const PlacarPage({ - super.key, - required this.gameId, - required this.myTeam, - required this.opponentTeam, - }); + final String gameId, myTeam, opponentTeam; + const PlacarPage({super.key, required this.gameId, required this.myTeam, required this.opponentTeam}); @override State createState() => _PlacarPageState(); @@ -21,7 +13,10 @@ class PlacarPage extends StatefulWidget { class _PlacarPageState extends State { int _myScore = 0; int _opponentScore = 0; - + int _myFouls = 0; + int _opponentFouls = 0; + int _currentQuarter = 1; + Duration _duration = const Duration(minutes: 10); Timer? _timer; bool _isRunning = false; @@ -29,7 +24,6 @@ class _PlacarPageState extends State { @override void initState() { super.initState(); - // Força a tela na horizontal SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft, @@ -41,95 +35,71 @@ class _PlacarPageState extends State { _timer?.cancel(); } else { _timer = Timer.periodic(const Duration(seconds: 1), (timer) { - if (_duration.inSeconds > 0) { - setState(() => _duration -= const Duration(seconds: 1)); - } else { - _timer?.cancel(); - setState(() => _isRunning = false); - } + setState(() { + if (_duration.inSeconds > 0) { + _duration -= const Duration(seconds: 1); + } else { + _timer?.cancel(); + _isRunning = false; + } + }); }); } setState(() => _isRunning = !_isRunning); } - String _formatTime(Duration d) { - return "${d.inMinutes.toString().padLeft(2, '0')}:${d.inSeconds.remainder(60).toString().padLeft(2, '0')}"; - } + String _formatTime(Duration d) => + "${d.inMinutes.toString().padLeft(2, '0')}:${d.inSeconds.remainder(60).toString().padLeft(2, '0')}"; @override void dispose() { _timer?.cancel(); - // Restaura a vertical ao sair - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); super.dispose(); } @override Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + final screenHeight = MediaQuery.of(context).size.height; + return Scaffold( body: Stack( children: [ - // 1. FUNDO (O CAMPO DE BASQUETEBOL) + // Fundo do Campo Container( - width: double.infinity, - height: double.infinity, decoration: const BoxDecoration( - color: Color(0xFFD2B48C), // Cor de madeira temporária - // TODO: Descomenta a linha abaixo e usa a tua imagem do campo - // image: DecorationImage(image: AssetImage('assets/court.png'), fit: BoxFit.cover), - ), - // Linhas do campo desenhadas por cima (Opcional se usares imagem real) - child: const CustomPaint(painter: CourtPainterPlaceholder()), - ), - - // 2. BARRA SUPERIOR (PLACARD) - Positioned( - top: 0, - left: 0, - right: 0, - child: _buildTopScoreboard(), - ), - - // 3. JOGADORES NO CAMPO (Posições manuais usando Positioned) - // Exemplo de como posicionar os teus jogadores - Positioned(top: 120, left: 100, child: _buildPlayerCard("6", "LeBron James")), - Positioned(top: 250, left: 160, child: _buildPlayerCard("3", "Anthony Davis")), - Positioned(top: 320, left: 280, child: _buildPlayerCard("28", "Rui Hachimura")), - Positioned(top: 380, left: 160, child: _buildPlayerCard("1", "D'Angelo Russell")), - Positioned(top: 500, left: 100, child: _buildPlayerCard("15", "Austin Reaves")), - - // 4. BOTÃO CENTRAL (PLAY/PAUSE) - Center( - child: GestureDetector( - onTap: _toggleTimer, - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color(0xFF2662D9).withOpacity(0.8), - border: Border.all(color: Colors.blueAccent.withOpacity(0.5), width: 8), - ), - padding: const EdgeInsets.all(16), - child: Icon( - _isRunning ? Icons.pause : Icons.play_arrow, - color: Colors.white, - size: 40, - ), + image: DecorationImage( + image: AssetImage('assets/campo.png'), + fit: BoxFit.cover, + alignment: Alignment(0.0, 0.2), ), ), ), - // 5. PAINEL DE ACÇÕES EM BAIXO (Estatísticas: 1pt, 2pt, 3pt) - Positioned( - bottom: 20, - left: 0, - right: 0, - child: _buildActionButtonsPanel(), + // Posicionamento Tático (Jogadores como DragTargets) + ..._buildTacticalFormation(screenWidth, screenHeight), + + // Botão Central Play/Pause + Center( + child: GestureDetector( + onTap: _toggleTimer, + child: CircleAvatar( + radius: 35, + backgroundColor: Colors.white, + child: Icon(_isRunning ? Icons.pause : Icons.play_arrow, + color: const Color(0xFF1E2A38), size: 40), + ), + ), ), - // 6. BOTÃO DE FECHAR / GUARDAR NO CANTO + // Placard Superior + Positioned(top: 0, left: 0, right: 0, child: Center(child: _buildTopScoreboard())), + + // Painel de Ações Inferior (Botões de pontos como Draggables) + Positioned(bottom: 20, left: 0, right: 0, child: _buildActionButtonsPanel()), + + // Botão Fechar Positioned( bottom: 20, right: 20, @@ -145,119 +115,497 @@ class _PlacarPageState extends State { ); } - // --- WIDGETS AUXILIARES PARA LIMPAR O CÓDIGO --- + List _buildTacticalFormation(double w, double h) { + return [ + // CASA (Azul) + Positioned(top: h * 0.25, left: w * 0.02, child: _buildPlayerCard("1", "Russell", false)), + Positioned(top: h * 0.68, left: w * 0.02, child: _buildPlayerCard("15", "Reaves", false)), + Positioned(top: h * 0.48, left: w * 0.20, child: _buildPlayerCard("3", "Davis", false)), + Positioned(top: h * 0.15, left: w * 0.20, child: _buildPlayerCard("6", "James", false)), + Positioned(top: h * 0.80, left: w * 0.20, child: _buildPlayerCard("28", "Hachimura", false)), + + // VISITANTE (Vermelho) + Positioned(top: h * 0.25, right: w * 0.02, child: _buildPlayerCard("7", "Kyle", true)), + Positioned(top: h * 0.68, right: w * 0.02, child: _buildPlayerCard("9", "Serge", true)), + Positioned(top: h * 0.48, right: w * 0.20, child: _buildPlayerCard("2", "Kawhi", true)), + Positioned(top: h * 0.15, right: w * 0.20, child: _buildPlayerCard("14", "Danny", true)), + Positioned(top: h * 0.80, right: w * 0.20, child: _buildPlayerCard("23", "Fred", true)), + ]; + } + + // JOGADOR COMO DRAG TARGET (Recebe os pontos) + Widget _buildPlayerCard(String number, String name, bool isOpponent) { + final teamColor = isOpponent ? const Color(0xFFD92C2C) : const Color(0xFF1E5BB2); + + return DragTarget( + onWillAcceptWithDetails: (details) => true, + onAcceptWithDetails: (details) { + setState(() { + if (isOpponent) { + _opponentScore += details.data; + } else { + _myScore += details.data; + } + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("$name marcou ${details.data} pontos!"), duration: const Duration(seconds: 1)), + ); + }, + builder: (context, candidateData, rejectedData) { + return AnimatedContainer( + duration: const Duration(milliseconds: 200), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + decoration: BoxDecoration( + color: candidateData.isNotEmpty ? Colors.yellow.shade100 : Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: candidateData.isNotEmpty ? Colors.orange : Colors.transparent, + width: 2, + ), + boxShadow: const [BoxShadow(color: Colors.black26, blurRadius: 6, offset: Offset(0, 3))], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40, height: 40, + decoration: BoxDecoration(color: teamColor, borderRadius: BorderRadius.circular(8)), + alignment: Alignment.center, + child: Text(number, style: const TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold)), + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(name, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87)), + const Text("0 Pts | 0 Rbs | 0 Ast", style: TextStyle(fontSize: 12, color: Colors.grey)), + ], + ), + ], + ), + ); + }, + ); + } Widget _buildTopScoreboard() { return Container( - color: const Color(0xFF1E2A38), // Azul Escuro da barra - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - child: SafeArea( - bottom: false, - child: Row( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 30), + decoration: BoxDecoration( + color: const Color(0xFF16202C), + borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(15), bottomRight: Radius.circular(15)), + border: Border.all(color: Colors.white, width: 2), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _buildTeamSection(widget.myTeam, _myScore, _myFouls, const Color(0xFF1E5BB2), false), + const SizedBox(width: 25), + Column( + children: [ + _timeDisplay(), + const SizedBox(height: 5), + Text("PERÍODO $_currentQuarter", style: const TextStyle(color: Colors.orangeAccent, fontSize: 14, fontWeight: FontWeight.bold)), + ], + ), + const SizedBox(width: 25), + _buildTeamSection(widget.opponentTeam, _opponentScore, _opponentFouls, const Color(0xFFD92C2C), true), + ], + ), + ); + } + + Widget _buildTeamSection(String name, int score, int fouls, Color color, bool isOpponent) { + final info = Column( + children: [ + _scoreBox(score, color), + Text("FALTAS: $fouls", style: const TextStyle(color: Colors.yellowAccent, fontSize: 12)), + ], + ); + final teamName = Text(name.toUpperCase(), style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)); + + return Row( + children: isOpponent ? [info, const SizedBox(width: 15), teamName] : [teamName, const SizedBox(width: 15), info], + ); + } + + Widget _timeDisplay() => Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5), + decoration: BoxDecoration(color: const Color(0xFF2C3E50), borderRadius: BorderRadius.circular(5)), + child: Text(_formatTime(_duration), style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, fontFamily: 'monospace')), + ); + + Widget _scoreBox(int score, Color color) => Container( + width: 55, height: 45, + alignment: Alignment.center, + decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(8)), + child: Text(score.toString(), style: const TextStyle(color: Colors.white, fontSize: 26, fontWeight: FontWeight.bold)), + ); + + // PAINEL DE AÇÕES (Botões de pontos são DRAGGABLE) + Widget _buildActionButtonsPanel() { + return Column( + children: [ + Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - // Equipa Casa - Text(widget.myTeam.toUpperCase(), style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), - const SizedBox(width: 15), - _scoreBox(_myScore, const Color(0xFF2662D9)), // Azul - - const SizedBox(width: 20), - - // Relógio - Container( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), - decoration: BoxDecoration(color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(8)), - child: Text( - _formatTime(_duration), - style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, fontFamily: 'monospace'), + _draggableActionBtn("1", Colors.orange, 1), + _draggableActionBtn("2", Colors.orange, 2), + _draggableActionBtn("3", Colors.orange, 3), + _simpleActionBtn(null, const Color(0xFF1E2A38), Icons.shopping_basket), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _simpleActionBtn("1", Colors.orange, null, isX: true), + _simpleActionBtn("2", Colors.orange, null, isX: true), + _simpleActionBtn("3", Colors.orange, null, isX: true), + _simpleActionBtn(null, const Color(0xFF1E2A38), Icons.shield), + ], + ), + ], + ); + } + + // BOTÃO ARRASTÁVEL (PONTOS) + Widget _draggableActionBtn(String label, Color color, int points) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 6), + child: Draggable( + data: points, + feedback: _buildCircleContent(label, color, null, true), // O que voa com o dedo + childWhenDragging: Opacity(opacity: 0.3, child: _buildCircleContent(label, color, null, false)), + child: _buildCircleContent(label, color, null, false), + ), + ); + } + + // BOTÃO SIMPLES (REBOTES/DEFESA) + Widget _simpleActionBtn(String? label, Color color, IconData? icon, {bool isX = false}) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 6), + child: Stack( + alignment: Alignment.bottomRight, + children: [ + _buildCircleContent(label, color, icon, false), + if (isX) const Icon(Icons.cancel, color: Colors.red, size: 25), + ], + ), + ); + } + + Widget _buildCircleContent(String? label, Color color, IconData? icon, bool isFeedback) { + return Container( + width: isFeedback ? 70 : 60, + height: isFeedback ? 70 : 60, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + boxShadow: const [BoxShadow(color: Colors.black26, blurRadius: 4)], + ), + alignment: Alignment.center, + child: icon != null + ? Icon(icon, color: Colors.white, size: 35) + : Text(label!, style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, decoration: TextDecoration.none)), + ); + } +}*/import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class PlacarPage extends StatefulWidget { + final String gameId, myTeam, opponentTeam; + const PlacarPage({super.key, required this.gameId, required this.myTeam, required this.opponentTeam}); + + @override + State createState() => _PlacarPageState(); +} + +class _PlacarPageState extends State { + int _myScore = 0; + int _opponentScore = 0; + int _myFouls = 0; + int _opponentFouls = 0; + int _currentQuarter = 1; + + // MAPA PARA GUARDAR ESTATÍSTICAS INDIVIDUAIS (Key: Nome do Jogador) + final Map> _playerStats = { + "Russell": {"pts": 0, "rbs": 0, "ast": 0}, + "Reaves": {"pts": 0, "rbs": 0, "ast": 0}, + "Davis": {"pts": 0, "rbs": 0, "ast": 0}, + "James": {"pts": 0, "rbs": 0, "ast": 0}, + "Hachimura": {"pts": 0, "rbs": 0, "ast": 0}, + "Kyle": {"pts": 0, "rbs": 0, "ast": 0}, + "Serge": {"pts": 0, "rbs": 0, "ast": 0}, + "Kawhi": {"pts": 0, "rbs": 0, "ast": 0}, + "Danny": {"pts": 0, "rbs": 0, "ast": 0}, + "Fred": {"pts": 0, "rbs": 0, "ast": 0}, + }; + + Duration _duration = const Duration(minutes: 10); + Timer? _timer; + bool _isRunning = false; + + @override + void initState() { + super.initState(); + SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft]); + } + + void _toggleTimer() { + if (_isRunning) { + _timer?.cancel(); + } else { + _timer = Timer.periodic(const Duration(seconds: 1), (timer) { + setState(() { + if (_duration.inSeconds > 0) { + _duration -= const Duration(seconds: 1); + } else { + _timer?.cancel(); + _isRunning = false; + } + }); + }); + } + setState(() => _isRunning = !_isRunning); + } + + String _formatTime(Duration d) => + "${d.inMinutes.toString().padLeft(2, '0')}:${d.inSeconds.remainder(60).toString().padLeft(2, '0')}"; + + @override + void dispose() { + _timer?.cancel(); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + final screenHeight = MediaQuery.of(context).size.height; + + return Scaffold( + body: Stack( + children: [ + Container( + decoration: const BoxDecoration( + image: DecorationImage(image: AssetImage('assets/campo.png'), fit: BoxFit.cover, alignment: Alignment(0.0, 0.2)), + ), + ), + + ..._buildTacticalFormation(screenWidth, screenHeight), + + Center( + child: GestureDetector( + onTap: _toggleTimer, + child: CircleAvatar( + radius: 35, + backgroundColor: Colors.white, + child: Icon(_isRunning ? Icons.pause : Icons.play_arrow, color: const Color(0xFF1E2A38), size: 40), ), ), - - const SizedBox(width: 20), - - // Equipa Visitante - _scoreBox(_opponentScore, const Color(0xFFE74C3C)), // Vermelho - const SizedBox(width: 15), - Text(widget.opponentTeam.toUpperCase(), style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), + ), + + Positioned(top: 0, left: 0, right: 0, child: Center(child: _buildTopScoreboard())), + Positioned(bottom: 20, left: 0, right: 0, child: _buildActionButtonsPanel()), + + Positioned( + bottom: 20, right: 20, + child: FloatingActionButton( + backgroundColor: const Color(0xFF1E2A38), + mini: true, + onPressed: () => Navigator.pop(context), + child: const Icon(Icons.close, color: Colors.white), + ), + ), + ], + ), + ); + } + + List _buildTacticalFormation(double w, double h) { + return [ + // CASA + Positioned(top: h * 0.25, left: w * 0.02, child: _buildPlayerCard("1", "Russell", false)), + Positioned(top: h * 0.68, left: w * 0.02, child: _buildPlayerCard("15", "Reaves", false)), + Positioned(top: h * 0.48, left: w * 0.20, child: _buildPlayerCard("3", "Davis", false)), + Positioned(top: h * 0.15, left: w * 0.20, child: _buildPlayerCard("6", "James", false)), + Positioned(top: h * 0.80, left: w * 0.20, child: _buildPlayerCard("28", "Hachimura", false)), + + // VISITANTE + Positioned(top: h * 0.25, right: w * 0.02, child: _buildPlayerCard("7", "Kyle", true)), + Positioned(top: h * 0.68, right: w * 0.02, child: _buildPlayerCard("9", "Serge", true)), + Positioned(top: h * 0.48, right: w * 0.20, child: _buildPlayerCard("2", "Kawhi", true)), + Positioned(top: h * 0.15, right: w * 0.20, child: _buildPlayerCard("14", "Danny", true)), + Positioned(top: h * 0.80, right: w * 0.20, child: _buildPlayerCard("23", "Fred", true)), + ]; + } + + Widget _buildPlayerCard(String number, String name, bool isOpponent) { + final teamColor = isOpponent ? const Color(0xFFD92C2C) : const Color(0xFF1E5BB2); + final stats = _playerStats[name]!; + + return DragTarget( + onAcceptWithDetails: (details) { + setState(() { + // Atualiza Placard Geral + if (isOpponent) _opponentScore += details.data; else _myScore += details.data; + // ATUALIZA ESTATÍSTICA INDIVIDUAL DO JOGADOR + stats["pts"] = stats["pts"]! + details.data; + }); + }, + builder: (context, candidateData, rejectedData) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + decoration: BoxDecoration( + color: candidateData.isNotEmpty ? Colors.orange.shade50 : Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: candidateData.isNotEmpty ? Colors.orange : Colors.transparent, width: 2), + boxShadow: const [BoxShadow(color: Colors.black26, blurRadius: 6, offset: Offset(0, 3))], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40, height: 40, + decoration: BoxDecoration(color: teamColor, borderRadius: BorderRadius.circular(8)), + alignment: Alignment.center, + child: Text(number, style: const TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold)), + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(name, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87)), + const SizedBox(height: 2), + // AGORA MOSTRA OS PONTOS REAIS DO MAPA + Text( + "${stats["pts"]} Pts | ${stats["rbs"]} Rbs | ${stats["ast"]} Ast", + style: const TextStyle(fontSize: 12, color: Colors.grey, fontWeight: FontWeight.w500) + ), + ], + ), + ], + ), + ); + }, + ); + } + + Widget _buildTopScoreboard() { + return Container( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 30), + decoration: BoxDecoration( + color: const Color(0xFF16202C), + borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(15), bottomRight: Radius.circular(15)), + border: Border.all(color: Colors.white, width: 2), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _buildTeamSection(widget.myTeam, _myScore, _myFouls, const Color(0xFF1E5BB2), false), + const SizedBox(width: 25), + Column( + children: [ + _timeDisplay(), + const SizedBox(height: 5), + Text("PERÍODO $_currentQuarter", style: const TextStyle(color: Colors.orangeAccent, fontSize: 14, fontWeight: FontWeight.bold)), + ], + ), + const SizedBox(width: 25), + _buildTeamSection(widget.opponentTeam, _opponentScore, _opponentFouls, const Color(0xFFD92C2C), true), + ], + ), + ); + } + + Widget _buildTeamSection(String name, int score, int fouls, Color color, bool isOpp) { + final info = Column(children: [_scoreBox(score, color), Text("FALTAS: $fouls", style: const TextStyle(color: Colors.yellowAccent, fontSize: 12))]); + return Row(children: isOpp ? [info, const SizedBox(width: 15), Text(name.toUpperCase(), style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold))] + : [Text(name.toUpperCase(), style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(width: 15), info]); + } + + Widget _timeDisplay() => Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 6), + decoration: BoxDecoration(color: const Color(0xFF2C3E50), borderRadius: BorderRadius.circular(6)), + child: Text(_formatTime(_duration), style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, fontFamily: 'monospace')), + ); + + Widget _scoreBox(int score, Color color) => Container( + width: 50, height: 40, + alignment: Alignment.center, + decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(6)), + child: Text(score.toString(), style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold)), + ); + + Widget _buildActionButtonsPanel() { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _dragBtn("1", Colors.orange, 1), + _dragBtn("2", Colors.orange, 2), + _dragBtn("3", Colors.orange, 3), + _actionBtn("ORB", const Color(0xFF1E2A38), () {}, icon: Icons.shopping_basket), + ], + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _actionBtn("1", Colors.orange, () {}, isX: true), + _actionBtn("2", Colors.orange, () {}, isX: true), + _actionBtn("3", Colors.orange, () {}, isX: true), + _actionBtn("DRB", const Color(0xFF1E2A38), () {}, icon: Icons.shield), + ], + ), + ], + ); + } + + // BOTÃO ARRASTÁVEL + Widget _dragBtn(String label, Color color, int val) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Draggable( + data: val, + feedback: _circle(label, color, null, true), + childWhenDragging: Opacity(opacity: 0.5, child: _circle(label, color, null, false)), + child: _circle(label, color, null, false), + ), + ); + } + + // BOTÃO CLICÁVEL + Widget _actionBtn(String label, Color color, VoidCallback onTap, {IconData? icon, bool isX = false}) { + return GestureDetector( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Stack( + alignment: Alignment.bottomRight, + children: [ + _circle(label, color, icon, false), + if (isX) const Icon(Icons.cancel, color: Colors.red, size: 25), ], ), ), ); } - Widget _scoreBox(int score, Color color) { + Widget _circle(String label, Color color, IconData? icon, bool isFeed) { return Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(8)), - child: Text(score.toString(), style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold)), - ); - } - - Widget _buildPlayerCard(String number, String name) { - return Container( - decoration: BoxDecoration( - color: const Color(0xFF1E2A38).withOpacity(0.9), - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - CircleAvatar( - backgroundColor: const Color(0xFF2662D9), - radius: 12, - child: Text(number, style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)), - ), - const SizedBox(width: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(name, style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)), - const Text("0 Pts | 0 Rbs | 0 Ast", style: TextStyle(color: Colors.grey, fontSize: 8)), - ], - ) - ], - ), - ); - } - - Widget _buildActionButtonsPanel() { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Podes adicionar onTap nestes botões para chamarem setState(() => _myScore += X) - _actionBtn("1", Colors.orange), - _actionBtn("2", Colors.orange), - _actionBtn("3", Colors.orange), - const SizedBox(width: 20), - _actionBtn("M", Colors.blueGrey, icon: Icons.sports_basketball), - _actionBtn("F", Colors.redAccent, icon: Icons.pan_tool), - ], - ); - } - - Widget _actionBtn(String label, Color color, {IconData? icon}) { - return Container( - margin: const EdgeInsets.symmetric(horizontal: 4), + width: isFeed ? 70 : 60, height: isFeed ? 70 : 60, decoration: BoxDecoration(color: color, shape: BoxShape.circle), - padding: const EdgeInsets.all(12), - child: icon != null - ? Icon(icon, color: Colors.white, size: 20) - : Text(label, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16)), + alignment: Alignment.center, + child: icon != null ? Icon(icon, color: Colors.white, size: 35) + : Text(label, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 24, decoration: TextDecoration.none)), ); } -} - -// Classe temporária para desenhar as marcações do campo caso não tenhas imagem -class CourtPainterPlaceholder extends CustomPainter { - const CourtPainterPlaceholder(); - @override - void paint(Canvas canvas, Size size) { - final paint = Paint()..color = Colors.white.withOpacity(0.5)..style = PaintingStyle.stroke..strokeWidth = 2; - canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint); - canvas.drawLine(Offset(size.width / 2, 0), Offset(size.width / 2, size.height), paint); - canvas.drawCircle(Offset(size.width / 2, size.height / 2), 60, paint); - } - @override - bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index a7e3885..036a8bf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,7 +57,7 @@ flutter: assets: - assets/playmaker-logo.png - + - assets/campo.png # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images