diff --git a/lib/main.dart b/lib/main.dart index 935629f..be935c6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:intl/intl.dart'; import 'package:steamwar_multitool/src/app.dart'; +final kDateFormat = DateFormat("dd.MM.yyyy HH:mm"); + void main() => runApp(const ProviderScope(child: DevServerStarterApp())); diff --git a/lib/src/provider/events.dart b/lib/src/provider/events.dart index 960a7ea..e3bf099 100644 --- a/lib/src/provider/events.dart +++ b/lib/src/provider/events.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:steamwar_multitool/src/provider/types.dart'; @@ -122,15 +123,21 @@ class EventFight { this.blueTeam, this.kampfleiter, this.score); Team get winner { + return getTeamWithContextColor(Colors.white); + } + + Team getTeamWithContextColor(Color color) { switch (score) { case 1: return blueTeam; case 2: return redTeam; case 3: - return Team(-1, "Tie", "TIE", "7"); + return Team( + -1, "Tie", "TIE", color.computeLuminance() > 0.5 ? "f" : "0"); default: - return Team(-1, "Unknown", "UNK", "7"); + return Team( + -1, "Unknown", "UNK", color.computeLuminance() > 0.5 ? "f" : "0"); } } @@ -269,6 +276,9 @@ class ShortEvent { get isUpcoming => start.isAfter(DateTime.now()); + get isCurrent => + start.isBefore(DateTime.now()) && end.isAfter(DateTime.now()); + factory ShortEvent.fromJson(Map json) { return ShortEvent( json["name"], diff --git a/lib/src/provider/http.dart b/lib/src/provider/http.dart index a9dc1c4..46cb1c0 100644 --- a/lib/src/provider/http.dart +++ b/lib/src/provider/http.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:steamwar_multitool/src/provider/user.dart'; final serverUrlProvider = Provider((ref) { + return "https://steamwar.de/eventplanner-api"; if (kDebugMode) { return "http://localhost:1337"; } else { diff --git a/lib/src/screens/bracket_generator.dart b/lib/src/screens/bracket_generator.dart new file mode 100644 index 0000000..d920d9e --- /dev/null +++ b/lib/src/screens/bracket_generator.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class BracketGeneratorScreen extends HookConsumerWidget { + const BracketGeneratorScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return const Placeholder(); + } +} diff --git a/lib/src/screens/components/events_list.dart b/lib/src/screens/components/events_list.dart index 914481e..e3ca084 100644 --- a/lib/src/screens/components/events_list.dart +++ b/lib/src/screens/components/events_list.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:steamwar_multitool/main.dart'; import '../../provider/events.dart'; -import '../../provider/user.dart'; -import '../event.dart'; import 'error.dart'; import 'event_dialog.dart'; @@ -14,10 +13,11 @@ class EventListComponent extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final events = ref.watch(eventsListProvider); - final userData = ref.watch(userDataProvider); return events.when(data: (data) { final upcomingEvents = data.where((element) => element.isUpcoming); - final pastEvents = data.where((element) => !element.isUpcoming); + final pastEvents = + data.where((element) => !element.isUpcoming && !element.isCurrent); + final currentEvent = data.indexWhere((element) => element.isCurrent); return ListView( children: [ FloatingActionButton.extended( @@ -30,6 +30,21 @@ class EventListComponent extends HookConsumerWidget { const SizedBox( height: 16, ), + if (currentEvent != -1) + ListTile( + title: Text( + data[currentEvent].name, + style: Theme.of(context).textTheme.headline6, + ), + subtitle: Text( + "Current Event", + style: Theme.of(context).textTheme.subtitle1, + ), + leading: const Icon(Icons.priority_high), + onTap: () { + context.go("/event/${data[currentEvent].id}"); + }, + ), if (upcomingEvents.isNotEmpty) Text( "Upcoming Events", @@ -38,7 +53,8 @@ class EventListComponent extends HookConsumerWidget { ...upcomingEvents.map( (e) => ListTile( title: Text(e.name), - subtitle: Text("${e.start} - ${e.end}"), + subtitle: Text( + "${kDateFormat.format(e.start)} - ${kDateFormat.format(e.end)}"), leading: const Icon(Icons.event), onTap: () async { context.go("/event/${e.id}"); @@ -53,7 +69,8 @@ class EventListComponent extends HookConsumerWidget { ...pastEvents.map((e) => ListTile( title: Text(e.name), leading: const Icon(Icons.check), - subtitle: Text("${e.start} - ${e.end}"), + subtitle: Text( + "${kDateFormat.format(e.start)} - ${kDateFormat.format(e.end)}"), onTap: () async { context.go("/event/${e.id}"); }, diff --git a/lib/src/screens/event.dart b/lib/src/screens/event.dart index 6d3a827..cdebfd1 100644 --- a/lib/src/screens/event.dart +++ b/lib/src/screens/event.dart @@ -4,8 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:steamwar_multitool/src/provider/user.dart'; +import 'package:steamwar_multitool/src/util/event_fight_exporter.dart'; +import '../../main.dart'; import '../provider/events.dart'; import '../provider/types.dart'; import 'search_delegates.dart'; @@ -348,23 +349,42 @@ class _EventFightList extends HookConsumerWidget { return Column( children: [ const SizedBox(height: 8), - SizedBox( - width: double.infinity, - child: FloatingActionButton.extended( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return _AddFightWidget( - eventData, - () => update(), + Row( + children: [ + Expanded( + child: FloatingActionButton.extended( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return _AddFightWidget( + eventData, + () => update(), + ); + }, ); }, - ); - }, - label: const Text("Add Fight"), - icon: const Icon(Icons.add), - ), + label: const Text("Add Fight"), + icon: const Icon(Icons.add), + ), + ), + const SizedBox(width: 8), + PopupMenuButton( + itemBuilder: (context) { + return [ + PopupMenuItem( + child: const Text("Export Data"), + value: "export", + ), + ]; + }, + onSelected: (value) { + if (value == "export") { + openExportedFights(fights.value, event.name); + } + }, + ) + ], ), const SizedBox(height: 8), for (final fight in fights.value) @@ -372,16 +392,26 @@ class _EventFightList extends HookConsumerWidget { title: Text( "${fight.blueTeam.name} vs ${fight.redTeam.name}", style: TextStyle( - color: fight.winner.color.computeLuminance() > 0.5 + color: fight + .getTeamWithContextColor( + Theme.of(context).scaffoldBackgroundColor) + .color + .computeLuminance() > + 0.5 ? Colors.black : Colors.white), ), subtitle: Text( fight.score == 0 - ? fight.start.toString() + ? kDateFormat.format(fight.start) : "Winner: ${fight.winner.name}", style: TextStyle( - color: fight.winner.color.computeLuminance() > 0.5 + color: fight + .getTeamWithContextColor( + Theme.of(context).scaffoldBackgroundColor) + .color + .computeLuminance() > + 0.5 ? Colors.black : Colors.white)), onTap: () { @@ -725,7 +755,7 @@ class DateTimeEditor extends HookConsumerWidget { } } : null, - child: Text(initialDate.toString()), + child: Text(kDateFormat.format(initialDate)), ), IconButton( onPressed: enabled diff --git a/lib/src/util/event_fight_exporter.dart b/lib/src/util/event_fight_exporter.dart new file mode 100644 index 0000000..386b848 --- /dev/null +++ b/lib/src/util/event_fight_exporter.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; +import 'dart:html'; + +import 'package:csv/csv.dart'; +import 'package:steamwar_multitool/src/provider/events.dart'; + +/* +Start,BlueTeam,RedTeam,WinnerTeam + + */ + +Uri exportFights(List fights, String eventName) { + List> csv = []; + csv.add(['Start', 'BlueTeam', 'RedTeam', 'WinnerTeam']); + for (var fight in fights) { + csv.add([ + fight.start.toString(), + fight.blueTeam.name, + fight.redTeam.name, + fight.winner.name, + ]); + } + + return Uri.dataFromBytes( + Encoding.getByName("utf-8")! + .encode(const ListToCsvConverter(eol: "\n").convert(csv)), + mimeType: "text/csv", + ); +} + +void openExportedFights(List fights, String eventName) async { + final uri = exportFights(fights, eventName); + window.open(uri.toString(), "export"); +} diff --git a/pubspec.lock b/pubspec.lock index 3f35b37..f770dc3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -119,7 +119,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "4.3.0" + version: "4.4.0" collection: dependency: transitive description: @@ -141,6 +141,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.2" + csv: + dependency: "direct main" + description: + name: csv + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.1" cupertino_icons: dependency: "direct main" description: @@ -222,7 +229,7 @@ packages: name: flutter_riverpod url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" flutter_test: dependency: "direct dev" description: flutter @@ -281,7 +288,7 @@ packages: name: hooks_riverpod url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" http_multi_server: dependency: transitive description: @@ -296,6 +303,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.2" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.18.0" io: dependency: transitive description: @@ -463,7 +477,7 @@ packages: name: riverpod url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" shared_preferences: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index e827707..d65260f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,6 +21,8 @@ dependencies: xterm: ^3.4.0 dio: ^4.0.6 go_router: ^6.0.0 + intl: ^0.18.0 + csv: ^5.0.1 dev_dependencies: diff --git a/web/index.html b/web/index.html index 2958c68..f03efee 100644 --- a/web/index.html +++ b/web/index.html @@ -37,7 +37,7 @@ var serviceWorkerVersion = null; - +