diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..2f0f891 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "dart", + "command": "dart", + "args": [ + "pub", + "get" + ], + "problemMatcher": [], + "label": "dart: dart pub get" + } + ] +} \ No newline at end of file diff --git a/team_c_f/assets/images/google.svg b/team_c_f/assets/images/google.svg deleted file mode 100644 index 0b0dfe3..0000000 --- a/team_c_f/assets/images/google.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/team_c_f/lib/components/createschedule.dart b/team_c_f/lib/components/createschedule.dart new file mode 100644 index 0000000..8cf12c8 --- /dev/null +++ b/team_c_f/lib/components/createschedule.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:team_c_f/servises/servises.dart'; +import 'package:team_c_f/storebloc/blocs/createschedule.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/storebloc/blocs/schedule.dart'; + +class CreateScheduleView extends StatelessWidget { + const CreateScheduleView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + CreateScheduleBloc bloc = context.watch(); + return Container( + child: Card( + child: ListTile( + title: Container( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + showRegisterTeam(bloc.state.registTeam) + + ' ' + + showTeam(bloc.state.registTeam), + ), + SizedBox(height: 20), + Text( + showFullTeam(bloc.state.fullTeam) + + ' ' + + showTeam(bloc.state.fullTeam), + ), + SizedBox(height: 20), + Text('Укажите количество кругов в чемпионате'), + TextField( + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + onChanged: (circle) { + circle.trim(); + bloc.state.circle = circle != '' ? int.parse(circle) : 1; + bloc.add(CreateScheduleEvent.changeCircle); + }, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[0-9]')), + ], + ), + SizedBox(height: 20), + Text( + 'Ожидается ' + + showMatches( + matches: bloc.state.matches, + ) + + ' в каждом туре', + ), + SizedBox(height: 20), + Text( + 'Ожидается ' + + showTours( + tours: bloc.state.tours, + ), + ), + SizedBox(height: 20), + ElevatedButton( + onPressed: () { + bloc.add(CreateScheduleEvent.createSchedule); + context + .read() + .add(ScheduleEvent(event: Event.createSuccessful)); + }, + child: Text( + 'Создать расписание', + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/components/login.dart b/team_c_f/lib/components/login.dart new file mode 100644 index 0000000..24e7737 --- /dev/null +++ b/team_c_f/lib/components/login.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/components/reglament.dart'; +import 'package:team_c_f/components/selectteam.dart'; +import 'package:team_c_f/store/login/login.dart'; + +class LoginView extends StatelessWidget { + @override + Widget build(BuildContext context) { + final Login login = Provider.of(context); + return Container( + height: double.infinity, + width: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Observer( + builder: (_) => ElevatedButton( + onPressed: () { + login.updatedLoginStatus + ? login.googleLogout() + : login.googleLogin(); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + login.updatedLoginStatus ? 'Выйти' : 'Войти', + ), + SizedBox(width: 10), + Image( + image: AssetImage('assets/images/google.png'), + fit: BoxFit.fill, + height: 30, + ), + ], + ), + ), + ), + Observer( + builder: (_) => Text( + login.updatedLoginStatus + ? 'Вход выполнен, осталось совсем чуть чуть' + : 'Необходимо войти в аккаунт', + textAlign: TextAlign.center, + ), + ), + Observer( + builder: (_) => TextButton( + onPressed: () { + if (login.info != null) + Navigator.of(context) + .push(MaterialPageRoute( + builder: (_) => ReglamentView(info: login.info!))) + .then((value) => login.changeName(value!.toString())); + }, + child: Text('Правила конкурса'), + ), + ), + Container( + padding: const EdgeInsets.all(8.0), + margin: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(16.0), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Введите ваше имя и фамилию', + style: TextStyle( + color: Colors.white, + ), + ), + ), + TextField( + // Ввод имени участника + decoration: InputDecoration( + fillColor: Colors.white, + filled: true, + ), + onChanged: login.changeName, + textAlign: TextAlign.center, + ), + ], + ), + ), + Observer( + builder: (_) { + Provider.of(context) + .setDataToSelectTeam(buttonText: 'Зарегистрироваться'); + return SelectTeamView( + selectTeam: context.read().selectTeam, + updateMyTeam: false, + ); + }, + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/components/meet.dart b/team_c_f/lib/components/meet.dart new file mode 100644 index 0000000..dd9de58 --- /dev/null +++ b/team_c_f/lib/components/meet.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/models/meet.dart'; +import 'package:intl/intl.dart'; + +class MeetView extends StatelessWidget { + final MeetData meetData; + const MeetView({Key? key, required this.meetData}) : super(key: key); + + @override + Widget build(BuildContext context) { + DateTime date = DateFormat('yyyy-MM-dd HH:mm').parse(meetData.date); + String status = meetData.status == 'Не начат' + ? date.day == DateTime.now().day + ? DateFormat('HH:mm').format(date) + : DateFormat('dd.MM').format(date) + : meetData.status; + String score = meetData.started + ? '${meetData.score.first}:${meetData.score.last}' + : '-'; + double width = MediaQuery.of(context).size.width; + return Padding( + padding: const EdgeInsets.all(2.0), + child: Container( + padding: const EdgeInsets.all(8.0), + color: meetData.started ? Colors.green[100] : Colors.yellow[300], + width: width - 15, + child: Column( + children: [ + Table( + columnWidths: { + 0: FixedColumnWidth(width/6.5), + 1: FixedColumnWidth(width/3), + 2: FixedColumnWidth(width/10), + 3: FixedColumnWidth(width/3) + }, + children: [ + TableRow( + children: [ + Text(status, textAlign: TextAlign.center), + Text(meetData.team.first, textAlign: TextAlign.right), + Text(score, textAlign: TextAlign.center), + Text(meetData.team.last), + ], + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/team_c_f/lib/components/oneteam.dart b/team_c_f/lib/components/oneteam.dart new file mode 100644 index 0000000..2897e59 --- /dev/null +++ b/team_c_f/lib/components/oneteam.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/storebloc/blocs/leaveforecast.dart'; +import 'package:team_c_f/storebloc/models/leaveforecast.dart'; +import 'package:provider/provider.dart'; + +class OneTeamView extends StatelessWidget { + final LeaveForecastModel forecast; + OneTeamView({Key? key, required this.forecast}) : super(key: key); + + final List numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + @override + Widget build(BuildContext context) { + LeaveForecastBloc bloc = context.read(); + double size = MediaQuery.of(context).size.width; + return Card( + color: Colors.blue[400], + child: Table( + defaultVerticalAlignment: TableCellVerticalAlignment.middle, + columnWidths: { + 0: FixedColumnWidth(size / 7), + 1: FixedColumnWidth(size / 3), + 2: FixedColumnWidth(size / 11), + 3: FixedColumnWidth(size / 40), + 4: FixedColumnWidth(size / 11), + 5: FixedColumnWidth(size / 3), + }, + children: [ + TableRow( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(forecast.date), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + forecast.teams.first, + textAlign: TextAlign.right, + ), + ), + DropdownButton( + value: forecast.home, + onChanged: (i) { + bloc.add( + LeaveForecastEvent( + event: Event.changeValue, + position: true, + index: bloc.state.meets.indexOf(forecast), + newValue: i), + ); + }, + items: [ + ...numbers.map>( + (int number) => DropdownMenuItem( + child: Text(number.toString()), + value: number, + ), + ), + ], + ), + Text(':'), + DropdownButton( + value: forecast.away, + onChanged: (i) { + bloc.add( + LeaveForecastEvent( + event: Event.changeValue, + position: false, + index: bloc.state.meets.indexOf(forecast), + newValue: i), + ); + }, + items: [ + ...numbers.map>( + (int number) => DropdownMenuItem( + child: Text(number.toString()), + value: number, + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + forecast.teams.last, + textAlign: TextAlign.left, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/components/reglament.dart b/team_c_f/lib/components/reglament.dart new file mode 100644 index 0000000..fa5f6db --- /dev/null +++ b/team_c_f/lib/components/reglament.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/models/info.dart'; + +class ReglamentView extends StatelessWidget { + final InfoData info; + ReglamentView({required this.info}); + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: Row( + children: [ + InkWell( + child: Icon(Icons.arrow_back, size: 30), + onTap: () { + Navigator.of(context).pop(true); + }, + ), + SizedBox(width: 20), + Text('Правила конкурса'), + ], + ), + ), + body: Container( + height: double.infinity, + width: double.infinity, + child: ListView( + padding: const EdgeInsets.all(8.0), + children: [ + ...info.regulations.map( + (String item) => Padding( + padding: const EdgeInsets.all(2.0), + child: Text(item), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/components/selectteam.dart b/team_c_f/lib/components/selectteam.dart new file mode 100644 index 0000000..3a2a447 --- /dev/null +++ b/team_c_f/lib/components/selectteam.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/storebloc/blocs/myteam.dart'; +import 'package:team_c_f/store/login/login.dart'; +import 'package:team_c_f/store/selectteam/selectteam.dart'; + +class SelectTeamView extends StatelessWidget { + // Класс отображения выбора команды или регистрации новой + final SelectTeam selectTeam; + final bool updateMyTeam; + + const SelectTeamView({ + Key? key, + required this.selectTeam, + required this.updateMyTeam, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + padding: const EdgeInsets.all(8.0), + margin: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(16.0), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Observer( + builder: (_) => Checkbox( + // Чекбокс для капитанов + value: selectTeam.capitan, + checkColor: Colors.blue, + activeColor: Colors.white, + onChanged: selectTeam.changeCapitan, + ), + ), + Text( + 'Я капитан команды', + style: TextStyle( + color: Colors.white, + ), + ), + ], + ), + Observer( + builder: (_) => Container( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + selectTeam.capitan + ? 'Введите название вашей команды' + : 'Выбери команду', + style: TextStyle( + color: Colors.white, + ), + ), + ), + selectTeam.capitan + ? Observer( + builder: (_) => TextField( + // Ввод названия команды для капитана + decoration: InputDecoration( + fillColor: Colors.white, filled: true), + onChanged: selectTeam.changeTeam, + controller: TextEditingController.fromValue( + TextEditingValue( + text: selectTeam.lastTeamName, + selection: TextSelection.collapsed( + offset: selectTeam.lastTeamName.length), + ), + ), + textAlign: TextAlign.center, + ), + ) + : Observer( + builder: (_) => selectTeam.allTeamNames.isNotEmpty + ? DropdownButton( + value: selectTeam.selectedTeam, + onChanged: selectTeam.selestTeam, + items: [ + ...selectTeam.allTeamNames + .map>( + (String team) => DropdownMenuItem( + child: Text(team), + value: team, + ), + ) + .toList(), + ], + ) + : Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Ни одной доступной команды нет', + style: TextStyle( + color: Colors.white, + ), + ), + Text( + 'Можешь создать команду сам \u261d', + style: TextStyle( + color: Colors.white, + ), + ) + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + Observer( + builder: (_) => ElevatedButton( + // Кнопка регистрации + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(Colors.green), + ), + onPressed: selectTeam.uName.isNotEmpty + ? selectTeam.capitan + ? selectTeam.teamName.isNotEmpty + ? selectTeam.enableName + ? () { + selectTeam.registrateTeam().then( + (_) { + context.read().validateInApp(); + context.read().refreshData(); + if (updateMyTeam) + context + .read() + .add(MyTeamEvent.reset); + }, + ); + } + : null + : null + : selectTeam.selectedTeam != null + ? () { + selectTeam.assertTeam().then( + (_) { + context.read().validateInApp(); + context.read().refreshData(); + if (updateMyTeam) + context + .read() + .add(MyTeamEvent.reset); + }, + ); + } + : null + : null, + child: Observer( + builder: (_) => Text(selectTeam.uId.isNotEmpty + ? selectTeam.uName.isNotEmpty + ? selectTeam.capitan + ? selectTeam.teamName.isNotEmpty + ? selectTeam.enableName + ? 'Зарегистрировать команду' + : 'Данное название команды недоступно' + : 'Введите название команды' + : selectTeam.selectedTeam != null + ? selectTeam.regButtonText + : 'Выберите команду' + : 'Введите имя и фамилию' + : 'Необходимо войти в Google-аккаунт'), + ), + ), + ), + ], + ); + } +} diff --git a/team_c_f/lib/components/unconfirmedplayer.dart b/team_c_f/lib/components/unconfirmedplayer.dart new file mode 100644 index 0000000..01767c8 --- /dev/null +++ b/team_c_f/lib/components/unconfirmedplayer.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:team_c_f/storebloc/blocs/myteam.dart'; +import 'package:team_c_f/storebloc/models/unconfirmedplayer.dart'; +import 'package:provider/provider.dart'; + +class UnconfirmedPlayerView extends StatelessWidget { + // Класс, для отображения неподтвержденных игроков + final UnconfirmedPlayerModel player; // Неподтвержденный игрок + UnconfirmedPlayerView({Key? key, required this.player}) : super(key: key); + + @override + Widget build(BuildContext context) { + MyTeamBloc bloc = context.watch(); + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsets.all(10.0), + child: Text(player.name), + ), + IconButton( + icon: Icon( + Icons.check_box, + size: 30, + color: Colors.green, + ), + onPressed: () { + bloc.state.selectId = player.uid; + bloc.add(MyTeamEvent.confirmedPlayer); + Fluttertoast.showToast( + msg: '${player.name} добавлен в вашу команду', + ); + }, + ), + IconButton( + icon: Icon( + Icons.cancel, + size: 30, + color: Colors.red, + ), + onPressed: () { + bloc.state.selectId = player.uid; + bloc.add(MyTeamEvent.unconfirmedPlayer); + Fluttertoast.showToast( + msg: 'Заявка отклонена', + ); + }, + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/data/data.dart b/team_c_f/lib/data/data.dart index a95623b..aad02b8 100644 --- a/team_c_f/lib/data/data.dart +++ b/team_c_f/lib/data/data.dart @@ -1,51 +1,117 @@ -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:team_c_f/servise/auth.dart'; -import 'package:team_c_f/servise/operationdb.dart'; - -class Account with ChangeNotifier { - // Единый класс с информацией о Google-аккаунте и регистрации в приложении - bool _signInGoogle = false; - bool _registedInApp = false; - String _userId = ''; - - bool get signIn => _signInGoogle; // Выполнен вход в Google-аккаунт - bool get registedInApp => - _registedInApp; // Выполнена ли регистрации в приложении - String get userId => _userId; // Уникальный идентификатор Google-аккаунта - - Account() { - // Конструктор - calculateVariables(); +import 'package:team_c_f/models/currenttour.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/player.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/models/tour.dart'; +import 'package:team_c_f/servises/data.dart'; +import 'package:team_c_f/servises/tour.dart'; + +class Data with ChangeNotifier { + bool downloadSuccessful = false; + + Data() { + initData(); + } + + void refreshData() { + downloadSuccessful = false; + notifyListeners(); + initData(); } - void calculateVariables() { - // Вычисление переменных - if (FirebaseAuth.instance.currentUser != null) { - _userId = FirebaseAuth.instance.currentUser.uid; - _signInGoogle = true; - DatabaseService().userExists(userId: _userId).then((value) { - _registedInApp = value; - notifyListeners(); - }); - } else { - _userId = ''; - _signInGoogle = false; - _registedInApp = false; + void initData(){ + DataService().initData().then((result) { + sortData(); + downloadSuccessful = result; notifyListeners(); - } + }); } - Future changeSignIn() async { - // Изменение статуса входа в Google-аккаунт - _signInGoogle ? await signOutGoogle() : await signInWithGoogle(); - calculateVariables(); + static late CurrentTourData currentTour; + static late List players; + static late List teams; + static late List tours; + static late List meets; + static late List names = []; + + static void sortTour() { + tours.sort((TourData a, b) => + a.round.compareTo(b.round)); // сортировка туров по порядку } - void registedUser() { - // Регистрация пользователя в приложении - _registedInApp = true; + static void sortData() { + sortTour(); + sortPlayer(players: players); + players.forEach( + (PlayerData p) { + p.prevPosition = players.indexOf(p) + 1; + }, + ); // указание текущей позиции игрока - notifyListeners(); + tours.forEach( + (TourData tour) { + int round = tours.indexOf(tour); + tour.team.forEach( + (List pair) { + TeamData home = + teams.where((TeamData team) => team.name == pair[0]).single; + TeamData away = + teams.where((TeamData team) => team.name == pair[1]).single; + if (home.goal.length > round) { + if (home.goal[round] == null && away.goal[round] == null) { + home.lose++; + away.lose++; + } else if (home.goal[round] == null) { + home.lose++; + away.win++; + home.missed += away.goal[round]!; + } else if (away.goal[round] == null) { + away.lose++; + home.win++; + away.missed += home.goal[round]!; + } else { + int goalHome = home.goal[round]!; + int goalAway = away.goal[round]!; + home.missed += goalAway; + away.missed += goalHome; + if (goalHome > goalAway) { + home.win++; + away.lose++; + } else if (goalAway > goalHome) { + away.win++; + home.lose++; + } else { + home.draw++; + away.draw++; + } + } + } + }, + ); + }, + ); // определение wdl для команд и количества пропущенных + sortTeam(teams: teams); + teams.forEach( + (TeamData t) { + t.prevPosition = teams.indexOf(t) + 1; + }, + ); // указание текущей позиции команды + } + + static void sortTeam({required List teams}) { + teams.sort((TeamData a, b) => (b.goals - b.missed) + .compareTo(a.goals - a.missed)); // сортировка команд по разнице забитых + teams.sort((TeamData a, b) => + b.win.compareTo(a.win)); // сортировка команд по количеству побед + teams.sort((TeamData a, b) => + b.goals.compareTo(a.goals)); // сортировка команд по количеству забитых + teams.sort((TeamData a, b) => + b.points.compareTo(a.points)); // сортировка команд по количеству очков + } + + static void sortPlayer({required List players}) { + players.sort((PlayerData a, b) => b.goals + .compareTo(a.goals)); // сортировка участников по количеству забитых } } diff --git a/team_c_f/lib/element/player.dart b/team_c_f/lib/element/player.dart deleted file mode 100644 index 1f53206..0000000 --- a/team_c_f/lib/element/player.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:team_c_f/data/player.dart'; -import 'package:team_c_f/servise/make.dart'; -import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:provider/provider.dart'; -import 'package:team_c_f/data/tournament.dart'; - -class ShowPlayer extends StatelessWidget { - // Класс отображающий информацию об указанном игроке - final Player player; - ShowPlayer({Key key, @required this.player}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - child: InkWell( - onLongPress: () async { - if (context.read().me.capitan) if (await showAlertDialog( - context: context, - title: 'Изменение состава', - message: 'Удалить ${player.name}', - actions: [ - AlertDialogAction( - key: true, - label: 'Да, удалить', - isDefaultAction: true, - ), - AlertDialogAction( - key: false, - label: 'Отмена', - isDestructiveAction: true, - ), - ], - )) context.read().removePlayerFromMyTeam(uid: player.uid); - }, - child: Card( - child: ListTile( - leading: CircleAvatar( - child: Text(player.position.toString()), - ), - title: Text(player.name), - trailing: Text(showPoints(player.points)), - ), - ), - ), - ); - } -} diff --git a/team_c_f/lib/main.dart b/team_c_f/lib/main.dart index b5d443e..ec9dff9 100644 --- a/team_c_f/lib/main.dart +++ b/team_c_f/lib/main.dart @@ -1,13 +1,12 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:team_c_f/data/data.dart'; -import 'package:team_c_f/data/shortmatch.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/page/home.dart'; -import 'package:team_c_f/page/sign.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:onesignal_flutter/onesignal_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/pages/login.dart'; +import 'package:team_c_f/store/login/login.dart'; +import 'package:team_c_f/pages/home.dart'; Future main() async { myApp(); @@ -17,307 +16,29 @@ myApp() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // Инициализация Firebase - //OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none); - - OneSignal.shared.init('93b27d54-e442-4af5-86e4-a215faf20e3a', iOSSettings: { - OSiOSSettings.autoPrompt: false, - OSiOSSettings.inAppLaunchUrl: false - }); - OneSignal.shared - .setInFocusDisplayType(OSNotificationDisplayType.notification); + OneSignal.shared.setAppId('93b27d54-e442-4af5-86e4-a215faf20e3a'); runApp( - MultiProvider( - // Мультипровайдер, для упроощения взаимодействия с данными - providers: [ - ChangeNotifierProvider( - create: (context) => Account(), - ), // Данные связанные с аутентификацией (гугл-вход и регистрация в приложении) - ChangeNotifierProvider( - create: (context) => Tournament(), - ), // Данные полученные из Firebase - ChangeNotifierProvider( - create: (context) => DataMatch(), - ), - ], - child: MaterialApp( - // theme: ThemeData( - // textTheme: TextTheme( - // bodyText2: TextStyle( - // color: Colors.black, - // fontWeight: FontWeight.normal, - // ), - // bodyText1: TextStyle( - // color: Colors.black, - // decoration: TextDecoration.lineThrough, - // fontWeight: FontWeight.normal, - // ), - // caption: TextStyle( - // color: Colors.green, - // fontWeight: FontWeight.w400, - // ), - // ), - // ), - home: SafeArea( - child: Page(), - ), + MaterialApp( + home: MultiProvider( + providers: [ + Provider(create: (_) => Login()), + ChangeNotifierProvider(create: (_) => Data()), + ], + child: FirstPage(), ), ), ); } -class Page extends StatefulWidget { - const Page({Key key}) : super(key: key); - - @override - _PageState createState() => _PageState(); -} +class FirstPage extends StatelessWidget { + const FirstPage({Key? key}) : super(key: key); -class _PageState extends State { @override Widget build(BuildContext context) { - return Container( - child: context - .watch() - .registedInApp // Проверка зарегистрирован ли пользователь в приложении - ? Homepage() // Домашняя страница приложения - : Sign(), // Регистрация в приложении + вход в гугл + return Observer( + builder: (_) => + context.read().registrateInApp ? HomePage() : LoginPage(), ); } } - -// class Prob extends StatelessWidget { -// const Prob({Key key}) : super(key: key); - -// @override -// Widget build(BuildContext context) { -// return Container( -// child: Text( -// '1 - 1', -// style: Theme.of(context).textTheme.bodyText2, -// ), -// ); -// } -// } - -// class Content extends StatefulWidget { -// const Content({Key key}) : super(key: key); - -// @override -// _ContentState createState() => _ContentState(); -// } - -// class _ContentState extends State { -// Tournament tournament; -// String currentTour = 'start msg'; -// int matchNumber = 0; -// Team home; -// Team away; -// bool dataDownload = false; - -// Tournament parseTournament(String responseBody) { -// final parsed = json.decode(responseBody); - -// return Tournament.fromJson(parsed); -// } - -// Future downloadInfo(http.Client client) async { -// final response = await client -// .get(Uri.parse('http://tcfserver.azurewebsites.net/info?tour=31')); - -// return parseTournament(response.body); -// } - -// changeMatch(int index, CarouselPageChangedReason reason) { -// setState(() { -// matchNumber = index; -// home = tournament.teams -// .where((element) => element.name == tournament.pair[matchNumber * 2]) -// .first; -// away = tournament.teams -// .where( -// (element) => element.name == tournament.pair[matchNumber * 2 + 1]) -// .first; -// }); -// } - -// void download() async { -// downloadInfo(http.Client()).then( -// (all) => setState(() { -// currentTour = 'Текущий тур ${all.currentTour}'; -// tournament = all; -// home = all.teams -// .where((element) => element.name == all.pair[matchNumber * 2]) -// .first; -// away = all.teams -// .where((element) => element.name == all.pair[matchNumber * 2 + 1]) -// .first; -// dataDownload = true; -// }), -// ); -// setState(() { -// currentTour = 'Загрузка данных'; -// }); -// } - -// Widget headerBuilder(int i) { -// Team home = tournament.teams -// .where((element) => element.name == tournament.pair[i * 2]) -// .first; -// Team away = tournament.teams -// .where((element) => element.name == tournament.pair[i * 2 + 1]) -// .first; -// return Container( -// decoration: BoxDecoration( -// borderRadius: BorderRadius.circular(20), -// color: Colors.blue[100], -// ), -// alignment: Alignment.center, -// margin: const EdgeInsets.symmetric( -// vertical: 8, -// ), -// child: Column( -// mainAxisSize: MainAxisSize.max, -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// Row( -// mainAxisSize: MainAxisSize.max, -// children: [ -// Expanded( -// flex: 2, -// child: Text( -// '${home.countPerRound}', -// textAlign: TextAlign.center, -// style: TextStyle( -// fontSize: 30, -// ), -// ), -// ), -// Expanded( -// flex: 1, -// child: Text( -// '-', -// textAlign: TextAlign.center, -// style: TextStyle( -// fontSize: 30, -// ), -// ), -// ), -// Expanded( -// flex: 2, -// child: Text( -// '${away.countPerRound}', -// textAlign: TextAlign.center, -// style: TextStyle( -// fontSize: 30, -// ), -// ), -// ), -// ], -// ), -// Expanded( -// flex: 1, -// child: Row( -// children: [ -// Expanded( -// flex: 1, -// child: Text( -// '${home.name.split("\"")[1]}', -// textAlign: TextAlign.center, -// style: TextStyle( -// fontSize: 18, -// ), -// ), -// ), -// SizedBox( -// width: 20, -// ), -// Expanded( -// flex: 1, -// child: Text( -// '${away.name.split("\"")[1]}', -// textAlign: TextAlign.center, -// style: TextStyle( -// fontSize: 18, -// ), -// ), -// ), -// ], -// ), -// ), -// ], -// ), -// ); -// } - -// @override -// Widget build(BuildContext context) { -// Widget wrap() { -// return Column( -// children: [ -// Wrap( -// spacing: 10, -// runSpacing: 10, -// alignment: WrapAlignment.center, -// direction: Axis.horizontal, -// children: [ -// for (int i = 0; i < 10; i++) -// Meet( -// number: i, -// home: home, -// away: away, -// real: tournament.realResults, -// rHome: tournament.names.team[i * 2], -// rAway: tournament.names.team[i * 2 + 1], -// info: tournament.names.info[i], -// ) -// ], -// ), -// ], -// ); -// } - -// Widget headers() { -// return CarouselSlider( -// items: [ -// for (int i = 0; i * 2 < tournament.pair.length; i++) headerBuilder(i) -// ], -// options: CarouselOptions( -// autoPlay: false, -// enlargeCenterPage: true, -// onPageChanged: changeMatch, -// aspectRatio: 4, -// ), -// ); -// } - -// return Container( -// color: Colors.indigo, -// alignment: Alignment.center, -// width: double.infinity, -// height: double.infinity, -// padding: const EdgeInsets.all(10), -// child: Column( -// children: [ -// dataDownload ? headers() : SizedBox(height: 0), -// Expanded( -// child: Container( -// child: ListView( -// children: [ -// dataDownload ? wrap() : Text('Прогнозы ещё не загружены'), -// ElevatedButton( -// child: Text('Download'), -// onPressed: download, -// ), -// Text( -// currentTour, -// ), -// ], -// ), -// ), -// ), -// ], -// ), -// ); -// } -// } diff --git a/team_c_f/lib/models/choicemeet.dart b/team_c_f/lib/models/choicemeet.dart new file mode 100644 index 0000000..62544a0 --- /dev/null +++ b/team_c_f/lib/models/choicemeet.dart @@ -0,0 +1,47 @@ +import 'package:html/dom.dart'; +import 'package:intl/intl.dart'; + +class ChoiceMeetData { + final List team; + final DateTime date; + late bool selected; + + ChoiceMeetData({ + required this.team, + required this.date, + required this.selected, + }); + + factory ChoiceMeetData.fromHtml({ + required String date, + required Element html, + }) { + List team = [ + html.getElementsByClassName('owner-td').single.text.replaceAll( + '\n', + '', + ), + html.getElementsByClassName('guests-td').single.text.replaceAll( + '\n', + '', + ), + ]; + String time = html.getElementsByClassName('alLeft gray-text').first.text; + time = date + ' ' + (time != '—' ? time : '00:00'); + DateTime dateTime = DateFormat('yyyy-MM-dd HH:mm').parse(time); + bool selected = false; + return ChoiceMeetData( + team: team, + date: dateTime, + selected: selected, + ); + } + + ChoiceMeetData copyWith({required bool selected}) { + return ChoiceMeetData( + team: this.team, + date: this.date, + selected: selected, + ); + } +} diff --git a/team_c_f/lib/models/currenttour.dart b/team_c_f/lib/models/currenttour.dart new file mode 100644 index 0000000..585fba4 --- /dev/null +++ b/team_c_f/lib/models/currenttour.dart @@ -0,0 +1,17 @@ +class CurrentTourData { + late String docId; + int round; + CurrentTourData({required this.round}); + + Map toMap() { + return { + 'Round': round, + }; + } + + factory CurrentTourData.fromMap({required Map data, required String docId}){ + CurrentTourData curr = CurrentTourData(round: data['Round']); + curr.docId = docId; + return curr; + } +} diff --git a/team_c_f/lib/models/forecast.dart b/team_c_f/lib/models/forecast.dart new file mode 100644 index 0000000..71d62d5 --- /dev/null +++ b/team_c_f/lib/models/forecast.dart @@ -0,0 +1,37 @@ +class ForecastData { + late String docId; + final String uid; + final List rate; + final String? team; + final int round; + int result = 0; + + ForecastData({ + required this.uid, + required this.rate, + required this.team, + required this.round, + }); + + Map toMap() { + return { + 'UserId': uid, + 'Rate': rate, + 'Team': team, + 'Round': round, + 'Result': result, + }; + } + + factory ForecastData.fromMap({required Map data, required String docId}) { + ForecastData f = ForecastData( + uid: data['UserId'], + rate: data['Rate'].cast(), + team: data['Team'], + round: data['Round'], + ); + f.result = data['Result']; + f.docId = docId; + return f; + } +} diff --git a/team_c_f/lib/models/info.dart b/team_c_f/lib/models/info.dart new file mode 100644 index 0000000..d53112f --- /dev/null +++ b/team_c_f/lib/models/info.dart @@ -0,0 +1,22 @@ +class InfoData { + final List regulations; + final String link; + InfoData({ + required this.regulations, + required this.link, + }); + + factory InfoData.fromMap({required Map data}) { + return InfoData( + link: data['Link'], + regulations: [...data['Regulations']], + ); + } + + Map toMap(){ + return { + 'Link': link, + 'Regulations': regulations, + }; + } +} diff --git a/team_c_f/lib/models/meet.dart b/team_c_f/lib/models/meet.dart new file mode 100644 index 0000000..17add45 --- /dev/null +++ b/team_c_f/lib/models/meet.dart @@ -0,0 +1,50 @@ +class MeetData { + final List team; + final String date; + late List score; + final bool started; + late String status; + + MeetData({ + required this.team, + required this.date, + required this.score, + required this.started, + required this.status, + }); + + factory MeetData.fromMap({required Map data}) { + return MeetData( + team: data['Team'].cast(), + date: data['Date'], + score: data['Score'].cast(), + started: data['Started'], + status: data['Status'], + ); + } + + Map toMap() { + return { + 'Team': team, + 'Date': date, + 'Score': score, + 'Started': started, + 'Status': status, + }; + } + + String toString() { + return '${team.first} - ${team.last}|$date|${score.first}:${score.last}|$started|$status'; + } + + factory MeetData.fromString({required String data}) { + List split = data.split('|'); + return MeetData( + team: split[0].split(' - '), + date: split[1], + score: split[2].split(':').map((String goal) => int.parse(goal)).toList(), + started: bool.fromEnvironment(split[3]), + status: split[4], + ); + } +} diff --git a/team_c_f/lib/models/meets.dart b/team_c_f/lib/models/meets.dart new file mode 100644 index 0000000..d81b500 --- /dev/null +++ b/team_c_f/lib/models/meets.dart @@ -0,0 +1,48 @@ +import 'meet.dart'; + +class MeetsData { + late String docId; + final int round; + final List meets; + final String deadline; + late bool started; + + MeetsData({ + required this.round, + required this.meets, + required this.deadline, + required this.started, + }); + + factory MeetsData.fromMap( + {required Map data, required String docId}) { + List a = []; + if (data['Meets'].isNotEmpty) + a.addAll( + [ + ...data['Meets'] + .map( + (meet) => MeetData.fromString(data: meet), + ) + .toList(), + ], + ); + MeetsData meets = MeetsData( + round: data['Round'], + meets: a, + deadline: data['Deadline'], + started: data['Started'], + ); + meets.docId = docId; + return meets; + } + + Map toMap() { + return { + 'Round': round, + 'Meets': meets.map((e) => e.toString()).toList(), + 'Deadline': deadline, + 'Started': started, + }; + } +} diff --git a/team_c_f/lib/models/player.dart b/team_c_f/lib/models/player.dart new file mode 100644 index 0000000..2baaceb --- /dev/null +++ b/team_c_f/lib/models/player.dart @@ -0,0 +1,47 @@ +class PlayerData { + String? docId; + final String uid; + String name; + String? team; + late List points = []; + + int get maxTour => points.fold( + 0, + (value, current) => current != null + ? current > value + ? current + : value + : value); + int get goals => points.fold( + 0, + (value, current) => value + (current != null ? current : 0), + ); + late int prevPosition; + + PlayerData({ + required this.uid, + required this.name, + required this.team, + this.docId, + }); + + Map toMap() { + return { + 'UserId': uid, + 'Name': name, + 'Team': team, + 'Points': points, + }; + } + + factory PlayerData.fromMap({required Map data, required String docId}) { + PlayerData p = PlayerData( + name: data['Name'], + team: data['Team'], + uid: data['UserId'], + ); + p.points = [...data['Points']]; + p.docId = docId; + return p; + } +} diff --git a/team_c_f/lib/models/team.dart b/team_c_f/lib/models/team.dart new file mode 100644 index 0000000..23bc927 --- /dev/null +++ b/team_c_f/lib/models/team.dart @@ -0,0 +1,49 @@ +class TeamData { + late String docId; + final String name; + final String uidCapitan; + List players = []; + List goal = []; + + int get maxTour => goal.fold( + 0, + (value, current) => current != null + ? current > value + ? current + : value + : value); + int get goals => goal.fold( + 0, + (value, current) => value + (current != null ? current : 0), + ); + int missed = 0; + int win = 0; + int draw = 0; + int lose = 0; + int get points => win * 3 + draw; + late int prevPosition; + + TeamData({required this.name, required this.uidCapitan}) { + players.add(this.uidCapitan); + } + + Map toMap() { + return { + 'Name': name, + 'Capitan': uidCapitan, + 'Players': players, + 'Goal': goal, + }; + } + + factory TeamData.fromMap({required Map data, required String docId}) { + TeamData t = TeamData( + name: data['Name'] as String, + uidCapitan: data['Capitan'], + ); + t.players = [...data['Players']]; + t.goal = [...data['Goal']]; + t.docId = docId; + return t; + } +} diff --git a/team_c_f/lib/models/tour.dart b/team_c_f/lib/models/tour.dart new file mode 100644 index 0000000..e7648c2 --- /dev/null +++ b/team_c_f/lib/models/tour.dart @@ -0,0 +1,28 @@ +class TourData { + final int round; + String? name; + late List> team; + TourData({required this.round, this.name}); + + String get stage => name?? round.toString(); + + TourData.all({ + required this.round, + required this.team, + }); + + Map toMap() { + return { + 'Round': round, + 'Team': team.map((List match) => match.first + '><' + match.last).toList(), + 'Name': name ?? round.toString(), + }; + } + + factory TourData.fromMap({required Map data}) { + TourData t = TourData(round: data['Round'], name: data['Name']); + List match = data['Team'].cast(); + t.team = match.map((String pair) => pair.split('><').toList()).toList(); + return t; + } +} diff --git a/team_c_f/lib/data/currenttour.dart b/team_c_f/lib/old/data/currenttour.dart similarity index 58% rename from team_c_f/lib/data/currenttour.dart rename to team_c_f/lib/old/data/currenttour.dart index 3a01d59..f4801cd 100644 --- a/team_c_f/lib/data/currenttour.dart +++ b/team_c_f/lib/old/data/currenttour.dart @@ -1,17 +1,17 @@ import 'package:flutter/material.dart'; class CurrentTour { // Класс с данными о текущем туре - final String tour; // Номер или стадия текущего тура - final String tournament; // Название текущей стадии + final String? tour; // Номер или стадия текущего тура + final String? tournament; // Название текущей стадии CurrentTour({ // Базовый конструктор @required this.tour, @required this.tournament, }); - factory CurrentTour.fromJson({Map json}) { // Именованный конструктор, используется для десериализации + factory CurrentTour.fromJson({Map? json}) { // Именованный конструктор, используется для десериализации return CurrentTour( - tour: json['Tour'], + tour: json!['Tour'], tournament: json['Tournament'], ); } diff --git a/team_c_f/lib/old/data/data.dart b/team_c_f/lib/old/data/data.dart new file mode 100644 index 0000000..1110e25 --- /dev/null +++ b/team_c_f/lib/old/data/data.dart @@ -0,0 +1,51 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:team_c_f/old/servise/auth.dart'; +import 'package:team_c_f/old/servise/operationdb.dart'; + +class Account with ChangeNotifier { + // Единый класс с информацией о Google-аккаунте и регистрации в приложении + bool? _signInGoogle = false; + bool? _registedInApp = false; + String? _userId = ''; + + bool get signIn => _signInGoogle!; // Выполнен вход в Google-аккаунт + bool get registedInApp => + _registedInApp!; // Выполнена ли регистрации в приложении + String get userId => _userId!; // Уникальный идентификатор Google-аккаунта + + Account() { + // Конструктор + calculateVariables(); + } + + void calculateVariables() { + // Вычисление переменных + if (FirebaseAuth.instance.currentUser != null) { + _userId = FirebaseAuth.instance.currentUser!.uid; + _signInGoogle = true; + DatabaseService().userExists(userId: _userId!).then((value) { + _registedInApp = value; + notifyListeners(); + }); + } else { + _userId = ''; + _signInGoogle = false; + _registedInApp = false; + notifyListeners(); + } + } + + Future changeSignIn() async { + // Изменение статуса входа в Google-аккаунт + _signInGoogle! ? await signOutGoogle() : await signInWithGoogle(); + calculateVariables(); + } + + void registedUser() { + // Регистрация пользователя в приложении + _registedInApp = true; + + notifyListeners(); + } +} diff --git a/team_c_f/lib/data/forecast.dart b/team_c_f/lib/old/data/forecast.dart similarity index 75% rename from team_c_f/lib/data/forecast.dart rename to team_c_f/lib/old/data/forecast.dart index 40d9e6f..1d0c3fb 100644 --- a/team_c_f/lib/data/forecast.dart +++ b/team_c_f/lib/old/data/forecast.dart @@ -1,24 +1,23 @@ import 'dart:convert'; -import 'package:flutter/material.dart'; -import 'package:team_c_f/data/match.dart'; -import 'package:team_c_f/servise/make.dart'; +import 'package:team_c_f/old/data/match.dart'; +import 'package:team_c_f/old/servise/make.dart'; class Forecast { // Информация о прогнозе - String _docId; // Идентификатор документа с прогнозом + late String _docId; // Идентификатор документа с прогнозом final String userId; // Идентификатор Google-аккаунта участника оставившего прогноз final String tour; // Номер тура final List rate; // Список прогнозов - int _points; // Количество набранных очков + late int _points; // Количество набранных очков final String team; Forecast({ // Конструктор - @required this.userId, - @required this.tour, - @required this.rate, - @required this.team, + required this.userId, + required this.tour, + required this.rate, + required this.team, }); set docId(String docId) { @@ -27,7 +26,7 @@ class Forecast { int get points => _points; - factory Forecast.fromJson({Map json, String docId}) { + factory Forecast.fromJson({required Map json, required String docId}) { // Именованный конструктор для десериализации Forecast f = Forecast( userId: json['UserId'], diff --git a/team_c_f/lib/data/match.dart b/team_c_f/lib/old/data/match.dart similarity index 78% rename from team_c_f/lib/data/match.dart rename to team_c_f/lib/old/data/match.dart index d506bac..cee18d0 100644 --- a/team_c_f/lib/data/match.dart +++ b/team_c_f/lib/old/data/match.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - class Match { // Информация о матче final String home; // Хозяева @@ -11,15 +9,15 @@ class Match { Match({ // Базовый конструктов - @required this.home, - @required this.away, - @required this.time, - @required this.date, - @required this.score, - @required this.started, + required this.home, + required this.away, + required this.time, + required this.date, + required this.score, + required this.started, }); - factory Match.fromJson({Map json}) { + factory Match.fromJson({required Map json}) { // Именованный конструктор, используемый при десериализации return Match( home: json['Home'], diff --git a/team_c_f/lib/data/player.dart b/team_c_f/lib/old/data/player.dart similarity index 74% rename from team_c_f/lib/data/player.dart rename to team_c_f/lib/old/data/player.dart index fbb3d29..ef885e9 100644 --- a/team_c_f/lib/data/player.dart +++ b/team_c_f/lib/old/data/player.dart @@ -1,10 +1,8 @@ -import 'package:flutter/material.dart'; - class Player { // Информация об участнике - String docId; // Идентификатор документа с информацией об участнике + late String docId; // Идентификатор документа с информацией об участнике final String name; // Имя и фамилия участника - String uid; // Идентификатор Google-аккаунта участника + late String uid; // Идентификатор Google-аккаунта участника bool capitan; // Флаг капитана bool confirmed; // Флаг подтверждения участия в команде String team; // Название команды @@ -13,18 +11,18 @@ class Player { Player({ // Конструктор - @required this.name, - @required String uid, - @required this.capitan, - @required this.team, - @required this.confirmed, + required this.name, + required String uid, + required this.capitan, + required this.team, + required this.confirmed, this.points = 0, this.position = 1, }) { this.uid = uid; } - factory Player.fromJson({Map json, String docId}) { + factory Player.fromJson({required Map json, required String docId}) { // Именованный конструктор для десериализации Player p = Player( name: json['Name'], diff --git a/team_c_f/lib/data/push.dart b/team_c_f/lib/old/data/push.dart similarity index 75% rename from team_c_f/lib/data/push.dart rename to team_c_f/lib/old/data/push.dart index 5bec592..fa2dd15 100644 --- a/team_c_f/lib/data/push.dart +++ b/team_c_f/lib/old/data/push.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class Push { @@ -6,19 +5,19 @@ class Push { final String ruTitle; final String enContent; final String ruContent; - final DateTime date; + final DateTime? date; Push({ - @required this.enTitle, - @required this.ruTitle, - @required this.enContent, - @required this.ruContent, + required this.enTitle, + required this.ruTitle, + required this.enContent, + required this.ruContent, this.date, }); String toJson() { String lateSend = (date != null) - ? '"send_after": "${DateFormat('yyyy-MM-dd HH:mm:ss').format(date)}",' + ? '"send_after": "${DateFormat('yyyy-MM-dd HH:mm:ss').format(date!)}",' : ''; return '{"app_id": "93b27d54-e442-4af5-86e4-a215faf20e3a",' + '"headings" : {"en": "$enTitle", "ru": "$ruTitle"},' + diff --git a/team_c_f/lib/data/schedule.dart b/team_c_f/lib/old/data/schedule.dart similarity index 80% rename from team_c_f/lib/data/schedule.dart rename to team_c_f/lib/old/data/schedule.dart index 71df023..ccf09fd 100644 --- a/team_c_f/lib/data/schedule.dart +++ b/team_c_f/lib/old/data/schedule.dart @@ -1,11 +1,10 @@ import 'dart:convert'; -import 'package:team_c_f/data/match.dart'; -import 'package:flutter/material.dart'; +import 'package:team_c_f/old/data/match.dart'; import 'package:intl/intl.dart'; class Tour { // Информация о туре - String docId; // Идентификатор документа с информацией о туре + late String docId; // Идентификатор документа с информацией о туре final String tour; // Номер тура final List pair; // Список участников тура List matches = []; // Список матчей тура @@ -16,22 +15,22 @@ class Tour { Tour.basic({ // Именованный конструктор, используемый администраторами для создания расписания - @required this.tour, - @required this.pair, + required this.tour, + required this.pair, }); Tour({ // Конструктор - @required this.tour, - @required this.pair, - @required this.matches, - @required this.deadline, - @required this.ending, + required this.tour, + required this.pair, + required this.matches, + required this.deadline, + required this.ending, }); bool get show => _show; - factory Tour.fromJson({Map json, String docId}) { + factory Tour.fromJson({required Map json, required String docId}) { // Именованный конструктор, используемый для десериализации Tour t = Tour( tour: json['Tour'], diff --git a/team_c_f/lib/data/shortmatch.dart b/team_c_f/lib/old/data/shortmatch.dart similarity index 81% rename from team_c_f/lib/data/shortmatch.dart rename to team_c_f/lib/old/data/shortmatch.dart index 43e9ce0..f984565 100644 --- a/team_c_f/lib/data/shortmatch.dart +++ b/team_c_f/lib/old/data/shortmatch.dart @@ -1,16 +1,16 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/match.dart'; +import 'package:team_c_f/old/data/match.dart'; class ShortMatch extends Match { // Основаная информация о матче, используется при выборе матчей String tournament; bool selected = false; ShortMatch({ - String home, - String away, - String time, - String date, - @required this.tournament, + required String home, + required String away, + required String time, + required String date, + required this.tournament, }) : super( home: home, away: away, diff --git a/team_c_f/lib/data/team.dart b/team_c_f/lib/old/data/team.dart similarity index 79% rename from team_c_f/lib/data/team.dart rename to team_c_f/lib/old/data/team.dart index 6259ae1..b5b9b7f 100644 --- a/team_c_f/lib/data/team.dart +++ b/team_c_f/lib/old/data/team.dart @@ -1,10 +1,8 @@ import 'dart:convert'; -import 'package:flutter/material.dart'; - class Team { // Информация о команде - String docId; // Идентификатор документа с командой на сервере + late String docId; // Идентификатор документа с командой на сервере final String title; // Название команды final List members; // Список участников int points = 0; // Количество очков в чемпионате @@ -12,13 +10,13 @@ class Team { Team({ // Конструктор - @required this.title, - @required this.members, + required this.title, + required this.members, this.points = 0, this.position = 1, }); - factory Team.fromJson({Map json, String docId}) { + factory Team.fromJson({required Map json, required String docId}) { // Именованный конструктор, используемый при десериализации Team t = Team( title: json['Title'], diff --git a/team_c_f/lib/data/tournament.dart b/team_c_f/lib/old/data/tournament.dart similarity index 85% rename from team_c_f/lib/data/tournament.dart rename to team_c_f/lib/old/data/tournament.dart index f7b5937..da5586e 100644 --- a/team_c_f/lib/data/tournament.dart +++ b/team_c_f/lib/old/data/tournament.dart @@ -1,26 +1,26 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:team_c_f/data/currenttour.dart'; -import 'package:team_c_f/data/forecast.dart'; -import 'package:team_c_f/data/player.dart'; -import 'package:team_c_f/data/push.dart'; -import 'package:team_c_f/data/schedule.dart'; -import 'package:team_c_f/data/shortmatch.dart'; -import 'package:team_c_f/data/team.dart'; -import 'package:team_c_f/servise/operationdb.dart'; +import 'package:team_c_f/old/data/currenttour.dart'; +import 'package:team_c_f/old/data/forecast.dart'; +import 'package:team_c_f/old/data/player.dart'; +import 'package:team_c_f/old/data/push.dart'; +import 'package:team_c_f/old/data/schedule.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; +import 'package:team_c_f/old/data/team.dart'; +import 'package:team_c_f/old/servise/operationdb.dart'; import 'package:intl/intl.dart'; import 'package:http/http.dart' as http; class Tournament with ChangeNotifier { // Класс хранящий актуальную информацию с сервера - List allTeams = []; // Все команды - CurrentTour current; // Информацию о текущем туре - List schedule = []; // Расписание - List currentForecasts = []; // Прогнозы на текущий тур - List allPlayers = []; // Все игроки - Player me; // Текущий игрок - Team myTeam; // Моя команда - String selectTour = ''; // Тур для просмотра + late List allTeams = []; // Все команды + late CurrentTour current; // Информацию о текущем туре + late List schedule = []; // Расписание + late List currentForecasts = []; // Прогнозы на текущий тур + late List allPlayers = []; // Все игроки + late Player me; // Текущий игрок + late Team? myTeam; // Моя команда + late String selectTour = ''; // Тур для просмотра // bool leaveForecastForSelectedTour = // false; // Оставлен ли прогноз на текущий тур @@ -32,7 +32,7 @@ class Tournament with ChangeNotifier { current = currentTour; Stream> streamCurrentForecast = - DatabaseService().getCurrentForecasts(stage: current.tour); + DatabaseService().getCurrentForecasts(stage: current.tour!); streamCurrentForecast.listen( (List forecasts) { currentForecasts = forecasts; @@ -79,13 +79,12 @@ class Tournament with ChangeNotifier { curr.sort((a, b) => a.tour[6].compareTo(b.tour[6])); schedule.addAll([...curr]); - // schedule.sort((a, b) => a.tour.length.compareTo(b.tour.length)); notifyListeners(); }, ); } - Future checkForecast({@required String stage}) async { + Future checkForecast({required String stage}) async { return DatabaseService().checkForecast(uid: me.uid, stage: stage); } @@ -99,7 +98,7 @@ class Tournament with ChangeNotifier { : []; } - void initMeAndMyTeam({@required String uid}) { + void initMeAndMyTeam({required String uid}) { // Инициализация для более быстрой работы if (allPlayers.isNotEmpty) me = allPlayers.where((player) => player.uid == uid).single; @@ -146,7 +145,7 @@ class Tournament with ChangeNotifier { notifyListeners(); } - void confirmPlayer({@required String uid, @required bool confirm}) { + void confirmPlayer({required String uid, required bool confirm}) { // Подтверждение игрока и доабвление его в команду Player p = allPlayers.where((player) => player.uid == uid).single; Team t = allTeams.where((team) => team.title == p.team).single; @@ -156,7 +155,7 @@ class Tournament with ChangeNotifier { DatabaseService().updatePlayer(player: p); } - void removePlayerFromMyTeam({@required String uid}) { + void removePlayerFromMyTeam({required String uid}) { // Удаление игрока из команды и обнуление команды у игрока Player p = allPlayers.where((player) => player.uid == uid).first; Team t = allTeams.where((team) => team.title == p.team).first; @@ -167,7 +166,7 @@ class Tournament with ChangeNotifier { DatabaseService().updatePlayer(player: p); } - void createSchedule({@required List tours}) { + void createSchedule({required List tours}) { //Создание расписания tours.forEach( (tour) { @@ -185,7 +184,7 @@ class Tournament with ChangeNotifier { notifyListeners(); } - Future getTour({@required String tour}) async { + Future getTour({required String tour}) async { // Получение информации о туре Tour t = await DatabaseService().getTour(stage: tour).first; schedule.setAll( @@ -193,19 +192,19 @@ class Tournament with ChangeNotifier { return t; } - Future makeForecast({@required Forecast forecast}) { + Future makeForecast({required Forecast forecast}) { return DatabaseService().makeForecast(forecast: forecast).then( (response) => DatabaseService() .checkForecast(uid: me.uid, stage: forecast.tour), ); } - Future getCurrentForecast({@required String stage}) { + Future getCurrentForecast({required String stage}) { return DatabaseService().getForecast(uid: me.uid, tour: stage); } void createMatchesForTour( - {@required List matches, String stage}) { + {required List matches, String? stage}) { // Добавление матчей для прогнозирования на сервер Tour t = schedule.where((tour) => tour.tour == stage).single; matches.sort( @@ -232,7 +231,7 @@ class Tournament with ChangeNotifier { String notifyNow = Push( enTitle: 'New tour', enContent: - 'You can leave a forecast for ${!stage.contains(' ') ? '$stage round' : stage}', + 'You can leave a forecast for ${!stage!.contains(' ') ? '$stage round' : stage}', ruTitle: 'Новый тур', ruContent: 'Можно оставить прогноз на ${!stage.contains(' ') ? '$stage тур' : '$stage'}', diff --git a/team_c_f/lib/element/createschedule.dart b/team_c_f/lib/old/element/createschedule.dart similarity index 95% rename from team_c_f/lib/element/createschedule.dart rename to team_c_f/lib/old/element/createschedule.dart index 1e82b56..7a8ff20 100644 --- a/team_c_f/lib/element/createschedule.dart +++ b/team_c_f/lib/old/element/createschedule.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/schedule.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/servise/make.dart'; +import 'package:team_c_f/old/data/schedule.dart'; +import 'package:team_c_f/old/data/tournament.dart'; +import 'package:team_c_f/old/servise/make.dart'; class CreateSchedule extends StatefulWidget { // Класс отображающий виджет для создания основы расписания - const CreateSchedule({Key key}) : super(key: key); + const CreateSchedule({Key? key}) : super(key: key); @override _CreateScheduleState createState() => _CreateScheduleState(); diff --git a/team_c_f/lib/element/forecast.dart b/team_c_f/lib/old/element/forecast.dart similarity index 94% rename from team_c_f/lib/element/forecast.dart rename to team_c_f/lib/old/element/forecast.dart index 75e2bd8..170fa8d 100644 --- a/team_c_f/lib/element/forecast.dart +++ b/team_c_f/lib/old/element/forecast.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/match.dart'; -import 'package:team_c_f/page/leaveforecast.dart'; +import 'package:team_c_f/old/data/match.dart'; +import 'package:team_c_f/old/page/leaveforecast.dart'; class ForecastView extends StatefulWidget { final int index; final Match match; ForecastView({ - Key key, - @required this.match, - @required this.index, + Key? key, + required this.match, + required this.index, }) : super(key: key); @override @@ -16,8 +16,8 @@ class ForecastView extends StatefulWidget { } class _ForecastViewState extends State { - String home; - String away; + String? home; + String? away; List numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; int get index => widget.index; @@ -62,7 +62,7 @@ class _ForecastViewState extends State { setState( () { home = result; - LeaveForecast.rate[index] = home + + LeaveForecast.rate[index] = home! + '-' + LeaveForecast.rate[index].split('-')[1]; }, @@ -95,7 +95,7 @@ class _ForecastViewState extends State { LeaveForecast.rate[index] = LeaveForecast.rate[index].split('-')[0] + '-' + - away; + away!; }, ); }, diff --git a/team_c_f/lib/element/match.dart b/team_c_f/lib/old/element/match.dart similarity index 95% rename from team_c_f/lib/element/match.dart rename to team_c_f/lib/old/element/match.dart index 7f46934..8a04f90 100644 --- a/team_c_f/lib/element/match.dart +++ b/team_c_f/lib/old/element/match.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/match.dart'; +import 'package:team_c_f/old/data/match.dart'; import 'package:intl/intl.dart'; class MatchView extends StatelessWidget { // Показ одного выбранного матча для прогнозирования final Match match; - const MatchView({Key key, this.match}) : super(key: key); + const MatchView({Key? key, required this.match}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/element/meet.dart b/team_c_f/lib/old/element/meet.dart similarity index 86% rename from team_c_f/lib/element/meet.dart rename to team_c_f/lib/old/element/meet.dart index 182a82b..3a429fa 100644 --- a/team_c_f/lib/element/meet.dart +++ b/team_c_f/lib/old/element/meet.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class MeetView extends StatelessWidget { // Показ одного выбранного матча для прогнозирования final String match; - const MeetView({Key key, this.match}) : super(key: key); + const MeetView({Key? key, required this.match}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/element/notconfirmedplayer.dart b/team_c_f/lib/old/element/notconfirmedplayer.dart similarity index 91% rename from team_c_f/lib/element/notconfirmedplayer.dart rename to team_c_f/lib/old/element/notconfirmedplayer.dart index 36b1d10..958e80a 100644 --- a/team_c_f/lib/element/notconfirmedplayer.dart +++ b/team_c_f/lib/old/element/notconfirmedplayer.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:team_c_f/data/player.dart'; -import 'package:team_c_f/data/tournament.dart'; +import 'package:team_c_f/old/data/player.dart'; +import 'package:team_c_f/old/data/tournament.dart'; import 'package:provider/provider.dart'; class PlayerToConfirm extends StatelessWidget { // Класс, для отображения неподтвержденных игроков final Player player; // Неподтвержденный игрок - PlayerToConfirm({Key key, @required this.player}) : super(key: key); + PlayerToConfirm({Key? key, required this.player}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/old/element/player.dart b/team_c_f/lib/old/element/player.dart new file mode 100644 index 0000000..0d491f9 --- /dev/null +++ b/team_c_f/lib/old/element/player.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/old/data/player.dart'; +import 'package:team_c_f/old/servise/make.dart'; +import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/old/data/tournament.dart'; + +class ShowPlayer extends StatelessWidget { + // Класс отображающий информацию об указанном игроке + final Player player; + ShowPlayer({Key? key, required this.player}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + child: InkWell( + onLongPress: () async { + if (context.read().me.capitan && + (await showAlertDialog( + context: context, + title: 'Изменение состава', + message: 'Удалить ${player.name}', + actions: [ + AlertDialogAction( + key: true, + label: 'Да, удалить', + isDefaultAction: true, + ), + AlertDialogAction( + key: false, + label: 'Отмена', + isDestructiveAction: true, + ), + ], + ))!) { + context.read().removePlayerFromMyTeam(uid: player.uid); + } + }, + child: Card( + child: ListTile( + leading: CircleAvatar( + child: Text(player.position.toString()), + ), + title: Text(player.name), + trailing: Text(showPoints(player.points)), + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/element/schedule.dart b/team_c_f/lib/old/element/schedule.dart similarity index 87% rename from team_c_f/lib/element/schedule.dart rename to team_c_f/lib/old/element/schedule.dart index e3e3218..d26d3b6 100644 --- a/team_c_f/lib/element/schedule.dart +++ b/team_c_f/lib/old/element/schedule.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/schedule.dart'; +import 'package:team_c_f/old/data/schedule.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/tournament.dart'; +import 'package:team_c_f/old/data/tournament.dart'; class TourView extends StatelessWidget { // Элементы, отвечающие за вид туров при их выборе final Tour tour; - const TourView({Key key, @required this.tour}) : super(key: key); + const TourView({Key? key, required this.tour}) : super(key: key); @override Widget build(BuildContext context) { @@ -19,7 +19,7 @@ class TourView extends StatelessWidget { // Элементы, отвечающи : tour.tour.length != 12 ? tour.tour.substring(4) : tour.tour.substring(6); - TextStyle styleTitle = tour.tour.length != 12 + TextStyle? styleTitle = tour.tour.length != 12 ? Theme.of(context).textTheme.headline5 : Theme.of(context).textTheme.headline6; return Container( diff --git a/team_c_f/lib/element/selectTeam.dart b/team_c_f/lib/old/element/selectTeam.dart similarity index 96% rename from team_c_f/lib/element/selectTeam.dart rename to team_c_f/lib/old/element/selectTeam.dart index 498dca2..2a62f78 100644 --- a/team_c_f/lib/element/selectTeam.dart +++ b/team_c_f/lib/old/element/selectTeam.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:team_c_f/data/data.dart'; -import 'package:team_c_f/data/tournament.dart'; +import 'package:team_c_f/old/data/data.dart'; +import 'package:team_c_f/old/data/tournament.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/servise/operationdb.dart'; +import 'package:team_c_f/old/servise/operationdb.dart'; class SelectTeam extends StatefulWidget { // Класс отображения выбора команды или регистрации новой final String message; - final String name; - SelectTeam({Key key, @required this.message, this.name}) : super(key: key); + final String? name; + SelectTeam({Key? key, required this.message, this.name}) : super(key: key); @override _SelectTeamState createState() => _SelectTeamState(); @@ -17,7 +17,7 @@ class SelectTeam extends StatefulWidget { class _SelectTeamState extends State { TextEditingController teamController = TextEditingController(); - String teamSelect; + String? teamSelect; bool capitan = false; @override Widget build(BuildContext context) { @@ -43,7 +43,7 @@ class _SelectTeamState extends State { onChanged: (value) { setState( () { - capitan = value; + capitan = value!; }, ); }, diff --git a/team_c_f/lib/element/team.dart b/team_c_f/lib/old/element/team.dart similarity index 84% rename from team_c_f/lib/element/team.dart rename to team_c_f/lib/old/element/team.dart index 8006eab..27d8305 100644 --- a/team_c_f/lib/element/team.dart +++ b/team_c_f/lib/old/element/team.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/team.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/element/player.dart'; +import 'package:team_c_f/old/data/team.dart'; +import 'package:team_c_f/old/data/tournament.dart'; +import 'package:team_c_f/old/element/player.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/servise/make.dart'; +import 'package:team_c_f/old/servise/make.dart'; class ShowTeam extends StatelessWidget { // Класс отображения информации об указанной команде final Team team; // Команда - ShowTeam({Key key, @required this.team}) : super(key: key); + ShowTeam({Key? key, required this.team}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/element/tour.dart b/team_c_f/lib/old/element/tour.dart similarity index 79% rename from team_c_f/lib/element/tour.dart rename to team_c_f/lib/old/element/tour.dart index 974236d..a47a06f 100644 --- a/team_c_f/lib/element/tour.dart +++ b/team_c_f/lib/old/element/tour.dart @@ -1,25 +1,25 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/forecast.dart'; -import 'package:team_c_f/data/schedule.dart'; -import 'package:team_c_f/data/shortmatch.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/element/meet.dart'; -import 'package:team_c_f/element/match.dart'; -import 'package:team_c_f/page/leaveforecast.dart'; -import 'package:team_c_f/page/selectmatch.dart'; +import 'package:team_c_f/old/data/forecast.dart'; +import 'package:team_c_f/old/data/schedule.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; +import 'package:team_c_f/old/data/tournament.dart'; +import 'package:team_c_f/old/element/meet.dart'; +import 'package:team_c_f/old/element/match.dart'; +import 'package:team_c_f/old/page/leaveforecast.dart'; +import 'package:team_c_f/old/page/selectmatch.dart'; class ShowTour extends StatefulWidget { // Класс, отображающий результаты выбранного тура тура - final String tour; - ShowTour({Key key, this.tour}) : super(key: key); + final String? tour; + ShowTour({Key? key, this.tour}) : super(key: key); @override _ShowTourState createState() => _ShowTourState(); } class _ShowTourState extends State { - Tour selectTour; + Tour? selectTour; bool leaveForecast = false; @override @@ -28,11 +28,9 @@ class _ShowTourState extends State { context .read() .getTour( - tour: widget.tour == null - ? context.read().selectTour == null - ? '1' - : context.read().selectTour - : widget.tour) + tour: (widget.tour == null + ? context.read().selectTour + : widget.tour)!) .then( (value) { setState( @@ -40,12 +38,12 @@ class _ShowTourState extends State { selectTour = value; }, ); - context.read().checkForecast(stage: selectTour.tour).then( - (response) { + context.read().checkForecast(stage: selectTour!.tour).then( + (bool response) async { LeaveForecast.rate = response - ? context + ? (await context .read() - .getCurrentForecast(stage: selectTour.tour) + .getCurrentForecast(stage: selectTour!.tour)).rate : ['-', '-', '-', '-', '-', '-', '-', '-', '-', '-']; setState(() { leaveForecast = response; @@ -64,13 +62,13 @@ class _ShowTourState extends State { Card( color: Colors.yellow, child: ListTile( - leading: Text(selectTour.tour), + leading: Text(selectTour!.tour), title: Text( - '${selectTour.matches.where((element) => element.started).length}/10 матчей'), + '${selectTour!.matches.where((element) => element.started).length}/10 матчей'), ), ), SizedBox(height: 20), - selectTour.matches.length == 10 + selectTour!.matches.length == 10 ? Column( children: [ Wrap( @@ -79,11 +77,11 @@ class _ShowTourState extends State { spacing: 10, runSpacing: 10, children: [ - ...selectTour.matches + ...selectTour!.matches .map((match) => MatchView(match: match)), ], ), - if (DateTime.now().isBefore(selectTour.deadline)) + if (DateTime.now().isBefore(selectTour!.deadline)) Column( children: [ SizedBox(height: 20), @@ -94,12 +92,12 @@ class _ShowTourState extends State { MaterialPageRoute>( builder: (BuildContext context) { return LeaveForecast( - tour: selectTour, + tour: selectTour!, ); }, ), ).then( - (List value) { + (List? value) { //context.read() //! отправка прогноза if (value != null) { @@ -134,7 +132,7 @@ class _ShowTourState extends State { Navigator.of(context).push( MaterialPageRoute>( builder: (BuildContext context) { - return SelectMatch(stage: selectTour.tour); + return SelectMatch(stage: selectTour!.tour); }, ), ).then( @@ -153,7 +151,7 @@ class _ShowTourState extends State { spacing: 10, runSpacing: 10, children: [ - ...selectTour.pair.map((pair) => MeetView(match: pair)), + ...selectTour!.pair.map((pair) => MeetView(match: pair)), ], ), ], diff --git a/team_c_f/lib/old/oldmain.dart b/team_c_f/lib/old/oldmain.dart new file mode 100644 index 0000000..3d9939e --- /dev/null +++ b/team_c_f/lib/old/oldmain.dart @@ -0,0 +1,81 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +// import 'package:team_c_f/data/data.dart'; +// import 'package:team_c_f/data/shortmatch.dart'; +// import 'package:team_c_f/data/tournament.dart'; +// import 'package:team_c_f/page/home.dart'; +// import 'package:team_c_f/page/sign.dart'; +import 'package:firebase_core/firebase_core.dart'; +// ignore: import_of_legacy_library_into_null_safe +import 'package:onesignal_flutter/onesignal_flutter.dart'; + +Future main() async { + myApp(); +} + +myApp() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(); // Инициализация Firebase + + OneSignal.shared.setAppId('93b27d54-e442-4af5-86e4-a215faf20e3a'); + + runApp( + MultiProvider( + // Мультипровайдер, для упроощения взаимодействия с данными + providers: [ + // ChangeNotifierProvider( + // create: (context) => Account(), + // ), // Данные связанные с аутентификацией (гугл-вход и регистрация в приложении) + // ChangeNotifierProvider( + // create: (context) => Tournament(), + // ), // Данные полученные из Firebase + // ChangeNotifierProvider( + // create: (context) => DataMatch(), + // ), + ], + child: MaterialApp( + // theme: ThemeData( + // textTheme: TextTheme( + // bodyText2: TextStyle( + // color: Colors.black, + // fontWeight: FontWeight.normal, + // ), + // bodyText1: TextStyle( + // color: Colors.black, + // decoration: TextDecoration.lineThrough, + // fontWeight: FontWeight.normal, + // ), + // caption: TextStyle( + // color: Colors.green, + // fontWeight: FontWeight.w400, + // ), + // ), + // ), + home: SafeArea( + child: Page(), + ), + ), + ), + ); +} + +class Page extends StatefulWidget { + const Page({Key? key}) : super(key: key); + + @override + _PageState createState() => _PageState(); +} + +class _PageState extends State { + @override + Widget build(BuildContext context) { + return Container( + // child: context + // .watch() + // .registedInApp // Проверка зарегистрирован ли пользователь в приложении + // ? Homepage() // Домашняя страница приложения + // : Sign(), // Регистрация в приложении + вход в гугл + ); + } +} \ No newline at end of file diff --git a/team_c_f/lib/page/home.dart b/team_c_f/lib/old/page/home.dart similarity index 86% rename from team_c_f/lib/page/home.dart rename to team_c_f/lib/old/page/home.dart index f130359..2754ecf 100644 --- a/team_c_f/lib/page/home.dart +++ b/team_c_f/lib/old/page/home.dart @@ -1,19 +1,19 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/currenttour.dart'; -import 'package:team_c_f/element/tour.dart'; -import 'package:team_c_f/view/emptyschedule.dart'; -import 'package:team_c_f/view/scorers.dart'; -import 'package:team_c_f/view/table.dart'; -import 'package:team_c_f/view/team.dart'; +import 'package:team_c_f/old/data/currenttour.dart'; +import 'package:team_c_f/old/element/tour.dart'; +import 'package:team_c_f/old/view/emptyschedule.dart'; +import 'package:team_c_f/old/view/scorers.dart'; +import 'package:team_c_f/old/view/table.dart'; +import 'package:team_c_f/old/view/team.dart'; import 'package:custom_navigation_bar/custom_navigation_bar.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/old/data/tournament.dart'; +import 'package:team_c_f/old/data/data.dart'; class Homepage extends StatefulWidget { // Класс отображающий домашнюю страницу с баром снизу - const Homepage({Key key}) : super(key: key); + const Homepage({Key? key}) : super(key: key); @override _HomepageState createState() => _HomepageState(); @@ -42,7 +42,7 @@ class _HomepageState extends State { : ShowTable() : selectedPage > 0 ? selectedPage == 2 - ? ShowTour(tour: current != null ? current.tour : null) + ? ShowTour(tour: current.tour) : ScheduleView() : TeamView(), bottomNavigationBar: CustomNavigationBar( diff --git a/team_c_f/lib/page/leaveforecast.dart b/team_c_f/lib/old/page/leaveforecast.dart similarity index 88% rename from team_c_f/lib/page/leaveforecast.dart rename to team_c_f/lib/old/page/leaveforecast.dart index 1d64348..cd73740 100644 --- a/team_c_f/lib/page/leaveforecast.dart +++ b/team_c_f/lib/old/page/leaveforecast.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/schedule.dart'; -import 'package:team_c_f/element/forecast.dart'; -import 'package:team_c_f/data/match.dart'; +import 'package:team_c_f/old/data/schedule.dart'; +import 'package:team_c_f/old/element/forecast.dart'; +import 'package:team_c_f/old/data/match.dart'; class LeaveForecast extends StatefulWidget { final Tour tour; - const LeaveForecast({Key key, this.tour}) : super(key: key); + const LeaveForecast({Key? key, required this.tour}) : super(key: key); static List rate = ['-', '-', '-', '-', '-', '-', '-', '-', '-', '-']; diff --git a/team_c_f/lib/page/selectmatch.dart b/team_c_f/lib/old/page/selectmatch.dart similarity index 63% rename from team_c_f/lib/page/selectmatch.dart rename to team_c_f/lib/old/page/selectmatch.dart index 0bc6239..d51e1ef 100644 --- a/team_c_f/lib/page/selectmatch.dart +++ b/team_c_f/lib/old/page/selectmatch.dart @@ -1,16 +1,14 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/shortmatch.dart'; -import 'package:team_c_f/servise/htmlparse.dart'; -import 'package:team_c_f/servise/make.dart'; -import 'package:intl/intl.dart'; -import 'package:date_range_picker/date_range_picker.dart' as DateRangePicker; +import 'package:team_c_f/old/data/shortmatch.dart'; +import 'package:team_c_f/old/servise/htmlparse.dart'; +import 'package:team_c_f/old/servise/make.dart'; import 'package:http/http.dart' as http; class SelectMatch extends StatefulWidget { // Отображение выбора 10 матчей на тур final String stage; - SelectMatch({Key key, @required this.stage}) : super(key: key); + SelectMatch({Key? key, required this.stage}) : super(key: key); @override _SelectMatchState createState() => _SelectMatchState(); @@ -27,16 +25,18 @@ class _SelectMatchState extends State { (date) { http.Client() .get(Uri.parse('https://www.sports.ru/football/match/$date/')) - .then((value) { - context.read().add( - [ - ...getMatchs( - body: value.body, - date: '$date', - ) - ], - ); - }); + .then( + (value) { + context.read().add( + [ + ...getMatchs( + body: value.body, + date: '$date', + ) + ], + ); + }, + ); }, ); } @@ -58,24 +58,24 @@ class _SelectMatchState extends State { ElevatedButton( onPressed: () { range.clear(); - DateRangePicker.showDatePicker( - context: context, - initialFirstDate: DateTime.now(), - initialLastDate: DateTime.now(), - firstDate: DateTime(2021), - lastDate: DateTime(2040), - ).then((value) { - setState(() { - period = value; - for (DateTime i = value.first; - i.isBefore(value.last.add(Duration(minutes: 1))); - i = i.add(Duration(days: 1))) { - range.add(DateFormat('yyyy-MM-dd').format(i)); - } - }); - context.read().data.clear(); - download(); - }); + // DateRangePicker.showDatePicker( + // context: context, + // initialFirstDate: DateTime.now(), + // initialLastDate: DateTime.now(), + // firstDate: DateTime(2021), + // lastDate: DateTime(2040), + // ).then((value) { + // setState(() { + // period = value; + // for (DateTime i = value.first; + // i.isBefore(value.last.add(Duration(minutes: 1))); + // i = i.add(Duration(days: 1))) { + // range.add(DateFormat('yyyy-MM-dd').format(i)); + // } + // }); + // context.read().data.clear(); + // download(); + // }); }, child: Text('Выбрать даты'), ), diff --git a/team_c_f/lib/page/sign.dart b/team_c_f/lib/old/page/sign.dart similarity index 95% rename from team_c_f/lib/page/sign.dart rename to team_c_f/lib/old/page/sign.dart index d3ea08f..1a4b198 100644 --- a/team_c_f/lib/page/sign.dart +++ b/team_c_f/lib/old/page/sign.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/data.dart'; -import 'package:team_c_f/element/selectTeam.dart'; +import 'package:team_c_f/old/data/data.dart'; +import 'package:team_c_f/old/element/selectTeam.dart'; class Sign extends StatefulWidget { // Класс отображения страницы входа в Google-аккаунт и регистрации в приложении - Sign({Key key}) : super(key: key); + Sign({Key? key}) : super(key: key); @override _SignState createState() => _SignState(); diff --git a/team_c_f/lib/servise/auth.dart b/team_c_f/lib/old/servise/auth.dart similarity index 74% rename from team_c_f/lib/servise/auth.dart rename to team_c_f/lib/old/servise/auth.dart index 09f7b6d..8c6a4cf 100644 --- a/team_c_f/lib/servise/auth.dart +++ b/team_c_f/lib/old/servise/auth.dart @@ -4,16 +4,16 @@ import 'package:google_sign_in/google_sign_in.dart'; Future signInWithGoogle() async { // Выполнение входа в Google-аккаунт - final GoogleSignInAccount googleUser = await GoogleSignIn().signIn(); + final GoogleSignInAccount googleUser = (await GoogleSignIn().signIn())!; final GoogleSignInAuthentication googleAuth = await googleUser.authentication; - final GoogleAuthCredential credential = GoogleAuthProvider.credential( + final OAuthCredential credential = GoogleAuthProvider.credential( accessToken: googleAuth.accessToken, idToken: googleAuth.idToken, ); - return (await FirebaseAuth.instance.signInWithCredential(credential)).user; + return (await FirebaseAuth.instance.signInWithCredential(credential)).user!; } -Future signOutGoogle({BuildContext context}) async { +Future signOutGoogle({BuildContext? context}) async { // Выполнение выхода из Google-аккаунта FirebaseAuth.instance.signOut(); return GoogleSignIn().signOut().then((value) => true); diff --git a/team_c_f/lib/servise/htmlparse.dart b/team_c_f/lib/old/servise/htmlparse.dart similarity index 90% rename from team_c_f/lib/servise/htmlparse.dart rename to team_c_f/lib/old/servise/htmlparse.dart index 93ef346..8ae1bed 100644 --- a/team_c_f/lib/servise/htmlparse.dart +++ b/team_c_f/lib/old/servise/htmlparse.dart @@ -1,11 +1,10 @@ -import 'package:flutter/material.dart' as material; import 'package:html/dom.dart'; import 'package:html/parser.dart' show parse; -import 'package:team_c_f/data/shortmatch.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; List getMatchs({ - @material.required String body, // Html-текст страницы - @material.required String date, // Дата + required String body, // Html-текст страницы + required String date, // Дата }) { List m = []; Map> data = Map>(); diff --git a/team_c_f/lib/servise/make.dart b/team_c_f/lib/old/servise/make.dart similarity index 86% rename from team_c_f/lib/servise/make.dart rename to team_c_f/lib/old/servise/make.dart index 6af76e2..ace7bfd 100644 --- a/team_c_f/lib/servise/make.dart +++ b/team_c_f/lib/old/servise/make.dart @@ -1,10 +1,9 @@ -import 'package:flutter/widgets.dart'; -import 'package:team_c_f/data/shortmatch.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; import 'package:collection/collection.dart'; -import 'package:team_c_f/view/day.dart'; -import 'package:team_c_f/view/tournament.dart'; +import 'package:team_c_f/old/view/day.dart'; +import 'package:team_c_f/old/view/tournament.dart'; -List makeTournaments({List matches}) { +List makeTournaments({required List matches}) { // Функция группировки матчей по соревнованиям Map> gr = groupBy( matches, (obj) => obj.tournament); // Группировка матчей по соревнованиям @@ -70,7 +69,7 @@ String showTeam(int points) { : 'команд'); } -String showMatches({@required int teams, @required int circles}) { +String showMatches({required int teams, required int circles}) { int matches = (teams * (teams - 1) / 2).round() * circles; return matches.toString() + ' ' + @@ -81,7 +80,7 @@ String showMatches({@required int teams, @required int circles}) { : 'матчей'); } -String showTours({@required int teams, @required int circles}) { +String showTours({required int teams, required int circles}) { int tours = circles * (teams.isEven ? teams - 1 : teams); return tours.toString() + ' ' + @@ -93,12 +92,12 @@ String showTours({@required int teams, @required int circles}) { } int calculatePointPerMatch({ - @required String result, - @required String forecast, + required String result, + required String forecast, }) { // Фукнция подсчета очков за матч - List res = result.split('-').map((e) => int.parse(e)); - List forec = forecast.split('-').map((e) => int.parse(e)); + List res = result.split('-').map((e) => int.parse(e)).toList(); + List forec = forecast.split('-').map((e) => int.parse(e)).toList(); return res[0] - res[1] == forec[0] - forec[1] ? res[0] == forec[0] && res[1] == forec[1] ? 3 diff --git a/team_c_f/lib/servise/operationdb.dart b/team_c_f/lib/old/servise/operationdb.dart similarity index 84% rename from team_c_f/lib/servise/operationdb.dart rename to team_c_f/lib/old/servise/operationdb.dart index 2ae8823..0394929 100644 --- a/team_c_f/lib/servise/operationdb.dart +++ b/team_c_f/lib/old/servise/operationdb.dart @@ -1,11 +1,10 @@ import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:flutter/material.dart'; -import 'package:team_c_f/data/currenttour.dart'; -import 'package:team_c_f/data/forecast.dart'; -import 'package:team_c_f/data/player.dart'; -import 'package:team_c_f/data/schedule.dart'; -import 'package:team_c_f/data/team.dart'; -import 'package:team_c_f/data/match.dart'; +import 'package:team_c_f/old/data/currenttour.dart'; +import 'package:team_c_f/old/data/forecast.dart'; +import 'package:team_c_f/old/data/player.dart'; +import 'package:team_c_f/old/data/schedule.dart'; +import 'package:team_c_f/old/data/team.dart'; +import 'package:team_c_f/old/data/match.dart'; class DatabaseService { final CollectionReference currentCollection = @@ -42,7 +41,7 @@ class DatabaseService { ); } - Stream> getCurrentForecasts({@required String stage}) { + Stream> getCurrentForecasts({required String stage}) { // Получение всех прогнозов на текущий тур return forecastsCollection .where( @@ -76,7 +75,7 @@ class DatabaseService { ); } - Stream getTour({@required String stage}) { + Stream getTour({required String stage}) { // Получение информации о туре stage return scheduleCollection .where( @@ -106,7 +105,7 @@ class DatabaseService { ); } - Future userExists({@required String userId}) { + Future userExists({required String userId}) { // Проверка существует ли пользователь с указанным Google-аккаунтом return playersCollection .where('UserId', isEqualTo: userId) @@ -114,21 +113,21 @@ class DatabaseService { .then((value) => value.docs.length == 1); } - Future registrationPlayer({@required Player player}) { + Future registrationPlayer({required Player player}) { // Регистрация игрока return playersCollection .add(player.toMap()) .then((response) => player.docId = response.id); } - Future registrationTeam({@required Team team}) { + Future registrationTeam({required Team team}) { // Регистрация команды return teamsCollection .add(team.toMap()) .then((response) => team.docId = response.id); } - Future checkTeamName({@required String name}) { + Future checkTeamName({required String name}) { // Проверка названия команды на уникальность return teamsCollection .where('Title', isEqualTo: name) @@ -136,28 +135,28 @@ class DatabaseService { .then((response) => response.docs.length == 0); } - void updatePlayer({@required Player player}) { + void updatePlayer({required Player player}) { // Обновление информации об игроке playersCollection.doc(player.docId).update( player.toMap(), ); } - void updateTeam({@required Team team}) { + void updateTeam({required Team team}) { // Обновление информации о команде teamsCollection.doc(team.docId).update( team.toMap(), ); } - void addTour({@required Tour tour}) { + void addTour({required Tour tour}) { // Добавление тура на сервер scheduleCollection .add(tour.toMap()) .then((reaponse) => tour.docId = reaponse.id); } - void updateTour({@required Tour tour}) { + void updateTour({required Tour tour}) { // Обновление тура на сервере scheduleCollection.doc(tour.docId).update( tour.toMap(), @@ -172,8 +171,8 @@ class DatabaseService { //! Выше используется и не требует изменений Future checkForecast({ - @required String uid, - @required String stage, + required String uid, + required String stage, }) { return forecastsCollection .where( @@ -185,7 +184,7 @@ class DatabaseService { .then((QuerySnapshot response) => response.docs.length == 1); } - Future makeForecast({@required Forecast forecast}) async { + Future makeForecast({required Forecast forecast}) async { // Создание прогноза return forecastsCollection .add(forecast.toMap()) @@ -193,8 +192,8 @@ class DatabaseService { } Future getForecast({ - @required String uid, - @required String tour, + required String uid, + required String tour, }) async { // Получение прогноза указанного пользователя на указанный тур Query query = forecastsCollection @@ -204,7 +203,7 @@ class DatabaseService { (QuerySnapshot value) => value.docs .map( (DocumentSnapshot doc) => Forecast.fromJson( - json: doc.data(), + json: doc.data()!, docId: doc.id, ), ) @@ -212,14 +211,14 @@ class DatabaseService { ); } - Future> getForecasts({String tour}) async { + Future> getForecasts({required String tour}) async { // Получение всех прогноз на указанный тур Query query = forecastsCollection.where('Tour', isEqualTo: tour); return query.get().then( (QuerySnapshot value) => value.docs .map( (DocumentSnapshot doc) => Forecast.fromJson( - json: doc.data(), + json: doc.data()!, docId: doc.id, ), ) @@ -228,7 +227,7 @@ class DatabaseService { } //! Использовать для обновления результатов с сервера - Future> getResults({String tour}) { + Future> getResults({required String tour}) { // Получение результатов матчей return scheduleCollection .where( @@ -245,7 +244,7 @@ class DatabaseService { } //! Обновление результатов на сервера - void updateResults({Tour tour}) { + void updateResults({required Tour tour}) { // Обновление результатов матчей конкретного тура scheduleCollection.doc(tour.docId).update( tour.toMap(), diff --git a/team_c_f/lib/view/day.dart b/team_c_f/lib/old/view/day.dart similarity index 93% rename from team_c_f/lib/view/day.dart rename to team_c_f/lib/old/view/day.dart index 033ea3b..304e0e0 100644 --- a/team_c_f/lib/view/day.dart +++ b/team_c_f/lib/old/view/day.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/shortmatch.dart'; -import 'package:team_c_f/servise/make.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; +import 'package:team_c_f/old/servise/make.dart'; class DayView extends StatefulWidget { // Класс, отобращающий все соревнования, в которых есть матчи, в текущий день final String date; // Дата final List matches; // Список матчей для отображения const DayView({ - Key key, - @required this.date, - @required this.matches, + Key? key, + required this.date, + required this.matches, }) : super(key: key); @override diff --git a/team_c_f/lib/view/emptyschedule.dart b/team_c_f/lib/old/view/emptyschedule.dart similarity index 81% rename from team_c_f/lib/view/emptyschedule.dart rename to team_c_f/lib/old/view/emptyschedule.dart index b9b61c8..31361f2 100644 --- a/team_c_f/lib/view/emptyschedule.dart +++ b/team_c_f/lib/old/view/emptyschedule.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/element/createschedule.dart'; -import 'package:team_c_f/element/tour.dart'; -import 'package:team_c_f/view/schedule.dart'; +import 'package:team_c_f/old/data/tournament.dart'; +import 'package:team_c_f/old/element/createschedule.dart'; +import 'package:team_c_f/old/element/tour.dart'; +import 'package:team_c_f/old/view/schedule.dart'; class ScheduleView extends StatefulWidget { // Если расписание отсутствует - const ScheduleView({Key key}) : super(key: key); + const ScheduleView({Key? key}) : super(key: key); @override _ScheduleViewState createState() => _ScheduleViewState(); diff --git a/team_c_f/lib/view/forecast.dart b/team_c_f/lib/old/view/forecast.dart similarity index 86% rename from team_c_f/lib/view/forecast.dart rename to team_c_f/lib/old/view/forecast.dart index 2d33d45..4f2f69a 100644 --- a/team_c_f/lib/view/forecast.dart +++ b/team_c_f/lib/old/view/forecast.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; class MakeForecast extends StatelessWidget { // Класс, позволяющий сделать прогноз на следующий тур - const MakeForecast({Key key}) : super(key: key); + const MakeForecast({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/view/match.dart b/team_c_f/lib/old/view/match.dart similarity index 87% rename from team_c_f/lib/view/match.dart rename to team_c_f/lib/old/view/match.dart index d661277..0d977b5 100644 --- a/team_c_f/lib/view/match.dart +++ b/team_c_f/lib/old/view/match.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/shortmatch.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; class MatchView extends StatefulWidget { // Класс, отображащий информацию о матче, при выборе матчей final ShortMatch match; // Краткая информация о матче const MatchView({ - Key key, - @required this.match, + Key? key, + required this.match, }) : super(key: key); @override @@ -33,7 +33,7 @@ class _MatchViewState extends State { value: selected, title: Text('$time. $home - $away'), onChanged: (a) { - context.read().selectMatch(widget.match, a); + context.read().selectMatch(widget.match, a!); }, ), ); diff --git a/team_c_f/lib/view/meet.dart b/team_c_f/lib/old/view/meet.dart similarity index 100% rename from team_c_f/lib/view/meet.dart rename to team_c_f/lib/old/view/meet.dart diff --git a/team_c_f/lib/view/schedule.dart b/team_c_f/lib/old/view/schedule.dart similarity index 86% rename from team_c_f/lib/view/schedule.dart rename to team_c_f/lib/old/view/schedule.dart index 221c04e..5f8e8f7 100644 --- a/team_c_f/lib/view/schedule.dart +++ b/team_c_f/lib/old/view/schedule.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/data/tournament.dart'; -import 'package:team_c_f/element/schedule.dart'; +import 'package:team_c_f/old/data/tournament.dart'; +import 'package:team_c_f/old/element/schedule.dart'; class ShowSchedules extends StatefulWidget { // Класс, отображающий результаты тура, по умолчанию текущего - const ShowSchedules({Key key}) : super(key: key); + const ShowSchedules({Key? key}) : super(key: key); @override _ShowSchedulesState createState() => _ShowSchedulesState(); diff --git a/team_c_f/lib/view/scorers.dart b/team_c_f/lib/old/view/scorers.dart similarity index 85% rename from team_c_f/lib/view/scorers.dart rename to team_c_f/lib/old/view/scorers.dart index bfd5387..ecbfef8 100644 --- a/team_c_f/lib/view/scorers.dart +++ b/team_c_f/lib/old/view/scorers.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class ShowScorers extends StatelessWidget { // Класс, отображающий список бомбардиров - const ShowScorers({Key key}) : super(key: key); + const ShowScorers({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/view/table.dart b/team_c_f/lib/old/view/table.dart similarity index 91% rename from team_c_f/lib/view/table.dart rename to team_c_f/lib/old/view/table.dart index 4dbfa6d..1794155 100644 --- a/team_c_f/lib/view/table.dart +++ b/team_c_f/lib/old/view/table.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; class ShowTable extends StatelessWidget { // Класс, отображающий туры, с возможностью их выбора для просмотра - const ShowTable({Key key}) : super(key: key); + const ShowTable({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/team_c_f/lib/view/team.dart b/team_c_f/lib/old/view/team.dart similarity index 88% rename from team_c_f/lib/view/team.dart rename to team_c_f/lib/old/view/team.dart index 6a83cc4..cb5e789 100644 --- a/team_c_f/lib/view/team.dart +++ b/team_c_f/lib/old/view/team.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/data.dart'; -import 'package:team_c_f/data/tournament.dart'; +import 'package:team_c_f/old/data/data.dart'; +import 'package:team_c_f/old/data/tournament.dart'; import 'package:provider/provider.dart'; -import 'package:team_c_f/element/notconfirmedplayer.dart'; -import 'package:team_c_f/element/selectTeam.dart'; -import 'package:team_c_f/element/team.dart'; +import 'package:team_c_f/old/element/notconfirmedplayer.dart'; +import 'package:team_c_f/old/element/selectTeam.dart'; +import 'package:team_c_f/old/element/team.dart'; class TeamView extends StatefulWidget { // Класс, отображающий информацию о команде участника - const TeamView({Key key}) : super(key: key); + const TeamView({Key? key}) : super(key: key); @override _TeamViewState createState() => _TeamViewState(); @@ -17,7 +17,7 @@ class TeamView extends StatefulWidget { class _TeamViewState extends State { bool capitan = false; TextEditingController teamController = TextEditingController(); - String teamSelect; + String? teamSelect; @override Widget build(BuildContext context) { return Container( @@ -75,7 +75,7 @@ class _TeamViewState extends State { .watch() .allPlayers .where((player) => (!player.confirmed && - player.team == context.read().myTeam.title)) + player.team == context.read().myTeam!.title)) .map( (p) => PlayerToConfirm(player: p), ), @@ -83,8 +83,8 @@ class _TeamViewState extends State { if (context.read().myTeam != null) ShowTeam( // Показ информации о моей команде - team: context.read().myTeam, - ) + team: context.read().myTeam!, + ), ], ), ); diff --git a/team_c_f/lib/view/tournament.dart b/team_c_f/lib/old/view/tournament.dart similarity index 92% rename from team_c_f/lib/view/tournament.dart rename to team_c_f/lib/old/view/tournament.dart index a5aa59a..0bef1ed 100644 --- a/team_c_f/lib/view/tournament.dart +++ b/team_c_f/lib/old/view/tournament.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:team_c_f/data/shortmatch.dart'; -import 'package:team_c_f/view/match.dart'; +import 'package:team_c_f/old/data/shortmatch.dart'; +import 'package:team_c_f/old/view/match.dart'; class TournamentView extends StatefulWidget { // Класс, отображения соревнований, в которых выбираются матчи @@ -8,9 +8,9 @@ class TournamentView extends StatefulWidget { final String tournament; // Название соревнования const TournamentView({ // Конструктор - Key key, - @required this.tournament, - @required this.matches, + Key? key, + required this.tournament, + required this.matches, }) : super(key: key); @override diff --git a/team_c_f/lib/pages/home.dart b/team_c_f/lib/pages/home.dart new file mode 100644 index 0000000..61ca13c --- /dev/null +++ b/team_c_f/lib/pages/home.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/pages/schedule.dart'; +import 'package:team_c_f/pages/team.dart'; +import 'package:team_c_f/pages/tour.dart'; +import 'package:team_c_f/storebloc/blocs/myteam.dart'; +import 'package:team_c_f/storebloc/blocs/schedule.dart'; +import 'package:team_c_f/storebloc/blocs/tour.dart'; +import 'package:team_c_f/storebloc/models/meet.dart'; +import 'package:team_c_f/storebloc/states/myteam.dart'; +import 'package:team_c_f/storebloc/states/schedule.dart'; +import 'package:team_c_f/store/home/home.dart'; +import 'package:team_c_f/store/login/login.dart'; +import 'package:bottom_navy_bar/bottom_navy_bar.dart'; +import 'package:team_c_f/storebloc/states/tour.dart'; + +class HomePage extends StatelessWidget { + static Home state = Home(); + @override + Widget build(BuildContext context) { + return SafeArea( + child: context.watch().downloadSuccessful + ? MultiBlocProvider( + providers: [ + BlocProvider( + create: (BuildContext context) => MyTeamBloc( + MyTeamState(uid: context.read().userId), + ), + ), + BlocProvider( + create: (BuildContext context) => ScheduleBloc( + ScheduleState(), + ), + ), + BlocProvider( + create: (BuildContext context) => TourBloc( + TourState( + round: Data.currentTour.round, + uid: context.read().userId, + ), + ), + ), + ], + child: Scaffold( + body: Observer( + builder: (_) => SingleChildScrollView( + child: Column( + children: [ + if (state.selectedIndex == 0) + TeamPage() + else if (state.selectedIndex == 1) + SchedulePage() + else if (state.selectedIndex == 2) + TourPage(back: false) + ], + ), + ), + ), + bottomNavigationBar: Observer( + builder: (_) => BottomNavyBar( + // Бар с вариантами выбора страниц + onItemSelected: state.selectIndex, + selectedIndex: state.selectedIndex, + iconSize: 20.0, + items: [ + BottomNavyBarItem( + icon: Icon(Icons.people), + title: Text( + 'Моя команда', + style: Theme.of(context).textTheme.caption, + ), + ), + BottomNavyBarItem( + icon: Icon(Icons.calendar_today), + title: Text( + 'Календарь', + style: Theme.of(context).textTheme.caption, + ), + ), + BottomNavyBarItem( + icon: Icon(Icons.add_to_photos), + title: Text( + 'Текущий тур', + style: Theme.of(context).textTheme.caption, + ), + ), + BottomNavyBarItem( + icon: Icon(Icons.toc), + title: Text( + 'Таблица', + style: Theme.of(context).textTheme.caption, + ), + ), + BottomNavyBarItem( + icon: Icon(Icons.list_alt), + title: Text( + 'Бомбардиры', + style: Theme.of(context).textTheme.caption, + ), + ), + ], + ), + ), + ), + ) + : Scaffold( + body: Text('DOWNLOADING'), + ), + ); + } +} diff --git a/team_c_f/lib/pages/leaveforecast.dart b/team_c_f/lib/pages/leaveforecast.dart new file mode 100644 index 0000000..bf96ec3 --- /dev/null +++ b/team_c_f/lib/pages/leaveforecast.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/components/oneteam.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/tour.dart'; +import 'package:team_c_f/storebloc/blocs/leaveforecast.dart'; +import 'package:team_c_f/storebloc/models/leaveforecast.dart'; +import 'package:team_c_f/storebloc/states/leaveforecast.dart'; + +class LeaveForecastPage extends StatelessWidget { + //final MeetsData meetsData; + LeaveForecastPage({ + Key? key, + //required this.meetsData, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + bloc: context.watch(), + builder: (context, state) => SafeArea( + child: Scaffold( + appBar: AppBar( + title: Text( + 'Прогноз на ' + + Data.tours + .where((TourData t) => t.round == state.round) + .single + .name! + + ((Data.tours + .where((TourData t) => t.round == state.round) + .single + .name! + .length) < + 3 + ? ' тур' + : ''), + ), + ), + body: Center( + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + ...state.meets + .map( + (LeaveForecastModel forecast) => OneTeamView( + forecast: forecast, + ), + ) + .toList(), + ], + ), + ), + ElevatedButton( + onPressed: () { + Navigator.pop( + context, + state, + ); + }, + child: Text('Оставить прогноз'), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/pages/login.dart b/team_c_f/lib/pages/login.dart new file mode 100644 index 0000000..32184f2 --- /dev/null +++ b/team_c_f/lib/pages/login.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/components/login.dart'; + +class LoginPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + body: LoginView(), + ), + ); + } +} diff --git a/team_c_f/lib/pages/schedule.dart b/team_c_f/lib/pages/schedule.dart new file mode 100644 index 0000000..8c17be5 --- /dev/null +++ b/team_c_f/lib/pages/schedule.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/components/createschedule.dart'; +import 'package:team_c_f/pages/tour.dart'; +import 'package:team_c_f/storebloc/blocs/createschedule.dart'; +import 'package:team_c_f/storebloc/blocs/schedule.dart'; +import 'package:team_c_f/storebloc/states/createschedule.dart'; +import 'package:team_c_f/storebloc/states/schedule.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/storebloc/models/tour.dart'; +import 'package:team_c_f/views/touravatar.dart'; + +class SchedulePage extends StatelessWidget { + @override + Widget build(BuildContext context) { + ScheduleBloc bloc = context.watch(); + return BlocBuilder( + bloc: bloc, + builder: (context, state) => state.enableSchedule + ? state.tourSelected + ? TourPage(back: true) + : Container( + height: MediaQuery.of(context).size.height, + width: double.infinity, + child: Wrap( + alignment: WrapAlignment.spaceAround, + runAlignment: WrapAlignment.center, + spacing: 20, + runSpacing: 20, + children: [ + ...bloc.state.tours.map( + (TourModel tour) => ShowTourAvatar(tour: tour), + ), + ], + ), + ) + : BlocProvider( + create: (context) => CreateScheduleBloc( + CreateScheduleState(), + ), + child: CreateScheduleView(), + ), + ); + } +} diff --git a/team_c_f/lib/pages/selectmeets.dart b/team_c_f/lib/pages/selectmeets.dart new file mode 100644 index 0000000..7afeba5 --- /dev/null +++ b/team_c_f/lib/pages/selectmeets.dart @@ -0,0 +1,217 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/models/choicemeet.dart'; +import 'package:team_c_f/models/meet.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/servises/selectmeets.dart'; +import 'package:team_c_f/servises/servises.dart'; +import 'package:team_c_f/storebloc/blocs/selectmeets.dart'; +import 'package:team_c_f/storebloc/blocs/tour.dart' as tourBloc; +import 'package:team_c_f/storebloc/states/selectmeets.dart'; +import 'package:flutter_date_pickers/flutter_date_pickers.dart'; +import 'package:intl/intl.dart'; + +class SelectMeetsPage extends StatelessWidget { + final int round; + const SelectMeetsPage({Key? key, required this.round}) : super(key: key); + + @override + Widget build(BuildContext context) { + SelectMeetsBloc bloc = SelectMeetsBloc(SelectMeetsState()); + return BlocBuilder( + bloc: bloc, + builder: (context, state) => Container( + child: SafeArea( + child: Scaffold( + body: Center( + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + RangePicker( + selectedPeriod: DatePeriod( + bloc.state.dateRange.isNotEmpty + ? bloc.state.dateRange.first + : DateTime.now().add( + Duration(days: 3), + ), + bloc.state.dateRange.isNotEmpty + ? bloc.state.dateRange.last + : DateTime.now().add( + Duration(days: 4), + ), + ), + firstDate: DateTime.now().add( + Duration(days: 2), + ), + lastDate: DateTime(2099), + onChanged: (DatePeriod period) { + bloc.add( + SelectMeetsEvent( + event: Event.changeRange, + range: [period.start, period.end], + ), + ); + }, + ), + ...bloc.state.allMeets.keys.map((String date) { + int countDate = bloc.state.allMeets[date]!.values + .map( + (list) => list + .where((element) => element.selected) + .length, + ) + .reduce((value, element) => value + element); + return Column( + children: [ + TextButton( + onPressed: () { + bloc.add( + SelectMeetsEvent( + event: Event.changeDateState, + key: date, + ), + ); + }, + child: Text( + date + showSelectIn(countDate), + ), + ), + if (bloc.state.openDate[date]!) + ...bloc.state.allMeets[date]!.keys.map( + (String tournament) { + int countTournament = bloc + .state.allMeets[date]![tournament]! + .where((element) => element.selected) + .length; + return Column( + children: [ + TextButton( + onPressed: () { + bloc.add( + SelectMeetsEvent( + event: + Event.changeTournamentState, + key: date + tournament, + ), + ); + }, + child: Text( + tournament + + showSelectIn( + countTournament, + ), + ), + ), + if (bloc.state + .openTornament[date + tournament]!) + ...bloc.state + .allMeets[date]![tournament]! + .map( + (ChoiceMeetData meetData) { + return Card( + child: CheckboxListTile( + value: meetData.selected, + onChanged: (bool? a) { + bloc.add( + SelectMeetsEvent( + event: Event.selectMeet, + meet: meetData, + choice: a, + ), + ); + }, + title: Text(DateFormat( + 'HH:mm ') + .format( + meetData.date) + + meetData.team.first + + ' - ' + + meetData.team.last), + ), + ); + }, + ), + ], + ); + }, + ).toList(), + ], + ); + }).toList(), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: TextButton( + onPressed: bloc.state.selectedMeets.length == 10 + ? () { + bloc.state.selectedMeets + .sort((a, b) => a.date.compareTo(b.date)); + List team = []; + bloc.state.selectedMeets.forEach( + (ChoiceMeetData meet) { + team.addAll(meet.team); + }, + ); + SelectMeetsService().cteateMeet( + meet: MeetsData( + round: round, + meets: bloc.state.selectedMeets + .map( + (ChoiceMeetData choiceMeetData) => + MeetData( + date: DateFormat('yyyy-MM-dd HH:mm') + .format(choiceMeetData.date), + score: [0, 0], + started: false, + team: [ + choiceMeetData.team.first, + choiceMeetData.team.last + ], + status: 'Не начат', + ), + ) + .toList(), + deadline: + DateFormat('yyyy-MM-dd HH:mm').format( + bloc.state.selectedMeets[0].date.add( + Duration(hours: -1), + ), + ), + started: false, + ), + // MeetsData( + // round: round, + // team: team, + // date: DateFormat('yyyy-MM-dd HH:mm').format( + // bloc.state.selectedMeets[0].date.add( + // Duration(hours: -1), + // ), + // ), + // score: [], + // started: false, + // ), + ); + Navigator.pop( + context, + tourBloc.TourEvent( + event: tourBloc.Event.selectMeets, + ), + ); + } + : null, + child: Text('Выбрано ${bloc.state.selectedMeets.length}'), + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/pages/team.dart b/team_c_f/lib/pages/team.dart new file mode 100644 index 0000000..1f2725b --- /dev/null +++ b/team_c_f/lib/pages/team.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/components/unconfirmedplayer.dart'; +import 'package:team_c_f/components/selectteam.dart'; +import 'package:team_c_f/storebloc/blocs/myteam.dart'; +import 'package:team_c_f/storebloc/states/myteam.dart'; +import 'package:team_c_f/store/login/login.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/views/team.dart'; + +class TeamPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + MyTeamBloc bloc = context.watch(); + context.read().changeName(bloc.state.name); + context.read().setDataToSelectTeam(buttonText: 'Выбрать команду'); + return BlocBuilder( + bloc: bloc, + builder: (context, state) => Column( + children: [ + Container( + padding: const EdgeInsets.all(8.0), + margin: const EdgeInsets.all(8.0), + child: Column( + children: [ + Card( + color: Colors.cyan[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: ListTile( + leading: CircleAvatar( + // Показывает место в таблице бомбардиров + backgroundColor: Colors.blue[100], + child: Text(bloc.state.position), + ), + title: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(bloc.state.name), // Показывает имя участника + ], + ), + subtitle: bloc.state.team != 'Нет команды' + ? Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.done, + color: bloc.state.confirmed + ? Colors.green + : Colors.grey), + Text(bloc.state.team), + ], + ) + : Text( + 'Нет команды', + textAlign: TextAlign.center, + ), + trailing: CircleAvatar( + backgroundColor: Colors.blue[100], + child: IconButton( + icon: Icon(Icons.exit_to_app), + onPressed: () { + context.read().googleLogout(); + }), + ), + ), + ), + if (bloc.state.team == 'Нет команды') + SelectTeamView( + selectTeam: context.read().selectTeam, + updateMyTeam: true, + ), + ], + ), + ), + if (bloc.state.capitan && + bloc.state.unconfirm + .isNotEmpty) // Отображение для капитана списка игроков, которые зарегистрировались, но ещё не получили подтверждение в его команде + ...bloc.state.unconfirm.map( + (p) => UnconfirmedPlayerView(player: p), + ), + if (bloc.state.teamData != null) + ShowTeam( + // Показ информации о моей команде + team: bloc.state.teamData!, + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/pages/tour.dart b/team_c_f/lib/pages/tour.dart new file mode 100644 index 0000000..607481f --- /dev/null +++ b/team_c_f/lib/pages/tour.dart @@ -0,0 +1,219 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/forecast.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/player.dart'; +import 'package:team_c_f/pages/leaveforecast.dart'; +import 'package:team_c_f/pages/selectmeets.dart'; +import 'package:team_c_f/servises/tour.dart'; +import 'package:team_c_f/store/login/login.dart'; +import 'package:team_c_f/storebloc/blocs/leaveforecast.dart' as leave; +import 'package:team_c_f/storebloc/blocs/schedule.dart' as schedule; +import 'package:team_c_f/storebloc/blocs/tour.dart'; +import 'package:team_c_f/storebloc/models/leaveforecast.dart'; +import 'package:team_c_f/storebloc/states/leaveforecast.dart'; +import 'package:team_c_f/storebloc/states/tour.dart'; +import 'package:team_c_f/views/meets.dart'; +import 'package:team_c_f/views/tour.dart'; + +class TourPage extends StatelessWidget { + final bool back; + const TourPage({Key? key, required this.back}) : super(key: key); + @override + Widget build(BuildContext context) { + TourBloc bloc = back + ? context.watch().state.tourBloc! + : context.watch(); + return BlocBuilder( + bloc: bloc, + builder: (context, state) => SingleChildScrollView( + child: Center( + child: Column( + children: [ + back + ? TextButton( + onPressed: () { + context.read().add( + schedule.ScheduleEvent( + event: schedule.Event.unselectTour), + ); + }, + child: Text( + 'Назад', + textAlign: TextAlign.center, + ), + ) + : Card( + color: Colors.yellow[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20)), + child: Container( + width: MediaQuery.of(context).size.width - 20, + child: Column( + children: [ + TextButton( + onPressed: () { + bloc.add( + TourEvent(event: Event.showListAbsense)); + }, + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(8.0), + child: Text( + 'Список неявок', + textAlign: TextAlign.center, + ), + ), + ), + state.size + ? Container( + child: Column( + children: [ + ...Data.players + .where( + (player) => player.team != '') + .where((player) => Data.names.every( + (leave) => leave != player.uid)) + .map( + (player) => Padding( + padding: + const EdgeInsets.all(8.0), + child: Text(player.name), + ), + ), + ], + ), + ) + : SizedBox( + height: 0, + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Матчи ${state.tour.name} ${state.tour.name.length < 3 ? 'тура' : ''}'), + ), + state.meets.meets.isNotEmpty + ? Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: ShowMeets( + meetsModel: state.meets, + ), + ), + if (!state.meets.started) + TextButton( + onPressed: () async { + ForecastData? oldForecast; + if (Data.names.isNotEmpty) + oldForecast = await TourService().getForecast( + uid: context.read().userId, + round: state.round, + ); + await TourService() + .enableTour(round: state.tour.stage) + ? Navigator.of(context) + .push( + MaterialPageRoute( + builder: (context) => BlocProvider< + leave.LeaveForecastBloc>( + create: (_) => + leave.LeaveForecastBloc( + LeaveForecastState( + meetsData: Data.meets + .where((MeetsData m) => + m.round == state.round) + .single, + forecast: oldForecast, + ), + ), + child: LeaveForecastPage(), + ), + ), + ) + .then( + (LeaveForecastState? result) { + if (result != null) { + List rate = []; + PlayerData me = Data.players + .where((PlayerData p) => + p.uid == + context + .read() + .userId) + .single; + ForecastData forecast = + ForecastData( + uid: me.uid, + team: me.team, + round: result.round, + rate: rate, + ); + result.meets.forEach( + (LeaveForecastModel model) { + rate.addAll( + [model.home, model.away]); + }, + ); + if (oldForecast != null) { + forecast.docId = + oldForecast.docId; + TourService().updateForecast( + forecast: forecast, + ); + } else + TourService().leaveForecast( + forecast: forecast, + ); + bloc.add( + TourEvent( + event: Event.makeForecast, + ), + ); + } + }, + ) + : Fluttertoast.showToast( + msg: 'Приём прогнозов закрыт'); + }, + child: Text('Мой прогноз')), + ], + ) + : TextButton( + onPressed: () { + Navigator.of(context) + .push( + MaterialPageRoute( + builder: (context) => + SelectMeetsPage(round: state.round), + ), + ) + .then( + (TourEvent? event) { + if (event != null) bloc.add(event); + }, + ); + }, + child: Text('Выбрать матчи'), + ), + ShowTour(tour: state.tour), + ElevatedButton( + onPressed: () { + bloc.add(TourEvent(event: Event.closeForecasting)); + }, + child: Text('Закрыть приём прогнозов'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/servises/createschedule.dart b/team_c_f/lib/servises/createschedule.dart new file mode 100644 index 0000000..582e90b --- /dev/null +++ b/team_c_f/lib/servises/createschedule.dart @@ -0,0 +1,28 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/tour.dart'; + +class CreateScheduleService { + final CollectionReference _scheduleCollection = + FirebaseFirestore.instance.collection('schedule'); + final CollectionReference _meetsCollection = + FirebaseFirestore.instance.collection('meets'); + + void create() { + Data.tours.forEach( + (TourData tour) { + _scheduleCollection.add( + tour.toMap(), + ); + }, + ); + Data.meets.forEach( + (MeetsData meets) { + _meetsCollection.add( + meets.toMap(), + ); + }, + ); + } +} diff --git a/team_c_f/lib/servises/data.dart b/team_c_f/lib/servises/data.dart new file mode 100644 index 0000000..ef8207a --- /dev/null +++ b/team_c_f/lib/servises/data.dart @@ -0,0 +1,103 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/models/currenttour.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/forecast.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/player.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/models/tour.dart'; + +class DataService { + final CollectionReference _playersCollection = + FirebaseFirestore.instance.collection('players'); + final CollectionReference _teamsCollection = + FirebaseFirestore.instance.collection('teams'); + final CollectionReference _currentTourCollection = + FirebaseFirestore.instance.collection('currentTour'); + final CollectionReference _toursCollection = + FirebaseFirestore.instance.collection('schedule'); + final CollectionReference _meetsCollection = + FirebaseFirestore.instance.collection('meets'); + final CollectionReference _forecastsCollection = + FirebaseFirestore.instance.collection('forecasts'); + + Future initData() async { + Data.currentTour = await getCurrentTour(); + Data.players = await getPlayers(); + Data.teams = await getTeams(); + Data.tours = await getTours(); + Data.meets = await getMeets(); + Data.names = await getUidLeftForecast(); + return true; + } + + Future> getUidLeftForecast() { + int round = Data.currentTour.round; + if (Data.meets.where((element) => element.round == round).single.started) + round++; + return _forecastsCollection.where('Round', isEqualTo: round).get().then( + (QuerySnapshot response) => response.docs + .map((QueryDocumentSnapshot doc) => + ForecastData.fromMap(data: doc.data(), docId: doc.id).uid) + .toList(), + ); + } + + Future getCurrentTour() { + return _currentTourCollection.get().then( + (QuerySnapshot response) => CurrentTourData.fromMap( + data: response.docs.single.data(), + docId: response.docs.single.id, + ), + ); + } + + Future> getPlayers() { + return _playersCollection.get().then( + (QuerySnapshot response) => response.docs + .map( + (QueryDocumentSnapshot doc) => PlayerData.fromMap( + data: doc.data(), + docId: doc.id, + ), + ) + .toList(), + ); + } + + Future> getTeams() { + return _teamsCollection.get().then( + (QuerySnapshot response) => response.docs + .map( + (QueryDocumentSnapshot doc) => TeamData.fromMap( + data: doc.data(), + docId: doc.id, + ), + ) + .toList(), + ); + } + + Future> getTours() { + return _toursCollection.get().then( + (QuerySnapshot response) => response.docs + .map( + (QueryDocumentSnapshot doc) => TourData.fromMap( + data: doc.data(), + ), + ) + .toList(), + ); + } + + Future> getMeets() { + return _meetsCollection.get().then( + (QuerySnapshot response) => response.docs + .map( + (QueryDocumentSnapshot doc) => + MeetsData.fromMap(data: doc.data(), docId: doc.id), + ) + .toList(), + ); + } +} diff --git a/team_c_f/lib/servises/login.dart b/team_c_f/lib/servises/login.dart new file mode 100644 index 0000000..eb61631 --- /dev/null +++ b/team_c_f/lib/servises/login.dart @@ -0,0 +1,27 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/models/info.dart'; + +class LoginService { + final CollectionReference _playersCollection = + FirebaseFirestore.instance.collection('players'); + final CollectionReference _infoCollection = + FirebaseFirestore.instance.collection('information'); + + Future existPlayer({required String uid}) { + return _playersCollection + .where( + 'UserId', + isEqualTo: uid, + ) + .get() + .then((QuerySnapshot response) => response.docs.isNotEmpty); + } + + Future getInfo() { + return _infoCollection.get().then( + (QuerySnapshot response) => InfoData.fromMap( + data: response.docs.single.data(), + ), + ); + } +} diff --git a/team_c_f/lib/servises/myteam.dart b/team_c_f/lib/servises/myteam.dart new file mode 100644 index 0000000..b3bdcb0 --- /dev/null +++ b/team_c_f/lib/servises/myteam.dart @@ -0,0 +1,29 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/player.dart'; +import 'package:team_c_f/models/team.dart'; + +class MyTeamService { + final CollectionReference _playersCollection = + FirebaseFirestore.instance.collection('players'); + final CollectionReference _teamsCollection = + FirebaseFirestore.instance.collection('teams'); + + void confirmedPlayer(bool confirmed, String uid) { + PlayerData player = + Data.players.where((PlayerData p) => p.uid == uid).single; + TeamData team = + Data.teams.where((TeamData t) => t.name == player.team).single; + if (confirmed) { + team.players.add(uid); + _teamsCollection.doc(team.docId).update(team.toMap()); + } else { + player.team = null; + _playersCollection.doc(player.docId).update(player.toMap()); + if (team.players.any((String playerUid) => playerUid == uid)) { + team.players.removeWhere((String playerId) => playerId == uid); + _teamsCollection.doc(team.docId).update(team.toMap()); + } + } + } +} diff --git a/team_c_f/lib/servises/schedule.dart b/team_c_f/lib/servises/schedule.dart new file mode 100644 index 0000000..1c08f76 --- /dev/null +++ b/team_c_f/lib/servises/schedule.dart @@ -0,0 +1,2 @@ +class ScheduleService { +} diff --git a/team_c_f/lib/servises/selectmeets.dart b/team_c_f/lib/servises/selectmeets.dart new file mode 100644 index 0000000..cd21159 --- /dev/null +++ b/team_c_f/lib/servises/selectmeets.dart @@ -0,0 +1,16 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/meets.dart'; + +class SelectMeetsService { + final CollectionReference _meetsCollection = + FirebaseFirestore.instance.collection('meets'); + + void cteateMeet({required MeetsData meet}) { + MeetsData current = Data.meets.where((element) => element.round == meet.round).single; + meet.docId = current.docId; + Data.meets.remove(current); + Data.meets.add(meet); + _meetsCollection.doc(meet.docId).update(meet.toMap()); + } +} diff --git a/team_c_f/lib/servises/selectteam.dart b/team_c_f/lib/servises/selectteam.dart new file mode 100644 index 0000000..635c687 --- /dev/null +++ b/team_c_f/lib/servises/selectteam.dart @@ -0,0 +1,67 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/models/player.dart'; + +class SelectTeamService { + final CollectionReference _playersCollection = + FirebaseFirestore.instance.collection('players'); + final CollectionReference _teamsCollection = + FirebaseFirestore.instance.collection('teams'); + + Future checkTeamName({required String name}) { + // Проверка названия команды на уникальность + return _teamsCollection + .where('Name', isEqualTo: name) + .get() + .then((response) => response.docs.length == 0); + } + + Future registrateTeam({required TeamData team}) async { + // регистрация команды + await _teamsCollection.add(team.toMap()); + } + + Future existPlayer({required String uid}) { + return _playersCollection + .where( + 'UserId', + isEqualTo: uid, + ) + .get() + .then((QuerySnapshot response) => + response.docs.isNotEmpty ? response.docs.single.id : null); + } + + Future?> allTeamNames() { + return _teamsCollection.get().then( + (QuerySnapshot response) => response.docs + .where((QueryDocumentSnapshot doc) => + TeamData.fromMap( + data: doc.data(), + docId: doc.id, + ).players.length < + 3) + .map( + (QueryDocumentSnapshot doc) => TeamData.fromMap( + data: doc.data(), + docId: doc.id, + ).name, + ) + .toList(), + ); + } + + Future registratePlayer({required PlayerData player}) async { + // регистрация игрока + await _playersCollection.add(player.toMap()); + return true; + } + + Future updatePlayer({required PlayerData player}) async { + // обновление игрока (добавление команды) + await _playersCollection.doc(player.docId).update( + player.toMap(), + ); + return true; + } +} diff --git a/team_c_f/lib/servises/servises.dart b/team_c_f/lib/servises/servises.dart new file mode 100644 index 0000000..63ef156 --- /dev/null +++ b/team_c_f/lib/servises/servises.dart @@ -0,0 +1,121 @@ +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/models/tour.dart'; + +String showSelectIn(int count) { + return count > 0 + ? count == 1 + ? ' (Выбран 1 матч)' + : count < 5 + ? ' (Выбрано $count матча)' + : ' (Выбрано $count матчей)' + : ''; +} + +String showPoints(int points) { + // Функция изменения склонения слова "N очков" + return points.toString() + + ' ' + + ((points % 10 == 1 && points ~/ 10 != 1) + ? 'очко' + : ((points - 1) % 10 - 4 < 0 && points ~/ 10 != 1) + ? 'очка' + : 'очков'); +} + +String showGoals(int goals) { + // Функция изменения склонения слова "N забытых" + return goals.toString() + + ' ' + + ((goals % 10 == 1 && goals ~/ 10 != 1) ? 'забитый' : 'забитых'); +} + +String showRegisterTeam(int count) { + // Функция изменения склонения слова "Зарегистрировано" + return (count % 10 == 1 && count ~/ 10 != 1) + ? 'Зарегистрирована' + : 'Зарегистрировано'; +} + +String showFullTeam(int count) { + // Функция изменения склонения выражения "Готово к участию" + return (count % 10 == 1 && count ~/ 10 != 1) + ? 'Готова к участию' + : 'Готово к участию'; +} + +String showTeam(int points) { + // Функция изменения склонения слова "N команд" + return points.toString() + + ' ' + + ((points % 10 == 1 && points ~/ 10 != 1) + ? 'команда' + : ((points - 1) % 10 - 4 < 0 && points ~/ 10 != 1) + ? 'команды' + : 'команд'); +} + +String showMatches({required int matches}) { + return matches.toString() + + ' ' + + ((matches % 10 == 1 && matches ~/ 10 != 1) + ? 'матч' + : ((matches - 1) % 10 - 4 < 0 && matches ~/ 10 != 1) + ? 'матча' + : 'матчей'); +} + +String showTours({required int tours}) { + return tours.toString() + + ' ' + + ((tours % 10 == 1 && tours ~/ 10 != 1) + ? 'тур' + : ((tours - 1) % 10 - 4 < 0 && tours ~/ 10 != 1) + ? 'тура' + : 'туров'); +} + +List createSchedule(int circles) { + List registTeam = + Data.teams.where((TeamData team) => team.players.length == 3).toList(); + List teams = ['1', '2', '3', '4', '5']; + // registTeam + // .map((TeamData team) => team.name) + // .toList(); //['1', '2', '3', '4', '5']; + List curr = []; + int count = 5; //registTeam.length; + int tour = (count.isEven ? count - 1 : count); + for (int q = 0; q < circles; q++) { + for (int i = 0; i < tour; i++) { + List> pair = []; + for (int j = 0; j < count ~/ 2; j++) { + List match = []; + int k = count.isEven ? j : j + 1; + int home = i.isOdd + ? k == 0 + ? count - 1 + : (count ~/ 2 + i ~/ 2 + k + (count.isEven ? 0 : 1)) % + (count.isOdd ? count : count - 1) + : k + i ~/ 2; + int away = i.isOdd + ? count ~/ 2 + i ~/ 2 - j + : k == 0 + ? count - 1 + : (count + i ~/ 2 - 1 - k + (count.isEven ? 0 : 1)) % + (count.isOdd ? count : count - 1); + if (q.isEven) { + match.add(teams[home]); + match.add(teams[away]); + } else { + match.add(teams[away]); + match.add(teams[home]); + } + pair.add(match); + } + curr.add( + TourData.all(round: (i + 1 + q * tour), team: pair), + ); + } + } + return [...curr]; +} diff --git a/team_c_f/lib/servises/tour.dart b/team_c_f/lib/servises/tour.dart new file mode 100644 index 0000000..2158695 --- /dev/null +++ b/team_c_f/lib/servises/tour.dart @@ -0,0 +1,53 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:team_c_f/models/forecast.dart'; +import 'package:team_c_f/models/meets.dart'; + +class TourService { + final CollectionReference _forecastsCollection = + FirebaseFirestore.instance.collection('forecasts'); + final CollectionReference _meetsCollection = + FirebaseFirestore.instance.collection('meets'); + + void leaveForecast({required ForecastData forecast}) { + _forecastsCollection.add(forecast.toMap()); + } + + void updateForecast({required ForecastData forecast}) { + _forecastsCollection.doc(forecast.docId).update(forecast.toMap()); + } + + Future getForecast({required String uid, required int round}) { + return _forecastsCollection + .where('Round', isEqualTo: round) + .where('UserId', isEqualTo: uid) + .get() + .then( + (QuerySnapshot response) => response.docs.length == 1 + ? ForecastData.fromMap( + data: response.docs.single.data(), + docId: response.docs.single.id, + ) + : null, + ); + } + + Future enableTour({required int round}) { + return _meetsCollection + .where('Round', isEqualTo: round) + .get() + .then((QuerySnapshot response) => !MeetsData.fromMap( + data: response.docs.single.data(), + docId: response.docs.single.id, + ).started); + } + + Future closeForecasting({required int round}) async { + QueryDocumentSnapshot doc = + (await _meetsCollection.where('Round', isEqualTo: round).get()) + .docs + .single; + MeetsData meets = MeetsData.fromMap(data: doc.data(), docId: doc.id); + meets.started = true; + _meetsCollection.doc(doc.id).update(meets.toMap()); + } +} diff --git a/team_c_f/lib/store/home/home.dart b/team_c_f/lib/store/home/home.dart new file mode 100644 index 0000000..a696e07 --- /dev/null +++ b/team_c_f/lib/store/home/home.dart @@ -0,0 +1,14 @@ +import 'package:mobx/mobx.dart'; +part 'home.g.dart'; + +class Home = _HomeBase with _$Home; + +abstract class _HomeBase with Store { + @observable + int selectedIndex = 1; + + @action + void selectIndex(int index){ + selectedIndex = index; + } +} \ No newline at end of file diff --git a/team_c_f/lib/store/home/home.g.dart b/team_c_f/lib/store/home/home.g.dart new file mode 100644 index 0000000..9958a96 --- /dev/null +++ b/team_c_f/lib/store/home/home.g.dart @@ -0,0 +1,46 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'home.dart'; + +// ************************************************************************** +// StoreGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic + +mixin _$Home on _HomeBase, Store { + final _$selectedIndexAtom = Atom(name: '_HomeBase.selectedIndex'); + + @override + int get selectedIndex { + _$selectedIndexAtom.reportRead(); + return super.selectedIndex; + } + + @override + set selectedIndex(int value) { + _$selectedIndexAtom.reportWrite(value, super.selectedIndex, () { + super.selectedIndex = value; + }); + } + + final _$_HomeBaseActionController = ActionController(name: '_HomeBase'); + + @override + void selectIndex(int index) { + final _$actionInfo = + _$_HomeBaseActionController.startAction(name: '_HomeBase.selectIndex'); + try { + return super.selectIndex(index); + } finally { + _$_HomeBaseActionController.endAction(_$actionInfo); + } + } + + @override + String toString() { + return ''' +selectedIndex: ${selectedIndex} + '''; + } +} diff --git a/team_c_f/lib/store/login/login.dart b/team_c_f/lib/store/login/login.dart new file mode 100644 index 0000000..d227d66 --- /dev/null +++ b/team_c_f/lib/store/login/login.dart @@ -0,0 +1,124 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:mobx/mobx.dart'; +import 'package:team_c_f/models/info.dart'; +import 'package:team_c_f/servises/login.dart'; +import 'package:team_c_f/store/selectteam/selectteam.dart'; + +part 'login.g.dart'; + +final GoogleSignIn _googleSignIn = GoogleSignIn(); +final FirebaseAuth _auth = FirebaseAuth.instance; + +class Login = LoginBase with _$Login; + +abstract class LoginBase with Store { + LoginBase() { + googleLogin(); + initInfo(); + } + @observable + InfoData? info; + + @action + void initInfo() { + LoginService().getInfo().then((InfoData value) => info = value); + } + + String userId = ''; + + @observable + String userName = ''; + + @action + void changeName(String text) { + userName = text.trim(); + } + + final selectTeam = SelectTeam(); + + @observable + bool registrateInApp = false; + + @observable + ObservableFuture loginStatus = ObservableFuture.value(false); + + @action + void changeLoginStatus(dynamic status) { + loginStatus = status; + } + + @computed + bool get updatedLoginStatus => loginStatus.value!; + + @action + Future googleLogin() async { + GoogleSignInAccount gUser = await getGoogleUser(); + GoogleSignInAuthentication googAuth = await gUser.authentication; + User? user; + + final AuthCredential credential = GoogleAuthProvider.credential( + idToken: googAuth.idToken, + accessToken: googAuth.accessToken, + ); + UserCredential userCredential = + await _auth.signInWithCredential(credential); + + user = userCredential.user; + + if (user != null) { + loginStatus = ObservableFuture.value(true); + userId = user.uid; + validateInApp(); + } else { + loginStatus = ObservableFuture.value(false); + userId = ''; + registrateInApp = false; + } + return Future.value(true); + } + + @action + Future googleLogout() async { + _googleSignIn.signOut(); + _auth.signOut(); + loginStatus = ObservableFuture.value(false); + userId = ''; + registrateInApp = false; + clearData(); + return await Future.value(true); + } + + @action + Future validateInApp() async { + registrateInApp = await LoginService().existPlayer(uid: userId); + } + + Future getGoogleUser() async { + GoogleSignInAccount? googleUser = _googleSignIn.currentUser; + if (googleUser == null) { + googleUser = await _googleSignIn.signInSilently(); + } + if (googleUser == null) { + googleUser = await _googleSignIn.signIn(); + } + return googleUser; + } + + @action + void clearData() { + userName = ''; + selectTeam.lastTeamName = ''; + selectTeam.teamName = ''; + selectTeam.uName = ''; + selectTeam.selectedTeam = null; + } + + void setDataToSelectTeam({ + required String buttonText, + }) { + selectTeam.uId = userId; + selectTeam.uName = userName; + selectTeam.regButtonText = buttonText; + } +} diff --git a/team_c_f/lib/store/login/login.g.dart b/team_c_f/lib/store/login/login.g.dart new file mode 100644 index 0000000..7a254a6 --- /dev/null +++ b/team_c_f/lib/store/login/login.g.dart @@ -0,0 +1,157 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'login.dart'; + +// ************************************************************************** +// StoreGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic + +mixin _$Login on LoginBase, Store { + Computed? _$updatedLoginStatusComputed; + + @override + bool get updatedLoginStatus => (_$updatedLoginStatusComputed ??= + Computed(() => super.updatedLoginStatus, + name: 'LoginBase.updatedLoginStatus')) + .value; + + final _$infoAtom = Atom(name: 'LoginBase.info'); + + @override + InfoData? get info { + _$infoAtom.reportRead(); + return super.info; + } + + @override + set info(InfoData? value) { + _$infoAtom.reportWrite(value, super.info, () { + super.info = value; + }); + } + + final _$userNameAtom = Atom(name: 'LoginBase.userName'); + + @override + String get userName { + _$userNameAtom.reportRead(); + return super.userName; + } + + @override + set userName(String value) { + _$userNameAtom.reportWrite(value, super.userName, () { + super.userName = value; + }); + } + + final _$registrateInAppAtom = Atom(name: 'LoginBase.registrateInApp'); + + @override + bool get registrateInApp { + _$registrateInAppAtom.reportRead(); + return super.registrateInApp; + } + + @override + set registrateInApp(bool value) { + _$registrateInAppAtom.reportWrite(value, super.registrateInApp, () { + super.registrateInApp = value; + }); + } + + final _$loginStatusAtom = Atom(name: 'LoginBase.loginStatus'); + + @override + ObservableFuture get loginStatus { + _$loginStatusAtom.reportRead(); + return super.loginStatus; + } + + @override + set loginStatus(ObservableFuture value) { + _$loginStatusAtom.reportWrite(value, super.loginStatus, () { + super.loginStatus = value; + }); + } + + final _$googleLoginAsyncAction = AsyncAction('LoginBase.googleLogin'); + + @override + Future googleLogin() { + return _$googleLoginAsyncAction.run(() => super.googleLogin()); + } + + final _$googleLogoutAsyncAction = AsyncAction('LoginBase.googleLogout'); + + @override + Future googleLogout() { + return _$googleLogoutAsyncAction.run(() => super.googleLogout()); + } + + final _$validateInAppAsyncAction = AsyncAction('LoginBase.validateInApp'); + + @override + Future validateInApp() { + return _$validateInAppAsyncAction.run(() => super.validateInApp()); + } + + final _$LoginBaseActionController = ActionController(name: 'LoginBase'); + + @override + void initInfo() { + final _$actionInfo = + _$LoginBaseActionController.startAction(name: 'LoginBase.initInfo'); + try { + return super.initInfo(); + } finally { + _$LoginBaseActionController.endAction(_$actionInfo); + } + } + + @override + void changeName(String text) { + final _$actionInfo = + _$LoginBaseActionController.startAction(name: 'LoginBase.changeName'); + try { + return super.changeName(text); + } finally { + _$LoginBaseActionController.endAction(_$actionInfo); + } + } + + @override + void changeLoginStatus(dynamic status) { + final _$actionInfo = _$LoginBaseActionController.startAction( + name: 'LoginBase.changeLoginStatus'); + try { + return super.changeLoginStatus(status); + } finally { + _$LoginBaseActionController.endAction(_$actionInfo); + } + } + + @override + void clearData() { + final _$actionInfo = + _$LoginBaseActionController.startAction(name: 'LoginBase.clearData'); + try { + return super.clearData(); + } finally { + _$LoginBaseActionController.endAction(_$actionInfo); + } + } + + @override + String toString() { + return ''' +info: ${info}, +userName: ${userName}, +registrateInApp: ${registrateInApp}, +loginStatus: ${loginStatus}, +updatedLoginStatus: ${updatedLoginStatus} + '''; + } +} diff --git a/team_c_f/lib/store/selectteam/selectteam.dart b/team_c_f/lib/store/selectteam/selectteam.dart new file mode 100644 index 0000000..d9df678 --- /dev/null +++ b/team_c_f/lib/store/selectteam/selectteam.dart @@ -0,0 +1,99 @@ +import 'package:mobx/mobx.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/servises/selectteam.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/models/player.dart'; +part 'selectteam.g.dart'; + +class SelectTeam = _SelectTeamBase with _$SelectTeam; + +abstract class _SelectTeamBase with Store { + _SelectTeamBase() { + getAllTeamNames().then( + (List? allNames) => + allTeamNames = allNames == null ? [] : [...allNames], + ); + } + String regButtonText = 'Зарегистрироваться'; + String uId = ''; + String uName = ''; + + @observable + String teamName = ''; + + @action + void changeTeam(String text) { + teamName = text.trim(); + SelectTeamService().checkTeamName(name: teamName).then((bool enable) { + enableName = enable; + }); + editNameComplite(text: text); + } + + @observable + bool enableName = false; + + @observable + String lastTeamName = ''; + + void editNameComplite({required String text}) { + lastTeamName = text; + } + + @observable + bool capitan = false; + + @action + void changeCapitan(bool? value) { + capitan = value!; + lastTeamName = teamName; + } + + @observable + String? selectedTeam; + + @action + void selestTeam(String? name) { + selectedTeam = name; + } + + @observable + List allTeamNames = []; + + @action + Future assertTeam() async { + // Выбор команды + String? docId = await SelectTeamService().existPlayer(uid: uId); + + PlayerData p = PlayerData( + team: capitan ? teamName : selectedTeam, + name: uName, + uid: uId, + docId: docId, + ); + Data().refreshData(); + return docId == null + ? await SelectTeamService().registratePlayer( + player: p, + ) + : await SelectTeamService().updatePlayer( + player: p, + ); + } + + @action + Future registrateTeam() async { + // Регистрация команды + await SelectTeamService().registrateTeam( + team: TeamData( + name: teamName, + uidCapitan: uId, + ), + ); + await assertTeam(); + } + + Future?> getAllTeamNames() { + return SelectTeamService().allTeamNames(); + } +} diff --git a/team_c_f/lib/store/selectteam/selectteam.g.dart b/team_c_f/lib/store/selectteam/selectteam.g.dart new file mode 100644 index 0000000..cb6729b --- /dev/null +++ b/team_c_f/lib/store/selectteam/selectteam.g.dart @@ -0,0 +1,164 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'selectteam.dart'; + +// ************************************************************************** +// StoreGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic + +mixin _$SelectTeam on _SelectTeamBase, Store { + final _$teamNameAtom = Atom(name: '_SelectTeamBase.teamName'); + + @override + String get teamName { + _$teamNameAtom.reportRead(); + return super.teamName; + } + + @override + set teamName(String value) { + _$teamNameAtom.reportWrite(value, super.teamName, () { + super.teamName = value; + }); + } + + final _$enableNameAtom = Atom(name: '_SelectTeamBase.enableName'); + + @override + bool get enableName { + _$enableNameAtom.reportRead(); + return super.enableName; + } + + @override + set enableName(bool value) { + _$enableNameAtom.reportWrite(value, super.enableName, () { + super.enableName = value; + }); + } + + final _$lastTeamNameAtom = Atom(name: '_SelectTeamBase.lastTeamName'); + + @override + String get lastTeamName { + _$lastTeamNameAtom.reportRead(); + return super.lastTeamName; + } + + @override + set lastTeamName(String value) { + _$lastTeamNameAtom.reportWrite(value, super.lastTeamName, () { + super.lastTeamName = value; + }); + } + + final _$capitanAtom = Atom(name: '_SelectTeamBase.capitan'); + + @override + bool get capitan { + _$capitanAtom.reportRead(); + return super.capitan; + } + + @override + set capitan(bool value) { + _$capitanAtom.reportWrite(value, super.capitan, () { + super.capitan = value; + }); + } + + final _$selectedTeamAtom = Atom(name: '_SelectTeamBase.selectedTeam'); + + @override + String? get selectedTeam { + _$selectedTeamAtom.reportRead(); + return super.selectedTeam; + } + + @override + set selectedTeam(String? value) { + _$selectedTeamAtom.reportWrite(value, super.selectedTeam, () { + super.selectedTeam = value; + }); + } + + final _$allTeamNamesAtom = Atom(name: '_SelectTeamBase.allTeamNames'); + + @override + List get allTeamNames { + _$allTeamNamesAtom.reportRead(); + return super.allTeamNames; + } + + @override + set allTeamNames(List value) { + _$allTeamNamesAtom.reportWrite(value, super.allTeamNames, () { + super.allTeamNames = value; + }); + } + + final _$assertTeamAsyncAction = AsyncAction('_SelectTeamBase.assertTeam'); + + @override + Future assertTeam() { + return _$assertTeamAsyncAction.run(() => super.assertTeam()); + } + + final _$registrateTeamAsyncAction = + AsyncAction('_SelectTeamBase.registrateTeam'); + + @override + Future registrateTeam() { + return _$registrateTeamAsyncAction.run(() => super.registrateTeam()); + } + + final _$_SelectTeamBaseActionController = + ActionController(name: '_SelectTeamBase'); + + @override + void changeTeam(String text) { + final _$actionInfo = _$_SelectTeamBaseActionController.startAction( + name: '_SelectTeamBase.changeTeam'); + try { + return super.changeTeam(text); + } finally { + _$_SelectTeamBaseActionController.endAction(_$actionInfo); + } + } + + @override + void changeCapitan(bool? value) { + final _$actionInfo = _$_SelectTeamBaseActionController.startAction( + name: '_SelectTeamBase.changeCapitan'); + try { + return super.changeCapitan(value); + } finally { + _$_SelectTeamBaseActionController.endAction(_$actionInfo); + } + } + + @override + void selestTeam(String? name) { + final _$actionInfo = _$_SelectTeamBaseActionController.startAction( + name: '_SelectTeamBase.selestTeam'); + try { + return super.selestTeam(name); + } finally { + _$_SelectTeamBaseActionController.endAction(_$actionInfo); + } + } + + @override + String toString() { + return ''' +teamName: ${teamName}, +enableName: ${enableName}, +lastTeamName: ${lastTeamName}, +capitan: ${capitan}, +selectedTeam: ${selectedTeam}, +allTeamNames: ${allTeamNames} + '''; + } +} diff --git a/team_c_f/lib/storebloc/blocs/createschedule.dart b/team_c_f/lib/storebloc/blocs/createschedule.dart new file mode 100644 index 0000000..5718504 --- /dev/null +++ b/team_c_f/lib/storebloc/blocs/createschedule.dart @@ -0,0 +1,39 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/tour.dart'; +import 'package:team_c_f/servises/createschedule.dart'; +import 'package:team_c_f/servises/servises.dart'; +import 'package:team_c_f/storebloc/states/createschedule.dart'; + +enum CreateScheduleEvent { changeCircle, createSchedule } + +class CreateScheduleBloc + extends Bloc { + CreateScheduleBloc(CreateScheduleState initialState) : super(initialState); + + @override + Stream mapEventToState( + CreateScheduleEvent event) async* { + switch (event) { + case CreateScheduleEvent.changeCircle: + yield state.copyWith(circle: state.circle); + break; + case CreateScheduleEvent.createSchedule: + Data.tours = createSchedule(state.circle); + Data.tours.forEach((TourData tour) { + Data.meets.add( + MeetsData( + deadline: '2099-01-01 00:00', + meets: [], + round: tour.round, + started: false, + ), + ); + }); + CreateScheduleService().create(); + yield state; + break; + } + } +} diff --git a/team_c_f/lib/storebloc/blocs/leaveforecast.dart b/team_c_f/lib/storebloc/blocs/leaveforecast.dart new file mode 100644 index 0000000..e52e3f4 --- /dev/null +++ b/team_c_f/lib/storebloc/blocs/leaveforecast.dart @@ -0,0 +1,41 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/storebloc/states/leaveforecast.dart'; + +class LeaveForecastEvent { + final bool? position; + final int? index; + final int? newValue; + final Event event; + + LeaveForecastEvent({ + this.position, + this.index, + this.newValue, + required this.event, + }); +} + +enum Event { + changeValue, +} + +class LeaveForecastBloc extends Bloc { + LeaveForecastBloc(LeaveForecastState initialState) : super(initialState); + + @override + Stream mapEventToState(LeaveForecastEvent event) async* { + switch (event.event) { + case Event.changeValue: + if (event.index != null && + event.newValue != null && + event.position != null) { + if (event.position!) + state.meets[event.index!].home = event.newValue!; + else + state.meets[event.index!].away = event.newValue!; + yield state.copyWith(meets: state.meets); + } + break; + } + } +} diff --git a/team_c_f/lib/storebloc/blocs/myteam.dart b/team_c_f/lib/storebloc/blocs/myteam.dart new file mode 100644 index 0000000..7847ec4 --- /dev/null +++ b/team_c_f/lib/storebloc/blocs/myteam.dart @@ -0,0 +1,33 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/servises/myteam.dart'; +import 'package:team_c_f/storebloc/states/myteam.dart'; +import 'package:team_c_f/storebloc/models/unconfirmedplayer.dart'; + +enum MyTeamEvent { confirmedPlayer, unconfirmedPlayer, reset } + +class MyTeamBloc extends Bloc { + MyTeamBloc(MyTeamState initialState) : super(initialState); + + @override + Stream mapEventToState(MyTeamEvent event) async* { + switch (event) { + case MyTeamEvent.confirmedPlayer: // текущий игрок одобрил заявку + MyTeamService().confirmedPlayer(true, state.selectId); + state.unconfirm.removeWhere( + (UnconfirmedPlayerModel player) => player.uid == state.selectId); + yield state.copyWith(unconfirm: state.unconfirm); + break; + case MyTeamEvent.unconfirmedPlayer: // текущий игрок не одобрил заявку + MyTeamService().confirmedPlayer(false, state.selectId); + if (state.unconfirm + .any((UnconfirmedPlayerModel player) => player.uid == state.selectId)) + state.unconfirm.removeWhere( + (UnconfirmedPlayerModel player) => player.uid == state.selectId); + yield state.copyWith(unconfirm: state.unconfirm); + break; + case MyTeamEvent.reset: + yield MyTeamState(uid: state.uid); + break; + } + } +} diff --git a/team_c_f/lib/storebloc/blocs/schedule.dart b/team_c_f/lib/storebloc/blocs/schedule.dart new file mode 100644 index 0000000..c724cd4 --- /dev/null +++ b/team_c_f/lib/storebloc/blocs/schedule.dart @@ -0,0 +1,62 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/tour.dart'; +import 'package:team_c_f/storebloc/blocs/tour.dart'; +import 'package:team_c_f/storebloc/models/meet.dart'; +import 'package:team_c_f/storebloc/states/schedule.dart'; +import 'package:team_c_f/storebloc/models/tour.dart'; +import 'package:team_c_f/storebloc/states/tour.dart'; + +class ScheduleEvent { + int? round; + String? uid; + final Event event; + + ScheduleEvent({required this.event, this.round, this.uid}); +} + +enum Event { + createSuccessful, + selectTour, + unselectTour, +} + +class ScheduleBloc extends Bloc { + ScheduleBloc(ScheduleState initialState) : super(initialState); + + @override + Stream mapEventToState(ScheduleEvent event) async* { + switch (event.event) { + case Event.createSuccessful: + yield state.copyWith( + tours: Data.tours + .map( + (TourData tour) => TourModel(tour: tour), + ) + .toList(), + ); + break; + case Event.selectTour: + state.tourBloc = TourBloc( + TourState( + round: event.round!, + uid: event.uid!, + // meets: MeetsModel( + // meet: Data.meets + // .where((MeetsData m) => m.round == event.round) + // .single), + ), + ); + yield state.copyWith( + tourSelected: true, + round: event.round!, + tourBloc: state.tourBloc, + ); + break; + case Event.unselectTour: + yield state.copyWith(tourSelected: false); + break; + } + } +} diff --git a/team_c_f/lib/storebloc/blocs/selectmeets.dart b/team_c_f/lib/storebloc/blocs/selectmeets.dart new file mode 100644 index 0000000..0578127 --- /dev/null +++ b/team_c_f/lib/storebloc/blocs/selectmeets.dart @@ -0,0 +1,132 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/models/choicemeet.dart'; +import 'package:team_c_f/storebloc/states/selectmeets.dart'; +import 'package:http/http.dart'; +import 'package:intl/intl.dart'; +import 'package:html/dom.dart'; +import 'package:html/parser.dart'; + +class SelectMeetsEvent { + final String? key; + final List? range; + final ChoiceMeetData? meet; + final bool? choice; + final Event event; + + SelectMeetsEvent({ + this.choice, + this.key, + this.range, + this.meet, + required this.event, + }); +} + +enum Event { + changeRange, + selectMeet, + changeDateState, + changeTournamentState, +} + +class SelectMeetsBloc extends Bloc { + SelectMeetsBloc(SelectMeetsState initialState) : super(initialState); + + @override + Stream mapEventToState(SelectMeetsEvent event) async* { + switch (event.event) { + case Event.changeRange: + if (event.range != null) { + List range = []; + Map>> allMeets = {}; + Map openDate = {}; + Map openTournament = {}; + for (DateTime i = event.range!.first; + i.isBefore(event.range!.last); + i = i.add( + Duration(days: 1), + ),) { + Map> map = {}; + range.add(i); + String date = DateFormat('yyyy-MM-dd').format(i); + openDate.addAll({date: false}); + Document doc = parse((await Client().get( + Uri.parse('https://www.sports.ru/football/match/$date/'))) + .body); + Element element = doc.getElementsByClassName('match-center').single; + element = element.getElementsByTagName('li').first; + List divs = [...element.children]; + divs.removeWhere((Element el) => + el.innerHtml.contains('Реклама') || + el.innerHtml.contains('Матч дня')); + String tournament = ''; + for (int index = 0; index < divs.length; index++) { + if (index.isEven) { + tournament = divs[index].text.replaceAll('\n', ''); + openTournament.addAll({date + tournament: false}); + } else { + map[tournament] = [ + ...divs[index].getElementsByTagName('tr').map( + (Element meet) => ChoiceMeetData.fromHtml( + html: meet, + date: date, + ), + ) + ]; + } + } + allMeets[date] = map; + } + yield state.copyWith( + dateRange: range, + allMeets: allMeets, + openDate: openDate, + openTornament: openTournament, + ); + } + break; + case Event.selectMeet: + if (event.meet != null) { + state.allMeets.forEach( + (date, value) { + value.forEach( + (tournament, list) { + list.where((element) => element == event.meet). + forEach( + (sel) { + sel.selected = event.choice!; + }, + ); + }, + ); + }, + ); + if (event.choice!) + state.selectedMeets.add( + event.meet!, + ); + else + state.selectedMeets.removeWhere( + (element) => element == event.meet!, + ); + yield state.copyWith( + allMeets: state.allMeets, + selectedMeets: state.selectedMeets, + ); + } + break; + case Event.changeDateState: + if (event.key != null) { + state.openDate[event.key!] = !state.openDate[event.key]!; + yield state.copyWith(openDate: state.openDate); + } + break; + case Event.changeTournamentState: + if (event.key != null) { + state.openTornament[event.key!] = !state.openTornament[event.key]!; + yield state.copyWith(openTornament: state.openTornament); + } + break; + } + } +} diff --git a/team_c_f/lib/storebloc/blocs/tour.dart b/team_c_f/lib/storebloc/blocs/tour.dart new file mode 100644 index 0000000..95807a6 --- /dev/null +++ b/team_c_f/lib/storebloc/blocs/tour.dart @@ -0,0 +1,54 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/servises/tour.dart'; +import 'package:team_c_f/storebloc/states/tour.dart'; + +class TourEvent { + int? stage; + final Event event; + + TourEvent({this.stage, required this.event}); +} + +enum Event { + closeForecasting, + showListAbsense, + makeForecast, + selectMeets, + selectTour, +} + +class TourBloc extends Bloc { + TourBloc(TourState initialState) : super(initialState); + + @override + Stream mapEventToState(TourEvent event) async* { + switch (event.event) { + case Event.closeForecasting: + TourService().closeForecasting(round: state.tour.stage); + Data().refreshData(); + yield state.copyWith(meetsData: Data.meets.where((m) => m.round == state.tour.stage).single); + break; + case Event.showListAbsense: + yield state.copyWith(size: !state.size); + break; + case Event.makeForecast: + yield state.copyWith(); + break; + case Event.selectMeets: + Data().refreshData(); + yield state.copyWith(round: state.round); + break; + case Event.selectTour: + if (event.stage != null) { + yield state.copyWith( + round: event.stage, + // meetsData: Data.meets + // .where((element) => element.round == event.stage) + // .single, + ); + } + break; + } + } +} diff --git a/team_c_f/lib/storebloc/models/leaveforecast.dart b/team_c_f/lib/storebloc/models/leaveforecast.dart new file mode 100644 index 0000000..968977f --- /dev/null +++ b/team_c_f/lib/storebloc/models/leaveforecast.dart @@ -0,0 +1,17 @@ +import 'package:team_c_f/models/meet.dart'; +import 'package:intl/intl.dart'; + +class LeaveForecastModel { + late String date; + late int home; + late int away; + late List teams = []; + + LeaveForecastModel({required MeetData meet, List? goal}) { + date = DateFormat('dd.MM') + .format(DateFormat('yyyy-MM-dd HH:mm').parse(meet.date)); + home = goal != null ? goal[0] : meet.score.first; + away = goal != null ? goal[1] : meet.score.last; + teams.addAll([...meet.team]); + } +} diff --git a/team_c_f/lib/storebloc/models/meet.dart b/team_c_f/lib/storebloc/models/meet.dart new file mode 100644 index 0000000..5637e53 --- /dev/null +++ b/team_c_f/lib/storebloc/models/meet.dart @@ -0,0 +1,16 @@ +import 'package:team_c_f/models/meet.dart'; +import 'package:team_c_f/models/meets.dart'; + +class MeetsModel { + late int round; + late String deadline; + late List meets; + late bool started; + + MeetsModel({required MeetsData meet}) { + started = meet.started; + deadline = meet.deadline; + meets = meet.meets; + round = meet.round; + } +} diff --git a/team_c_f/lib/storebloc/models/team.dart b/team_c_f/lib/storebloc/models/team.dart new file mode 100644 index 0000000..2cf5a6a --- /dev/null +++ b/team_c_f/lib/storebloc/models/team.dart @@ -0,0 +1,14 @@ +import 'package:team_c_f/models/team.dart'; + +class TeamModel{ + final TeamData team; + late String teamName; + late String position; + late int points; + + TeamModel({required this.team}){ + teamName = team.name; + position = team.prevPosition.toString(); + points = team.points; + } +} \ No newline at end of file diff --git a/team_c_f/lib/storebloc/models/tour.dart b/team_c_f/lib/storebloc/models/tour.dart new file mode 100644 index 0000000..45c8d51 --- /dev/null +++ b/team_c_f/lib/storebloc/models/tour.dart @@ -0,0 +1,28 @@ +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/models/tour.dart'; + +class TourModel { + late int stage; + late String name; + late List>> result; + + TourModel({required TourData tour}) { + name = tour.name ?? tour.round.toString(); + stage = tour.round; + int round = tour.round - 1; + result = tour.team.map( + (List pair) { + return pair.map( + (String team) { + TeamData teamData = + Data.teams.where((TeamData t) => t.name == team).single; + return { + team: teamData.goal.length > round ? teamData.goal[round] : null + }; + }, + ).toList(); + }, + ).toList(); + } +} diff --git a/team_c_f/lib/storebloc/models/unconfirmedplayer.dart b/team_c_f/lib/storebloc/models/unconfirmedplayer.dart new file mode 100644 index 0000000..7ab8e1c --- /dev/null +++ b/team_c_f/lib/storebloc/models/unconfirmedplayer.dart @@ -0,0 +1,10 @@ +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/player.dart'; + +class UnconfirmedPlayerModel { + final String uid; + late String name; + UnconfirmedPlayerModel({required this.uid}) { + name = Data.players.where((PlayerData p) => p.uid == uid).single.name; + } +} diff --git a/team_c_f/lib/storebloc/states/createschedule.dart b/team_c_f/lib/storebloc/states/createschedule.dart new file mode 100644 index 0000000..24b1f6c --- /dev/null +++ b/team_c_f/lib/storebloc/states/createschedule.dart @@ -0,0 +1,34 @@ +import 'dart:core'; +import 'package:team_c_f/data/data.dart'; + +class CreateScheduleState { + late int circle; + late int registTeam; + late int fullTeam; + int get matches => (fullTeam / 2).floor(); + int get tours => circle * (fullTeam.isEven ? fullTeam - 1 : fullTeam); + + CreateScheduleState() { + circle = 1; + registTeam = Data.teams.length; + fullTeam = 16; + //Data.teams.where((TeamData team) => team.players.length == 3).length; + } + + CreateScheduleState copyWith({ + int? circle, + int? registTeam, + int? fullTeam, + }) => + CreateScheduleState.all( + circle: circle ?? this.circle, + registTeam: registTeam ?? this.registTeam, + fullTeam: fullTeam ?? this.fullTeam, + ); + + CreateScheduleState.all({ + required this.circle, + required this.registTeam, + required this.fullTeam, + }); +} diff --git a/team_c_f/lib/storebloc/states/leaveforecast.dart b/team_c_f/lib/storebloc/states/leaveforecast.dart new file mode 100644 index 0000000..4f303e6 --- /dev/null +++ b/team_c_f/lib/storebloc/states/leaveforecast.dart @@ -0,0 +1,43 @@ +import 'package:team_c_f/models/forecast.dart'; +import 'package:team_c_f/models/meet.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/storebloc/models/leaveforecast.dart'; + +class LeaveForecastState { + late int round; + late List meets = []; + + LeaveForecastState({ + required MeetsData meetsData, + ForecastData? forecast, + }) { + round = meetsData.round; + meets.addAll([ + ...meetsData.meets.map( + (MeetData meet) => LeaveForecastModel( + meet: meet, + goal: forecast != null + ? [ + forecast.rate[meetsData.meets.indexOf(meet) * 2], + forecast.rate[meetsData.meets.indexOf(meet) * 2 + 1] + ] + : null, + ), + ), + ]); + } + + LeaveForecastState copyWith({ + int? round, + List? meets, + }) => + LeaveForecastState.all( + round: round ?? this.round, + meets: meets ?? this.meets, + ); + + LeaveForecastState.all({ + required this.round, + required this.meets, + }); +} diff --git a/team_c_f/lib/storebloc/states/myteam.dart b/team_c_f/lib/storebloc/states/myteam.dart new file mode 100644 index 0000000..2a98239 --- /dev/null +++ b/team_c_f/lib/storebloc/states/myteam.dart @@ -0,0 +1,81 @@ +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/player.dart'; +import 'package:team_c_f/models/team.dart'; +import 'package:team_c_f/storebloc/models/team.dart'; +import 'package:team_c_f/storebloc/models/unconfirmedplayer.dart'; + +class MyTeamState { + final String uid; + late String position; + late String name; + late String team = 'Нет команды'; + TeamModel? teamData; + late bool confirmed; + late bool capitan; + List unconfirm = []; + late String selectId; + + MyTeamState({required this.uid}) { + PlayerData p = Data.players + .where((PlayerData playerData) => playerData.uid == uid) + .single; + position = p.prevPosition.toString(); + name = p.name; + if (p.team != null) { + team = p.team!; + TeamData t = + Data.teams.where((TeamData teamData) => teamData.name == team).single; + teamData = TeamModel(team: t); + confirmed = t.players.any((String uid) => uid == this.uid); + capitan = t.uidCapitan == uid; + + if (capitan) { + unconfirm = [ + ...Data.players + .where((PlayerData playerData) => playerData.team == team) + .where((PlayerData playerData) => + t.players.every((String uid) => uid != playerData.uid)) + .map((PlayerData playerData) => + UnconfirmedPlayerModel(uid: playerData.uid)) + ]; + } + } else { + capitan = false; + confirmed = false; + } + } + + MyTeamState copyWith({ + String? position, + bool? confirmed, + String? team, + TeamModel? teamData, + bool? capitan, + List? unconfirm, + }) => + MyTeamState.all( + uid: uid, + position: position ?? this.position, + confirmed: confirmed ?? this.confirmed, + name: name, + team: team == null + ? this.team + : team == '' + ? 'Нет команды' + : team, + teamData: teamData ?? this.teamData, + capitan: capitan ?? this.capitan, + unconfirm: unconfirm ?? this.unconfirm, + ); + + MyTeamState.all({ + required this.uid, + required this.position, + required this.confirmed, + required this.name, + required this.team, + required this.teamData, + required this.capitan, + required this.unconfirm, + }); +} diff --git a/team_c_f/lib/storebloc/states/schedule.dart b/team_c_f/lib/storebloc/states/schedule.dart new file mode 100644 index 0000000..458b834 --- /dev/null +++ b/team_c_f/lib/storebloc/states/schedule.dart @@ -0,0 +1,38 @@ +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/tour.dart'; +import 'package:team_c_f/storebloc/blocs/tour.dart'; +import 'package:team_c_f/storebloc/models/tour.dart'; + +class ScheduleState { + bool get enableSchedule => Data.tours.isNotEmpty; + late bool tourSelected = false; + late List tours = []; + late int? round; + late TourBloc? tourBloc; + + ScheduleState() { + tours = [...Data.tours.map((TourData tour) => TourModel(tour: tour))]; + } + + ScheduleState copyWith({ + List? tours, + int? nameTour, + bool? tourSelected, + int? round, + TourBloc? tourBloc, + }) { + return ScheduleState.all( + tours: tours ?? this.tours, + tourSelected: tourSelected ?? this.tourSelected, + round: round ?? this.round, + tourBloc: tourBloc ?? this.tourBloc, + ); + } + + ScheduleState.all({ + required this.tours, + required this.tourSelected, + required this.round, + required this.tourBloc, + }); +} diff --git a/team_c_f/lib/storebloc/states/selectmeets.dart b/team_c_f/lib/storebloc/states/selectmeets.dart new file mode 100644 index 0000000..fc6060a --- /dev/null +++ b/team_c_f/lib/storebloc/states/selectmeets.dart @@ -0,0 +1,34 @@ +import 'package:team_c_f/models/choicemeet.dart'; + +class SelectMeetsState { + List dateRange = []; + Map>> allMeets = {}; + Map openDate = {}; + Map openTornament = {}; + List selectedMeets = []; + + SelectMeetsState(); + + SelectMeetsState copyWith({ + List? dateRange, + Map>>? allMeets, + Map? openDate, + Map? openTornament, + List? selectedMeets, + }) => + SelectMeetsState.all( + dateRange: dateRange ?? this.dateRange, + allMeets: allMeets ?? this.allMeets, + openDate: openDate ?? this.openDate, + openTornament: openTornament ?? this.openTornament, + selectedMeets: selectedMeets ?? this.selectedMeets, + ); + + SelectMeetsState.all({ + required this.dateRange, + required this.allMeets, + required this.openDate, + required this.openTornament, + required this.selectedMeets, + }); +} diff --git a/team_c_f/lib/storebloc/states/tour.dart b/team_c_f/lib/storebloc/states/tour.dart new file mode 100644 index 0000000..b8f903b --- /dev/null +++ b/team_c_f/lib/storebloc/states/tour.dart @@ -0,0 +1,45 @@ +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/models/forecast.dart'; +import 'package:team_c_f/models/meets.dart'; +import 'package:team_c_f/models/tour.dart'; +import 'package:team_c_f/storebloc/models/meet.dart'; +import 'package:team_c_f/storebloc/models/tour.dart'; + +class TourState { + final int round; + late MeetsModel meets; + late TourModel tour; + late bool size = false; + + TourState({required this.round, required String uid}) { + tour = TourModel( + tour: Data.tours.where((TourData t) => t.round == round).single); + meets = MeetsModel( + meet: Data.meets.where((MeetsData m) => m.round == round).single); + // TourService() + // .getForecast(uid: uid, round: round) + // .then((ForecastData? response) => forecast = response); + } + + TourState copyWith({ + int? round, + MeetsData? meetsData, + TourModel? tour, + bool? size, + }) { + MeetsModel? meets = meetsData != null ? MeetsModel(meet: meetsData) : null; + return TourState.all( + round: round ?? this.round, + meets: meets ?? this.meets, + tour: tour ?? this.tour, + size: size ?? this.size, + ); + } + + TourState.all({ + required this.round, + required this.meets, + required this.tour, + required this.size, + }); +} diff --git a/team_c_f/lib/views/meets.dart b/team_c_f/lib/views/meets.dart new file mode 100644 index 0000000..2341e78 --- /dev/null +++ b/team_c_f/lib/views/meets.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/components/meet.dart'; +import 'package:team_c_f/models/meet.dart'; +import 'package:team_c_f/storebloc/models/meet.dart'; +import 'package:intl/intl.dart'; + +class ShowMeets extends StatelessWidget { + final MeetsModel meetsModel; + const ShowMeets({Key? key, required this.meetsModel}) : super(key: key); + + @override + Widget build(BuildContext context) { + DateTime deadline = + DateFormat('yyyy-MM-dd HH:mm').parse(meetsModel.deadline); + String day; + switch (deadline.weekday) { + case 1: + day = 'понедельник'; + break; + case 2: + day = 'вторник'; + break; + case 3: + day = 'среду'; + break; + case 4: + day = 'четверг'; + break; + case 5: + day = 'пятницу'; + break; + case 6: + day = 'субботу'; + break; + default: + day = 'воскресенье'; + break; + } + String date = DateFormat('dd.MM').format(deadline); + String time = DateFormat('HH:mm').format(deadline); + return Container( + child: Column( + children: [ + if (!meetsModel.started) + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Дедлайн в ' + day + ' ' + date + ' в ' + time + ' по МСК'), + ), + Wrap( + children: [ + ...meetsModel.meets.map( + (MeetData meetData) => MeetView( + meetData: meetData, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/views/player.dart b/team_c_f/lib/views/player.dart new file mode 100644 index 0000000..3e8811e --- /dev/null +++ b/team_c_f/lib/views/player.dart @@ -0,0 +1,59 @@ +import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:team_c_f/models/player.dart'; +import 'package:team_c_f/servises/servises.dart'; +import 'package:team_c_f/storebloc/blocs/myteam.dart'; +import 'package:provider/provider.dart'; + +class ShowPlayer extends StatelessWidget { + // Класс отображающий информацию об указанном игроке + final PlayerData player; + ShowPlayer({Key? key, required this.player}) : super(key: key); + + @override + Widget build(BuildContext context) { + MyTeamBloc bloc = context.watch(); + return Container( + child: InkWell( + onLongPress: () async { + if (bloc.state.capitan && + (await showAlertDialog( + context: context, + title: 'Изменение состава', + message: 'Удалить ${player.name}', + actions: [ + AlertDialogAction( + key: true, + label: 'Да, удалить', + isDefaultAction: true, + ), + AlertDialogAction( + key: false, + label: 'Отмена', + isDestructiveAction: true, + ), + ], + ))!) { + bloc.state.selectId = player.uid; + bloc.add(MyTeamEvent.unconfirmedPlayer); + } + }, + child: Card( + color: Colors.cyan[100], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: ListTile( + leading: CircleAvatar( + child: Text(player.prevPosition.toString()), + ), + title: Text(player.name), + trailing: Text( + showGoals(player.goals), + ), + ), + ), + ), + ); + } +} diff --git a/team_c_f/lib/views/team.dart b/team_c_f/lib/views/team.dart new file mode 100644 index 0000000..ef0194c --- /dev/null +++ b/team_c_f/lib/views/team.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:team_c_f/data/data.dart'; +import 'package:team_c_f/servises/servises.dart'; +import 'package:team_c_f/storebloc/models/team.dart'; +import 'package:team_c_f/views/player.dart'; + +class ShowTeam extends StatelessWidget { + // Класс отображения информации об указанной команде + final TeamModel team; // Команда + ShowTeam({Key? key, required this.team}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Column( + children: [ + Card( + color: Colors.cyan[200], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Observer( + builder: (_) => ListTile( + // Информация о команде + leading: CircleAvatar( + child: Text( + team.team.prevPosition.toString(), + ), + ), + title: Text(team.team.name), + trailing: Text( + //team.team.points.toString() + showPoints(team.points), + ), + ), + ), + ), + Container( + // Информация об участниках команды + margin: const EdgeInsets.all(8.0), + child: Column( + children: [ + ...team.team.players.map( + (String uid) => ShowPlayer( + player: Data.players + .where((player) => player.uid == uid) + .first), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/views/tour.dart b/team_c_f/lib/views/tour.dart new file mode 100644 index 0000000..e2134d2 --- /dev/null +++ b/team_c_f/lib/views/tour.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:team_c_f/storebloc/models/tour.dart'; + +class ShowTour extends StatelessWidget { + final TourModel tour; + const ShowTour({Key? key, required this.tour}) : super(key: key); + + @override + Widget build(BuildContext context) { + double size = MediaQuery.of(context).size.width; + return Container( + padding: const EdgeInsets.all(3.0), + child: Table( + border: TableBorder( + top: BorderSide( + width: 2, + color: Colors.amber, + ), + right: BorderSide( + width: 2, + color: Colors.amber, + ), + bottom: BorderSide( + width: 2, + color: Colors.amber, + ), + left: BorderSide( + width: 2, + color: Colors.amber, + ), + horizontalInside: BorderSide( + width: 2, + color: Colors.amber, + ), + ), + columnWidths: { + 0: FixedColumnWidth(size / 2.5), + 1: FixedColumnWidth(size / 8), + 2: FixedColumnWidth(size / 2.5), + }, + children: [ + ...tour.result.map( + (List> match) { + String home = match.first.values.single != null + ? match.first.values.single.toString() + : ''; + String away = match.last.values.single != null + ? match.last.values.single.toString() + : ''; + return TableRow( + children: [ + Container( + padding: const EdgeInsets.all(8.0), + child: Text( + match.first.keys.single, + textAlign: TextAlign.center, + ), + color: tour.result.indexOf(match).isEven + ? Colors.cyan[100] + : Colors.cyan[400], + ), + Container( + padding: const EdgeInsets.all(8.0), + child: Text( + home + ':' + away, + textAlign: TextAlign.center, + ), + color: tour.result.indexOf(match).isEven + ? Colors.cyan[100] + : Colors.cyan[400], + ), + Container( + padding: const EdgeInsets.all(8.0), + child: Text( + match.last.keys.single, + textAlign: TextAlign.center, + ), + color: tour.result.indexOf(match).isEven + ? Colors.cyan[100] + : Colors.cyan[400], + ), + ], + ); + }, + ), + ], + ), + ); + } +} diff --git a/team_c_f/lib/views/touravatar.dart b/team_c_f/lib/views/touravatar.dart new file mode 100644 index 0000000..5cbecd2 --- /dev/null +++ b/team_c_f/lib/views/touravatar.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:team_c_f/store/login/login.dart'; +import 'package:team_c_f/storebloc/blocs/schedule.dart'; +import 'package:team_c_f/storebloc/blocs/tour.dart' as tourBloc; +import 'package:team_c_f/storebloc/models/tour.dart'; +import 'package:provider/provider.dart'; + +class ShowTourAvatar extends StatelessWidget { + final TourModel tour; + const ShowTourAvatar({Key? key, required this.tour}) : super(key: key); + + @override + Widget build(BuildContext context) { + String title; + double fontSize; + if (tour.name.split(' ').length > 1) { + title = + tour.name.split(' ')[0] + '\n' + tour.name.split(' ')[1] + ' матч'; + fontSize = MediaQuery.of(context).size.width / 20; + } else { + title = tour.name; + fontSize = MediaQuery.of(context).size.width / 15; + } + return Container( + padding: const EdgeInsets.all(3.0), + child: InkWell( + onTap: () { + context.read().add( + ScheduleEvent( + event: Event.selectTour, + round: tour.stage, + uid: context.read().userId, + ), + ); + context.read().add( + tourBloc.TourEvent( + event: tourBloc.Event.selectTour, + stage: tour.stage, + ), + ); + }, + child: CircleAvatar( + radius: MediaQuery.of(context).size.width / 10, + child: Text( + title, + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle(fontSize: fontSize), + )), + ), + ); + } +} diff --git a/team_c_f/pubspec.lock b/team_c_f/pubspec.lock index 330d35c..96f9144 100644 --- a/team_c_f/pubspec.lock +++ b/team_c_f/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "21.0.0" adaptive_dialog: dependency: "direct main" description: @@ -8,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.0+5" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" animations: dependency: transitive description: @@ -15,6 +29,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" async: dependency: transitive description: @@ -22,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.5.0" + bloc: + dependency: transitive + description: + name: bloc + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.0" boolean_selector: dependency: transitive description: @@ -29,6 +57,69 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + bottom_navy_bar: + dependency: "direct main" + description: + name: bottom_navy_bar + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.0" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.0.5" carousel_slider: dependency: "direct main" description: @@ -50,6 +141,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" clock: dependency: transitive description: @@ -63,21 +168,28 @@ packages: name: cloud_firestore url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.6" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.2" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.6" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" collection: dependency: transitive description: @@ -85,6 +197,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" csslib: dependency: transitive description: @@ -113,13 +239,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" - date_range_picker: - dependency: "direct main" + dart_style: + dependency: transitive description: - name: date_range_picker + name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.0.7" + version: "2.0.0" fake_async: dependency: transitive description: @@ -127,34 +253,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.0" firebase_auth: dependency: "direct main" description: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.1" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.1.1" firebase_auth_web: dependency: transitive description: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.7" firebase_core: dependency: transitive description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" firebase_core_platform_interface: dependency: transitive description: @@ -169,11 +302,44 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.0" + flutter_date_pickers: + dependency: "direct main" + description: + name: flutter_date_pickers + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.4" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_mobx: + dependency: "direct main" + description: + name: flutter_mobx + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -190,14 +356,21 @@ packages: name: fluttertoast url: "https://pub.dartlang.org" source: hosted - version: "8.0.3" + version: "8.0.6" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" google_sign_in: dependency: "direct main" description: name: google_sign_in url: "https://pub.dartlang.org" source: hosted - version: "5.0.1" + version: "5.0.2" google_sign_in_platform_interface: dependency: transitive description: @@ -212,6 +385,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.0" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" html: dependency: "direct main" description: @@ -226,6 +406,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.1" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" http_parser: dependency: transitive description: @@ -240,6 +427,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.17.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" js: dependency: transitive description: @@ -247,6 +441,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.3" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" matcher: dependency: transitive description: @@ -261,6 +476,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + mobx: + dependency: "direct main" + description: + name: mobx + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + mobx_codegen: + dependency: "direct dev" + description: + name: mobx_codegen + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1+3" nested: dependency: transitive description: @@ -274,7 +510,14 @@ packages: name: onesignal_flutter url: "https://pub.dartlang.org" source: hosted - version: "2.6.3" + version: "3.0.0-beta2" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" path: dependency: transitive description: @@ -296,6 +539,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" provider: dependency: "direct main" description: @@ -303,18 +553,53 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" source_span: dependency: transitive description: @@ -336,6 +621,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -357,6 +649,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.19" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" typed_data: dependency: transitive description: @@ -371,6 +670,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" sdks: dart: ">=2.12.0 <3.0.0" flutter: ">=1.20.0" diff --git a/team_c_f/pubspec.yaml b/team_c_f/pubspec.yaml index df6b702..c6ef25b 100644 --- a/team_c_f/pubspec.yaml +++ b/team_c_f/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: @@ -32,17 +32,26 @@ dependencies: http: ^0.13.1 html: ^0.15.0 carousel_slider: ^3.0.0 + flutter_bloc: ^7.0.0 custom_navigation_bar: ^0.8.1 + bottom_navy_bar: ^6.0.0 + provider: ^5.0.0 - date_range_picker: ^1.0.7 + flutter_date_pickers: ^0.2.4 firebase_auth: ^1.0.1 cloud_firestore: ^1.0.3 google_sign_in: ^5.0.1 fluttertoast: ^8.0.3 adaptive_dialog: ^0.10.0+5 - onesignal_flutter: ^2.6.3 + onesignal_flutter: ^3.0.0-beta2 + mobx: ^2.0.1 + flutter_mobx: ^2.0.0 dev_dependencies: + build_runner: ^2.0.1 + mobx_codegen: ^2.0.1+3 + json_serializable: ^4.1.1 + flutter_test: sdk: flutter