Projects section usable, Sticky headers added

This commit is contained in:
Sewmina
2022-03-29 04:02:10 +05:30
parent 0763820b97
commit cad1b5db5a
8 changed files with 209 additions and 40 deletions

View File

@@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.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';
@@ -65,11 +66,12 @@ class _ActivitiesState extends State<Activities> {
// progressDialog.update(value: 100);
} catch (e) {}
}
Map<Widget, List<Widget>> activitiesGroups =<Widget, List<Widget>>{};
@override
Widget build(BuildContext context) {
// progressDialog = ProgressDialog(context: context);
List<Widget> activities = PrintTasks();
// List<Widget> activities = PrintTasks();
activitiesGroups = PrintTasks();
return Scaffold(
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
@@ -171,9 +173,15 @@ class _ActivitiesState extends State<Activities> {
body: Container(
padding: EdgeInsets.all(0),
child: ListView.builder(
itemCount: activities.length,
itemCount: activitiesGroups.length,
itemBuilder: (context, index){
return activities[index];
// return activities[index];
return StickyHeader(
header:activitiesGroups.keys.toList()[index],
content:Column(children: activitiesGroups.values.toList()[index],)
);
})
// SingleChildScrollView(
// child: Column(
@@ -183,8 +191,8 @@ class _ActivitiesState extends State<Activities> {
}
int searchTime = 0;
List<Widget> PrintTasks() {
List<Widget> _tasks = [];
Map<Widget,List<Widget>> PrintTasks() {
Map<Widget,List<Widget>> _tasks = <Widget,List<Widget>>{};
print('Priting cats : ' + User.taskTypes.length.toString());
String lastDate = "";
DateFormat dFormat = DateFormat("MM/dd");
@@ -239,7 +247,9 @@ class _ActivitiesState extends State<Activities> {
if (thisDate != lastDate) {
int prodActs = productivtyActs[thisDate] ?? 0;
int unProdActs = unproductivtyActs[thisDate] ?? 0;
_tasks.add(DateSeperator(thisDate, prodActs, unProdActs));
//_tasks.add(DateSeperator(thisDate, prodActs, unProdActs));
_tasks.putIfAbsent(DateSeperator(thisDate, prodActs, unProdActs), () => [Container()]);
print('adding');
lastDate = thisDate;
}
String name = element.taskType.name;
@@ -250,7 +260,7 @@ 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.add(task);
_tasks.values.toList()[_tasks.length-1].add(task);
}
//Check for gaps
if(i < User.activities.length-1){
@@ -258,7 +268,7 @@ class _ActivitiesState extends State<Activities> {
if(gap > 10) {
Widget addGap = timeGap(User.activities[i].trueStartTime, User.activities[i+1].trueEndTime);
_tasks.add(addGap);
_tasks.values.toList()[_tasks.length-1].add(addGap);
}
}
}
@@ -317,9 +327,11 @@ class _ActivitiesState extends State<Activities> {
future: Settings.getUntrackedUnproductive(),
builder: (context, snapshot) {
double prodPercentage = (User.ParseBool(snapshot.data))? ((prodActs / 1440) * 100) : ((prodActs / unprodActs) * 100);
return Padding(
padding: const EdgeInsets.fromLTRB(0, 20, 10, 0),
return Container(
color: Color(0xFF333333),
padding: const EdgeInsets.fromLTRB(0, 10, 10, 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.max,
@@ -538,4 +550,5 @@ class _ActivitiesState extends State<Activities> {
}
}
List<Activity> selectedActivities = [];

View File

@@ -72,6 +72,54 @@ class Dialogs{
}
}
static showQuestionDialog(String title, String message, {bool hasCancel = false, required Function(bool) onResponse}) async{
context=navigatorKey.currentContext;
if(context!=null) {
return showDialog(
context: context!,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
backgroundColor: Color(0xFF1C1C1C),
title: Text(title),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(message)
],
),
actions: [
if(hasCancel)MaterialButton(
onPressed: (){
Navigator.of(context).pop();
},
child: Text('Cancel', style:TextStyle(color: Colors.grey)),
),
MaterialButton(
onPressed: (){
onResponse(false);
Navigator.of(context).pop();
},
child: Text('No', style:TextStyle(color: Colors.red)),
),
MaterialButton(
onPressed: (){
onResponse(true);
Navigator.of(context).pop();
},
child: Text('Yes', style:TextStyle(color: Colors.green)),
)
],
);
}
);
}else{
print('context is null');
}
}
static ongoing() async{
List<String>? data= await User.getOngoingData();
if(data == null){return;}

View File

@@ -51,11 +51,12 @@ class _ProjectDetailsState extends State<ProjectDetails> {
(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 (firstDateTime == null) {
firstDateTime = element.startTime;
}
lastDateTime = element.startTime;
if (withinRange) {
if (firstDateTime == null) {
firstDateTime = element.startTime;
}
lastDateTime = element.startTime;
if (lastDay != element.startTime.day) {
if (totalTimeSpent > 0) {
@@ -321,11 +322,37 @@ class _ProjectDetailsState extends State<ProjectDetails> {
child: Column(
children: [
Text('Actions'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
if(project.steps.length<=0)ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green,
),
onPressed: () {
Dialogs.showQuestionDialog("WARNING!", 'You will lose all data about this project if you continue!\nAre you sure you want to delete?', onResponse: (value){
});
},
child: Row(
children: [
FaIcon(FontAwesomeIcons.check),
SizedBox(
width: 10,
),
Text('Complete'),
],
)),
ElevatedButton(
onPressed: () {},
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>NewProject(multiline: project.steps.isNotEmpty, projectName: project.name, selectedCategory: project.cat!.name,m_steps: project.steps,)));
},
child: Row(
children: [
FaIcon(FontAwesomeIcons.edit),
@@ -339,7 +366,11 @@ class _ProjectDetailsState extends State<ProjectDetails> {
style: ElevatedButton.styleFrom(
primary: Colors.red,
),
onPressed: () {},
onPressed: () {
Dialogs.showQuestionDialog("WARNING!", 'You will lose all data about this project if you continue!\nAre you sure you want to delete?', onResponse: (value){
});
},
child: Row(
children: [
FaIcon(FontAwesomeIcons.deleteLeft),
@@ -370,10 +401,25 @@ class _ProjectDetailsState extends State<ProjectDetails> {
ProjectStep value = project.steps[i];
_steps.add(Row(
children: [
InkWell(onTap: (){
Dialogs.completeStepDialog(project,(date) {
User.UserOperations.CompleteProjectStep(project, project.steps[i], date);
}, project.steps[i]);
InkWell(onTap: ()async{
if(project.steps[i].finishedDate!= null){
await Dialogs.showQuestionDialog('Are you sure?', 'Do you want to undone following step?\n\n${project.steps[i].stepName}', onResponse: (value)async{
if(value==true){
await User.UserOperations.UndoProjectStep(project, project.steps[i]);
}
});
setState(() {
});
}else {
await Dialogs.completeStepDialog(project, (date)async {
await User.UserOperations.CompleteProjectStep(project, project.steps[i], date);
}, project.steps[i]);
setState(() {
});
}
},child: Container(margin:EdgeInsets.all(2),child: Icon((project.steps[i].finishedDate!= null) ?Icons.check_box : Icons.check_box_outline_blank))),
Expanded(
child: Container(

View File

@@ -1180,6 +1180,47 @@ class UserOperations {
await executeQueries();
}
static Future<void> UndoProjectStep(Project project, ProjectStep step) async {
project.steps.forEach((element) {
if(element.stepName == step.stepName){
element.finishedDate = null;
}
});
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 {
Map<String, String> queryBody = <String, String>{
'id': username + name,

View File

@@ -1,4 +1,5 @@
import 'dart:ui';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';
@@ -19,7 +20,10 @@ class _WelcomePageState extends State<WelcomePage> {
return SafeArea(
child: Scaffold(
body: Container(
color: Colors.pink,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.pink, Colors.purple],stops: [0,1],begin: Alignment.topLeft, end: Alignment.bottomRight)
),
//color: Colors.pink,
child: Flex(
direction: Axis.vertical,
mainAxisSize: MainAxisSize.max,
@@ -90,7 +94,10 @@ class _SignInPageState extends State<SignInPage> {
return SafeArea(
child: Scaffold(
body: Container(
color: Colors.deepPurpleAccent,
// color: Colors.deepPurpleAccent,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.deepPurple, Colors.purple],stops: [0,1],begin: Alignment.topLeft, end: Alignment.bottomRight)
),
child: Flex(
direction: Axis.vertical,
mainAxisSize: MainAxisSize.max,
@@ -182,7 +189,10 @@ class _onlineLoginPageState extends State<onlineLoginPage>
return SafeArea(
child: Scaffold(
body: Container(
color: Colors.purpleAccent,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.blue, Colors.deepPurpleAccent],stops: [0,1],begin: Alignment.topLeft, end: Alignment.bottomRight)
),
// color: Colors.purpleAccent,
child: Flex(
direction: Axis.vertical,
mainAxisSize: MainAxisSize.max,
@@ -210,7 +220,7 @@ class _onlineLoginPageState extends State<onlineLoginPage>
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.purple),
color: Colors.black26),
child: Padding(
padding: EdgeInsets.all(10),
child: TabBar(
@@ -220,8 +230,8 @@ class _onlineLoginPageState extends State<onlineLoginPage>
borderRadius:
BorderRadius.circular(10)),
tabs: [
TabItem('Our Account'),
TabItem('OAuth')
TabItem('Login / Register'),
TabItem('Or, Continue with')
],
))),
Divider(
@@ -236,7 +246,7 @@ class _onlineLoginPageState extends State<onlineLoginPage>
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
color: Colors.purple),
color: Colors.black26),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
@@ -253,18 +263,18 @@ class _onlineLoginPageState extends State<onlineLoginPage>
)),
Expanded(
child: Container(
padding: EdgeInsets.all(15),
padding: EdgeInsets.symmetric(horizontal: 15,vertical: 0),
child: TextField(
controller: usernameController,
autocorrect: false,
style: TextStyle(
color: Colors.black,
// color: Colors.black,
),
decoration: InputDecoration(
hintText: 'Username',
filled: true,
fillColor:
Colors.white,
Colors.white12,
border: OutlineInputBorder(
borderRadius:
BorderRadius
@@ -276,7 +286,7 @@ class _onlineLoginPageState extends State<onlineLoginPage>
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.fromLTRB(
10, 10, 10, 0),
10, 0, 10, 0),
child: Text(
'Password',
style:
@@ -284,7 +294,7 @@ class _onlineLoginPageState extends State<onlineLoginPage>
)),
Expanded(
child: Container(
padding: EdgeInsets.all(15),
padding: EdgeInsets.symmetric(horizontal: 15,vertical: 0),
child: TextField(
controller: passwordController,
obscureText: true,
@@ -293,13 +303,13 @@ class _onlineLoginPageState extends State<onlineLoginPage>
style: TextStyle(
fontWeight:
FontWeight.bold,
color: Colors.black,
// color: Colors.black,
),
decoration: InputDecoration(
hintText: 'Password',
filled: true,
fillColor:
Colors.white,
Colors.white12,
border: OutlineInputBorder(
borderRadius:
BorderRadius
@@ -329,7 +339,7 @@ class _onlineLoginPageState extends State<onlineLoginPage>
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
color: Colors.purple),
color: Colors.black26),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
@@ -339,7 +349,7 @@ class _onlineLoginPageState extends State<onlineLoginPage>
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green,
primary: Colors.blue,
),
onPressed: (){
final provider = Provider.of<GoogleSignInProvider>(context, listen:false);
@@ -354,9 +364,9 @@ class _onlineLoginPageState extends State<onlineLoginPage>
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.android),
FaIcon(FontAwesomeIcons.google),
SizedBox(width: 20,),
Text("Sign with Google", style: TextStyle(fontSize: 20))
Text("Google", style: TextStyle(fontSize: 20))
],)),
),
Divider(height: 50,),

View File

@@ -90,7 +90,10 @@ class _SplashScreenState extends State<SplashScreen> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.redAccent,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.lightBlue, Colors.blue],stops: [0,1],begin: Alignment.topLeft, end: Alignment.bottomRight)
),
// color: Colors.redAccent,
padding: EdgeInsets.all(80),
child: Column(
mainAxisSize: MainAxisSize.max,

View File

@@ -553,6 +553,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
sticky_headers:
dependency: "direct main"
description:
name: sticky_headers
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
stream_channel:
dependency: transitive
description:

View File

@@ -30,6 +30,7 @@ dependencies:
flutter:
sdk: flutter
sticky_headers: ^0.2.0
flutter_switch: ^0.3.2
sqflite_common_ffi: ^2.1.0+2
flutter_spinkit: ^5.1.0