diff options
| author | Aldrik Ramaekers <aldrik@amftech.nl> | 2023-02-08 20:08:23 +0100 |
|---|---|---|
| committer | Aldrik Ramaekers <aldrik@amftech.nl> | 2023-02-08 20:08:23 +0100 |
| commit | fcbf592d10199dbac80198dd8c2efb181f95165e (patch) | |
| tree | 4fd50f1bf1c65c7180f1f3b7d64fc1603bf9be73 | |
| parent | e37d74527e03b6a804a35cbfb0956d4e0100889f (diff) | |
blacklist
| -rw-r--r-- | lib/RoutingExample.dart | 49 | ||||
| -rw-r--r-- | lib/config/defaults.dart | 2 | ||||
| -rw-r--r-- | lib/main.dart | 4 | ||||
| -rw-r--r-- | lib/pages/all_routes_page.dart | 27 | ||||
| -rw-r--r-- | lib/pages/blacklist_page.dart | 233 | ||||
| -rw-r--r-- | lib/pages/home_page.dart | 10 | ||||
| -rw-r--r-- | lib/services/iblacklist_provider_service.dart | 31 | ||||
| -rw-r--r-- | lib/services/local_blacklist_provider_service.dart | 57 | ||||
| -rw-r--r-- | lib/services/storegear_api_service.dart | 2 |
9 files changed, 401 insertions, 14 deletions
diff --git a/lib/RoutingExample.dart b/lib/RoutingExample.dart index 910fe3e..ebe08b3 100644 --- a/lib/RoutingExample.dart +++ b/lib/RoutingExample.dart @@ -20,6 +20,7 @@ import 'package:training_planner/events/MapPanningEvent.dart'; import 'package:training_planner/events/NextStopLoadedEvent.dart'; import 'package:training_planner/events/StopCompletedEvent.dart'; import 'package:training_planner/pages/navigation_page.dart'; +import 'package:training_planner/services/iblacklist_provider_service.dart'; import 'route.dart' as DHLRoute; import 'main.dart'; @@ -30,11 +31,19 @@ typedef ShowDialogFunction = void Function(String title, String message); class DestinationPin { final String text; final GeoCoordinates? coords; + final String? postalcodeNumeric; + final String? postalcodeAlpha; + final String? houseNumberWithExtra; WidgetPin? pin; bool isDoublePlannedAddress; DestinationPin( - {this.text = '', this.coords, required this.isDoublePlannedAddress}); + {this.text = '', + this.coords, + required this.isDoublePlannedAddress, + required this.postalcodeNumeric, + required this.postalcodeAlpha, + required this.houseNumberWithExtra}); } class ActiveTask { @@ -76,6 +85,8 @@ class RoutingExample { late SearchOptions _searchOptions; late MapMarker mapMarker; + List<BlacklistEntry> blacklist = []; + Future<Uint8List> _loadFileAsUint8List(String assetPathToFile) async { // The path refers to the assets directory as specified in pubspec.yaml. ByteData fileData = await rootBundle.load(assetPathToFile); @@ -131,6 +142,8 @@ class RoutingExample { updateHighlightedRouteSections(); eventBus.fire(NextStopLoadedEvent()); }); + + blacklistProvider.getBlacklist().then((value) => {blacklist = value}); } void destroy() { @@ -189,6 +202,7 @@ class RoutingExample { padding: EdgeInsets.all(2), decoration: BoxDecoration( color: backgroundColor, + borderRadius: BorderRadius.circular(10), shape: BoxShape.rectangle, border: Border.all( color: isDoublePlannedAddress @@ -273,7 +287,11 @@ class RoutingExample { ? item.houseNumberAddition! : ''), coords: destinationGeoCoordinates, - isDoublePlannedAddress: false), + isDoublePlannedAddress: false, + postalcodeNumeric: item.postalCodeNumeric, + postalcodeAlpha: item.postalCodeAlpha, + houseNumberWithExtra: + item.houseNumber! + (item.houseNumberAddition ?? '')), ); _destinationCoords.add(destinationGeoCoordinates); @@ -354,6 +372,24 @@ class RoutingExample { } } + bool destinationPinIsInBlacklist(DestinationPin pin) { + try { + for (int i = 0; i < blacklist.length; i++) { + if (pin.postalcodeNumeric == blacklist[i].postalcodeNumeric && + pin.postalcodeAlpha!.toLowerCase() == + blacklist[i].postalcodeAplha && + pin.houseNumberWithExtra!.toLowerCase() == + (blacklist[i].houseNumber.toString() + + blacklist[i].houseNumberExtra.toLowerCase())) { + return true; + } + } + return false; + } catch (e) { + return false; + } + } + void updateHighlightedRouteSections() { // Show the next 20 parcel pins, to let the delivery driver decide on possible detours. int maxPins = 300; @@ -391,6 +427,15 @@ class RoutingExample { widgetPin?.anchor = Anchor2D.withHorizontalAndVertical(0.5, 0.5); pin.pin = widgetPin; } + + if (destinationPinIsInBlacklist(_parcelNumberPins[i])) { + var widgetPin = hereMapController.pinWidget( + _createWidget(pin.text, ui.Color.fromARGB(255, 255, 0, 234), + isDoublePlannedAddress: pin.isDoublePlannedAddress), + _destinationCoords[i]); + widgetPin?.anchor = Anchor2D.withHorizontalAndVertical(0.5, 0.5); + pin.pin = widgetPin; + } } // Show the next 5 sections as to not clutter the screen. diff --git a/lib/config/defaults.dart b/lib/config/defaults.dart index 2de00ad..f629861 100644 --- a/lib/config/defaults.dart +++ b/lib/config/defaults.dart @@ -1,4 +1,4 @@ -String program_version = '0.11 [06/02/2023]'; +String program_version = '0.12 [08/02/2023]'; bool debug_mode = false; class ShiftType { diff --git a/lib/main.dart b/lib/main.dart index a860b91..ca99946 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,9 +7,11 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:training_planner/services/iblacklist_provider_service.dart'; import 'package:training_planner/services/iroute_provider_service.dart'; import 'package:training_planner/services/ishift_provider_service.dart'; import 'package:training_planner/services/istoregear_api_service.dart'; +import 'package:training_planner/services/local_blacklist_provider_service.dart'; import 'package:training_planner/services/local_salary_provider_service.dart'; import 'package:training_planner/services/log_service.dart'; import 'package:training_planner/services/messaging_service.dart'; @@ -64,6 +66,8 @@ final MessagingService messageService = MessagingService(); final SettingsService settingsService = SettingsService(); final IStoregearApiService apiService = StoregearApiService(); final LocalSalaryProviderService incomeProvider = LocalSalaryProviderService(); +final IBlacklistProviderService blacklistProvider = + LocalBlacklistProviderService(); final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); diff --git a/lib/pages/all_routes_page.dart b/lib/pages/all_routes_page.dart index d3c1637..58a580e 100644 --- a/lib/pages/all_routes_page.dart +++ b/lib/pages/all_routes_page.dart @@ -27,7 +27,6 @@ class _AllRoutesPageState extends State<AllRoutesPage> { try { apiService.getRoutes().then((value) { - debugPrint('xddd 2'); setState(() => {routeInfo = value}); }); } catch (e) { @@ -62,7 +61,7 @@ class _AllRoutesPageState extends State<AllRoutesPage> { padding: const EdgeInsets.only(bottom: 8, left: 10, right: 10), child: Container( decoration: BoxDecoration( - color: Color.fromARGB(40, 0, 0, 0), + color: Color.fromARGB(80, 0, 0, 0), border: Border.all(color: Color.fromARGB(160, 0, 0, 0)), borderRadius: BorderRadius.all(Radius.circular(4))), child: Padding( @@ -71,13 +70,23 @@ class _AllRoutesPageState extends State<AllRoutesPage> { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - 'Route ' + route.tripNumber.toString(), - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 24), + Column( + children: [ + Text( + 'Route ' + route.tripNumber.toString(), + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 24), + ), + Text( + route.tripPdaStatusDescription ?? '', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w300, + fontSize: 16), + ), + ], ), Expanded( child: Padding( diff --git a/lib/pages/blacklist_page.dart b/lib/pages/blacklist_page.dart new file mode 100644 index 0000000..2a76d67 --- /dev/null +++ b/lib/pages/blacklist_page.dart @@ -0,0 +1,233 @@ +import 'package:flutter/material.dart'; +import 'package:loading_animation_widget/loading_animation_widget.dart'; +import 'package:training_planner/main.dart'; +import 'package:training_planner/services/iblacklist_provider_service.dart'; +import 'package:training_planner/services/settings_service.dart'; +import 'package:training_planner/style/style.dart'; + +class BlacklistPage extends StatefulWidget { + @override + _BlacklistPageState createState() => _BlacklistPageState(); + + const BlacklistPage({Key? key}) : super(key: key); +} + +class _BlacklistPageState extends State<BlacklistPage> { + List<BlacklistEntry>? blacklist; + + final postalCodeNumericController = TextEditingController(); + final postalCodeAlphaController = TextEditingController(); + final houseNumberController = TextEditingController(); + final houseNumberExtraController = TextEditingController(); + + @override + initState() { + super.initState(); + + blacklistProvider.getBlacklist().then((value) async { + if (mounted) { + setState( + () { + blacklist = value; + }, + ); + } + }); + } + + Widget getLoadingScreen() { + return LoadingAnimationWidget.flickr( + leftDotColor: Style.titleColor, + rightDotColor: Style.background, + size: MediaQuery.of(context).size.width / 4, + ); + } + + List<Widget> createBlacklistWidgets() { + List<Widget> result = []; + + for (var entry in blacklist!) { + result.add( + Padding( + padding: const EdgeInsets.only(bottom: 8, left: 10, right: 10), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Style.logbookEntryBorder), + color: Style.logbookEntryBackground, + borderRadius: BorderRadius.all(Radius.circular(4))), + child: Padding( + padding: const EdgeInsets.all(8), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + entry.postalcodeNumeric + + ' ' + + entry.postalcodeAplha + + ' ' + + entry.houseNumber.toString() + + entry.houseNumberExtra, + style: TextStyle( + color: Colors.black, fontWeight: FontWeight.bold), + ), + ], + ), + ], + ), + ), + ), + ), + ); + } + + return result; + } + + Widget getDataList() { + var monthDataWidgets = createBlacklistWidgets(); + if (monthDataWidgets.isEmpty) { + return Center( + child: Text('Geen data beschikbaar'), + ); + } + + return SafeArea( + child: CustomScrollView( + physics: null, + slivers: [ + SliverPadding(padding: EdgeInsets.only(top: 20)), + SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return monthDataWidgets[index]; + }, + childCount: monthDataWidgets.length, + )), + SliverPadding(padding: EdgeInsets.only(top: 20)), + ], + ), + ); + } + + Widget getLoadingScreenOrDataList() { + if (blacklist != null) { + return getDataList(); + } else { + return getLoadingScreen(); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Blacklist'), + backgroundColor: Style.background, + foregroundColor: Style.titleColor, + ), + body: ShaderMask( + shaderCallback: (Rect rect) { + return LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Style.background, + Colors.transparent, + Colors.transparent, + Style.background + ], + stops: [ + 0.0, + 0.05, + 0.95, + 1.0 + ], // 10% purple, 80% transparent, 10% purple + ).createShader(rect); + }, + blendMode: BlendMode.dstOut, + child: getLoadingScreenOrDataList(), + ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + await showAddAddressDialog(); + //eventBus.fire(RefreshWeekEvent()); + }, + backgroundColor: Style.titleColor, + child: const Icon(Icons.add), + ), + ); + } + + Future<void> addAddressFromDialog() async { + await blacklistProvider.addToBlacklist(BlacklistEntry( + postalCodeNumericController.text, + postalCodeAlphaController.text, + int.tryParse(houseNumberController.text) ?? 0, + houseNumberExtraController.text)); + } + + Future<void> showAddAddressDialog() async { + // set up the buttons + Widget cancelButton = TextButton( + child: Text("Terug"), + onPressed: () { + Navigator.pop(context); + }, + ); + Widget continueButton = TextButton( + child: Text("Ok"), + onPressed: () async { + await addAddressFromDialog(); + Navigator.pop(context); + }, + ); + + // show the dialog + await showDialog( + context: context, + builder: (BuildContext context) { + return StatefulBuilder(builder: (context, setState) { + return AlertDialog( + title: Text("Vul adres in"), + content: Column(children: [ + TextField( + controller: postalCodeNumericController, + decoration: const InputDecoration( + labelText: 'Postcode', + ), + keyboardType: TextInputType.number, + ), + TextField( + controller: postalCodeAlphaController, + decoration: const InputDecoration( + labelText: 'Postcode Toevoeging', + ), + keyboardType: TextInputType.text, + ), + TextField( + controller: houseNumberController, + decoration: const InputDecoration( + labelText: 'Huisnummer', + ), + keyboardType: TextInputType.number, + ), + TextField( + controller: houseNumberExtraController, + decoration: const InputDecoration( + labelText: 'Huisnummer Toegoeging', + ), + keyboardType: TextInputType.text, + ), + ]), + actions: [ + cancelButton, + continueButton, + ], + ); + }); + }, + ); + } +} diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index b669edb..e53df61 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:training_planner/pages/agenda_page.dart'; +import 'package:training_planner/pages/blacklist_page.dart'; import 'package:training_planner/pages/delivery_login_page.dart'; import 'package:training_planner/pages/developer_page.dart'; import 'package:training_planner/pages/logbook_page.dart'; @@ -87,6 +88,15 @@ class _HomePageState extends State<HomePage> { ); }, ), + ListTile( + title: const Text('Blacklist'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => BlacklistPage()), + ); + }, + ), ], ), ); diff --git a/lib/services/iblacklist_provider_service.dart b/lib/services/iblacklist_provider_service.dart new file mode 100644 index 0000000..c66a909 --- /dev/null +++ b/lib/services/iblacklist_provider_service.dart @@ -0,0 +1,31 @@ +import 'dart:async'; + +class BlacklistEntry { + String postalcodeNumeric; + String postalcodeAplha; + int houseNumber; + String houseNumberExtra; + + BlacklistEntry(this.postalcodeNumeric, this.postalcodeAplha, this.houseNumber, + this.houseNumberExtra); + + BlacklistEntry.fromJson(Map<String, dynamic> json) + : postalcodeNumeric = json['postalcodeNumeric'], + postalcodeAplha = json['postalcodeAplha'], + houseNumber = json['houseNumber'], + houseNumberExtra = json['houseNumberExtra']; + + Map<String, dynamic> toJson() { + return { + 'postalcodeNumeric': postalcodeNumeric, + 'postalcodeAplha': postalcodeAplha, + 'houseNumber': houseNumber, + 'houseNumberExtra': houseNumberExtra, + }; + } +} + +abstract class IBlacklistProviderService { + Future<List<BlacklistEntry>> getBlacklist(); + Future<void> addToBlacklist(BlacklistEntry data); +} diff --git a/lib/services/local_blacklist_provider_service.dart b/lib/services/local_blacklist_provider_service.dart new file mode 100644 index 0000000..cb3840e --- /dev/null +++ b/lib/services/local_blacklist_provider_service.dart @@ -0,0 +1,57 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; +import 'package:training_planner/pages/logbook_page.dart'; +import 'package:training_planner/services/iblacklist_provider_service.dart'; +import 'package:training_planner/services/log_service.dart'; + +class LocalBlacklistProviderService extends IBlacklistProviderService { + Future<Directory> get _localDir async { + final directory = await getApplicationDocumentsDirectory(); + return directory; + } + + Future<String> get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + return directory.path; + } + + Future<File> _localFile() async { + final path = await _localPath; + String fullPath = '$path/blacklist.json'; + File file = File(fullPath); + + bool exists = await file.exists(); + if (!exists) { + LogService.log('creating ' + fullPath); + await file.create(); + await file.writeAsString(jsonEncode([])); + } + + return File(fullPath); + } + + @override + Future<List<BlacklistEntry>> getBlacklist() async { + var file = await _localFile(); + var data = await file.readAsString(); + final Iterable iterable = await jsonDecode(data); + List<BlacklistEntry> parsedData = List<BlacklistEntry>.from( + iterable.map((model) => BlacklistEntry.fromJson(model))); + LogService.log('read ' + data); + return parsedData; + } + + @override + Future<void> addToBlacklist(BlacklistEntry data) async { + var file = await _localFile(); + + List<BlacklistEntry> dataToStore = await getBlacklist(); + dataToStore.add(BlacklistEntry(data.postalcodeNumeric, data.postalcodeAplha, + data.houseNumber, data.houseNumberExtra)); + + LogService.log('writing ' + jsonEncode(dataToStore)); + file.writeAsString(jsonEncode(dataToStore)); + } +} diff --git a/lib/services/storegear_api_service.dart b/lib/services/storegear_api_service.dart index f4d96b1..7b3657f 100644 --- a/lib/services/storegear_api_service.dart +++ b/lib/services/storegear_api_service.dart @@ -56,8 +56,6 @@ class StoregearApiService extends IStoregearApiService { // If the server did return a 200 OK response, // then parse the JSON. - - var content = jsonDecode(response.body); if (content["message"] != null) { return RouteList(routes: []); |
