diff --git a/lib/app/services/converters.dart b/lib/app/services/converters.dart index 6f7b7936..714afa38 100644 --- a/lib/app/services/converters.dart +++ b/lib/app/services/converters.dart @@ -28,3 +28,4 @@ part 'converters/poi_parsing.dart'; part 'converters/slider_range_parsing.dart'; part 'converters/place_parser.dart'; part 'converters/string_extension.dart'; +part 'converters/date_time_parsing.dart'; diff --git a/lib/app/services/converters/date_time_parsing.dart b/lib/app/services/converters/date_time_parsing.dart new file mode 100644 index 00000000..f6ca8f6f --- /dev/null +++ b/lib/app/services/converters/date_time_parsing.dart @@ -0,0 +1,13 @@ +part of '../converters.dart'; + +extension DateTimeParsing on DateTime { + String getAsLocalDateTimeString() { + DateTime utcDateTime = this; + DateTime localDateTime = utcDateTime.toLocal(); + final dateString = DateFormat(t.campaigns.poster.date_format).format(localDateTime); + final timeString = DateFormat(t.campaigns.poster.time_format).format(localDateTime); + return t.campaigns.poster.datetime_display_template + .replaceAll('{date}', dateString) + .replaceAll('{time}', timeString); + } +} diff --git a/lib/app/services/gruene_api_campaigns_statistics_service.dart b/lib/app/services/gruene_api_campaigns_statistics_service.dart index 21ff5de0..768d246f 100644 --- a/lib/app/services/gruene_api_campaigns_statistics_service.dart +++ b/lib/app/services/gruene_api_campaigns_statistics_service.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; +import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics.dart'; +import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics_set.dart'; import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart'; class GrueneApiCampaignsStatisticsService { @@ -41,19 +43,3 @@ extension PoiStatisticsParser on PoiStatistics { ); } } - -class CampaignStatisticsSet { - final double own, division, state, germany; - - const CampaignStatisticsSet({required this.own, required this.division, required this.state, required this.germany}); -} - -class CampaignStatistics { - final CampaignStatisticsSet flyerStats, houseStats, posterStats; - - const CampaignStatistics({ - required this.flyerStats, - required this.houseStats, - required this.posterStats, - }); -} diff --git a/lib/features/campaigns/helper/campaign_session_settings.dart b/lib/features/campaigns/helper/campaign_session_settings.dart index 0658dc42..5d4bbf1a 100644 --- a/lib/features/campaigns/helper/campaign_session_settings.dart +++ b/lib/features/campaigns/helper/campaign_session_settings.dart @@ -1,10 +1,14 @@ import 'package:gruene_app/app/services/nominatim_service.dart'; +import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; class CampaignSessionSettings { LatLng? lastPosition; double? lastZoomLevel; + CampaignStatistics? recentStatistics; + DateTime? recentStatisticsFetchTimestamp; + bool imageConsentConfirmed = false; String? searchString; diff --git a/lib/features/campaigns/models/statistics/campaign_statistics.dart b/lib/features/campaigns/models/statistics/campaign_statistics.dart new file mode 100644 index 00000000..766cb4b4 --- /dev/null +++ b/lib/features/campaigns/models/statistics/campaign_statistics.dart @@ -0,0 +1,11 @@ +import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics_set.dart'; + +class CampaignStatistics { + final CampaignStatisticsSet flyerStats, houseStats, posterStats; + + const CampaignStatistics({ + required this.flyerStats, + required this.houseStats, + required this.posterStats, + }); +} diff --git a/lib/features/campaigns/models/statistics/campaign_statistics_set.dart b/lib/features/campaigns/models/statistics/campaign_statistics_set.dart new file mode 100644 index 00000000..e4258364 --- /dev/null +++ b/lib/features/campaigns/models/statistics/campaign_statistics_set.dart @@ -0,0 +1,10 @@ +class CampaignStatisticsSet { + final double own, division, state, germany; + + const CampaignStatisticsSet({ + required this.own, + required this.division, + required this.state, + required this.germany, + }); +} diff --git a/lib/features/campaigns/screens/statistics_screen.dart b/lib/features/campaigns/screens/statistics_screen.dart index b7f7778e..836c3619 100644 --- a/lib/features/campaigns/screens/statistics_screen.dart +++ b/lib/features/campaigns/screens/statistics_screen.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get_it/get_it.dart'; +import 'package:gruene_app/app/services/converters.dart'; import 'package:gruene_app/app/services/gruene_api_campaigns_statistics_service.dart'; import 'package:gruene_app/app/theme/theme.dart'; +import 'package:gruene_app/features/campaigns/helper/app_settings.dart'; import 'package:gruene_app/features/campaigns/helper/campaign_constants.dart'; +import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics.dart'; +import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics_set.dart'; import 'package:gruene_app/i18n/translations.g.dart'; import 'package:intl/intl.dart'; @@ -26,6 +30,7 @@ class StatisticsScreen extends StatelessWidget { } SingleChildScrollView _buildStatScreen(CampaignStatistics statistics, ThemeData theme, BuildContext context) { + var lastUpdateTime = GetIt.I().campaign.recentStatisticsFetchTimestamp ?? DateTime.now(); return SingleChildScrollView( child: Container( padding: EdgeInsets.all(16), @@ -57,7 +62,7 @@ class StatisticsScreen extends StatelessWidget { child: Align( alignment: Alignment.centerLeft, child: Text( - 'Stand: ${DateTime.now().toString()} (${t.campaigns.statistic.update_info})', + '${t.campaigns.statistic.as_at}: ${lastUpdateTime.getAsLocalDateTimeString()} (${t.campaigns.statistic.update_info})', style: theme.textTheme.labelMedium!.apply(color: ThemeColors.textDisabled), ), ), @@ -111,7 +116,6 @@ class StatisticsScreen extends StatelessWidget { } Widget _getBadgeRow(String title, int ownCounter, ThemeData theme) { - // var rng = Random(); return Container( decoration: BoxDecoration( border: Border( @@ -158,7 +162,7 @@ class StatisticsScreen extends StatelessWidget { alignment: Alignment.center, child: Text( currentThreshold.toString(), - style: theme.textTheme.labelMedium!.apply(fontWeightDelta: 3), + style: theme.textTheme.labelMedium!.apply(fontWeightDelta: 3, fontStyle: FontStyle.italic), ), ), ), @@ -193,7 +197,7 @@ class StatisticsScreen extends StatelessWidget { ), ); } - widgets.add(SizedBox(width: 6)); + if (currentThreshold != thresholds.last) widgets.add(SizedBox(width: 5)); } return widgets; } @@ -266,7 +270,18 @@ class StatisticsScreen extends StatelessWidget { } Future _loadStatistics() async { + var campaignSettings = GetIt.I().campaign; + + if (campaignSettings.recentStatistics != null && + DateTime.now().isBefore(campaignSettings.recentStatisticsFetchTimestamp!.add(Duration(minutes: 5)))) { + return campaignSettings.recentStatistics!; + } var statApiService = GetIt.I(); - return await statApiService.getStatistics(); + var campaignStatistics = await statApiService.getStatistics(); + + campaignSettings.recentStatistics = campaignStatistics; + campaignSettings.recentStatisticsFetchTimestamp = DateTime.now(); + + return campaignStatistics; } } diff --git a/lib/i18n/app_de.json b/lib/i18n/app_de.json index 048f37e0..facd9b07 100644 --- a/lib/i18n/app_de.json +++ b/lib/i18n/app_de.json @@ -122,7 +122,8 @@ "by_my_KV": "von meinen Kreisverband", "by_my_LV": "von meinem Landesverband", "in_germany": "deutschlandweit", - "update_info": "wird alle 5 Minuten aktualisiert" + "update_info": "wird alle 5 Minuten aktualisiert", + "as_at": "Stand" }, "address": { "street": "Straße",