Project Steps completion
This commit is contained in:
@@ -127,17 +127,19 @@ class Project{
|
|||||||
class ProjectStep{
|
class ProjectStep{
|
||||||
ProjectStep(this.stepName,this.eta,this.progress);
|
ProjectStep(this.stepName,this.eta,this.progress);
|
||||||
|
|
||||||
ProjectStep.fromJson(Map<String,dynamic> json): stepName=json['name'], eta=json['eta'], progress=json['progress'];
|
ProjectStep.fromJson(Map<String,dynamic> json): stepName=json['name'], eta=json['eta'], progress=json['progress'], finishedDate=(json['finishedDate']!=null) ? DateTime.parse(json['finishedDate']) : null;
|
||||||
|
|
||||||
Map<String, dynamic> toJson()=>{
|
Map<String, dynamic> toJson()=>{
|
||||||
'name': stepName,
|
'name': stepName,
|
||||||
'eta':eta,
|
'eta':eta,
|
||||||
'progress':progress
|
'progress':progress,
|
||||||
|
if(finishedDate!=null) 'finishedDate':finishedDate.toString()
|
||||||
};
|
};
|
||||||
|
|
||||||
String stepName;
|
String stepName;
|
||||||
int eta;
|
int eta;
|
||||||
int progress;
|
int progress;
|
||||||
|
DateTime? finishedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
|
||||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@@ -186,6 +187,81 @@ class Dialogs{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static completeStepDialog(Project project,Function(DateTime) onComplete, ProjectStep step) async{
|
||||||
|
context=navigatorKey.currentContext;
|
||||||
|
DateTime finishedDate = DateTime.now();
|
||||||
|
DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
||||||
|
if(context!=null) {
|
||||||
|
// return StatefulBuilder(builder: (context, setState) {
|
||||||
|
return showDialog(
|
||||||
|
context: context!,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return StatefulBuilder(builder: (context, setState)
|
||||||
|
{
|
||||||
|
return AlertDialog(
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
|
||||||
|
backgroundColor: Color(0xFF1C1C1C),
|
||||||
|
title: Text('Completed ${step.stepName}?'),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('When did you complete?'),
|
||||||
|
SizedBox(height: 20,),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
DatePicker.showDatePicker(context,
|
||||||
|
showTitleActions: true,
|
||||||
|
theme: DatePickerTheme(), onChanged: (date) {
|
||||||
|
// print('change $date');
|
||||||
|
}, onConfirm: (date) {
|
||||||
|
setState(() {
|
||||||
|
finishedDate = date;
|
||||||
|
});
|
||||||
|
}, currentTime: finishedDate, locale: LocaleType.en);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black26,
|
||||||
|
borderRadius: BorderRadius.circular(15)
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 25, vertical: 10),
|
||||||
|
child: Text((dateFormat.format(finishedDate) ==dateFormat.format(DateTime.now())) ? 'Today' : dateFormat.format(finishedDate), style: TextStyle(color: Colors.blue),),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
MaterialButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text('No', style: TextStyle(color: Colors.red)),
|
||||||
|
),
|
||||||
|
MaterialButton(
|
||||||
|
color: Colors.green,
|
||||||
|
onPressed: () {
|
||||||
|
User.UserOperations.CompleteProjectStep(project, step, finishedDate);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text('Complete', style: TextStyle(color: Colors.white)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
print('context is null');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static hide(){
|
static hide(){
|
||||||
showing=false;
|
showing=false;
|
||||||
Navigator.of(navigatorKey.currentContext!).popUntil((route){
|
Navigator.of(navigatorKey.currentContext!).popUntil((route){
|
||||||
|
|||||||
@@ -1,230 +1,410 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||||
|
import 'package:tasktracker/NewProject.dart';
|
||||||
import 'package:tasktracker/Projects.dart';
|
import 'package:tasktracker/Projects.dart';
|
||||||
import 'User.dart' as User;
|
import 'User.dart' as User;
|
||||||
|
import 'Dialogs.dart';
|
||||||
|
|
||||||
import 'Data.dart';
|
import 'Data.dart';
|
||||||
|
import 'main.dart';
|
||||||
|
|
||||||
class ProjectDetails extends StatefulWidget {
|
class ProjectDetails extends StatefulWidget {
|
||||||
ProjectDetails({Key? key, required this.project}) : super(key: key);
|
ProjectDetails({Key? key, required this.project}) : super(key: key);
|
||||||
Project project;
|
Project project;
|
||||||
@override
|
@override
|
||||||
State<ProjectDetails> createState() => _ProjectDetailsState(project);
|
State<ProjectDetails> createState() => _ProjectDetailsState(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime justDate(DateTime dateTime){
|
DateTime justDate(DateTime dateTime) {
|
||||||
return DateTime(dateTime.year, dateTime.month, dateTime.day);
|
return DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ProjectDetailsState extends State<ProjectDetails> {
|
class _ProjectDetailsState extends State<ProjectDetails> {
|
||||||
|
|
||||||
_ProjectDetailsState(this.project);
|
_ProjectDetailsState(this.project);
|
||||||
Project project ;
|
Project project;
|
||||||
int etaHours = 0;
|
int etaHours = 0;
|
||||||
List<ProjectChartData> chartData = [];
|
int totalTimeSpent = 0;
|
||||||
|
List<ProjectChartData> timeSpentData = [];
|
||||||
|
List<ProjectChartData> timeProgressionData = [];
|
||||||
|
|
||||||
|
String chartOption = 'Time Spent';
|
||||||
|
DateTimeRange? chartRange;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
List<Widget> stepsWidgets = printSteps();
|
List<Widget> stepsWidgets = printSteps();
|
||||||
etaHours =0;
|
etaHours = (project.steps.length > 0) ? 0 : project.eta ?? 0;
|
||||||
|
totalTimeSpent = 0;
|
||||||
project.steps.forEach((element) {
|
project.steps.forEach((element) {
|
||||||
etaHours+=element.eta;
|
etaHours += element.eta;
|
||||||
});
|
});
|
||||||
int lastIndex = -1;
|
int lastIndex = -1;
|
||||||
int lastDay = -1;
|
int lastDay = -1;
|
||||||
User.activities.forEach((element) {
|
timeSpentData = [];
|
||||||
if(element.taskType.relatedProject == project){
|
timeProgressionData = [];
|
||||||
if(lastDay != element.startTime.day){
|
DateTime? firstDateTime = null;
|
||||||
chartData.add(ProjectChartData(justDate(element.startTime), element.endTime.difference(element.startTime).inMinutes));
|
DateTime? lastDateTime = null;
|
||||||
lastIndex++;
|
User.activities.reversed.forEach((element) {
|
||||||
lastDay = element.startTime.day;
|
|
||||||
}else{
|
bool withinRange =
|
||||||
chartData[lastIndex].timeSpent += element.endTime.difference(element.startTime).inMinutes;
|
(chartRange == null) || (chartRange != null && chartRange!.start.isBefore(element.startTime) && chartRange!.end.isAfter(element.endTime));
|
||||||
|
if (element.taskType.relatedProject != null && element.taskType.relatedProject!.name == project.name) {
|
||||||
|
print('here');
|
||||||
|
if (withinRange) {
|
||||||
|
if (firstDateTime == null) {
|
||||||
|
firstDateTime = element.startTime;
|
||||||
|
}
|
||||||
|
lastDateTime = element.startTime;
|
||||||
|
|
||||||
|
if (lastDay != element.startTime.day) {
|
||||||
|
if (totalTimeSpent > 0) {
|
||||||
|
timeProgressionData.add(ProjectChartData(justDate(element.startTime), totalTimeSpent));
|
||||||
|
}
|
||||||
|
timeSpentData.add(ProjectChartData(justDate(element.startTime), element.endTime.difference(element.startTime).inMinutes));
|
||||||
|
lastIndex++;
|
||||||
|
lastDay = element.startTime.day;
|
||||||
|
print('new day : $lastDay');
|
||||||
|
} else {
|
||||||
|
timeSpentData[lastIndex].timeSpent += element.endTime.difference(element.startTime).inMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
totalTimeSpent += element.endTime.difference(element.startTime).inMinutes;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
chartRange ??= (lastDateTime != null && firstDateTime != null) ? DateTimeRange(end: lastDateTime!, start: firstDateTime!) : null;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: Row(
|
appBar: AppBar(
|
||||||
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
FaIcon(FontAwesomeIcons.projectDiagram),
|
FaIcon(FontAwesomeIcons.projectDiagram),
|
||||||
SizedBox(width: 15,),
|
SizedBox(
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
Text(project.name),
|
Text(project.name),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Column(
|
child: SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
Card(
|
children: [
|
||||||
|
Card(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
DropdownButton<String>(
|
||||||
|
value: chartOption,
|
||||||
|
icon: const Icon(Icons.arrow_downward),
|
||||||
|
elevation: 16,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
underline: Container(
|
||||||
|
height: 2,
|
||||||
|
color: Colors.deepPurpleAccent,
|
||||||
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
chartOption = newValue!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
items: <String>['Time Spent', 'Time Progression', 'Steps Progression', 'Time & Steps Progression']
|
||||||
|
.map<DropdownMenuItem<String>>((String value) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: value,
|
||||||
|
child: Text(value),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
FaIcon(FontAwesomeIcons.calendar),
|
||||||
|
SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
DateTimeRange? value = await showDateRangePicker(
|
||||||
|
context: context, firstDate: firstDay ?? DateTime.now(), lastDate: lastDateTime ?? DateTime.now());
|
||||||
|
if (value != null) {
|
||||||
|
chartRange = value;
|
||||||
|
}
|
||||||
|
|
||||||
),
|
setState(() {});
|
||||||
Card(child: Padding(
|
},
|
||||||
padding: EdgeInsets.all(8),
|
child: Text((chartRange != null)
|
||||||
child: Column(
|
? (DateFormat("MM/dd").format(chartRange!.start) + " - " + DateFormat("MM/dd").format(chartRange!.end))
|
||||||
children: [
|
: 'n/a'),
|
||||||
Text("Time Management"),
|
),
|
||||||
SizedBox(height: 10,),
|
],
|
||||||
Padding(
|
)
|
||||||
padding: const EdgeInsets.all(5.0),
|
],
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(flex:1,child: Text('ETA :',textAlign: TextAlign.end,)),
|
|
||||||
Expanded(flex: 3,child: Text( '${etaHours} Hours',textAlign: TextAlign.center,),)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(flex:1,child: Text('Deadline :',textAlign: TextAlign.end,)),
|
|
||||||
Expanded(flex: 3,child: Text( '${DateFormat('yyyy-MM-dd').format(project.deadline)}',textAlign: TextAlign.center,),)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(flex:1,child: Text('Remaining :',textAlign: TextAlign.end,)),
|
|
||||||
Expanded(flex: 3,child: Text( '${durationToDays(project.deadline.difference(DateTime.now()))}',textAlign: TextAlign.center,),)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Card(child:Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text('Steps',),
|
|
||||||
LimitedBox(
|
|
||||||
maxHeight: 300,
|
|
||||||
child: Container(
|
|
||||||
|
|
||||||
padding: EdgeInsets.all(10),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.vertical,
|
|
||||||
child: (stepsWidgets.isNotEmpty) ? Container(
|
|
||||||
child: Column(
|
|
||||||
children: stepsWidgets,
|
|
||||||
),
|
),
|
||||||
) : Container(
|
),
|
||||||
|
SfCartesianChart(
|
||||||
height: 20,
|
// Initialize category axis
|
||||||
child: Text('Click on + to add steps')
|
primaryXAxis: CategoryAxis(),
|
||||||
)),
|
series: <LineSeries<ProjectChartData, String>>[
|
||||||
|
if (chartOption == 'Time Spent')
|
||||||
|
LineSeries<ProjectChartData, String>(
|
||||||
|
// Bind data source
|
||||||
|
dataSource: timeSpentData,
|
||||||
|
xValueMapper: (ProjectChartData sales, _) => DateFormat("MM/dd").format(sales.day),
|
||||||
|
yValueMapper: (ProjectChartData sales, _) => sales.timeSpent / 60,
|
||||||
|
dataLabelMapper: (ProjectChartData sales, _) => MinutesToTimeString(sales.timeSpent),
|
||||||
|
dataLabelSettings: DataLabelSettings(overflowMode: OverflowMode.hide, showZeroValue: false, isVisible: true),
|
||||||
|
onPointTap: (ChartPointDetails point) {
|
||||||
|
showAlertDialog(context, DateFormat("MM/dd").format(timeSpentData[point.pointIndex!].day),
|
||||||
|
"I'll show you detailed info about this day in future, When my master creates the feature");
|
||||||
|
},
|
||||||
|
color: Colors.blue),
|
||||||
|
if (chartOption == 'Time Progression')
|
||||||
|
LineSeries<ProjectChartData, String>(
|
||||||
|
// Bind data source
|
||||||
|
dataSource: timeProgressionData,
|
||||||
|
xValueMapper: (ProjectChartData sales, _) => DateFormat("MM/dd").format(sales.day),
|
||||||
|
yValueMapper: (ProjectChartData sales, _) => sales.timeSpent / 60,
|
||||||
|
dataLabelMapper: (ProjectChartData sales, _) => MinutesToTimeString(sales.timeSpent),
|
||||||
|
dataLabelSettings: DataLabelSettings(overflowMode: OverflowMode.hide, showZeroValue: false, isVisible: true),
|
||||||
|
onPointTap: (ChartPointDetails point) {
|
||||||
|
showAlertDialog(context, DateFormat("MM/dd").format(timeSpentData[point.pointIndex!].day),
|
||||||
|
"I'll show you detailed info about this day in future, When my master creates the feature");
|
||||||
|
},
|
||||||
|
color: Colors.blue)
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
))),
|
||||||
|
Card(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text("Time Management"),
|
||||||
|
SizedBox(
|
||||||
|
height: 10,
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Container(
|
padding: const EdgeInsets.all(5.0),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 40,vertical: 10),
|
child: Row(
|
||||||
decoration: BoxDecoration(
|
children: [
|
||||||
borderRadius: BorderRadius.circular(20),
|
Expanded(
|
||||||
color: Colors.black26,
|
flex: 1,
|
||||||
|
child: Text(
|
||||||
|
'ETA :',
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Text(
|
||||||
|
(etaHours > 0) ? '${etaHours} Hours' : 'You have no idea',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text(
|
||||||
|
'Time Spent :',
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Text(
|
||||||
|
(totalTimeSpent > 0) ? MinutesToTimeString(totalTimeSpent) : 'Not a single minute',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text(
|
||||||
|
'Deadline :',
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Text(
|
||||||
|
'${DateFormat('yyyy-MM-dd').format(project.deadline)}',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text(
|
||||||
|
'Remaining :',
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Text(
|
||||||
|
'${durationToDays(project.deadline.difference(DateTime.now()))}',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
if (project.steps.length > 0)
|
||||||
|
Card(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text("Total time : $etaHours Hours"),
|
Text(
|
||||||
|
'Steps',
|
||||||
|
),
|
||||||
|
LimitedBox(
|
||||||
|
maxHeight: 300,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: (stepsWidgets.isNotEmpty)
|
||||||
|
? Container(
|
||||||
|
child: Column(
|
||||||
|
children: stepsWidgets,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container(height: 20, child: Text('Click on + to add steps'))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
color: Colors.black26,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text("Total time : $etaHours Hours"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
Card(
|
||||||
),),
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
Card(child:Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.all(8.0),
|
children: [
|
||||||
child: Column(
|
Text('Actions'),
|
||||||
children: [
|
Row(
|
||||||
Text('Actions'),
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
ElevatedButton(
|
||||||
children: [
|
onPressed: () {},
|
||||||
ElevatedButton(onPressed: (){}, child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
FaIcon(FontAwesomeIcons.edit),
|
FaIcon(FontAwesomeIcons.edit),
|
||||||
SizedBox(width: 10,),
|
SizedBox(
|
||||||
Text('Edit'),
|
width: 10,
|
||||||
],
|
),
|
||||||
)),
|
Text('Edit'),
|
||||||
ElevatedButton(style:ElevatedButton.styleFrom(
|
],
|
||||||
primary: Colors.red,
|
)),
|
||||||
),onPressed: (){}, child: Row(
|
ElevatedButton(
|
||||||
children: [
|
style: ElevatedButton.styleFrom(
|
||||||
FaIcon(FontAwesomeIcons.deleteLeft),
|
primary: Colors.red,
|
||||||
SizedBox(width: 10,),
|
),
|
||||||
Text('Delete'),
|
onPressed: () {},
|
||||||
],
|
child: Row(
|
||||||
))
|
children: [
|
||||||
],
|
FaIcon(FontAwesomeIcons.deleteLeft),
|
||||||
),
|
SizedBox(
|
||||||
],
|
width: 10,
|
||||||
),
|
),
|
||||||
))
|
Text('Delete'),
|
||||||
],
|
],
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
) ,
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> printSteps() {
|
List<Widget> printSteps() {
|
||||||
List<Widget> _steps = [];
|
List<Widget> _steps = [];
|
||||||
|
//Checkbox(value: false, onChanged: null),
|
||||||
Widget title=Container(
|
|
||||||
|
|
||||||
height: 30,
|
|
||||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: Colors.white10),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(flex: 4, child: Text('Name')),
|
|
||||||
// Expanded(flex:1,child: Icon(Icons.timelapse)),
|
|
||||||
Expanded(flex: 2, child: Text("Progress")),
|
|
||||||
Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: Text('ETA',textAlign: TextAlign.end,))
|
|
||||||
],
|
|
||||||
));
|
|
||||||
|
|
||||||
// _steps.add(title);
|
// _steps.add(title);
|
||||||
// _steps.add(Divider());
|
// _steps.add(Divider());
|
||||||
for (int i = 0; i < project.steps.length; i++) {
|
for (int i = 0; i < project.steps.length; i++) {
|
||||||
ProjectStep value = project.steps[i];
|
ProjectStep value = project.steps[i];
|
||||||
_steps.add(InkWell(
|
_steps.add(Row(
|
||||||
child: Container(
|
children: [
|
||||||
height: 30,
|
InkWell(onTap: (){
|
||||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color:Colors.black26),
|
Dialogs.completeStepDialog(project,(date) {
|
||||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
|
User.UserOperations.CompleteProjectStep(project, project.steps[i], date);
|
||||||
child: Row(
|
}, project.steps[i]);
|
||||||
mainAxisSize: MainAxisSize.max,
|
},child: Container(margin:EdgeInsets.all(2),child: Icon((project.steps[i].finishedDate!= null) ?Icons.check_box : Icons.check_box_outline_blank))),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Expanded(
|
||||||
children: [
|
child: Container(
|
||||||
Expanded(flex: 4, child: Text(value.stepName)),
|
height: 34,
|
||||||
// Expanded(flex:1,child: Icon(Icons.timelapse)),
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Colors.black26),
|
||||||
Expanded(flex: 1, child: Text("${value.progress}%")),
|
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
|
||||||
Expanded(
|
child: Row(
|
||||||
flex: 3,
|
mainAxisSize: MainAxisSize.max,
|
||||||
child: Text(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
value.eta.toString() + " Hours",
|
children: [
|
||||||
textAlign: TextAlign.end,
|
Expanded(flex: 4, child: Text(value.stepName)),
|
||||||
))
|
// Expanded(flex:1,child: Icon(Icons.timelapse)),
|
||||||
],
|
Expanded(flex: 1, child: Text("${value.progress}%")),
|
||||||
))));
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Text(
|
||||||
|
value.eta.toString() + " Hours",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
))
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return _steps;
|
return _steps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ProjectChartData {
|
||||||
class ProjectChartData{
|
|
||||||
|
|
||||||
ProjectChartData(this.day, this.timeSpent);
|
ProjectChartData(this.day, this.timeSpent);
|
||||||
|
|
||||||
DateTime day;
|
DateTime day;
|
||||||
|
|||||||
@@ -649,14 +649,14 @@ Future<List<Project>> GetProjects(bool forceOffline) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Map> cats = await cacheDb.rawQuery('SELECT * FROM Projects');
|
List<Map> cats = await cacheDb.rawQuery('SELECT * FROM Projects');
|
||||||
print(cats.length);
|
print('projects : ${cats.length}');
|
||||||
for (Map element in cats) {
|
for (Map element in cats) {
|
||||||
String? name = element[Project.colName];
|
String? name = element[Project.colName];
|
||||||
String? category = element[Project.colCat];
|
String? category = element[Project.colCat];
|
||||||
String? stepsJson = element[Project.colSteps];
|
String? stepsJson = element[Project.colSteps];
|
||||||
String? deadline = element[Project.colDeadline];
|
String? deadline = element[Project.colDeadline];
|
||||||
int? eta= element[Project.colEta];
|
int? eta= element[Project.colEta];
|
||||||
|
print(name);
|
||||||
|
|
||||||
if (name == null || category == null || stepsJson == null || deadline == null || eta==null) {
|
if (name == null || category == null || stepsJson == null || deadline == null || eta==null) {
|
||||||
print("Something is null!\nname:${name == null}, cat:${category == null}, steps:${stepsJson == null}, deadline${deadline == null}");
|
print("Something is null!\nname:${name == null}, cat:${category == null}, steps:${stepsJson == null}, deadline${deadline == null}");
|
||||||
@@ -1139,6 +1139,47 @@ class UserOperations {
|
|||||||
await executeQueries();
|
await executeQueries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> CompleteProjectStep(Project project, ProjectStep step, DateTime finishedDate) async {
|
||||||
|
|
||||||
|
project.steps.forEach((element) {
|
||||||
|
if(element.stepName == step.stepName){
|
||||||
|
element.finishedDate = finishedDate;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, String> queryBody = <String, String>{
|
||||||
|
'name': username+project.name,
|
||||||
|
'username': username,
|
||||||
|
'steps': jsonEncode(project.steps),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cacheEnabled) {
|
||||||
|
//Add Query
|
||||||
|
Map<String, Object> query = {Queries.colLink: 'update_projectSteps', Queries.colData: jsonEncode(queryBody)};
|
||||||
|
|
||||||
|
print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}");
|
||||||
|
|
||||||
|
await cacheDb.insert('Queries', query);
|
||||||
|
await cacheDb.rawUpdate("UPDATE Projects SET steps='${jsonEncode(project.steps)}' WHERE ${Project.colName}='${project.name}'");
|
||||||
|
//update Cache
|
||||||
|
// Map<String, Object> data = {Project.colName: username+name, Project.colCat: category, Project.colSteps: jsonEncode(steps),Project.colEta: eta, Project.colDeadline: deadline.toString()};
|
||||||
|
// await cacheDb.insert('Projects', data);
|
||||||
|
await refreshUserData(forceOffline: true);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/update_projectSteps.php'), body: queryBody));
|
||||||
|
print("Query executed : Results{${queryResponse.body}");
|
||||||
|
if (queryResponse.body.toLowerCase().contains("success")) {
|
||||||
|
//Success
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('NC: Error completing prjctStep $e}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await executeQueries();
|
||||||
|
}
|
||||||
|
|
||||||
static Future<void> deleteTask(String name, {bulk = false}) async {
|
static Future<void> deleteTask(String name, {bulk = false}) async {
|
||||||
Map<String, String> queryBody = <String, String>{
|
Map<String, String> queryBody = <String, String>{
|
||||||
'id': username + name,
|
'id': username + name,
|
||||||
|
|||||||
Reference in New Issue
Block a user