Summary page done
This commit is contained in:
816
lib/main.dart
816
lib/main.dart
@@ -1,25 +1,28 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tasktracker/Categories.dart';
|
||||
import 'package:tasktracker/Welcome.dart';
|
||||
import 'package:tasktracker/splash.dart';
|
||||
import 'package:wakelock/wakelock.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'Data.dart';
|
||||
import 'NewTask.dart';
|
||||
import 'newActivity.dart';
|
||||
import 'Tasks.dart';
|
||||
import 'Activities.dart';
|
||||
import 'User.dart' as User;
|
||||
import 'package:sn_progress_dialog/sn_progress_dialog.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
|
||||
late ProgressDialog progressDialog;
|
||||
|
||||
showAlertDialog(BuildContext context, String title, String message) {
|
||||
|
||||
// set up the button
|
||||
Widget okButton = TextButton(
|
||||
child: Text("OK"),
|
||||
onPressed: () { Navigator.of(context).pop(); },
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
|
||||
// set up the AlertDialog
|
||||
@@ -57,26 +60,6 @@ extension HexColor on Color {
|
||||
'${blue.toRadixString(16).padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
// To keep the screen on:
|
||||
final List<PopulationData> data = [
|
||||
PopulationData(
|
||||
name: "Rocket League",
|
||||
value: 45,
|
||||
barColor: charts.ColorUtil.fromDartColor(Colors.blue)),
|
||||
PopulationData(
|
||||
name: "CS:GO",
|
||||
value: 15,
|
||||
barColor: charts.ColorUtil.fromDartColor(Colors.yellow)),
|
||||
PopulationData(
|
||||
name: "Halo",
|
||||
value: 10,
|
||||
barColor: charts.ColorUtil.fromDartColor(Colors.grey)),
|
||||
PopulationData(
|
||||
name: "SneakyPeaky",
|
||||
value: 30,
|
||||
barColor: charts.ColorUtil.fromDartColor(Colors.red)),
|
||||
];
|
||||
|
||||
void main() {
|
||||
//Wakelock.enable(); // or Wakelock.toggle(on: true);
|
||||
runApp(const MyApp());
|
||||
@@ -88,26 +71,52 @@ class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
accentColor: Colors.redAccent,
|
||||
brightness: Brightness.dark,
|
||||
primaryColor: Colors.amber,
|
||||
fontFamily: 'Noto-Sans'),
|
||||
//home: const MyHomePage(),
|
||||
initialRoute: '/splash',
|
||||
routes:{
|
||||
'/splash':(context)=> const SplashScreen(),
|
||||
'/welcome':(context)=> const WelcomePage(),
|
||||
'/':(context) => const MyHomePage(),
|
||||
'/Tasks':(context)=> const Tasks(),
|
||||
'/Categories':(context)=>const Categories(),
|
||||
'/Activities':(context)=>const Activities()
|
||||
}
|
||||
);
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(accentColor: Colors.redAccent, brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'),
|
||||
//home: const MyHomePage(),
|
||||
initialRoute: '/splash',
|
||||
routes: {
|
||||
'/splash': (context) => const SplashScreen(),
|
||||
'/welcome': (context) => const WelcomePage(),
|
||||
'/': (context) => const MyHomePage(),
|
||||
'/Tasks': (context) => const Tasks(),
|
||||
'/Categories': (context) => const Categories(),
|
||||
'/Activities': (context) => const Activities()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
List<String> days = [];
|
||||
String curDay = "";
|
||||
|
||||
DateTime? firstDay = null;
|
||||
DateTime? lastDay = null;
|
||||
DateTimeRange? taskTypeRange = null;
|
||||
DateTimeRange? catsRange = null;
|
||||
|
||||
List<ProductivityMapData> productivityData = <ProductivityMapData>[
|
||||
ProductivityMapData('02/24', 35),
|
||||
ProductivityMapData('02/25', 28),
|
||||
ProductivityMapData('02/26', 34),
|
||||
ProductivityMapData('02/27', 32),
|
||||
ProductivityMapData('02/28', 40)
|
||||
];
|
||||
|
||||
List<TaskTypeMapData> taskTypesData = <TaskTypeMapData>[TaskTypeMapData('Eat', 3600, Colors.green), TaskTypeMapData('Play', 300, Colors.blue)];
|
||||
List<CatMapData> catsData = <CatMapData>[
|
||||
CatMapData('Jan', 35, Colors.green),
|
||||
CatMapData('Feb', 28, Colors.blueAccent),
|
||||
CatMapData('Mar', 34, Colors.yellow),
|
||||
CatMapData('Apr', 32, Colors.grey),
|
||||
];
|
||||
|
||||
List<CatMapData> dailyData = <CatMapData>[
|
||||
CatMapData('Jan', 35, Colors.green),
|
||||
CatMapData('Feb', 28, Colors.blueAccent),
|
||||
CatMapData('Mar', 34, Colors.yellow),
|
||||
CatMapData('Apr', 32, Colors.grey),
|
||||
];
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -116,215 +125,572 @@ class MyHomePage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
List<charts.Series<PopulationData, String>> series = [
|
||||
charts.Series(
|
||||
id: "Subscribers",
|
||||
data: data,
|
||||
domainFn: (PopulationData series, _) => series.name,
|
||||
measureFn: (PopulationData series, _) => series.value,
|
||||
colorFn: (PopulationData series, _) => series.barColor)
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
showOfflineSnack();
|
||||
progressDialog = ProgressDialog(context: context);
|
||||
User.progressDialog=progressDialog;
|
||||
User.refreshUserData().then((val) => LoadStats());
|
||||
// showOfflineSnack();
|
||||
LoadStats();
|
||||
// progressDialog = ProgressDialog(context: context);
|
||||
// User.progressDialog=progressDialog;
|
||||
}
|
||||
|
||||
void showOfflineSnack() async{
|
||||
void LoadStats() async {
|
||||
// return;
|
||||
|
||||
while (!User.userDataInitiated) {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
}
|
||||
|
||||
DateFormat dFormat = DateFormat("MM/dd");
|
||||
Map<Category, int> catTimeMap = <Category, int>{};
|
||||
Map<Category, int> catBriefMap = <Category, int>{};
|
||||
|
||||
Map<String, int> productivtyActs = <String, int>{};
|
||||
Map<String, int> unproductivtyActs = <String, int>{};
|
||||
Map<TaskType, int> taskTypesDuration = <TaskType, int>{};
|
||||
firstDay = null;
|
||||
lastDay = null;
|
||||
String lastDate = "";
|
||||
for (var element in User.activities) {
|
||||
if (lastDay == null) {
|
||||
lastDay = element.endTime;
|
||||
}
|
||||
if (taskTypeRange == null) {
|
||||
print("$lastDay - $firstDay");
|
||||
taskTypeRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 1)), end: lastDay!);
|
||||
}
|
||||
if (catsRange == null) {
|
||||
print("$lastDay - $firstDay");
|
||||
catsRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 1)), end: lastDay!);
|
||||
}
|
||||
firstDay = element.startTime;
|
||||
String thisDate = dFormat.format(element.startTime);
|
||||
int thisMinutes = element.endTime.difference(element.startTime).inMinutes;
|
||||
if (!days.contains(thisDate)) {
|
||||
days.add(dFormat.format(element.startTime));
|
||||
}
|
||||
if (curDay == "") {
|
||||
curDay = dFormat.format(DateTime.now());
|
||||
}
|
||||
|
||||
if ((element.startTime.isAfter(taskTypeRange!.start) && element.startTime.isBefore(taskTypeRange!.end)) ||
|
||||
(dFormat.format(element.startTime) == dFormat.format(taskTypeRange!.start) || dFormat.format(element.startTime) == dFormat.format(taskTypeRange!.end))) {
|
||||
if (taskTypesDuration.containsKey(element.taskType)) {
|
||||
taskTypesDuration[element.taskType] = taskTypesDuration[element.taskType]! + thisMinutes;
|
||||
} else {
|
||||
taskTypesDuration.putIfAbsent(element.taskType, () => thisMinutes);
|
||||
}
|
||||
}
|
||||
|
||||
if (element.taskType.cat?.productive ?? false) {
|
||||
if (productivtyActs.containsKey(thisDate)) {
|
||||
productivtyActs[thisDate] = (productivtyActs[thisDate]! + thisMinutes);
|
||||
} else {
|
||||
productivtyActs.putIfAbsent(thisDate, () => thisMinutes);
|
||||
}
|
||||
} else {
|
||||
if (unproductivtyActs.containsKey(thisDate)) {
|
||||
unproductivtyActs[thisDate] = (unproductivtyActs[thisDate]! + thisMinutes);
|
||||
} else {
|
||||
unproductivtyActs.putIfAbsent(thisDate, () => thisMinutes);
|
||||
}
|
||||
}
|
||||
|
||||
if (thisDate == curDay) {
|
||||
if (element.taskType.cat == null) {
|
||||
continue;
|
||||
}
|
||||
print("Null : ${thisMinutes}");
|
||||
if (catTimeMap.containsKey(element.taskType.cat)) {
|
||||
catTimeMap[element.taskType.cat!] = (catTimeMap[element.taskType.cat]! + thisMinutes);
|
||||
} else {
|
||||
catTimeMap.putIfAbsent(element.taskType.cat!, () => thisMinutes);
|
||||
}
|
||||
}
|
||||
|
||||
if ((element.startTime.isAfter(catsRange!.start) && element.startTime.isBefore(catsRange!.end)) ||
|
||||
(dFormat.format(element.startTime) == dFormat.format(catsRange!.start) || dFormat.format(element.startTime) == dFormat.format(catsRange!.end))) {
|
||||
if (element.taskType.cat == null) {
|
||||
continue;
|
||||
}
|
||||
print("Null : ${thisMinutes}");
|
||||
if (catBriefMap.containsKey(element.taskType.cat)) {
|
||||
catBriefMap[element.taskType.cat!] = (catBriefMap[element.taskType.cat]! + thisMinutes);
|
||||
} else {
|
||||
catBriefMap.putIfAbsent(element.taskType.cat!, () => thisMinutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//curDay = days[0];
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
dailyData = <CatMapData>[];
|
||||
productivityData = <ProductivityMapData>[];
|
||||
taskTypesData = <TaskTypeMapData>[];
|
||||
catsData = <CatMapData>[];
|
||||
|
||||
catTimeMap.forEach((key, value) {
|
||||
print(key.name + " : $value");
|
||||
Color barCol = HexColor.fromHex(key.color);
|
||||
dailyData.add(CatMapData(key.name, value, barCol));
|
||||
});
|
||||
|
||||
for (var element in days) {
|
||||
// if(productivtyActs.containsKey(element) && unproductivtyActs.containsKey(element)){
|
||||
int prodActs = (productivtyActs[element] ?? 0);
|
||||
int unprodActs = (unproductivtyActs[element] ?? 0);
|
||||
double prod = (prodActs / (prodActs + unprodActs)) * 100;
|
||||
productivityData.add(ProductivityMapData(element, prod));
|
||||
// }
|
||||
}
|
||||
|
||||
taskTypesDuration.forEach((key, value) {
|
||||
print("$key : $value");
|
||||
taskTypesData.add(TaskTypeMapData(key.name, value, HexColor.fromHex(key.cat!.color)));
|
||||
});
|
||||
|
||||
catBriefMap.forEach((key, value) {
|
||||
print(key.name + " : $value");
|
||||
Color barCol = HexColor.fromHex(key.color);
|
||||
catsData.add(CatMapData(key.name, value, barCol));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void showOfflineSnack() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
if(User.offline){
|
||||
const SnackBar offlineSnack = SnackBar(content: Text('Offline'),duration: Duration(seconds: 100),);
|
||||
ScaffoldMessenger.of(context).showSnackBar(offlineSnack);
|
||||
if (User.offline) {
|
||||
const SnackBar offlineSnack = SnackBar(
|
||||
content: Text('Offline'),
|
||||
duration: Duration(seconds: 100),
|
||||
);
|
||||
// ScaffoldMessenger.of(context).showSnackBar(offlineSnack);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
floatingActionButton: FloatingActionButton.extended(onPressed: (){
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context)=> NewActivity()));
|
||||
},
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewActivity())).then((value) => {User.refreshUserData().then((va) => LoadStats())});
|
||||
},
|
||||
label: Text("New Activity"),
|
||||
icon: Icon(Icons.add)
|
||||
),
|
||||
appBar: AppBar(title: Row(children:[Icon(Icons.article_outlined, color: Theme.of(context).primaryColor),SizedBox(width: 10),Text('Summary')])),
|
||||
drawer: navDrawer(context,0),
|
||||
body: SafeArea(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 300,
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Card(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.blueGrey,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: Column(
|
||||
children: [
|
||||
cardTitle('Daily Average'),
|
||||
Expanded(
|
||||
child: charts.BarChart(
|
||||
series,
|
||||
animate: true,
|
||||
barRendererDecorator:
|
||||
new charts.BarLabelDecorator(
|
||||
labelPosition:
|
||||
charts.BarLabelPosition.inside,
|
||||
labelPadding: 10,
|
||||
labelAnchor:
|
||||
charts.BarLabelAnchor.middle),
|
||||
))
|
||||
],
|
||||
)))),
|
||||
Container(
|
||||
height: 300,
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Card(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.green,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: Column(
|
||||
children: [
|
||||
cardTitle('Weekly Average'),
|
||||
Expanded(
|
||||
child: charts.BarChart(
|
||||
series,
|
||||
animate: true,
|
||||
barRendererDecorator:
|
||||
new charts.BarLabelDecorator(
|
||||
labelPosition:
|
||||
charts.BarLabelPosition.inside,
|
||||
labelPadding: 10,
|
||||
labelAnchor:
|
||||
charts.BarLabelAnchor.middle),
|
||||
))
|
||||
],
|
||||
))))
|
||||
],
|
||||
),
|
||||
icon: Icon(Icons.add)),
|
||||
appBar: AppBar(title: Row(children: [Icon(Icons.article_outlined, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Summary')])),
|
||||
drawer: navDrawer(context, 0),
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(
|
||||
children: [
|
||||
(false)
|
||||
? Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text("Good\nMorning!", style: TextStyle(fontSize: 23, fontStyle: FontStyle.italic)),
|
||||
Text(
|
||||
"12%",
|
||||
style: TextStyle(fontSize: 30),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text(DateFormat("yy - MM-dd").format(DateTime.now())),
|
||||
Text(DateFormat("HH:mm").format(DateTime.now()), style: TextStyle(fontSize: 40)),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
Container(
|
||||
height: 300,
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Card(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.blueGrey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text("Productivity", style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
Divider(),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text("Today : "),
|
||||
Text("${(productivityData.length > 0) ? productivityData[0].productivity.toStringAsFixed(1) : 'n/a'}%",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: (productivityData.length > 1)
|
||||
? ((productivityData[0].productivity > productivityData[1].productivity) ? Colors.lightGreenAccent : Colors.red)
|
||||
: Colors.white))
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text("Yesterday : "),
|
||||
Text("${(productivityData.length > 1) ? productivityData[1].productivity.toStringAsFixed(1) : 'n/a'}%", style: TextStyle(fontSize: 18))
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: SfCartesianChart(
|
||||
// Initialize category axis
|
||||
primaryXAxis: CategoryAxis(),
|
||||
series: <LineSeries<ProductivityMapData, String>>[
|
||||
LineSeries<ProductivityMapData, String>(
|
||||
// Bind data source
|
||||
dataSource: productivityData.reversed.toList(),
|
||||
xValueMapper: (ProductivityMapData sales, _) => sales.day,
|
||||
yValueMapper: (ProductivityMapData sales, _) => sales.productivity,
|
||||
color: Colors.green)
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
Container(
|
||||
height: 370,
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Card(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.blueGrey,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: (!days.isEmpty)
|
||||
? Column(
|
||||
children: [
|
||||
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Padding(padding: EdgeInsets.all(20), child: Text('Daily Briefing', style: TextStyle(fontWeight: FontWeight.bold))),
|
||||
dayPickerWidget(days, value: curDay, onChange: (_value) {
|
||||
print('new val : $_value');
|
||||
curDay = _value;
|
||||
setState(() {
|
||||
LoadStats();
|
||||
});
|
||||
}),
|
||||
]),
|
||||
Expanded(
|
||||
child: SfCircularChart(legend: Legend(isVisible: true), series: <CircularSeries>[
|
||||
// Render pie chart
|
||||
PieSeries<CatMapData, String>(
|
||||
dataSource: dailyData,
|
||||
pointColorMapper: (CatMapData data, _) => data.color,
|
||||
xValueMapper: (CatMapData data, _) => data.name,
|
||||
yValueMapper: (CatMapData data, _) => data.time,
|
||||
dataLabelMapper: (CatMapData sales, _) => MinutesToTimeString(sales.time),
|
||||
dataLabelSettings: DataLabelSettings(isVisible: true, useSeriesColor: true))
|
||||
]))
|
||||
],
|
||||
)
|
||||
: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [CircularProgressIndicator()])))),
|
||||
Container(
|
||||
height: 450,
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Card(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.blueGrey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 25),
|
||||
child: Column(children: [
|
||||
Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Text("Task Types", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
DateTimeRange? value = await showDateRangePicker(context: context, firstDate: firstDay ?? DateTime.now(), lastDate: lastDay ?? DateTime.now());
|
||||
if (value != null) {
|
||||
taskTypeRange = value;
|
||||
}
|
||||
|
||||
LoadStats();
|
||||
},
|
||||
child: Text((taskTypeRange != null) ? (DateFormat("MM/dd").format(taskTypeRange!.start) + " - " + DateFormat("MM/dd").format(taskTypeRange!.end)) : 'n/a'),
|
||||
)
|
||||
]),
|
||||
Expanded(
|
||||
// maxHeight: 300,
|
||||
// maxWidth: 100,
|
||||
child: SfCartesianChart(primaryXAxis: CategoryAxis(),
|
||||
//primaryYAxis: NumericAxis(minimum: 0, maximum: 40, interval: 10),
|
||||
series: <ChartSeries<TaskTypeMapData, String>>[
|
||||
BarSeries<TaskTypeMapData, String>(
|
||||
dataSource: taskTypesData,
|
||||
xValueMapper: (TaskTypeMapData data, _) => data.task,
|
||||
yValueMapper: (TaskTypeMapData data, _) => data.time / 60,
|
||||
pointColorMapper: (TaskTypeMapData data, _) => data.color,
|
||||
dataLabelMapper: (TaskTypeMapData data, _) => MinutesToTimeString(data.time),
|
||||
dataLabelSettings: DataLabelSettings(isVisible: true),
|
||||
color: Color.fromRGBO(8, 142, 255, 1))
|
||||
]),
|
||||
)
|
||||
])))),
|
||||
Container(
|
||||
height: 450,
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Card(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.blueGrey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 25),
|
||||
child: Column(children: [
|
||||
Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Text("Categories", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
DateTimeRange? value = await showDateRangePicker(context: context, firstDate: firstDay ?? DateTime.now(), lastDate: lastDay ?? DateTime.now());
|
||||
if (value != null) {
|
||||
catsRange = value;
|
||||
}
|
||||
|
||||
LoadStats();
|
||||
},
|
||||
child: Text((catsRange != null) ? (DateFormat("MM/dd").format(catsRange!.start) + " - " + DateFormat("MM/dd").format(catsRange!.end)) : 'n/a'),
|
||||
)
|
||||
]),
|
||||
Expanded(
|
||||
// maxHeight: 300,
|
||||
// maxWidth: 100,
|
||||
child: SfCartesianChart(primaryXAxis: CategoryAxis(),
|
||||
//primaryYAxis: NumericAxis(minimum: 0, maximum: 40, interval: 10),
|
||||
series: <ChartSeries<CatMapData, String>>[
|
||||
BarSeries<CatMapData, String>(
|
||||
dataSource: catsData,
|
||||
xValueMapper: (CatMapData data, _) => data.name,
|
||||
yValueMapper: (CatMapData data, _) => data.time / 60,
|
||||
pointColorMapper: (CatMapData data, _) => data.color,
|
||||
dataLabelMapper: (CatMapData data, _) => MinutesToTimeString(data.time),
|
||||
dataLabelSettings: DataLabelSettings(isVisible: true),
|
||||
color: Color.fromRGBO(8, 142, 255, 1))
|
||||
]),
|
||||
)
|
||||
])))),
|
||||
],
|
||||
),
|
||||
));
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget dayPickerWidget(List<String> list, {required String value, required Function(String value) onChange}) {
|
||||
if (!list.contains(value)) {
|
||||
print("resetting");
|
||||
onChange(list[0]);
|
||||
}
|
||||
bool nextAvailable = (list.indexOf(value) < (list.length - 1));
|
||||
bool prevAvailable = (list.indexOf(value) > 0);
|
||||
return Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (nextAvailable) {
|
||||
onChange(list[list.indexOf(value) + 1]);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
child: Icon(Icons.arrow_back_ios, size: 18, color: (nextAvailable) ? Colors.white : Colors.grey),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (prevAvailable) {
|
||||
onChange(list[list.indexOf(value) - 1]);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
child: Icon(Icons.arrow_forward_ios, size: 18, color: (prevAvailable) ? Colors.white : Colors.grey),
|
||||
))
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget cardTitle(String title) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children:[
|
||||
Padding(padding: EdgeInsets.all(20),child:Text(title,
|
||||
style: TextStyle(fontWeight: FontWeight.bold))),
|
||||
MaterialButton(onPressed: (){},child:moreButton())]);
|
||||
Widget moreButton() {
|
||||
return MaterialButton(
|
||||
onPressed: () {},
|
||||
color: Colors.green,
|
||||
child: Row(
|
||||
children: [Text('More'), Icon(Icons.keyboard_arrow_right)],
|
||||
));
|
||||
}
|
||||
|
||||
Widget moreButton(){
|
||||
return MaterialButton(
|
||||
onPressed: (){
|
||||
|
||||
},
|
||||
color: Colors.green,
|
||||
child:Row(
|
||||
Drawer navDrawer(BuildContext context, int pageIndex) {
|
||||
return Drawer(
|
||||
child: ListView(
|
||||
children: [
|
||||
Text('More'),Icon(Icons.keyboard_arrow_right)
|
||||
Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Text("Time Tracker", style: TextStyle(fontSize: 25, color: Theme.of(context).accentColor, fontWeight: FontWeight.bold)),
|
||||
Icon(
|
||||
Icons.more_time,
|
||||
size: 30,
|
||||
),
|
||||
])),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 0),
|
||||
title: Text('Summary'),
|
||||
leading: Icon(Icons.article_outlined, color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 0) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed('/');
|
||||
},
|
||||
),
|
||||
// ListTile(
|
||||
// selected: (pageIndex == 1),
|
||||
// title: Text('Analytics'),
|
||||
// leading: Icon(Icons.analytics_outlined,
|
||||
// color: Theme.of(context).primaryColor),
|
||||
// onTap: () {
|
||||
// if (pageIndex == 1) {
|
||||
// return;
|
||||
// }
|
||||
// // Navigator.of(context).pushReplacementNamed('/');
|
||||
// },
|
||||
// ),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 2),
|
||||
title: Text('Activities'),
|
||||
leading: Icon(Icons.task, color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 2) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed('/Activities');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 3),
|
||||
title: Text('Task Types'),
|
||||
leading: Icon(Icons.task, color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 3) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed('/Tasks');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 4),
|
||||
title: Text('Categories'),
|
||||
leading: Icon(Icons.account_tree_outlined, color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 4) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed('/Categories');
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 5),
|
||||
title: Text('Settings'),
|
||||
leading: Icon(Icons.settings, color: Colors.blueGrey),
|
||||
onTap: () {},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 6),
|
||||
title: Text('About'),
|
||||
leading: Icon(Icons.help_outline_outlined),
|
||||
onTap: () {},
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
class PopulationData {
|
||||
String name;
|
||||
int value;
|
||||
charts.Color barColor;
|
||||
PopulationData(
|
||||
{required this.name, required this.value, required this.barColor});
|
||||
class MyPlayerBar extends CustomPainter {
|
||||
MyPlayerBar(this.max, this.value, {this.background = Colors.lightBlue, this.fill = Colors.blue});
|
||||
|
||||
Color background = Colors.lightBlue;
|
||||
Color fill = Colors.blue;
|
||||
final int max;
|
||||
final int value;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
Paint paint = Paint();
|
||||
double cursor = (value * size.width) / max;
|
||||
Radius cornerRadius = Radius.circular(10.0);
|
||||
|
||||
// Already played half color (your darker orange)
|
||||
paint.color = background;
|
||||
|
||||
// Painting already played half
|
||||
canvas.drawRRect(RRect.fromRectAndCorners(Rect.fromLTWH(0.0, 0.0, cursor, size.height), topLeft: cornerRadius, bottomLeft: cornerRadius), paint);
|
||||
|
||||
// Yet to play half color (your lighter orange)
|
||||
paint.color = fill;
|
||||
|
||||
// Painting the remaining space
|
||||
canvas.drawRRect(RRect.fromRectAndCorners(Rect.fromLTWH(cursor, 0.0, size.width - cursor, size.height), bottomRight: cornerRadius, topRight: cornerRadius), paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => true;
|
||||
}
|
||||
|
||||
Drawer navDrawer(BuildContext context, int pageIndex){
|
||||
return Drawer(
|
||||
child: ListView(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children:[Text("Time Tracker",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: Theme.of(context).accentColor,
|
||||
fontWeight: FontWeight.bold)),
|
||||
Icon(Icons.more_time,size: 30,),
|
||||
])
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 0),
|
||||
title: Text('Summary'),
|
||||
leading: Icon(Icons.article_outlined,color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if(pageIndex==0){return;}
|
||||
Navigator.of(context).pushReplacementNamed('/');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 1),
|
||||
title: Text('Analytics'),
|
||||
leading: Icon(Icons.analytics_outlined,color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if(pageIndex==1){return;}
|
||||
// Navigator.of(context).pushReplacementNamed('/');
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 2),
|
||||
title: Text('Activities'),
|
||||
leading: Icon(Icons.task,color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if(pageIndex==2){return;}
|
||||
Navigator.of(context).pushReplacementNamed('/Activities');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 3),
|
||||
title: Text('Task Types'),
|
||||
leading: Icon(Icons.task,color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if(pageIndex==3){return;}
|
||||
Navigator.of(context).pushReplacementNamed('/Tasks');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 4),
|
||||
title: Text('Categories'),
|
||||
leading: Icon(Icons.account_tree_outlined,color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if(pageIndex==4){return;}
|
||||
Navigator.of(context).pushReplacementNamed('/Categories');
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 5),
|
||||
title: Text('Settings'),
|
||||
leading: Icon(Icons.settings,color: Colors.blueGrey),
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 6),
|
||||
title: Text('About'),
|
||||
leading: Icon(Icons.help_outline_outlined),
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
class CatMapData {
|
||||
CatMapData(this.name, this.time, this.color);
|
||||
final String name;
|
||||
final int time;
|
||||
final Color color;
|
||||
}
|
||||
|
||||
class ProductivityMapData {
|
||||
ProductivityMapData(this.day, this.productivity);
|
||||
|
||||
final String day;
|
||||
final double productivity;
|
||||
}
|
||||
|
||||
class TaskTypeMapData {
|
||||
TaskTypeMapData(this.task, this.time, this.color);
|
||||
final Color color;
|
||||
final String task;
|
||||
final int time;
|
||||
}
|
||||
|
||||
String MinutesToTimeString(minutes) {
|
||||
int hours = (minutes / 60).floor();
|
||||
int mins = minutes % 60;
|
||||
|
||||
String str = "";
|
||||
if (hours > 0) {
|
||||
str += hours.toString() + "h";
|
||||
}
|
||||
if (mins > 0) {
|
||||
str += ((hours > 0) ? " " : "") + mins.toString() + "m";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user