Journal section added
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:sticky_headers/sticky_headers/widget.dart';
|
||||
import 'main.dart' as Main;
|
||||
import 'newActivity.dart';
|
||||
import 'Data.dart';
|
||||
import 'User.dart' as User;
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
class Activities extends StatefulWidget {
|
||||
const Activities({Key? key}) : super(key: key);
|
||||
|
||||
@@ -66,7 +68,7 @@ class _ActivitiesState extends State<Activities> {
|
||||
// progressDialog.update(value: 100);
|
||||
} catch (e) {}
|
||||
}
|
||||
Map<Widget, List<Widget>> activitiesGroups =<Widget, List<Widget>>{};
|
||||
Map<String, ActivityListDateGroup> activitiesGroups = <String, ActivityListDateGroup>{};
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// progressDialog = ProgressDialog(context: context);
|
||||
@@ -172,14 +174,15 @@ class _ActivitiesState extends State<Activities> {
|
||||
drawer: Main.navDrawer(context, 2),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(0),
|
||||
child: ListView.builder(
|
||||
child: ScrollablePositionedList.builder(
|
||||
itemScrollController: scrollController,
|
||||
itemCount: activitiesGroups.length,
|
||||
itemBuilder: (context, index){
|
||||
// return activities[index];
|
||||
return StickyHeader(
|
||||
|
||||
header:activitiesGroups.keys.toList()[index],
|
||||
content:Column(children: activitiesGroups.values.toList()[index],)
|
||||
header:activitiesGroups.values.toList()[index].dateSeperator,
|
||||
content:Column(children: activitiesGroups.values.toList()[index].activities,)
|
||||
);
|
||||
|
||||
})
|
||||
@@ -189,13 +192,17 @@ class _ActivitiesState extends State<Activities> {
|
||||
// ))
|
||||
));
|
||||
}
|
||||
|
||||
DateFormat dFormat = DateFormat("yyyy-MM-dd");
|
||||
ItemScrollController scrollController = ItemScrollController();
|
||||
ScrollController controller = ScrollController();
|
||||
int searchTime = 0;
|
||||
Map<Widget,List<Widget>> PrintTasks() {
|
||||
Map<Widget,List<Widget>> _tasks = <Widget,List<Widget>>{};
|
||||
Map<String,ActivityListDateGroup> PrintTasks() {
|
||||
|
||||
Map<String,ActivityListDateGroup> _tasks = <String,ActivityListDateGroup>{};
|
||||
|
||||
print('Priting cats : ' + User.taskTypes.length.toString());
|
||||
String lastDate = "";
|
||||
DateFormat dFormat = DateFormat("MM/dd");
|
||||
|
||||
Map<String, int> productivtyActs = <String, int>{};
|
||||
Map<String, int> unproductivtyActs = <String, int>{};
|
||||
Map<String, int> totalMinutes = <String, int>{};
|
||||
@@ -248,7 +255,8 @@ class _ActivitiesState extends State<Activities> {
|
||||
int prodActs = productivtyActs[thisDate] ?? 0;
|
||||
int unProdActs = unproductivtyActs[thisDate] ?? 0;
|
||||
//_tasks.add(DateSeperator(thisDate, prodActs, unProdActs));
|
||||
_tasks.putIfAbsent(DateSeperator(thisDate, prodActs, unProdActs), () => [Container()]);
|
||||
// _tasks.putIfAbsent(DateSeperator(thisDate, prodActs, unProdActs), () => [List.generate(0, (i) => List(2));]);
|
||||
_tasks.putIfAbsent(thisDate, () => ActivityListDateGroup(DateSeperator(thisDate, prodActs, unProdActs), []));
|
||||
print('adding');
|
||||
lastDate = thisDate;
|
||||
}
|
||||
@@ -260,7 +268,8 @@ class _ActivitiesState extends State<Activities> {
|
||||
bool productive = element.taskType.cat?.productive ?? true;
|
||||
Widget task = ActivityCard(context, name, element.startTime, element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0);
|
||||
// print('Activity : ${name} ,sTime: ${element.startTime}, eTime: ${element.endTime}');
|
||||
_tasks.values.toList()[_tasks.length-1].add(task);
|
||||
// _tasks.values.toList()[_tasks.length-1].add(task);
|
||||
_tasks[thisDate]!.activities.add(task);
|
||||
}
|
||||
//Check for gaps
|
||||
if(i < User.activities.length-1){
|
||||
@@ -268,7 +277,8 @@ class _ActivitiesState extends State<Activities> {
|
||||
if(gap > 10) {
|
||||
Widget addGap = timeGap(User.activities[i].trueStartTime, User.activities[i+1].trueEndTime);
|
||||
|
||||
_tasks.values.toList()[_tasks.length-1].add(addGap);
|
||||
//_tasks.values.toList()[_tasks.length-1].add(addGap);
|
||||
_tasks[thisDate]!.activities.add(addGap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,7 +330,22 @@ class _ActivitiesState extends State<Activities> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget DateSeperator(date, prodActs, unprodActs) {
|
||||
void OnJumpToDate(date){
|
||||
int itemId = 0;
|
||||
List<String> keys = activitiesGroups.keys.toList();
|
||||
List<ActivityListDateGroup> values = activitiesGroups.values.toList();
|
||||
for(int i =0; i < activitiesGroups.length; i++){
|
||||
|
||||
if(keys[i] == dFormat.format(date)){
|
||||
break;
|
||||
}
|
||||
itemId++;
|
||||
// itemId+= values[i].activities.length;
|
||||
}
|
||||
scrollController.scrollTo(index: itemId, duration: Duration(seconds: 1),curve: Curves.fastOutSlowIn);
|
||||
}
|
||||
|
||||
Widget DateSeperator(date, prodActs, unprodActs,{Function? onTap}) {
|
||||
// double prodPercentage = (prodActs / (prodActs + unprodActs)) * 100;
|
||||
|
||||
return FutureBuilder(
|
||||
@@ -337,7 +362,17 @@ class _ActivitiesState extends State<Activities> {
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
InkWell(
|
||||
onTap: (){
|
||||
DatePicker.showDatePicker(context,
|
||||
showTitleActions: true,
|
||||
minTime: User.activities[User.activities.length-1].startTime,
|
||||
maxTime: User.activities[0].startTime,
|
||||
theme: DatePickerTheme(), onChanged: (date) {
|
||||
// print('change $date');
|
||||
}, onConfirm: OnJumpToDate, currentTime: DateTime.parse(date), locale: LocaleType.en);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(width: 15,),
|
||||
Icon(Icons.circle),
|
||||
@@ -350,6 +385,7 @@ class _ActivitiesState extends State<Activities> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Row(
|
||||
@@ -550,5 +586,11 @@ class _ActivitiesState extends State<Activities> {
|
||||
}
|
||||
}
|
||||
|
||||
class ActivityListDateGroup{
|
||||
ActivityListDateGroup(this.dateSeperator, this.activities);
|
||||
Widget dateSeperator;
|
||||
List<Widget> activities;
|
||||
}
|
||||
|
||||
|
||||
List<Activity> selectedActivities = [];
|
||||
|
||||
@@ -142,6 +142,19 @@ class ProjectStep{
|
||||
DateTime? finishedDate;
|
||||
}
|
||||
|
||||
class Journal{
|
||||
|
||||
Journal(this.id, this.day, {this.title, this.description});
|
||||
|
||||
String id;
|
||||
DateTime day;
|
||||
String? title;
|
||||
String? description;
|
||||
|
||||
static String colTitle = 'Title';
|
||||
static String colDescription = 'Desc';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
165
lib/Journal.dart
Normal file
165
lib/Journal.dart
Normal file
@@ -0,0 +1,165 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import 'package:tasktracker/NewJournal.dart';
|
||||
import 'package:tasktracker/main.dart';
|
||||
import 'User.dart' as User;
|
||||
import 'Dialogs.dart';
|
||||
|
||||
class JournalPage extends StatefulWidget {
|
||||
const JournalPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<JournalPage> createState() => _JournalPageState();
|
||||
}
|
||||
|
||||
class _JournalPageState extends State<JournalPage> {
|
||||
|
||||
bool selecting = false;
|
||||
List<int> selectedIndexes = [];
|
||||
var refreshStream;
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
refreshStream = User.refreshStream.stream.listen((event) {if(!event){setState(() {
|
||||
|
||||
});}});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
refreshStream?.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewJournal())).then((val) {
|
||||
setState(() {});
|
||||
});
|
||||
},
|
||||
label: Text("New Entry"),
|
||||
icon: Icon(Icons.add)),
|
||||
appBar: AppBar(
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
FaIcon(FontAwesomeIcons.bookJournalWhills),
|
||||
SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Text('Journal')
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
if(selecting && selectedIndexes.length > 0)InkWell(onTap:() async{
|
||||
selecting=false;
|
||||
for (int element in selectedIndexes) {
|
||||
await User.UserOperations.deleteJournal(User.journal[element].id);
|
||||
}setState(() {
|
||||
|
||||
});
|
||||
},child: Container(margin:EdgeInsets.all(8),child: Icon(Icons.delete))),
|
||||
if(selecting)InkWell(onTap:(){
|
||||
selecting=false;
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},child: Container(margin:EdgeInsets.all(8),child: Icon(Icons.cancel))),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
drawer: navDrawer(context, 8),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: ScrollablePositionedList.builder(
|
||||
itemCount: User.journal.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
|
||||
//duration: Duration(milliseconds: 500),
|
||||
child: InkWell(
|
||||
onTap: (){
|
||||
if(selecting){
|
||||
if(selectedIndexes.contains(index)){
|
||||
selectedIndexes.remove(index);
|
||||
}else{
|
||||
selectedIndexes.add(index);
|
||||
}
|
||||
setState(() {
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
selecting = !selecting;
|
||||
if(!selectedIndexes.contains(index)){selectedIndexes.add(index);}
|
||||
setState(() {});
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
if (selecting)
|
||||
Checkbox(
|
||||
value: selectedIndexes.contains(index),
|
||||
onChanged: (newVal) {
|
||||
if(selectedIndexes.contains(index)){
|
||||
selectedIndexes.remove(index);
|
||||
}else{
|
||||
selectedIndexes.add(index);
|
||||
}
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(User.journal[index].title ?? '', style: TextStyle(fontSize: 18)),
|
||||
Text(DateFormat('yyyy-MM-dd').format(User.journal[index].day))
|
||||
],
|
||||
),
|
||||
if (User.journal[index].description != null && User.journal[index].description!.isNotEmpty)
|
||||
Text(User.journal[index].description!)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if(selecting)InkWell(onTap:(){
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewJournal(date: User.journal[index].day, title: User.journal[index].title, text: User.journal[index].description,))).then((val) {
|
||||
setState(() {});
|
||||
});
|
||||
selecting=false;
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},child: Container(margin:EdgeInsets.all(8),child: FaIcon(FontAwesomeIcons.edit)))
|
||||
],
|
||||
),
|
||||
));
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
189
lib/NewJournal.dart
Normal file
189
lib/NewJournal.dart
Normal file
@@ -0,0 +1,189 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
||||
import 'User.dart' as User;
|
||||
import 'Data.dart';
|
||||
|
||||
class NewJournal extends StatefulWidget {
|
||||
NewJournal({Key? key, this.title, this.text, this.date}) : super(key: key);
|
||||
late String? title;
|
||||
late String? text;
|
||||
late DateTime? date;
|
||||
|
||||
@override
|
||||
_NewJournalState createState() => _NewJournalState(title: title, text: text, m_date: date);
|
||||
}
|
||||
|
||||
class _NewJournalState extends State<NewJournal> {
|
||||
bool editing =false;
|
||||
_NewJournalState({String? title, String? text, DateTime? m_date}){
|
||||
if(m_date!= null){
|
||||
editing = true;
|
||||
date=m_date;
|
||||
oldDate =m_date;
|
||||
}
|
||||
|
||||
titleController.text = title??'';
|
||||
descriptionEditingController.text = text??'';
|
||||
}
|
||||
|
||||
TextEditingController titleController = TextEditingController();
|
||||
TextEditingController descriptionEditingController = TextEditingController();
|
||||
bool productive = true;
|
||||
Color pickerColor = Colors.blue;
|
||||
DateTime date= DateTime.now();
|
||||
DateTime oldDate = DateTime.now();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('${(editing) ? 'Edit' : 'New'} Journal Entry')),
|
||||
body: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Expanded(flex: 9,
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(20, 50, 20, 50),
|
||||
child: Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: (){
|
||||
DatePicker.showDatePicker(context,
|
||||
showTitleActions: true,
|
||||
minTime: User.activities[User.activities.length-1].startTime,
|
||||
maxTime: User.activities[0].startTime,
|
||||
theme: DatePickerTheme(), onChanged: (date) {
|
||||
// print('change $date');
|
||||
}, onConfirm: (newDate){
|
||||
date = newDate;
|
||||
}, currentTime: DateTime.now(), locale: LocaleType.en);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FaIcon(FontAwesomeIcons.calendarDay),
|
||||
SizedBox(width: 10,),
|
||||
Text('Date : '),
|
||||
SizedBox(width: 30,),
|
||||
Text(
|
||||
DateFormat('yyyy-MM-dd').format(date),
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
SizedBox(width: 30,),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10,),
|
||||
Column(children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: TextField(
|
||||
controller: titleController,
|
||||
decoration: InputDecoration(hintText: 'Title (something special happened this day)', border: OutlineInputBorder()),
|
||||
),
|
||||
),
|
||||
Divider(),
|
||||
Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: TextField(
|
||||
|
||||
maxLines: 25,
|
||||
minLines: 10,
|
||||
controller: descriptionEditingController,
|
||||
decoration: InputDecoration(hintText: 'So how was your day? Write it all down here!', border: OutlineInputBorder()),
|
||||
),
|
||||
),
|
||||
]),
|
||||
],
|
||||
))),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 0),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(primary: Colors.red, shape: StadiumBorder()),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
Navigator.pop(context);
|
||||
});
|
||||
},
|
||||
child: Text('Back', style: TextStyle(fontSize: 20))))),
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 0),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(primary: Colors.green, shape: StadiumBorder()),
|
||||
onPressed: () {
|
||||
add_action();
|
||||
},
|
||||
child: Text('${editing ? 'Edit ' : 'Add '}Entry', style: TextStyle(fontSize: 20))))),
|
||||
],
|
||||
))
|
||||
])));
|
||||
}
|
||||
|
||||
void add_action() async {
|
||||
String title = titleController.value.text;
|
||||
String text = descriptionEditingController.text;
|
||||
|
||||
if (title.isEmpty && text.isEmpty) {
|
||||
showAlertDialog(context, 'Empty data', 'Journal entry is empty, Cannot add empty entries');
|
||||
return;
|
||||
}
|
||||
if(editing){
|
||||
await User.UserOperations.editJournal(oldDate,date,title,text);
|
||||
}else{
|
||||
await User.UserOperations.addJournal(date, title, text);
|
||||
}
|
||||
Navigator.of(context).popUntil((route) {
|
||||
return route.isFirst;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String _printDuration(Duration duration) {
|
||||
String twoDigits(int n) => n.toString().padLeft(2, "0");
|
||||
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
|
||||
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
|
||||
return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
|
||||
}
|
||||
|
||||
showAlertDialog(BuildContext context, String title, String message) {
|
||||
// set up the button
|
||||
Widget okButton = TextButton(
|
||||
child: Text("OK"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
|
||||
// set up the AlertDialog
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(message),
|
||||
actions: [
|
||||
okButton,
|
||||
],
|
||||
);
|
||||
|
||||
// show the dialog
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return alert;
|
||||
},
|
||||
);
|
||||
}
|
||||
220
lib/User.dart
220
lib/User.dart
@@ -28,6 +28,7 @@ List<Category> categories = [];
|
||||
List<TaskType> taskTypes = [];
|
||||
List<Activity> activities = [];
|
||||
List<Project> projects = [];
|
||||
List<Journal> journal = [];
|
||||
|
||||
bool offline = true;
|
||||
bool registered = false;
|
||||
@@ -136,14 +137,17 @@ Future<void> refreshUserData({bool forceOffline = false}) async {
|
||||
taskTypes = await GetTaskTypes(true);
|
||||
activities = await GetActivities(true);
|
||||
projects= await GetProjects(true);
|
||||
journal = await GetJournals(true);
|
||||
|
||||
refreshStream.add(false);
|
||||
}else{
|
||||
|
||||
await updateCatsList();
|
||||
await updateTasksList();
|
||||
await updateActList();
|
||||
await updateProjectsList();
|
||||
categories = await GetCategories(false);
|
||||
taskTypes = await GetTaskTypes(false);
|
||||
activities = await GetActivities(false);
|
||||
projects= await GetProjects(false);
|
||||
journal = await GetJournals(false);
|
||||
|
||||
}
|
||||
|
||||
m_refreshing=false;
|
||||
@@ -213,6 +217,8 @@ void onCacheDatabaseCreate(Database db, int newVersion) async {
|
||||
'CREATE TABLE Projects(id TEXT PRIMARY KEY, ${Project.colName} TEXT, ${Project.colCat} TEXT, ${Project.colSteps} TEXT, ${Project.colEta} INT, ${Project.colDeadline} DATETIME)';
|
||||
await db.execute(ProjectsTableSQL);
|
||||
|
||||
String JournalTableSQL = 'CREATE TABLE Journal(id TEXT PRIMARY KEY, ${Journal.colTitle} TEXT, ${Journal.colDescription})';
|
||||
await db.execute(JournalTableSQL);
|
||||
String QueriesTableSQL = 'CREATE TABLE Queries(id INTEGER PRIMARY KEY AUTOINCREMENT, ${Queries.colLink} TEXT,${Queries.colData} TEXT)';
|
||||
// print(QueriesTableSQL);
|
||||
await db.execute(QueriesTableSQL);
|
||||
@@ -750,6 +756,92 @@ Future<void> UpdateProjectsFromServer() async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Journal>> GetJournals(bool forceOffline) async {
|
||||
if (cacheEnabled) {
|
||||
List<Journal> _journals = [];
|
||||
if (offline || forceOffline) {
|
||||
//Retreive from cacheDB
|
||||
|
||||
} else {
|
||||
//Check if server got updated, If not go for cache
|
||||
|
||||
//Validate device_id to check updates
|
||||
|
||||
bool catsUpdated = false;
|
||||
// try {
|
||||
// http.Response update_response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/check_update.php'), body: <String, String>{"username": username, "device_id": android_id}));
|
||||
// final data = update_response.body.split(',');
|
||||
// catsUpdated = data[0] == '1';
|
||||
// } catch (e) {
|
||||
// print(e);
|
||||
// }
|
||||
|
||||
//Update CacheDB
|
||||
if (!catsUpdated) {
|
||||
await UpdateJournalsFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
List<Map> cats = await cacheDb.query('Journal');
|
||||
print(cats.length);
|
||||
for (Map element in cats) {
|
||||
String? id = element['id'].toString();
|
||||
String? title = element[Journal.colTitle].toString();
|
||||
String? text = element[Journal.colDescription].toString();
|
||||
if (id == null || title == null || text == null) {
|
||||
print("Something is null!");
|
||||
print("id:{$id}, title:{$title}, text:${text}");
|
||||
continue;
|
||||
}
|
||||
DateTime day = DateTime.parse(id.replaceAll(username, ''));
|
||||
// print("name:{$catName}, color:{$catColor}, prod:{$catProductive}");
|
||||
_journals.add(Journal(id,day,title: title,description: text));
|
||||
}
|
||||
journal = _journals;
|
||||
} else {
|
||||
print("NC: Updating Categories as $username");
|
||||
try {
|
||||
http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_journals.php'),
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
print(response.body);
|
||||
List<String> data = response.body.split("<td>");
|
||||
List<Journal> _categories = [];
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//print(catData);
|
||||
_categories.add(Journal(cat['id'],DateTime.parse(cat['id'].toString().replaceAll(username, '')), title:cat['title'], description:cat['text']));
|
||||
}
|
||||
journal = _categories;
|
||||
} catch (e) {
|
||||
print("Error while cats NC: $e");
|
||||
}
|
||||
}
|
||||
journal.sort((a,b)=> b.day.compareTo(a.day));
|
||||
return journal;
|
||||
}
|
||||
|
||||
Future<void> UpdateJournalsFromServer() async {
|
||||
print("Updating Journal as $username");
|
||||
try {
|
||||
http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_journals.php'),
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
print(response.body);
|
||||
List<String> data = response.body.split("<td>");
|
||||
await cacheDb.delete("Journal");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//print(catData);
|
||||
await cacheDb
|
||||
.rawInsert("INSERT OR REPLACE INTO Journal (id, ${Journal.colTitle},${Journal.colDescription}) "
|
||||
"VALUES ('${cat['id']}','${cat['title'].toString().replaceAll("'", "''")}','${cat['description'].toString().replaceAll("'", "''")}') ");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error while cats $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<TaskType?> getTaskFromId(String taskId) async {
|
||||
// await GetTaskTypes(false);
|
||||
TaskType? cat = null;
|
||||
@@ -1221,6 +1313,89 @@ class UserOperations {
|
||||
await executeQueries();
|
||||
}
|
||||
|
||||
static Future<void> addJournal(DateTime day, String title, String text) async {
|
||||
String id = username + DateFormat('yyyy-MM-dd').format(day);
|
||||
Map<String, String> queryBody = <String, String>{
|
||||
'username': username,
|
||||
'id': id,
|
||||
'title': title,
|
||||
'description': text
|
||||
};
|
||||
if (cacheEnabled) {
|
||||
//Add Query
|
||||
Map<String, Object> query = {Queries.colLink: 'add_journal', Queries.colData: jsonEncode(queryBody)};
|
||||
|
||||
print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}");
|
||||
|
||||
await cacheDb.insert('Queries', query);
|
||||
|
||||
//update Cache
|
||||
Map<String, Object> data = {
|
||||
'id':id,
|
||||
Journal.colTitle: title,
|
||||
Journal.colDescription:text
|
||||
};
|
||||
await cacheDb.insert('Journal', data);
|
||||
await refreshUserData(forceOffline: true);
|
||||
} else {
|
||||
try {
|
||||
http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_journal.php'), body: queryBody));
|
||||
print("Query executed : Results{${queryResponse.body}");
|
||||
if (queryResponse.body.toLowerCase().contains("success")) {
|
||||
//Success
|
||||
}
|
||||
} catch (e) {
|
||||
print('NC: Error adding journal entry $e}');
|
||||
}
|
||||
//executeQueries();
|
||||
}
|
||||
//Add to server and refresh Cache
|
||||
await executeQueries();
|
||||
|
||||
}
|
||||
static Future<void> editJournal(DateTime oldDay, DateTime day, String title, String text) async {
|
||||
String oldId = username + DateFormat('yyyy-MM-dd').format(oldDay);
|
||||
String id = username + DateFormat('yyyy-MM-dd').format(day);
|
||||
Map<String, String> queryBody = <String, String>{
|
||||
'username': username,
|
||||
'old_id':oldId,
|
||||
'id': id,
|
||||
'title': title,
|
||||
'description': text
|
||||
};
|
||||
if (cacheEnabled) {
|
||||
//Add Query
|
||||
Map<String, Object> query = {Queries.colLink: 'edit_journal', Queries.colData: jsonEncode(queryBody)};
|
||||
|
||||
print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}");
|
||||
|
||||
await cacheDb.insert('Queries', query);
|
||||
await cacheDb.rawUpdate("UPDATE Journal SET id='$id', ${Journal.colTitle}='${title.toString().replaceAll("'", "''")}', ${Journal.colDescription}='${text.toString().replaceAll("'", "''")}' WHERE id='$oldId'");
|
||||
//update Cache
|
||||
Map<String, Object> data = {
|
||||
'id':id,
|
||||
Journal.colTitle: title,
|
||||
Journal.colDescription:text
|
||||
};
|
||||
// await cacheDb.insert('Journal', data);
|
||||
await refreshUserData(forceOffline: true);
|
||||
} else {
|
||||
try {
|
||||
http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/edit_journal.php'), body: queryBody));
|
||||
print("Query executed : Results{${queryResponse.body}");
|
||||
if (queryResponse.body.toLowerCase().contains("success")) {
|
||||
//Success
|
||||
}
|
||||
} catch (e) {
|
||||
print('NC: Error adding journal entry $e}');
|
||||
}
|
||||
//executeQueries();
|
||||
}
|
||||
//Add to server and refresh Cache
|
||||
await executeQueries();
|
||||
|
||||
}
|
||||
|
||||
static Future<void> deleteTask(String name, {bulk = false}) async {
|
||||
Map<String, String> queryBody = <String, String>{
|
||||
'id': username + name,
|
||||
@@ -1372,6 +1547,43 @@ class UserOperations {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> deleteJournal(String id, {bulk = false}) async {
|
||||
Map<String, String> queryBody = <String, String>{
|
||||
'username': username,
|
||||
'id': id,
|
||||
};
|
||||
//Add Query
|
||||
Map<String, Object> query = {Queries.colLink: 'delete_journal', Queries.colData: jsonEncode(queryBody)};
|
||||
|
||||
print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}");
|
||||
|
||||
if (cacheEnabled) {
|
||||
await cacheDb.insert('Queries', query);
|
||||
|
||||
//update Cache
|
||||
String deleteQuery =
|
||||
"DELETE FROM Journal WHERE id='$id'";
|
||||
print("delteQuery : $deleteQuery");
|
||||
|
||||
await cacheDb.rawDelete(deleteQuery);
|
||||
await refreshUserData(forceOffline: true);
|
||||
//Add to server and refresh Cache
|
||||
} else {
|
||||
try {
|
||||
http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/delete_journal.php'), body: queryBody));
|
||||
print("Query executed : Results{${queryResponse.body}");
|
||||
if (queryResponse.body.toLowerCase().contains("success")) {
|
||||
//Success
|
||||
}
|
||||
} catch (e) {
|
||||
print('NC: Error deleting journal $e}');
|
||||
}
|
||||
}
|
||||
if (!bulk) {
|
||||
await executeQueries();
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> executeQueries() async {
|
||||
if (cacheEnabled) {
|
||||
if (offline) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tasktracker/Categories.dart';
|
||||
import 'package:tasktracker/Journal.dart';
|
||||
import 'package:tasktracker/Projects.dart';
|
||||
import 'package:tasktracker/Todo.dart';
|
||||
import 'package:tasktracker/Welcome.dart';
|
||||
@@ -111,7 +112,8 @@ class MyApp extends StatelessWidget {
|
||||
'/Categories': (context) => const Categories(),
|
||||
'/Activities': (context) => const Activities(),
|
||||
'/Settings': (context) => const SettingsPage(),
|
||||
'/Projects':(context)=> const Projects()
|
||||
'/Projects':(context)=> const Projects(),
|
||||
'/Journal': (context)=> const JournalPage()
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -283,7 +285,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
ongoingActName = "";
|
||||
}
|
||||
|
||||
if(mounted) {
|
||||
if(this.mounted) {
|
||||
setState(() {
|
||||
|
||||
});
|
||||
@@ -1003,7 +1005,7 @@ Drawer navDrawer(BuildContext context, int pageIndex) {
|
||||
ListTile(
|
||||
selected: (pageIndex == 7),
|
||||
title: Text('Projects'),
|
||||
leading: Icon(Icons.work_outline_sharp, color: Theme.of(context).primaryColor),
|
||||
leading: FaIcon(FontAwesomeIcons.rocket, color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 7) {
|
||||
return;
|
||||
@@ -1011,6 +1013,17 @@ Drawer navDrawer(BuildContext context, int pageIndex) {
|
||||
Navigator.of(context).pushReplacementNamed('/Projects');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
selected: (pageIndex == 8),
|
||||
title: Text('Journal'),
|
||||
leading: FaIcon(FontAwesomeIcons.bookJournalWhills, color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 8) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed('/Journal');
|
||||
},
|
||||
),
|
||||
// ListTile(
|
||||
// selected: (pageIndex == 7),
|
||||
// title: Text('TODO'),
|
||||
@@ -1046,37 +1059,6 @@ Drawer navDrawer(BuildContext context, int pageIndex) {
|
||||
));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
class CatMapData {
|
||||
CatMapData(this.name, this.time, this.color);
|
||||
final String name;
|
||||
|
||||
@@ -450,6 +450,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.27.3"
|
||||
scrollable_positioned_list:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: scrollable_positioned_list
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@@ -30,6 +30,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
scrollable_positioned_list: ^0.2.3
|
||||
sticky_headers: ^0.2.0
|
||||
flutter_switch: ^0.3.2
|
||||
sqflite_common_ffi: ^2.1.0+2
|
||||
|
||||
Reference in New Issue
Block a user