Skip to content

Commit

Permalink
575 enhancements for posters (#577)
Browse files Browse the repository at this point in the history
* 550: add new poster_icons
* 575: fix statistics interface
* 546: new poster status "to be moved"
* 550: update poster icons
* 564: show detail bottom sheet
* 564: set focus on map element
* 574: change edit view to show new state selection
  • Loading branch information
Stift authored Feb 5, 2025
1 parent 55c1d2f commit 432a2ab
Show file tree
Hide file tree
Showing 30 changed files with 535 additions and 305 deletions.
Binary file modified assets/symbols/posters/poster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/symbols/posters/poster_damaged.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/symbols/posters/poster_missing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/symbols/posters/poster_removed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/symbols/posters/poster_to_be_moved.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/symbols/posters/svg_inverted/poster_damaged.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/symbols/posters/svg_inverted/poster_missing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/symbols/posters/svg_inverted/poster_ok.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/symbols/posters/svg_inverted/poster_removed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/symbols/posters/svg_inverted/poster_tobemoved.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions lib/app/services/converters/poi_poster_status_parsing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extension PoiPosterStatusParsing on PoiPosterStatus {
PoiPosterStatus.damaged => PosterStatus.damaged,
PoiPosterStatus.missing => PosterStatus.missing,
PoiPosterStatus.removed => PosterStatus.removed,
PoiPosterStatus.toBeMoved => PosterStatus.toBeMoved,
PoiPosterStatus.swaggerGeneratedUnknown => throw UnimplementedError(),
};
}
Expand All @@ -17,6 +18,7 @@ extension PoiPosterStatusParsing on PoiPosterStatus {
PoiPosterStatus.damaged => t.campaigns.poster.status.damaged.label,
PoiPosterStatus.removed => t.campaigns.poster.status.removed.label,
PoiPosterStatus.missing => t.campaigns.poster.status.missing.label,
PoiPosterStatus.toBeMoved => t.campaigns.poster.status.to_be_moved.label,
PoiPosterStatus.swaggerGeneratedUnknown => throw UnimplementedError(),
};
}
Expand Down
1 change: 1 addition & 0 deletions lib/app/services/converters/poster_status_parsing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extension PosterStatusParsing on PosterStatus {
PosterStatus.damaged => PoiPosterStatus.damaged,
PosterStatus.missing => PoiPosterStatus.missing,
PosterStatus.removed => PoiPosterStatus.removed,
PosterStatus.toBeMoved => PoiPosterStatus.toBeMoved,
};
}

Expand Down
10 changes: 5 additions & 5 deletions lib/app/services/gruene_api_campaigns_statistics_service.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
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_model.dart';
import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics_set.dart';
import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart';

Expand All @@ -11,7 +11,7 @@ class GrueneApiCampaignsStatisticsService {
grueneApi = GetIt.I<GrueneApi>();
}

