Settings page added
This commit is contained in:
@@ -17,36 +17,77 @@ class Activities extends StatefulWidget {
|
|||||||
late ProgressDialog progressDialog;
|
late ProgressDialog progressDialog;
|
||||||
|
|
||||||
class _ActivitiesState extends State<Activities> {
|
class _ActivitiesState extends State<Activities> {
|
||||||
|
TextEditingController searchController = TextEditingController();
|
||||||
|
FocusNode _focus = FocusNode();
|
||||||
|
bool searching = false;
|
||||||
|
|
||||||
|
void _onFocusChange() {
|
||||||
|
print("FOCUS CHANGED! : ${_focus.hasFocus}");
|
||||||
|
|
||||||
|
if(!_focus.hasFocus){
|
||||||
|
searching=false;
|
||||||
|
setState(() {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_focus.addListener(_onFocusChange);
|
||||||
UpdateList();
|
UpdateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// TODO: implement dispose
|
||||||
|
super.dispose();
|
||||||
|
_focus.removeListener(_onFocusChange);
|
||||||
|
_focus.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
progressDialog = ProgressDialog(context: context);
|
progressDialog = ProgressDialog(context: context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
floatingActionButton: FloatingActionButton.extended(
|
floatingActionButton: FloatingActionButton.extended(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context)
|
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewActivity())).then((value) => UpdateList());
|
||||||
.push(MaterialPageRoute(builder: (context) => NewActivity()))
|
|
||||||
.then((value) => UpdateList());
|
|
||||||
},
|
},
|
||||||
label: Text("New Activity"),
|
label: Text("New Activity"),
|
||||||
icon: Icon(Icons.add)),
|
icon: Icon(Icons.add)),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: (searching)
|
||||||
|
? Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(onChanged: (text){setState(() {
|
||||||
|
|
||||||
|
});},controller: searchController, focusNode: _focus, decoration: InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
),),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: (){searching=false;
|
||||||
|
searchController.clear();
|
||||||
|
setState(() {
|
||||||
|
|
||||||
|
});},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Icon(Icons.cancel),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Row(children: [
|
Row(children: [Icon(Icons.task, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Activities')]),
|
||||||
Icon(Icons.task, color: Theme.of(context).primaryColor),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Text('Activities')
|
|
||||||
]),
|
|
||||||
(selecting)
|
(selecting)
|
||||||
? Row(children: [
|
? Row(children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
@@ -69,12 +110,39 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
child: Icon(Icons.close, size: 30),
|
child: Icon(Icons.close, size: 30),
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
: Container(),
|
: Row(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
searching = true;
|
||||||
|
_focus.requestFocus();
|
||||||
|
setState(() {
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.search,
|
||||||
|
size: 30,
|
||||||
|
)),
|
||||||
|
SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() async {
|
||||||
|
await User.refreshUserData();
|
||||||
|
UpdateList();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(Icons.refresh, size: 30),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
drawer: navDrawer(context, 2),
|
drawer: navDrawer(context, 2),
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.all(0),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: PrintTasks(),
|
children: PrintTasks(),
|
||||||
@@ -127,6 +195,14 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
}
|
}
|
||||||
print(productivtyActs);
|
print(productivtyActs);
|
||||||
for (var element in User.activities) {
|
for (var element in User.activities) {
|
||||||
|
if(searching){
|
||||||
|
if(element.metadata!.toLowerCase().contains(searchController.text.toLowerCase()) || element.taskType.name.toLowerCase().contains(searchController.text.toLowerCase())){
|
||||||
|
//Good to go
|
||||||
|
}else{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String thisDate = dFormat.format(element.startTime);
|
String thisDate = dFormat.format(element.startTime);
|
||||||
if (thisDate != lastDate) {
|
if (thisDate != lastDate) {
|
||||||
int prodActs = productivtyActs[thisDate] ?? 0;
|
int prodActs = productivtyActs[thisDate] ?? 0;
|
||||||
@@ -138,11 +214,9 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
if (element.taskType.cat == null) {
|
if (element.taskType.cat == null) {
|
||||||
print('Got some null cat : ${element.taskType.name}');
|
print('Got some null cat : ${element.taskType.name}');
|
||||||
} else {
|
} else {
|
||||||
Color color =
|
Color color = HexColor.fromHex(element.taskType.cat?.color ?? '#000000');
|
||||||
HexColor.fromHex(element.taskType.cat?.color ?? '#000000');
|
|
||||||
bool productive = element.taskType.cat?.productive ?? true;
|
bool productive = element.taskType.cat?.productive ?? true;
|
||||||
Widget task = ActivityCard(context, name, element.startTime,
|
Widget task = ActivityCard(context, name, element.startTime, element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0);
|
||||||
element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0);
|
|
||||||
_tasks.add(task);
|
_tasks.add(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,27 +227,55 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
Widget DateSeperator(date, prodActs, unprodActs) {
|
Widget DateSeperator(date, prodActs, unprodActs) {
|
||||||
double prodPercentage = (prodActs / (prodActs + unprodActs)) * 100;
|
double prodPercentage = (prodActs / (prodActs + unprodActs)) * 100;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(10, 20, 10, 0),
|
padding: const EdgeInsets.fromLTRB(0, 20, 10, 0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.remove_circle_outline),
|
||||||
|
SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
date,
|
date,
|
||||||
style: TextStyle(fontSize: 18),
|
style: TextStyle(fontSize: 18),
|
||||||
),
|
),
|
||||||
Row(children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Container(child:Align(child:Text(MinutesToTimeString(prodActs)), alignment: Alignment.center,),width: (prodPercentage) * 1.7, height: 25,decoration: BoxDecoration(color: Colors.green,borderRadius: BorderRadius.horizontal(left: Radius.circular(10))),),
|
|
||||||
Container(child:Align(child:Text(MinutesToTimeString(unprodActs)), alignment: Alignment.center,),width: (100-prodPercentage)* 1.7,height: 25,decoration: BoxDecoration(color: Colors.red,borderRadius: BorderRadius.horizontal(right: Radius.circular(10))),),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(width: 10,),
|
Row(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
child: Align(
|
||||||
|
child: FittedBox(fit: BoxFit.fitWidth,child: Text(MinutesToTimeString(prodActs),)),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
width: (prodPercentage) * 1.7,
|
||||||
|
height: 25,
|
||||||
|
decoration: BoxDecoration(color: Colors.green, borderRadius: BorderRadius.horizontal(left: Radius.circular(10))),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: Align(
|
||||||
|
child: Text(MinutesToTimeString(unprodActs)),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
width: (100 - prodPercentage) * 1.7,
|
||||||
|
height: 25,
|
||||||
|
decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.horizontal(right: Radius.circular(10))),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
Text(prodPercentage.toStringAsFixed(1) + "%", style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold, fontSize: 20))
|
Text(prodPercentage.toStringAsFixed(1) + "%", style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold, fontSize: 20))
|
||||||
],)
|
],
|
||||||
|
)
|
||||||
// CustomPaint(
|
// CustomPaint(
|
||||||
// painter: MyPlayerBar(100, prodPercentage.toInt(),
|
// painter: MyPlayerBar(100, prodPercentage.toInt(),
|
||||||
// background: Colors.green, fill: Colors.deepOrange),
|
// background: Colors.green, fill: Colors.deepOrange),
|
||||||
@@ -195,20 +297,14 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool selecting = false;
|
bool selecting = false;
|
||||||
Widget ActivityCard(BuildContext context, String name, DateTime sTime,
|
Widget ActivityCard(BuildContext context, String name, DateTime sTime, DateTime eTime, bool productive, Color color, Activity activity, int totalMinutes) {
|
||||||
DateTime eTime, bool productive, Color color, Activity activity,int totalMinutes) {
|
|
||||||
DateFormat dateFormat = DateFormat("HH:mm");
|
DateFormat dateFormat = DateFormat("HH:mm");
|
||||||
int thisMinutes = (activity.endTime.difference(activity.startTime).inMinutes);
|
int thisMinutes = (activity.endTime.difference(activity.startTime).inMinutes);
|
||||||
int timePercentage = ((thisMinutes / totalMinutes) * 100).toInt();
|
int timePercentage = ((thisMinutes / totalMinutes) * 100).toInt();
|
||||||
// print("$thisMinutes / $totalMinutes");
|
// print("$thisMinutes / $totalMinutes");
|
||||||
bool containsMetadata = ((activity.metadata ?? 'null') != 'null') &&
|
bool containsMetadata = ((activity.metadata ?? 'null') != 'null') && ((activity.metadata ?? '').isNotEmpty);
|
||||||
((activity.metadata ?? '').isNotEmpty);
|
|
||||||
var _timeSpan = eTime.difference(sTime);
|
var _timeSpan = eTime.difference(sTime);
|
||||||
String timeSpan =
|
String timeSpan = ((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') + ((_timeSpan.inMinutes % 60 > 0) ? (_timeSpan.inMinutes % 60).toString() + 'm' : '');
|
||||||
((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') +
|
|
||||||
((_timeSpan.inMinutes % 60 > 0)
|
|
||||||
? (_timeSpan.inMinutes % 60).toString() + 'm'
|
|
||||||
: '');
|
|
||||||
return Row(children: [
|
return Row(children: [
|
||||||
// Container(),
|
// Container(),
|
||||||
(selecting)
|
(selecting)
|
||||||
@@ -219,10 +315,12 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
OnItemSelected(activity);
|
OnItemSelected(activity);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
})
|
})
|
||||||
: Container(),
|
: Container(padding: EdgeInsets.fromLTRB(10, 0, 5, 0), child: SizedBox(width: 1, height: 100, child: Container(color: Colors.white))),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Card(
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 0, 5, 0),
|
||||||
|
child: Card(
|
||||||
|
|
||||||
// color: color,
|
// color: color,
|
||||||
elevation: 20,
|
elevation: 20,
|
||||||
@@ -245,17 +343,19 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
padding: EdgeInsets.all(15),
|
padding: EdgeInsets.all(15),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(children: [
|
Row(children: [
|
||||||
Text(name + " [$timeSpan]",
|
Text(name + " [$timeSpan]", style: TextStyle(fontSize: 17)),
|
||||||
style: TextStyle( fontSize: 17)),
|
|
||||||
if (containsMetadata)
|
if (containsMetadata)
|
||||||
Icon(Icons.arrow_forward_outlined, size: 20,),
|
Icon(
|
||||||
|
Icons.arrow_forward_outlined,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
if (containsMetadata)
|
if (containsMetadata)
|
||||||
Text(activity.metadata ?? '',overflow: TextOverflow.clip,)
|
Text(
|
||||||
|
activity.metadata ?? '',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
)
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Icon(Icons.analytics, color: color, size: 20,),
|
// Icon(Icons.analytics, color: color, size: 20,),
|
||||||
@@ -263,26 +363,15 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 5,
|
height: 5,
|
||||||
),
|
),
|
||||||
Row(
|
Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
mainAxisSize: MainAxisSize.max,
|
Text(dateFormat.format(sTime) + " - " + dateFormat.format(eTime)),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(dateFormat.format(sTime) +
|
|
||||||
" - " +
|
|
||||||
dateFormat.format(eTime)),
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 20,
|
width: 20,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
|
||||||
horizontal: 10, vertical: 2),
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: (productive) ? Colors.green : Colors.red),
|
||||||
decoration: BoxDecoration(
|
child: Text(activity.taskType.cat?.name ?? 'n/a'))
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
color: (productive)
|
|
||||||
? Colors.green
|
|
||||||
: Colors.red),
|
|
||||||
child: Text(
|
|
||||||
activity.taskType.cat?.name ?? 'n/a'))
|
|
||||||
// Icon(Icons.circle,
|
// Icon(Icons.circle,
|
||||||
// color: (productive)
|
// color: (productive)
|
||||||
// ? Colors.green
|
// ? Colors.green
|
||||||
@@ -290,13 +379,13 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
])
|
])
|
||||||
],
|
],
|
||||||
)))),
|
)))),
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.fromLTRB(15, 0, 15, 10),
|
margin: EdgeInsets.fromLTRB(15, 0, 15, 10),
|
||||||
height: 2,
|
height: 2,
|
||||||
child:Row(children: [
|
child: Row(
|
||||||
Expanded(flex:timePercentage ,child: Container(color:color)),
|
children: [Expanded(flex: timePercentage, child: Container(color: color)), Expanded(flex: 100 - timePercentage, child: Container())],
|
||||||
Expanded(flex:100-timePercentage,child:Container())
|
)),
|
||||||
],)),
|
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
@@ -311,8 +400,7 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeleteSelectedTasks() async {
|
void DeleteSelectedTasks() async {
|
||||||
progressDialog.show(
|
progressDialog.show(max: 100, msg: 'Deleteing ${selectedActivities.length} Activities');
|
||||||
max: 100, msg: 'Deleteing ${selectedActivities.length} Activities');
|
|
||||||
selectedActivities.forEach((element) async {
|
selectedActivities.forEach((element) async {
|
||||||
await User.UserOperations.deleteActivity(element, bulk: true);
|
await User.UserOperations.deleteActivity(element, bulk: true);
|
||||||
});
|
});
|
||||||
@@ -328,7 +416,4 @@ class _ActivitiesState extends State<Activities> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
List<Activity> selectedActivities = [];
|
List<Activity> selectedActivities = [];
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ class _CategoriesState extends State<Categories> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Card(
|
Card(
|
||||||
|
|
||||||
// color: color,
|
// color: color,
|
||||||
elevation:20,
|
elevation:20,
|
||||||
shadowColor: color,
|
shadowColor: color,
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
import 'theme_provider.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
class Category{
|
class Category{
|
||||||
|
|
||||||
Category(this.category_id, this.name, this.color, this.productive);
|
Category(this.category_id, this.name, this.color, this.productive);
|
||||||
@@ -80,8 +84,9 @@ class Queries{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Settings{
|
|
||||||
|
|
||||||
|
|
||||||
|
class Settings{
|
||||||
static Future<String> UUID() async{
|
static Future<String> UUID() async{
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
if(prefs.containsKey('uuid')){
|
if(prefs.containsKey('uuid')){
|
||||||
@@ -93,4 +98,11 @@ class Settings{
|
|||||||
return Future.value(_uuid);
|
return Future.value(_uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Future<void> setTheme(int value) async{
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setInt("theme", value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
final settings = Settings();
|
||||||
49
lib/Settings/AppearanceSettings.dart
Normal file
49
lib/Settings/AppearanceSettings.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tasktracker/Settings/Settings.dart';
|
||||||
|
import 'package:tasktracker/Data.dart';
|
||||||
|
import 'package:tasktracker/theme_provider.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
class AppearanceSettings extends StatefulWidget {
|
||||||
|
const AppearanceSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_AppearanceSettingsState createState() => _AppearanceSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppearanceSettingsState extends State<AppearanceSettings> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final themeProvider= Provider.of<ThemeProvider>(context);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text('Appearance Settings')),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 10,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text("Dark Mode",style: TextStyle(fontSize: 18)),
|
||||||
|
Switch.adaptive(value: themeProvider.isDarkMode, onChanged: (value){
|
||||||
|
final provider = Provider.of<ThemeProvider>(context, listen: false);
|
||||||
|
provider.toggleTheme(value);
|
||||||
|
Settings.setTheme(value ? 0:1);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
lib/Settings/NotificationSettings.dart
Normal file
37
lib/Settings/NotificationSettings.dart
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class NotificationSettings extends StatefulWidget {
|
||||||
|
const NotificationSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_NotificationSettingsState createState() => _NotificationSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NotificationSettingsState extends State<NotificationSettings> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text("Notification Settings")),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text("New Activity Notification"),
|
||||||
|
trailing: InkWell(onTap:(){},child: Text("1 hour")),
|
||||||
|
subtitle: Text("Notify you to track activities of past time"),
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
ListTile(
|
||||||
|
title: Text("Suggestion Notifications"), trailing:Switch.adaptive(value: true, onChanged: (val){}),
|
||||||
|
subtitle: Text("Notifies you about suggestions according to your data"),
|
||||||
|
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
lib/Settings/Settings.dart
Normal file
48
lib/Settings/Settings.dart
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tasktracker/Settings/AppearanceSettings.dart';
|
||||||
|
import 'package:tasktracker/Settings/NotificationSettings.dart';
|
||||||
|
import 'package:tasktracker/main.dart';
|
||||||
|
|
||||||
|
class SettingsPage extends StatefulWidget {
|
||||||
|
const SettingsPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SettingsPageState createState() => _SettingsPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SettingsPageState extends State<SettingsPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text('Settings')),
|
||||||
|
body: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
SettingItem('Appearance', ()=>Navigator.of(context).push(MaterialPageRoute(builder: (context)=> const AppearanceSettings()))),
|
||||||
|
Divider(),
|
||||||
|
SettingItem('Notifications', ()=>Navigator.of(context).push(MaterialPageRoute(builder: (context)=> const NotificationSettings()))),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Widget SettingItem(String name, Function onTap){
|
||||||
|
return InkWell(
|
||||||
|
onTap: ()=>onTap(),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(15.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Text(name, style: TextStyle(fontSize: 18)),
|
||||||
|
Icon(Icons.arrow_forward,size: 20,)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ List<TaskType> taskTypes = [];
|
|||||||
List<Activity> activities=[];
|
List<Activity> activities=[];
|
||||||
bool offline = true;
|
bool offline = true;
|
||||||
bool registered = false;
|
bool registered = false;
|
||||||
|
bool refreshing = true;
|
||||||
Future<http.Response> login(String _username, String password) async {
|
Future<http.Response> login(String _username, String password) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ Future<void> initUserData() async {
|
|||||||
bool userDataInitiated =false;
|
bool userDataInitiated =false;
|
||||||
Future<void> refreshUserData() async{
|
Future<void> refreshUserData() async{
|
||||||
ShowProgress("Loading data");
|
ShowProgress("Loading data");
|
||||||
|
refreshing = true;
|
||||||
// categories= await GetCategories(true);
|
// categories= await GetCategories(true);
|
||||||
// taskTypes= await GetTaskTypes(true);
|
// taskTypes= await GetTaskTypes(true);
|
||||||
// activities= await GetActivities(true);
|
// activities= await GetActivities(true);
|
||||||
@@ -71,6 +73,7 @@ Future<void> refreshUserData() async{
|
|||||||
await updateTasksList();
|
await updateTasksList();
|
||||||
await updateActList();
|
await updateActList();
|
||||||
userDataInitiated=true;
|
userDataInitiated=true;
|
||||||
|
refreshing = false;
|
||||||
HideProgress();
|
HideProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tasktracker/Categories.dart';
|
import 'package:tasktracker/Categories.dart';
|
||||||
import 'package:tasktracker/Welcome.dart';
|
import 'package:tasktracker/Welcome.dart';
|
||||||
import 'package:tasktracker/splash.dart';
|
import 'package:tasktracker/splash.dart';
|
||||||
|
import 'package:tasktracker/theme_provider.dart';
|
||||||
|
import 'Settings/Settings.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
import 'Data.dart';
|
import 'Data.dart';
|
||||||
import 'NewTask.dart';
|
import 'NewTask.dart';
|
||||||
@@ -69,10 +72,16 @@ class MyApp extends StatelessWidget {
|
|||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({Key? key}) : super(key: key);
|
||||||
// This widget is the root of your application.
|
// This widget is the root of your application.
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => ChangeNotifierProvider(
|
||||||
|
create: (context)=>ThemeProvider(),
|
||||||
|
builder: (context, _){
|
||||||
|
final themeProvider = Provider.of<ThemeProvider>(context);
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Flutter Demo',
|
title: 'Task Tracker',
|
||||||
theme: ThemeData(accentColor: Colors.redAccent, brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'),
|
themeMode: themeProvider.themeMode,
|
||||||
|
theme: ThemeData(accentColor: Colors.redAccent,brightness: Brightness.light, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'),
|
||||||
|
darkTheme: ThemeData(accentColor: Colors.redAccent,brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'),
|
||||||
//home: const MyHomePage(),
|
//home: const MyHomePage(),
|
||||||
initialRoute: '/splash',
|
initialRoute: '/splash',
|
||||||
routes: {
|
routes: {
|
||||||
@@ -81,9 +90,10 @@ class MyApp extends StatelessWidget {
|
|||||||
'/': (context) => const MyHomePage(),
|
'/': (context) => const MyHomePage(),
|
||||||
'/Tasks': (context) => const Tasks(),
|
'/Tasks': (context) => const Tasks(),
|
||||||
'/Categories': (context) => const Categories(),
|
'/Categories': (context) => const Categories(),
|
||||||
'/Activities': (context) => const Activities()
|
'/Activities': (context) => const Activities(),
|
||||||
|
'/Settings':(context) => const SettingsPage()
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> days = [];
|
List<String> days = [];
|
||||||
@@ -129,7 +139,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
super.initState();
|
super.initState();
|
||||||
User.refreshUserData().then((val) => LoadStats());
|
// User.refreshUserData().then((val) => LoadStats());
|
||||||
// showOfflineSnack();
|
// showOfflineSnack();
|
||||||
LoadStats();
|
LoadStats();
|
||||||
// progressDialog = ProgressDialog(context: context);
|
// progressDialog = ProgressDialog(context: context);
|
||||||
@@ -153,17 +163,18 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
firstDay = null;
|
firstDay = null;
|
||||||
lastDay = null;
|
lastDay = null;
|
||||||
String lastDate = "";
|
String lastDate = "";
|
||||||
|
days=[];
|
||||||
for (var element in User.activities) {
|
for (var element in User.activities) {
|
||||||
if (lastDay == null) {
|
if (lastDay == null) {
|
||||||
lastDay = element.endTime;
|
lastDay = element.endTime;
|
||||||
}
|
}
|
||||||
if (taskTypeRange == null) {
|
if (taskTypeRange == null) {
|
||||||
print("$lastDay - $firstDay");
|
print("$lastDay - $firstDay");
|
||||||
taskTypeRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 1)), end: lastDay!);
|
taskTypeRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 0)), end: lastDay!);
|
||||||
}
|
}
|
||||||
if (catsRange == null) {
|
if (catsRange == null) {
|
||||||
print("$lastDay - $firstDay");
|
print("$lastDay - $firstDay");
|
||||||
catsRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 1)), end: lastDay!);
|
catsRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 0)), end: lastDay!);
|
||||||
}
|
}
|
||||||
firstDay = element.startTime;
|
firstDay = element.startTime;
|
||||||
String thisDate = dFormat.format(element.startTime);
|
String thisDate = dFormat.format(element.startTime);
|
||||||
@@ -237,7 +248,9 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
Color barCol = HexColor.fromHex(key.color);
|
Color barCol = HexColor.fromHex(key.color);
|
||||||
dailyData.add(CatMapData(key.name, value, barCol));
|
dailyData.add(CatMapData(key.name, value, barCol));
|
||||||
});
|
});
|
||||||
|
dailyData.sort((a,b){
|
||||||
|
return a.name.toLowerCase().compareTo(b.name.toLowerCase());
|
||||||
|
});
|
||||||
for (var element in days) {
|
for (var element in days) {
|
||||||
// if(productivtyActs.containsKey(element) && unproductivtyActs.containsKey(element)){
|
// if(productivtyActs.containsKey(element) && unproductivtyActs.containsKey(element)){
|
||||||
int prodActs = (productivtyActs[element] ?? 0);
|
int prodActs = (productivtyActs[element] ?? 0);
|
||||||
@@ -252,11 +265,16 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
taskTypesData.add(TaskTypeMapData(key.name, value, HexColor.fromHex(key.cat!.color)));
|
taskTypesData.add(TaskTypeMapData(key.name, value, HexColor.fromHex(key.cat!.color)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
taskTypesData.sort((a,b){
|
||||||
|
return a.time.compareTo(b.time);
|
||||||
|
});
|
||||||
|
|
||||||
catBriefMap.forEach((key, value) {
|
catBriefMap.forEach((key, value) {
|
||||||
print(key.name + " : $value");
|
print(key.name + " : $value");
|
||||||
Color barCol = HexColor.fromHex(key.color);
|
Color barCol = HexColor.fromHex(key.color);
|
||||||
catsData.add(CatMapData(key.name, value, barCol));
|
catsData.add(CatMapData(key.name, value, barCol));
|
||||||
});
|
});
|
||||||
|
catsData.sort((a,b)=> a.time.compareTo(b.time));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,7 +299,23 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
},
|
},
|
||||||
label: Text("New Activity"),
|
label: Text("New Activity"),
|
||||||
icon: Icon(Icons.add)),
|
icon: Icon(Icons.add)),
|
||||||
appBar: AppBar(title: Row(children: [Icon(Icons.article_outlined, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Summary')])),
|
appBar: AppBar(title: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(children: [Icon(Icons.article_outlined, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Summary')]),
|
||||||
|
Row(children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
LoadStats();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(Icons.refresh, size: 30),
|
||||||
|
)
|
||||||
|
],)
|
||||||
|
],
|
||||||
|
)),
|
||||||
drawer: navDrawer(context, 0),
|
drawer: navDrawer(context, 0),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@@ -362,6 +396,12 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
dataSource: productivityData.reversed.toList(),
|
dataSource: productivityData.reversed.toList(),
|
||||||
xValueMapper: (ProductivityMapData sales, _) => sales.day,
|
xValueMapper: (ProductivityMapData sales, _) => sales.day,
|
||||||
yValueMapper: (ProductivityMapData sales, _) => sales.productivity,
|
yValueMapper: (ProductivityMapData sales, _) => sales.productivity,
|
||||||
|
dataLabelMapper: (ProductivityMapData sales, _) => sales.productivity.toStringAsFixed(1) + "%",
|
||||||
|
dataLabelSettings: DataLabelSettings(
|
||||||
|
overflowMode: OverflowMode.hide,
|
||||||
|
showZeroValue: false,
|
||||||
|
isVisible: true
|
||||||
|
),
|
||||||
color: Colors.green)
|
color: Colors.green)
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
@@ -616,7 +656,12 @@ Drawer navDrawer(BuildContext context, int pageIndex) {
|
|||||||
selected: (pageIndex == 5),
|
selected: (pageIndex == 5),
|
||||||
title: Text('Settings'),
|
title: Text('Settings'),
|
||||||
leading: Icon(Icons.settings, color: Colors.blueGrey),
|
leading: Icon(Icons.settings, color: Colors.blueGrey),
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
if (pageIndex == 5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Navigator.of(context).pushNamed('/Settings');
|
||||||
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
selected: (pageIndex == 6),
|
selected: (pageIndex == 6),
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:tasktracker/Data.dart';
|
||||||
import 'User.dart' as Users;
|
import 'User.dart' as Users;
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:sn_progress_dialog/sn_progress_dialog.dart';
|
import 'package:sn_progress_dialog/sn_progress_dialog.dart';
|
||||||
|
import 'theme_provider.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
late ProgressDialog progressDialog;
|
late ProgressDialog progressDialog;
|
||||||
class SplashScreen extends StatefulWidget {
|
class SplashScreen extends StatefulWidget {
|
||||||
const SplashScreen({Key? key}) : super(key: key);
|
const SplashScreen({Key? key}) : super(key: key);
|
||||||
@@ -13,6 +15,18 @@ class SplashScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SplashScreenState extends State<SplashScreen> {
|
class _SplashScreenState extends State<SplashScreen> {
|
||||||
|
Future<void> initSettings() async{
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
bool value = true;
|
||||||
|
if(prefs.containsKey("theme")){
|
||||||
|
value = ((await prefs.getInt("theme"))==0);
|
||||||
|
}else{
|
||||||
|
await prefs.setInt("theme", 0);
|
||||||
|
}
|
||||||
|
print('Dark theme is : $value');
|
||||||
|
final provider = Provider.of<ThemeProvider>(context, listen: false);
|
||||||
|
provider.toggleTheme(value);
|
||||||
|
}
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
@@ -23,6 +37,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init() async {
|
void init() async {
|
||||||
|
await initSettings();
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
// http.Response loginResponse = await Users.login('Test1', 'password');
|
// http.Response loginResponse = await Users.login('Test1', 'password');
|
||||||
// print(loginResponse.body);
|
// print(loginResponse.body);
|
||||||
|
|||||||
12
lib/theme_provider.dart
Normal file
12
lib/theme_provider.dart
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ThemeProvider extends ChangeNotifier{
|
||||||
|
ThemeMode themeMode = ThemeMode.dark;
|
||||||
|
|
||||||
|
bool get isDarkMode => themeMode == ThemeMode.dark;
|
||||||
|
|
||||||
|
void toggleTheme(bool isOn){
|
||||||
|
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
pubspec.lock
16
pubspec.lock
@@ -212,6 +212,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.7.0"
|
||||||
|
nested:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: nested
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -289,6 +296,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.4"
|
version: "4.2.4"
|
||||||
|
provider:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: provider
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.2"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -405,7 +419,7 @@ packages:
|
|||||||
name: syncfusion_flutter_charts
|
name: syncfusion_flutter_charts
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "19.4.53"
|
version: "19.4.54"
|
||||||
syncfusion_flutter_core:
|
syncfusion_flutter_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
provider: ^6.0.2
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
uuid: ^3.0.5
|
uuid: ^3.0.5
|
||||||
wakelock: ^0.6.1+1
|
wakelock: ^0.6.1+1
|
||||||
|
|||||||
Reference in New Issue
Block a user