diff --git a/lib/pages/gamePage.dart b/lib/pages/gamePage.dart new file mode 100644 index 0000000..db38039 --- /dev/null +++ b/lib/pages/gamePage.dart @@ -0,0 +1,266 @@ +import 'package:flutter/material.dart'; +import '../controllers/team_controller.dart'; +import '../models/team_model.dart'; +import '../widgets/team_widgets.dart'; + +class GamePage extends StatefulWidget { + const GamePage({super.key}); + + @override + State createState() => _GamePageState(); +} + +class _GamePageState extends State { + final TeamController controller = TeamController(); + final TextEditingController _searchController = TextEditingController(); + + String _selectedSeasonFilter = 'Todas'; + String _currentSort = 'Recentes'; + String _searchQuery = ''; + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + void _showCreateGameDialog(BuildContext context) { + showDialog( + context: context, + builder: (context) { + return CreateGameDialogManual(controller: controller); + }, + ); + } + + void _showFilterDialog(BuildContext context) { + showDialog( + context: context, + builder: (context) { + return StatefulBuilder( + builder: (context, setModalState) { + return AlertDialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text("Filtros", + style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 18) + ), + IconButton( + icon: const Icon(Icons.close, color: Colors.black, size: 20), + onPressed: () => Navigator.pop(context), + ) + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Divider(), + Row( + children: [ + _buildPopupColumn("TEMPORADA", ['Todas', '2023/24', '2024/25', '2025/26'], _selectedSeasonFilter, (val) { + setState(() => _selectedSeasonFilter = val); + setModalState(() {}); + }), + const SizedBox(width: 20), + _buildPopupColumn("ORDENAR", ['Recentes', 'Nome'], _currentSort, (val) { + setState(() => _currentSort = val); + setModalState(() {}); + }), + ], + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text("CONCLUÍDO", style: TextStyle(color: Color(0xFFE74C3C), fontWeight: FontWeight.bold)), + ), + ], + ); + }, + ); + }, + ); + } + + Widget _buildPopupColumn(String title, List options, String current, Function(String) onSelect) { + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: TextStyle(color: Colors.grey[700], fontSize: 11, fontWeight: FontWeight.bold)), + const SizedBox(height: 12), + ...options.map((opt) => InkWell( + onTap: () => onSelect(opt), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text(opt, + style: TextStyle( + color: current == opt ? const Color(0xFFE74C3C) : Colors.black, + fontWeight: current == opt ? FontWeight.bold : FontWeight.normal)), + ), + )), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFFF5F7FA), + appBar: AppBar( + title: const Text("Jogos", style: TextStyle(fontWeight: FontWeight.bold)), + backgroundColor: Colors.white, + elevation: 0, + actions: [ + IconButton( + icon: const Icon(Icons.filter_list, color: Color(0xFFE74C3C)), + onPressed: () => _showFilterDialog(context), + ), + ], + ), + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: TextField( + controller: _searchController, + onChanged: (v) => setState(() => _searchQuery = v.toLowerCase()), + decoration: InputDecoration( + hintText: 'Pesquisar jogo...', + prefixIcon: const Icon(Icons.search, color: Color(0xFFE74C3C)), + filled: true, + fillColor: Colors.white, + border: OutlineInputBorder(borderRadius: BorderRadius.circular(15), borderSide: BorderSide.none), + ), + ), + ), + const Expanded(child: Center(child: Text("Nenhum jogo registado."))), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: () => _showCreateGameDialog(context), + backgroundColor: const Color(0xFFE74C3C), + child: const Icon(Icons.add, color: Colors.white), + ), + ); + } +} + +class CreateGameDialogManual extends StatefulWidget { + final TeamController controller; + const CreateGameDialogManual({super.key, required this.controller}); + + @override + State createState() => _CreateGameDialogManualState(); +} + +class _CreateGameDialogManualState extends State { + final TextEditingController _seasonController = TextEditingController(); + String _myTeamName = ""; + String _opponentName = ""; + + @override + void dispose() { + _seasonController.dispose(); + super.dispose(); + } + + Widget _buildAutocompleteField({ + required String label, + required List teamNames, + required Function(String) onSelected, + }) { + return Autocomplete( + optionsBuilder: (TextEditingValue textEditingValue) { + if (textEditingValue.text.isEmpty) return const Iterable.empty(); + return teamNames.where((String name) => + name.toLowerCase().startsWith(textEditingValue.text.toLowerCase())); + }, + onSelected: (String selection) { + onSelected(selection); + }, + fieldViewBuilder: (context, fieldController, focusNode, onFieldSubmitted) { + return TextField( + controller: fieldController, + focusNode: focusNode, + onChanged: (value) => onSelected(value), + decoration: InputDecoration( + labelText: label, + prefixIcon: const Icon(Icons.shield, size: 20, color: Color(0xFFE74C3C)), + border: const OutlineInputBorder(), + ), + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return StreamBuilder>>( + stream: widget.controller.teamsStream, + builder: (context, snapshot) { + List existingTeamNames = []; + if (snapshot.hasData) { + existingTeamNames = snapshot.data!.map((t) => t['name'].toString()).toList(); + } + + return AlertDialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + title: const Text('Criar Novo Jogo', style: TextStyle(fontWeight: FontWeight.bold)), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: _seasonController, + decoration: const InputDecoration( + labelText: 'Temporada / Época', + prefixIcon: Icon(Icons.calendar_today, size: 20, color: Color(0xFFE74C3C)), + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 20), + _buildAutocompleteField( + label: "A Minha Equipa", + teamNames: existingTeamNames, + onSelected: (val) => _myTeamName = val, + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: Text("VS", style: TextStyle(fontWeight: FontWeight.bold, color: Colors.grey)), + ), + _buildAutocompleteField( + label: "Equipa Adversária", + teamNames: existingTeamNames, + onSelected: (val) => _opponentName = val, + ), + ], + ), + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(context), child: const Text('CANCELAR')), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFE74C3C), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + ), + onPressed: () { + if (_myTeamName.isNotEmpty && _opponentName.isNotEmpty) { + // Aqui podes adicionar a lógica para guardar o jogo no controller + print("Jogo criado: $_myTeamName vs $_opponentName na época ${_seasonController.text}"); + Navigator.pop(context); + } + }, + child: const Text('CRIAR', style: TextStyle(color: Colors.white)), + ), + ], + ); + }, + ); + } +} \ No newline at end of file diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 763e574..bb78e36 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -1,6 +1,7 @@ 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'; class HomeScreen extends StatefulWidget { @@ -21,7 +22,7 @@ class _HomeScreenState extends State { super.initState(); _pages = [ _buildHomeContent(), - const Center(child: Text('Tela de Jogo')), + const GamePage(), const TeamsPage(), const Center(child: Text('Tela de Status')), ]; @@ -84,12 +85,6 @@ class _HomeScreenState extends State { ), ); } - - // --- WIDGETS DE CONTEÚDO --- - - // REMOVIDO: Widget _buildTeamsContent()... - // Motivo: Este código foi movido para dentro de lib/pages/teams_page.dart - Widget _buildHomeContent() { return SingleChildScrollView( child: Padding(