Future<CampaignStatistics> getStatistics() async {
Future<CampaignStatisticsModel> getStatistics() async {
try {
var statResult = await grueneApi.v1CampaignsStatisticsGet();
return statResult.body!.asCampaignStatistics();
Expand All @@ -23,9 +23,9 @@ class GrueneApiCampaignsStatisticsService {
}
}

extension StatisticsParser on Statistics {
CampaignStatistics asCampaignStatistics() {
return CampaignStatistics(
extension StatisticsParser on CampaignStatistics {
CampaignStatisticsModel asCampaignStatistics() {
return CampaignStatisticsModel(
flyerStats: flyer.asStatisticsSet(),
houseStats: house.asStatisticsSet(),
posterStats: poster.asStatisticsSet(),
Expand Down
2 changes: 2 additions & 0 deletions lib/features/campaigns/helper/campaign_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ class CampaignConstants {
static const flyerAssetName = 'assets/symbols/flyer/flyer.png';
static const posterOkAssetName = 'assets/symbols/posters/poster.png';
static const posterDamagedAssetName = 'assets/symbols/posters/poster_damaged.png';
static const posterMissingAssetName = 'assets/symbols/posters/poster_missing.png';
static const posterRemovedAssetName = 'assets/symbols/posters/poster_removed.png';
static const posterToBeMovedAssetName = 'assets/symbols/posters/poster_to_be_moved.png';
static const addMarkerAssetName = 'assets/symbols/add_marker.svg';

static const markerSourceName = 'markers';
Expand Down
4 changes: 2 additions & 2 deletions lib/features/campaigns/helper/campaign_session_settings.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import 'package:gruene_app/app/services/nominatim_service.dart';
import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics.dart';
import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics_model.dart';
import 'package:maplibre_gl/maplibre_gl.dart';

class CampaignSessionSettings {
LatLng? lastPosition;
double? lastZoomLevel;

CampaignStatistics? recentStatistics;
CampaignStatisticsModel? recentStatistics;
DateTime? recentStatisticsFetchTimestamp;

bool imageConsentConfirmed = false;
Expand Down
2 changes: 2 additions & 0 deletions lib/features/campaigns/helper/enums.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
enum ModalEditResult { cancel, save, delete }

enum ModalDetailResult { close, edit }

enum ImageType { jpeg, png }
13 changes: 9 additions & 4 deletions lib/features/campaigns/helper/poster_status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@ import 'package:gruene_app/features/campaigns/models/posters/poster_detail_model
import 'package:gruene_app/i18n/translations.g.dart';

class PosterStatusHelper {
static List<(PosterStatus, String, String)> getPosterStatusOptions = <(PosterStatus, String, String)>[
static List<(PosterStatus, String)> getPosterStatusList = <(PosterStatus status, String label)>[
(
PosterStatus.ok,
t.campaigns.poster.status.ok.label,
),
(
PosterStatus.damaged,
t.campaigns.poster.status.damaged.label,
t.campaigns.poster.status.damaged.hint,
),
(
PosterStatus.missing,
t.campaigns.poster.status.missing.label,
t.campaigns.poster.status.missing.hint,
),
(
PosterStatus.toBeMoved,
t.campaigns.poster.status.to_be_moved.label,
),
(
PosterStatus.removed,
t.campaigns.poster.status.removed.label,
t.campaigns.poster.status.removed.hint,
),
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ enum PosterStatus {
missing,
@JsonValue(400)
removed,
@JsonValue(500)
toBeMoved,
}

@JsonSerializable()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:gruene_app/features/campaigns/models/statistics/campaign_statistics_set.dart';

class CampaignStatistics {
class CampaignStatisticsModel {
final CampaignStatisticsSet flyerStats, houseStats, posterStats;

const CampaignStatistics({
const CampaignStatisticsModel({
required this.flyerStats,
required this.houseStats,
required this.posterStats,
Expand Down
44 changes: 33 additions & 11 deletions lib/features/campaigns/screens/map_consumer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,44 @@ abstract class MapConsumer<T extends StatefulWidget, PoiCreateType, PoiUpdateTyp
GetPoiDetailWidgetCallback<U> getPoiDetail,
GetPoiEditWidgetCallback<U> getPoiEdit, {
Size desiredSize = const Size(100, 100),
bool useBottomSheet = false,
}) async {
final feature = rawFeature as Map<String, dynamic>;
final poiId = MapHelper.extractPoiIdFromFeature(feature);
U poi = await getPoi(poiId);
final poiDetailWidget = getPoiDetail(poi);
var popupWidget = SizedBox(
height: desiredSize.height,
width: desiredSize.width,
child: poiDetailWidget,
);
final coord = MapHelper.extractLatLngFromFeature(feature);
mapController.showMapPopover(
coord,
popupWidget,
() => _editPoi(() => getPoiEdit(poi)),
desiredSize,
if (useBottomSheet) {
await mapController.setFocusToMarkerItem(rawFeature);
var result = await showDetailBottomSheet(poiDetailWidget);
if (result != null && result == ModalDetailResult.edit) {
_editPoi(() => getPoiEdit(poi));
}
await mapController.unsetFocusToMarkerItem();
} else {
var popupWidget = SizedBox(
height: desiredSize.height,
width: desiredSize.width,
child: poiDetailWidget,
);
final coord = MapHelper.extractLatLngFromFeature(feature);
mapController.showMapPopover(
coord,
popupWidget,
() => _editPoi(() => getPoiEdit(poi)),
desiredSize,
);
}
}

Future<ModalDetailResult?> showDetailBottomSheet(Widget poiDetailWidget) async {
final theme = Theme.of(context);
return await showModalBottomSheet<ModalDetailResult>(
isScrollControlled: false,
isDismissible: true,
barrierColor: Colors.transparent,
context: context,
backgroundColor: theme.colorScheme.surface,
builder: (context) => poiDetailWidget,
);
}

Expand Down
131 changes: 102 additions & 29 deletions lib/features/campaigns/screens/poster_detail.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gruene_app/app/services/converters.dart';
import 'package:gruene_app/app/theme/theme.dart';
import 'package:gruene_app/features/campaigns/helper/campaign_constants.dart';
import 'package:gruene_app/features/campaigns/helper/enums.dart';
import 'package:gruene_app/features/campaigns/models/posters/poster_detail_model.dart';
import 'package:gruene_app/features/campaigns/widgets/address_field_detail.dart';
import 'package:gruene_app/features/campaigns/widgets/close_edit_widget.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class PosterDetail extends StatelessWidget {
final PosterDetailModel poi;
Expand All @@ -13,36 +17,105 @@ class PosterDetail extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Column(
children: [
AddressFieldDetail(
street: poi.address.street,
houseNumber: poi.address.houseNumber,
),
Expanded(
child: FutureBuilder(
future: Future.delayed(
Duration.zero,
() => poi.thumbnailUrl == null ? null : (thumbnailUrl: poi.thumbnailUrl),
getStatusColor() {
switch (poi.status) {
case PosterStatus.ok:
return ThemeColors.secondary;
case PosterStatus.damaged:
case PosterStatus.missing:
case PosterStatus.toBeMoved:
return Colors.red;
case PosterStatus.removed:
return ThemeColors.textDisabled;
}
}

getStatusText() {
return switch (poi.status) {
PosterStatus.ok => t.campaigns.poster.status.ok.description,
PosterStatus.damaged => t.campaigns.poster.status.damaged.description,
PosterStatus.missing => t.campaigns.poster.status.missing.description,
PosterStatus.toBeMoved => t.campaigns.poster.status.to_be_moved.description,
PosterStatus.removed => t.campaigns.poster.status.removed.description,
};
}

var theme = Theme.of(context);
return GestureDetector(
onTap: () => _closeDialog(context, result: ModalDetailResult.edit),
child: SizedBox(
height: 250,
child: Column(
children: [
Container(
padding: EdgeInsets.all(16),
child: CloseEditWidget(
onClose: () => _closeDialog(context),
onEdit: () => _closeDialog(context, result: ModalDetailResult.edit),
),
),
Row(
children: [
Container(
padding: EdgeInsets.only(left: 12, bottom: 12),
height: 150,
width: 120,
child: FutureBuilder(
future: Future.delayed(
Duration.zero,
() => poi.thumbnailUrl == null ? null : (thumbnailUrl: poi.thumbnailUrl),
),
builder: (context, snapshot) {
if (!snapshot.hasData && !snapshot.hasError) {
return Image.asset(CampaignConstants.dummyImageAssetName);
}
if (snapshot.data!.thumbnailUrl!.isNetworkImageUrl()) {
return FadeInImage.assetNetwork(
placeholder: CampaignConstants.dummyImageAssetName,
image: snapshot.data!.thumbnailUrl!,
);
} else {
return Image.file(
File(snapshot.data!.thumbnailUrl!),
);
}
},
),
),
SizedBox(width: 12),
Text(
'${poi.address.street} ${poi.address.houseNumber}\n${poi.address.zipCode} ${poi.address.city}',
style: theme.textTheme.labelLarge!.copyWith(color: ThemeColors.text),
),
],
),
builder: (context, snapshot) {
if (!snapshot.hasData && !snapshot.hasError) {
return Image.asset(CampaignConstants.dummyImageAssetName);
}
if (snapshot.data!.thumbnailUrl!.isNetworkImageUrl()) {
return FadeInImage.assetNetwork(
placeholder: CampaignConstants.dummyImageAssetName,
image: snapshot.data!.thumbnailUrl!,
);
} else {
return Image.file(
File(snapshot.data!.thumbnailUrl!),
);
}
},
),
Expanded(
child: Container(
color: getStatusColor(),
padding: EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
SizedBox(width: 12),
SvgPicture.asset(
'assets/symbols/posters/svg_inverted/poster_${poi.status.name.toLowerCase()}.svg',
height: 18,
),
SizedBox(width: 12),
Text(
getStatusText(),
style: theme.textTheme.labelLarge!.copyWith(color: ThemeColors.background),
),
],
),
),
),
],
),
],
),
);
}

void _closeDialog(BuildContext context, {ModalDetailResult result = ModalDetailResult.close}) {
Navigator.maybePop(context, result);
}
}
Loading

0 comments on commit 432a2ab

Please sign in to comment.