import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:libacflutter/Constants.dart'; import 'package:libacflutter/Prompt.dart'; import 'package:timetrack/consts.dart'; import 'package:timetrack/data.dart'; import 'package:url_launcher/url_launcher.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() { return _HomePageState(); } } class _HomePageState extends State { @override void didChangeDependencies() { setState(() {}); super.didChangeDependencies(); } @override void initState() { SessionData.Calls.HomeCallback = call; super.initState(); } void call() { setState(() {}); if (SessionData.DisplayError.isNotEmpty) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(SessionData.DisplayError), elevation: 8, duration: Duration(seconds: 5), ), ); SessionData.DisplayError = ""; } } @override void dispose() { SessionData.Calls.HomeCallback = null; super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Time Tracker"), backgroundColor: LibACFlutterConstants.TITLEBAR_COLOR, ), drawer: Drawer( elevation: 8, child: SingleChildScrollView( child: Column( children: [ DrawerHeader( child: Column( children: [ Text("Time Tracker"), Text("Created by Tara Piccari"), Text("Copyright 2025 - Present"), Text("Version: ${TTConsts.VERSION}"), ], ), ), ListTile( title: Text("Update Settings.."), subtitle: Text( "Open the update settings. Channel, check for updates, and installation", ), onTap: () async { await Navigator.pushNamed(context, "/upd"); setState(() {}); }, 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("Work Data"), subtitle: Text("View and edit work data"), leading: Icon(Icons.work_history), onTap: () async { // Open up the work data viewer and editor. // Edit will be disabled for web or read only mode. await Navigator.pushNamed(context, "/work"); setState(() {}); }, ), ListTile( title: Text("Source Code"), subtitle: Text("Licensed under the GPLv3"), leading: Icon(Icons.code_rounded), onTap: () async { final Uri url = Uri.parse( 'https://git.zontreck.com/AriasCreations/TimeTracker', ); if (!await launchUrl(url)) { throw Exception('Could not launch $url'); } }, ), /* ListTile( title: Text("RESET APP SESSION"), onTap: () async { setState(() { SessionData.IsOnTheClock = false; SessionData.StartTime = DateTime.fromMillisecondsSinceEpoch( 0, ); SessionData.Trips = []; SessionData.currentDelivery = null; SessionData.currentTrip = null; SessionData.positions = []; }); }, ),*/ ], ), ), ), body: SingleChildScrollView( child: Column( children: [ if (!SessionData.IsOnTheClock) Text( "Hit engage when you are ready to go online and start tracking location data, and trips.", style: TextStyle(fontSize: 18), ), if (SessionData.LastSessionID.isNotEmpty) ListTile( title: Text("Session ID"), subtitle: Text("${SessionData.LastSessionID} - Tap to copy"), onTap: () { Clipboard.setData( ClipboardData( text: "https://timetrack.zontreck.com/?code=${SessionData.LastSessionID}", ), ); }, ), if (!SessionData.IsOnTheClock) Center( child: ElevatedButton( onPressed: () async { var result = await SessionData.Login(); if (!result) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( "Fatal Error: Could not establish the background service for keeping the app alive.", ), ), ); } setState(() {}); }, child: Text("ENGAGE"), ), ), if (SessionData.IsOnTheClock) GetLoggedInWidgets(), ], ), ), ); } Widget GetTripWidgets() { return Column( children: [ Text("Trip started", style: TextStyle(fontSize: 18)), Text( "To end both your current delivery, and the trip, tap on END TRIP", style: TextStyle(fontSize: 18), ), Text( "You are currently on Delivery #${SessionData.currentTrip!.deliveries.length}", ), ElevatedButton( onPressed: () async { await showDialog( context: context, builder: (builder) { return AlertDialog( icon: Icon(Icons.warning), title: Text("Are you sure you want to end the trip?"), content: Text( "Once ended, a marker for your current delivery will be dropped at your current location", ), actions: [ ElevatedButton( onPressed: () { Navigator.pop(context); SessionData.currentDelivery!.MarkEndLocation(); SessionData.EndTrip(); setState(() {}); }, child: Text("Yes"), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text("Cancel"), ), ], ); }, ); }, child: Text("END TRIP"), ), ], ); } Widget GetDeliveryWidgets() { return Column( children: [ ElevatedButton( onPressed: () async { await showDialog( context: context, builder: (builder) { return AlertDialog( icon: Icon(Icons.warning), title: Text("Are you sure you want to start a new delivery?"), content: Text( "Once ended, a marker for your current delivery will be dropped at your current location", ), actions: [ ElevatedButton( onPressed: () { Navigator.pop(context); SessionData.currentDelivery!.MarkEndLocation(); SessionData.GetNewDelivery(); setState(() {}); }, child: Text("Yes"), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text("Cancel"), ), ], ); }, ); }, child: Text("Start new delivery"), ), ], ); } Widget GetNonTripWidgets() { return Column( children: [ ElevatedButton( onPressed: () async { await showDialog( context: context, builder: (builder) { return AlertDialog( icon: Icon(Icons.warning), title: Text("Are you sure you want to start a new trip?"), content: Text("Starting a trip will also start a delivery."), actions: [ ElevatedButton( onPressed: () { Navigator.pop(context); SessionData.GetNewTrip(); SessionData.GetNewDelivery(); setState(() {}); }, child: Text("Yes"), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text("Cancel"), ), ], ); }, ); }, 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 { await showDialog( context: context, builder: (builder) { return AlertDialog( icon: Icon(Icons.warning), title: Text("Are you sure you want to end the work day?"), content: Text( "Ending the work day will finalize your session. A code will pop up. To copy a URL to this session to your clipboard, tap and hold on the session code. You will be asked to enter the total pay if you tap yes.\n\nEnding the work day cannot be undone.", ), actions: [ ElevatedButton( onPressed: () async { Navigator.pop(context); // Prompt for the total pay var reply = await showDialog( context: context, builder: (bldx) { return InputPrompt( title: "What was the total pay?", prompt: "Enter the total pay here. If you do not want to, simply leave the field blank and a 0 will be used instead.", type: InputPromptType.Number, ); }, ); if (reply == null || reply as String == "") { reply = 0.0; } if (reply is String) reply = double.parse(reply); SessionData.TotalPay = reply as double; await SessionData.Logout(); setState(() {}); }, child: Text("Yes"), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text("Cancel"), ), ], ); }, ); } }, child: Text("End work day"), ), ], ); } Widget GetLoggedInWidgets() { return Column( children: [ Text( "You are now on the clock\nYour location is being tracked for record keeping purposes.\n\nYou started ${SessionData.GetTotalTimeWorked(SessionData.StartTime, DateTime.now())} ago\n\n", style: TextStyle(fontSize: 18), ), if (SessionData.currentTrip != null) GetTripWidgets(), if (SessionData.currentDelivery != null) GetDeliveryWidgets(), if (SessionData.currentTrip == null) GetNonTripWidgets(), ], ); } } class OverlayWidget extends StatefulWidget { @override State createState() { return _Overlay(); } } class _Overlay extends State { @override Widget build(BuildContext context) { return Scaffold(); } }