Fix the start and end time being missing
This commit is contained in:
parent
f6fcc4c390
commit
444d67cb28
7 changed files with 102 additions and 44 deletions
|
@ -7,9 +7,9 @@ class TTConsts {
|
||||||
static get UPDATE_URL =>
|
static get UPDATE_URL =>
|
||||||
"https://git.zontreck.com/AriasCreations/TimeTracker/raw/branch/main/latest-releases.json";
|
"https://git.zontreck.com/AriasCreations/TimeTracker/raw/branch/main/latest-releases.json";
|
||||||
static get SESSION_SERVER =>
|
static get SESSION_SERVER =>
|
||||||
"https://api.zontreck.com/timetrack/${UPDATE_CHANNEL}/timetrack.php";
|
"https://api.zontreck.com/timetrack/$UPDATE_CHANNEL/timetrack.php";
|
||||||
|
|
||||||
static const VERSION = "1.0.0-beta.5";
|
static const VERSION = "1.0.0-beta.6";
|
||||||
|
|
||||||
static bool UPDATE_AVAILABLE = false;
|
static bool UPDATE_AVAILABLE = false;
|
||||||
static UpdateChannel UPDATE_CHANNEL = UpdateChannel.beta;
|
static UpdateChannel UPDATE_CHANNEL = UpdateChannel.beta;
|
||||||
|
|
102
lib/data.dart
102
lib/data.dart
|
@ -11,6 +11,7 @@ import 'package:timetrack/consts.dart';
|
||||||
|
|
||||||
class SessionData {
|
class SessionData {
|
||||||
static DateTime StartTime = DateTime(0);
|
static DateTime StartTime = DateTime(0);
|
||||||
|
static DateTime EndTime = DateTime(0);
|
||||||
|
|
||||||
static bool IsOnTheClock = false;
|
static bool IsOnTheClock = false;
|
||||||
|
|
||||||
|
@ -102,8 +103,9 @@ class SessionData {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (d < minDistanceMeters) continue; // too small → jitter
|
if (d < minDistanceMeters) continue; // too small → jitter
|
||||||
if (maxDistanceMeters != null && d > maxDistanceMeters)
|
if (maxDistanceMeters != null && d > maxDistanceMeters) {
|
||||||
continue; // glitch
|
continue; // glitch
|
||||||
|
}
|
||||||
|
|
||||||
meters += d;
|
meters += d;
|
||||||
}
|
}
|
||||||
|
@ -159,6 +161,8 @@ class SessionData {
|
||||||
currentTrip = null;
|
currentTrip = null;
|
||||||
_listener.cancel();
|
_listener.cancel();
|
||||||
|
|
||||||
|
EndTime = DateTime.now();
|
||||||
|
|
||||||
var saveData = SaveData();
|
var saveData = SaveData();
|
||||||
print(saveData);
|
print(saveData);
|
||||||
|
|
||||||
|
@ -183,18 +187,20 @@ class SessionData {
|
||||||
static Map<String, dynamic> SaveData() {
|
static Map<String, dynamic> SaveData() {
|
||||||
Map<String, dynamic> saveData = {};
|
Map<String, dynamic> saveData = {};
|
||||||
|
|
||||||
List<Map<String, dynamic>> _trips = [];
|
List<Map<String, dynamic>> trips = [];
|
||||||
for (var trip in Trips) {
|
for (var trip in Trips) {
|
||||||
_trips.add(trip.toJsonMap());
|
trips.add(trip.toJsonMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, dynamic>> _pos = [];
|
List<Map<String, dynamic>> posx = [];
|
||||||
for (var pos in positions) {
|
for (var pos in positions) {
|
||||||
_pos.add(pos.toMap());
|
posx.add(pos.toMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
saveData["trips"] = _trips;
|
saveData["trips"] = trips;
|
||||||
saveData["positions"] = _pos;
|
saveData["positions"] = posx;
|
||||||
|
saveData["start"] = StartTime.toIso8601String();
|
||||||
|
saveData["end"] = EndTime.toIso8601String();
|
||||||
|
|
||||||
return saveData;
|
return saveData;
|
||||||
}
|
}
|
||||||
|
@ -209,28 +215,32 @@ class SessionData {
|
||||||
data: json.encode(payload),
|
data: json.encode(payload),
|
||||||
);
|
);
|
||||||
|
|
||||||
LoadData(reply.data as String);
|
LoadData(reply.data as Map<String, dynamic>);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadData(String js) {
|
static void LoadData(Map<String, dynamic> jsMap) {
|
||||||
Map<String, dynamic> _js = json.decode(js);
|
if (jsMap.containsKey("error")) {
|
||||||
if (_js.containsKey("error")) {
|
|
||||||
LastSessionID = "";
|
LastSessionID = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<Map<String, dynamic>> _trips =
|
List<dynamic> trips = jsMap['trips'] as List<dynamic>;
|
||||||
_js['trips'] as List<Map<String, dynamic>>;
|
List<dynamic> pos = jsMap['positions'] as List<dynamic>;
|
||||||
List<Map<String, dynamic>> _pos =
|
|
||||||
_js['positions'] as List<Map<String, dynamic>>;
|
|
||||||
|
|
||||||
for (var trip in _trips) {
|
for (var trip in trips) {
|
||||||
Trips.add(Trip.fromJsonMap(trip));
|
Trips.add(Trip.fromJsonMap(trip as Map<String, dynamic>));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var position in _pos) {
|
for (var position in pos) {
|
||||||
positions.add(SmallPosition.fromMap(position));
|
positions.add(SmallPosition.fromMap(position as Map<String, dynamic>));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (jsMap.containsKey("start")) {
|
||||||
|
StartTime = DateTime.parse(jsMap['start'] as String);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsMap.containsKey("end"))
|
||||||
|
EndTime = DateTime.parse(jsMap["end"] as String);
|
||||||
|
|
||||||
IsReadOnly = true;
|
IsReadOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +261,6 @@ class SessionData {
|
||||||
static Delivery GetNewDelivery() {
|
static Delivery GetNewDelivery() {
|
||||||
if (currentTrip != null) {
|
if (currentTrip != null) {
|
||||||
var dropOff = currentTrip!.startNewDelivery();
|
var dropOff = currentTrip!.startNewDelivery();
|
||||||
;
|
|
||||||
currentDelivery = dropOff;
|
currentDelivery = dropOff;
|
||||||
return dropOff;
|
return dropOff;
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,10 +272,31 @@ class SessionData {
|
||||||
currentDelivery = null;
|
currentDelivery = null;
|
||||||
currentTrip = null;
|
currentTrip = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [a] should be the Start Time,
|
||||||
|
///
|
||||||
|
/// [b] is the end time
|
||||||
|
static String GetTotalTimeWorked(DateTime a, DateTime b) {
|
||||||
|
Duration diff = b.difference(a);
|
||||||
|
|
||||||
|
int days = diff.inDays;
|
||||||
|
int hours = diff.inHours.remainder(24);
|
||||||
|
int minutes = diff.inMinutes.remainder(60);
|
||||||
|
int seconds = diff.inSeconds.remainder(60);
|
||||||
|
|
||||||
|
List<String> parts = [];
|
||||||
|
|
||||||
|
if (days > 0) parts.add('${days}d');
|
||||||
|
if (hours > 0) parts.add('${hours}h');
|
||||||
|
if (minutes > 0) parts.add('${minutes}m');
|
||||||
|
if (seconds > 0) parts.add('${seconds}s');
|
||||||
|
|
||||||
|
return parts.join(' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Delivery {
|
class Delivery {
|
||||||
Position? endLocation;
|
SmallPosition? endLocation;
|
||||||
DateTime StartTime = DateTime.now();
|
DateTime StartTime = DateTime.now();
|
||||||
|
|
||||||
Delivery() {
|
Delivery() {
|
||||||
|
@ -275,23 +305,26 @@ class Delivery {
|
||||||
|
|
||||||
Future<void> MarkEndLocation() async {
|
Future<void> MarkEndLocation() async {
|
||||||
var pos = await SessionData.GetNewLocation();
|
var pos = await SessionData.GetNewLocation();
|
||||||
endLocation = pos;
|
endLocation = SmallPosition.fromPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJsonMap() {
|
Map<String, dynamic> toJsonMap() {
|
||||||
return {
|
return {
|
||||||
"start": StartTime.toString(),
|
"start": StartTime.toString(),
|
||||||
"endPos": endLocation?.toJson() ?? "incomplete",
|
"endPos": endLocation?.toMap() ?? "incomplete",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Delivery fromMap(Map<String, dynamic> jsx) {
|
static Delivery fromMap(Map<String, dynamic> jsx) {
|
||||||
Delivery delivery = Delivery();
|
Delivery delivery = Delivery();
|
||||||
delivery.StartTime = DateTime.parse(jsx['start'] as String);
|
delivery.StartTime = DateTime.parse(jsx['start'] as String);
|
||||||
if (jsx['endPos'] as String == "incomplete")
|
if (jsx['endPos'] is String) {
|
||||||
delivery.endLocation = null;
|
delivery.endLocation = null;
|
||||||
else
|
} else {
|
||||||
delivery.endLocation = Position.fromMap(jsx['endPos']);
|
delivery.endLocation = SmallPosition.fromMap(
|
||||||
|
jsx['endPos'] as Map<String, dynamic>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return delivery;
|
return delivery;
|
||||||
}
|
}
|
||||||
|
@ -314,26 +347,25 @@ class Trip {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJsonMap() {
|
Map<String, dynamic> toJsonMap() {
|
||||||
Map<String, Object> _trip = {"start": StartTime.toString()};
|
Map<String, Object> trip = {"start": StartTime.toString()};
|
||||||
List<Map<String, dynamic>> _dropOffs = [];
|
List<Map<String, dynamic>> dropOffs = [];
|
||||||
for (var delivery in deliveries) {
|
for (var delivery in deliveries) {
|
||||||
_dropOffs.add(delivery.toJsonMap());
|
dropOffs.add(delivery.toJsonMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
_trip["deliveries"] = _dropOffs;
|
trip["deliveries"] = dropOffs;
|
||||||
|
|
||||||
return _trip;
|
return trip;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Trip fromJsonMap(Map<String, dynamic> jsx) {
|
static Trip fromJsonMap(Map<String, dynamic> jsx) {
|
||||||
Trip trip = Trip();
|
Trip trip = Trip();
|
||||||
trip.StartTime = DateTime.parse(jsx['start'] as String);
|
trip.StartTime = DateTime.parse(jsx['start'] as String);
|
||||||
trip.deliveries = [];
|
trip.deliveries = [];
|
||||||
List<Map<String, dynamic>> _dropOffs =
|
List<dynamic> dropOffs = jsx['deliveries'] as List<dynamic>;
|
||||||
jsx['deliveries'] as List<Map<String, dynamic>>;
|
|
||||||
|
|
||||||
for (var dropOff in _dropOffs) {
|
for (var dropOff in dropOffs) {
|
||||||
trip.deliveries.add(Delivery.fromMap(dropOff));
|
trip.deliveries.add(Delivery.fromMap(dropOff as Map<String, dynamic>));
|
||||||
}
|
}
|
||||||
|
|
||||||
return trip;
|
return trip;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
import 'package:libacflutter/Constants.dart';
|
import 'package:libacflutter/Constants.dart';
|
||||||
|
@ -7,7 +6,7 @@ import 'package:timetrack/data.dart';
|
||||||
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
|
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
|
||||||
|
|
||||||
class MapPage extends StatefulWidget {
|
class MapPage extends StatefulWidget {
|
||||||
MapPage({super.key});
|
const MapPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:libacflutter/Constants.dart';
|
import 'package:libacflutter/Constants.dart';
|
||||||
import 'package:ota_update/ota_update.dart';
|
import 'package:ota_update/ota_update.dart';
|
||||||
import 'package:timetrack/consts.dart';
|
import 'package:timetrack/consts.dart';
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:libacflutter/Constants.dart';
|
import 'package:libacflutter/Constants.dart';
|
||||||
import 'package:timetrack/consts.dart';
|
import 'package:timetrack/consts.dart';
|
||||||
import 'package:timetrack/data.dart';
|
import 'package:timetrack/data.dart';
|
||||||
|
|
||||||
class WebMain extends StatefulWidget {
|
class WebMain extends StatefulWidget {
|
||||||
|
const WebMain({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
return _WebMain();
|
return _WebMain();
|
||||||
|
@ -117,6 +118,7 @@ class _WebMain extends State<WebMain> {
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
SessionData.LastSessionID = sessionIDController.text;
|
||||||
await SessionData.DownloadData();
|
await SessionData.DownloadData();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:libacflutter/Constants.dart';
|
import 'package:libacflutter/Constants.dart';
|
||||||
import 'package:timetrack/data.dart';
|
import 'package:timetrack/data.dart';
|
||||||
|
|
||||||
class WorkDataPage extends StatefulWidget {
|
class WorkDataPage extends StatefulWidget {
|
||||||
WorkDataPage({super.key});
|
const WorkDataPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
|
@ -50,12 +49,39 @@ class _WorkData extends State<WorkDataPage> {
|
||||||
"Start Date & Time: ${SessionData.StartTime.toString()}",
|
"Start Date & Time: ${SessionData.StartTime.toString()}",
|
||||||
style: TextStyle(fontSize: 18),
|
style: TextStyle(fontSize: 18),
|
||||||
),
|
),
|
||||||
|
if (SessionData.IsReadOnly)
|
||||||
|
Text(
|
||||||
|
"End Date & Time: ${SessionData.EndTime.toString()}",
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"Total time worked: ${SessionData.GetTotalTimeWorked(SessionData.StartTime, SessionData.EndTime)}",
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
if (SessionData.StartTime.year == 0)
|
||||||
|
ListTile(
|
||||||
|
title: Text("ERROR"),
|
||||||
|
subtitle: Text(
|
||||||
|
"This TTX session file appears to have been saved in an early alpha version. It does not contain the Start time or End timestamp information.",
|
||||||
|
),
|
||||||
|
tileColor: LibACFlutterConstants.TITLEBAR_COLOR,
|
||||||
|
),
|
||||||
|
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Total Estimated Miles: ${SessionData.GetTotalMilesAsString()}\n(Note: The miles displayed above may not be 100% accurate)",
|
"Total Estimated Miles: ${SessionData.GetTotalMilesAsString()}\n(Note: The miles displayed above may not be 100% accurate)",
|
||||||
style: TextStyle(fontSize: 24),
|
style: TextStyle(fontSize: 24),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 40),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
// Process data export to GPX format.
|
||||||
|
},
|
||||||
|
child: Text("Export as GPX"),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.0-beta.5
|
version: 1.0.0-beta.6
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue