diff --git a/README.md b/README.md index 42b994c..86e9546 100644 --- a/README.md +++ b/README.md @@ -24,16 +24,17 @@ The app does not store data locally, due to the way android permissions function # Implementation -- [ ] Basic UI +- [x] Basic UI - [x] Permissions - [x] Automatic updates -- [ ] GPS Tracking -- [ ] Formatting GPS on a viewable map -- [ ] Track driving hours - - [ ] Track trips - - [ ] Track stops/deliveries -- [ ] Track trip base pay - - [ ] Track each delivery's tips +- [x] GPS Tracking +- [x] Formatting GPS on a viewable map +- [x] Track driving hours + - [x] Track trips + - [x] Track stops/deliveries +- [x] Track trip base pay + - [x] Track each delivery's tips +- [ ] Map marker for each stop/delivery with text saying "Trip #X/DropOff #X\nBase Pay: $$$; Tip: $$$" - [ ] Basic version of the app in readonly mode when deployed on a web server. - [ ] Backend server - [ ] PHP? diff --git a/latest-releases.json b/latest-releases.json index 3f7c553..489da18 100644 --- a/latest-releases.json +++ b/latest-releases.json @@ -1,3 +1,3 @@ { - "alpha": "1.0.0-dev.7" + "alpha": "1.0.0-dev.8" } diff --git a/lib/consts.dart b/lib/consts.dart index 5c90c74..f65b15a 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -6,11 +6,12 @@ import 'package:geolocator/geolocator.dart'; class TTConsts { static get UPDATE_URL => "https://git.zontreck.com/AriasCreations/TimeTracker/raw/branch/main/latest-releases.json"; - static const VERSION = "1.0.0-dev.7"; + static const VERSION = "1.0.0-dev.8"; static bool UPDATE_AVAILABLE = false; static UpdateChannel UPDATE_CHANNEL = UpdateChannel.alpha; static final LocationSettings LOCATION_SETTINGS = LocationSettings( accuracy: LocationAccuracy.bestForNavigation, + distanceFilter: 50, ); static Future checkUpdate() async { diff --git a/lib/pages/HomePage.dart b/lib/pages/HomePage.dart index 9188bc3..217fa73 100644 --- a/lib/pages/HomePage.dart +++ b/lib/pages/HomePage.dart @@ -53,6 +53,16 @@ class _HomePageState extends State { }, leading: Icon(Icons.update), ), + ListTile( + title: Text("Trip Map"), + leading: Icon(Icons.map), + subtitle: Text( + "View a map of the route\n(NOTE: This is not live, and reflects the current state as of the time the map is opened.)", + ), + onTap: () async { + await Navigator.pushNamed(context, "/map"); + }, + ), ListTile( title: Text("RESET APP SESSION"), onTap: () async { @@ -72,6 +82,10 @@ class _HomePageState extends State { body: SingleChildScrollView( child: Column( children: [ + Text( + "Hit engage when you are ready to go online and start tracking location data, and trips.", + style: TextStyle(fontSize: 18), + ), if (!SessionData.IsOnTheClock) Center( child: ElevatedButton( @@ -129,27 +143,6 @@ class _HomePageState extends State { }, child: Text("END TRIP"), ), - ElevatedButton( - onPressed: () async { - if (SessionData.currentTrip != null || - SessionData.currentDelivery != null) { - showDialog( - context: context, - builder: (build) { - return AlertDialog( - title: Text("Cannot end work day"), - content: Text( - "You must end the trip and any delivery before you can fully end the work day.", - ), - ); - }, - ); - } else { - SessionData.Logout(); - } - }, - child: Text("End work day"), - ), ], ); } @@ -185,6 +178,57 @@ class _HomePageState extends State { ); } + Widget GetNonTripWidgets() { + return Column( + children: [ + ElevatedButton( + onPressed: () async { + var reply = await showDialog( + context: context, + builder: (builder) { + return InputPrompt( + title: "What is the base pay?", + prompt: "Enter the base pay amount below.", + type: InputPromptType.Number, + ); + }, + ); + if (reply == null || reply == "") reply = "0"; + + double basePay = double.parse(reply as String); + SessionData.GetNewTrip(basePay: basePay); + SessionData.GetNewDelivery(); + + setState(() {}); + }, + child: Text("Start New Trip"), + ), + ElevatedButton( + onPressed: () async { + if (SessionData.currentTrip != null || + SessionData.currentDelivery != null) { + showDialog( + context: context, + builder: (build) { + return AlertDialog( + title: Text("Cannot end work day"), + content: Text( + "You must end the trip and any delivery before you can fully end the work day.", + ), + ); + }, + ); + } else { + SessionData.Logout(); + setState(() {}); + } + }, + child: Text("End work day"), + ), + ], + ); + } + Widget GetLoggedInWidgets() { return Column( children: [ @@ -194,29 +238,7 @@ class _HomePageState extends State { ), if (SessionData.currentTrip != null) GetTripWidgets(), if (SessionData.currentDelivery != null) GetDeliveryWidgets(), - if (SessionData.currentTrip == null) - ElevatedButton( - onPressed: () async { - var reply = await showDialog( - context: context, - builder: (builder) { - return InputPrompt( - title: "What is the base pay?", - prompt: "Enter the base pay amount below.", - type: InputPromptType.Number, - ); - }, - ); - if (reply == null || reply == "") reply = "0"; - - double basePay = double.parse(reply as String); - SessionData.GetNewTrip(basePay: basePay); - SessionData.GetNewDelivery(); - - setState(() {}); - }, - child: Text("Start New Trip"), - ), + if (SessionData.currentTrip == null) GetNonTripWidgets(), ], ); } diff --git a/lib/pages/MainApp.dart b/lib/pages/MainApp.dart index 6aa2ec4..1da68e6 100644 --- a/lib/pages/MainApp.dart +++ b/lib/pages/MainApp.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:timetrack/pages/HomePage.dart'; +import 'package:timetrack/pages/MapPage.dart'; import 'package:timetrack/pages/UpdateSettings.dart'; class MainApp extends StatefulWidget { @@ -21,7 +22,11 @@ class MainAppState extends State { Widget build(BuildContext context) { return MaterialApp( title: "Time Tracker", - routes: {"/": (ctx) => HomePage(), "/upd": (ctx) => UpdateSettingsPage()}, + routes: { + "/": (ctx) => HomePage(), + "/upd": (ctx) => UpdateSettingsPage(), + "/map": (ctx) => MapPage(), + }, theme: ThemeData.dark(), ); } diff --git a/lib/pages/MapPage.dart b/lib/pages/MapPage.dart new file mode 100644 index 0000000..0d9b075 --- /dev/null +++ b/lib/pages/MapPage.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:libacflutter/Constants.dart'; +import 'package:timetrack/data.dart'; + +class MapPage extends StatefulWidget { + MapPage({super.key}); + + @override + State createState() { + return _MapPage(); + } +} + +class _MapPage extends State { + MapController controller = MapController(); + LatLng initialPosition = LatLng(0, 0); + List PointMap = []; + + @override + void didChangeDependencies() { + PointMap = []; + + var firstPos = SessionData.positions[0]; + initialPosition = LatLng(firstPos.latitude, firstPos.longitude); + + for (var position in SessionData.positions) { + PointMap.add(LatLng(position.latitude, position.longitude)); + } + + setState(() {}); + super.didChangeDependencies(); + } + + @override + void dispose() { + print("Map page disposed"); + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Time Tracker - Map View"), + backgroundColor: LibACFlutterConstants.TITLEBAR_COLOR, + actions: [ + IconButton( + onPressed: () async { + didChangeDependencies(); + }, + icon: Icon(Icons.refresh), + ), + ], + ), + body: GestureDetector( + onTap: FocusScope.of(context).unfocus, + child: SafeArea( + child: FlutterMap( + mapController: controller, + options: MapOptions( + minZoom: 1, + maxZoom: 30, + initialZoom: 15, + initialCenter: initialPosition, + keepAlive: false, + ), + children: [ + TileLayer( + urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + userAgentPackageName: "dev.zontreck.timetrack", + ), + PolylineLayer( + polylines: [ + Polyline( + points: PointMap, + color: Colors.blue, + borderStrokeWidth: 3, + borderColor: Colors.blue, + ), + ], + ), + RichAttributionWidget( + attributions: [ + TextSourceAttribution('OpenStreetMap contributors'), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index c33c09a..267eb92 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0-dev.7 +version: 1.0.0-dev.8 environment: sdk: ^3.7.2 @@ -43,7 +43,8 @@ dependencies: dio: ^5.8.0+1 ota_update: ^7.0.1 geolocator: ^14.0.0 - free_map: ^2.0.3 + flutter_map: ^8.1.1 + latlong2: ^0.9.1 dev_dependencies: flutter_test: