import 'package:flutter/material.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'package:intl/intl.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'User.dart' as User; import 'Data.dart'; import 'package:flutter_switch/flutter_switch.dart'; import 'DateTimeRangeCustom.dart'; import 'Dialogs.dart'; DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat durationFormat = DateFormat("HH:mm:ss"); class NewProject extends StatefulWidget { const NewProject({Key? key}) : super(key: key); @override _NewProjectState createState() => _NewProjectState(); } List getCategoryNames() { List _cats = []; User.categories.forEach((element) { String name = element.name; _cats.add(name); }); return _cats; } bool multiLine = true; String selectedCat = User.categories[0].name; class _NewProjectState extends State { TextEditingController nameController = TextEditingController(); bool productive = true; Color pickerColor = Colors.blue; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('New Project')), body: Container( height: MediaQuery.of(context).size.height, child: Column(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SingleChildScrollView( child: Padding( padding: EdgeInsets.fromLTRB(20, 50, 20, 50), child: Column( children: [ Container(padding: EdgeInsets.all(0), child: Text('Project Name')), Container( padding: EdgeInsets.all(10), child: TextField( controller: nameController, decoration: InputDecoration(hintText: 'ex: Cool science project, Build a new game etc...', border: OutlineInputBorder()), ), ), Divider(), Column(children: [ Container(padding: EdgeInsets.all(0), child: Text('Related Category')), Container( margin: EdgeInsets.all(10), padding: EdgeInsets.symmetric(horizontal: 12, vertical: 1), decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey, width: 2)), child: DropdownButton( dropdownColor: Colors.black, iconSize: 30, elevation: 10, borderRadius: BorderRadius.circular(10), value: selectedCat, isExpanded: true, items: getCategoryNames().map>((String value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), onChanged: (String? _value) { setState(() { selectedCat = _value!; }); })), Divider(), Container( padding: EdgeInsets.all(10), child: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('This project is', style: TextStyle(fontSize: 18)), FlutterSwitch( width: 130, height: 35.0, valueFontSize: 15.0, toggleSize: 25.0, toggleColor: Colors.white70, activeTextColor: Colors.white, inactiveTextColor: Colors.white, value: multiLine, borderRadius: 30.0, showOnOff: true, activeText: 'Multi step', inactiveText: 'Single step', activeColor: Colors.deepOrange, activeIcon: Icon(Icons.linear_scale, color: Colors.orange), inactiveIcon: Icon(Icons.check, color: Colors.green), inactiveColor: Colors.green, onToggle: (val) { setState(() { multiLine = val; print("Multi=Step : $multiLine"); }); }, ) ])), ]), ], ))), 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('Cancel', 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(); if (nameController.text.length > 3) { Navigator.of(context).push(MaterialPageRoute( builder: (context) => NewProject2( projectName: nameController.text, ))); } else { Dialogs.showAlertDialog(context, 'Really?', 'Enter a valid name for this project!'); } }, child: Text('Next', style: TextStyle(fontSize: 20))))), ], )) ]))); } void pickColor(BuildContext context) => showDialog( context: context, builder: (context) => AlertDialog( title: Text('Pick Color for Category'), content: Column(mainAxisSize: MainAxisSize.min, children: [ MaterialPicker( pickerColor: pickerColor, onColorChanged: (color) { setState(() { pickerColor = color; }); }, enableLabel: false, portraitOnly: true, ), TextButton( child: Text('Select', style: TextStyle(fontSize: 20)), onPressed: () => Navigator.of(context).pop(), ) ]), )); } 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"; } class NewProject2 extends StatefulWidget { NewProject2({Key? key, this.projectName}) : super(key: key); late String? projectName; @override State createState() => _NewProject2State(pName: projectName); } bool knowEta = false; int etaHours = 1; List steps = []; DateTime deadline = DateTime.now().add(Duration(days: 7)); class _NewProject2State extends State { late String? projectName; _NewProject2State({String? pName}) { projectName = pName; } @override Widget build(BuildContext context) { List stepsWidgets = printSteps(); steps.forEach((element) { etaHours+=element.eta; }); return Scaffold( appBar: AppBar(title: Text(projectName ?? 'Error')), body: Container( height: MediaQuery.of(context).size.height, child: Column(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SingleChildScrollView( scrollDirection: Axis.vertical, child: Container( padding: EdgeInsets.fromLTRB(20, 50, 20, 50), child: (multiLine) ? Column( children: [ Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Container(padding: EdgeInsets.all(10), child: Text('List your steps down')), SizedBox(height: 20,), Column( children: [ 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,)) ], )), Divider(), LimitedBox( maxHeight: 300, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.white10, ), 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') )), ), ), ], ), SizedBox( height: 5, ), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.white10, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.max, children: [ InkWell( onTap: () { int maxProgress = 100; steps.forEach((element) { maxProgress -= element.progress; }); if (maxProgress > 0) { showStepEditor(context, maxProgress: maxProgress, onChange: (step) { steps.add(step); setState(() {}); }); } else { Dialogs.showAlertDialog(context, 'Progress full', 'Progress has already reached 100%, Cannot add more steps since the work is done'); } }, child: Container(margin: EdgeInsets.all(10), child: Icon(Icons.add))), InkWell( enableFeedback: (steps.length > 0), onTap: () { int maxProgress = 100; steps.forEach((element) { maxProgress -= element.progress; }); int stepProgress = steps[selectedStep].progress; showStepEditor(context, editStep: steps[selectedStep], maxProgress: (maxProgress > stepProgress) ? maxProgress : stepProgress, onChange: (step) { steps[selectedStep] = step; setState(() {}); }); }, child: Container( margin: EdgeInsets.all(10), child: Icon(Icons.edit, color: (steps.length > 0) ? Colors.white : Colors.grey))), InkWell(onTap: () { if(steps.length <= 0){return;} steps.remove(steps[selectedStep]); setState(() { }); }, child: Container(margin: EdgeInsets.all(10), child: Icon(Icons.remove, color: (steps.length > 0) ? Colors.white : Colors.grey))), ], )), SizedBox(height: 20,), 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"), ], ), ), SizedBox(height: 30,), Padding( padding: const EdgeInsets.all(8.0), child: Text('Deadline'), ), InkWell( onTap: (){ DatePicker.showDatePicker(context, showTitleActions: true, minTime: DateTime.now(), theme: DatePickerTheme(backgroundColor: Colors.white), onChanged: (date) { // print('change $date'); }, onConfirm: (date) { setState(() { if (deadline.isAfter(DateTime.now())) { deadline = date; } else { Dialogs.showAlertDialog(context, 'Come on!', 'Deadline was passed?'); } }); }, currentTime: deadline, locale: LocaleType.en); }, child:Container( padding: EdgeInsets.symmetric(horizontal: 40,vertical: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.white10, ), child:Text(DateFormat("MMMM dd yyyy").format(deadline)), )) ], ) ], ) : Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Container(padding: EdgeInsets.all(10), child: Text("Estimated Time to reach target")), Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ InkWell( onTap: () { showDurationSelector(context, selectedHour: etaHours, onChange: (newVal) { etaHours = newVal.inHours; knowEta = true; setState(() {}); print("Selected $newVal"); }); }, child: Container( decoration: BoxDecoration( color: (knowEta) ? Colors.green : Colors.white10, borderRadius: BorderRadius.circular(30), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 10), child: Text("${(knowEta) ? etaHours : '?'} Hours"), ), ), ), InkWell( onTap: () { knowEta = false; setState(() {}); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: (knowEta) ? Colors.white10 : Colors.redAccent), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), child: Text("I have no idea"), )), ) ], ), SizedBox( height: 20, ), Container(padding: EdgeInsets.all(8), child: Text("Deadline")), InkWell( onTap: () { DatePicker.showDatePicker(context, showTitleActions: true, minTime: DateTime.now(), theme: DatePickerTheme(backgroundColor: Colors.white), onChanged: (date) { // print('change $date'); }, onConfirm: (date) { setState(() { if (deadline.isAfter(DateTime.now())) { deadline = date; } else { Dialogs.showAlertDialog(context, 'Come on!', 'Deadline was passed?'); } }); }, currentTime: deadline, locale: LocaleType.en); setState(() {}); }, child: Container( decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(30), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 10), child: Text(DateFormat("MMMM dd yyyy").format(deadline)), ), ), ), ], ))), 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: () {}, child: Text('Next', style: TextStyle(fontSize: 20))))), ], )) ]))); } int selectedStep = 0; List printSteps() { List _steps = []; 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(Divider()); for (int i = 0; i < steps.length; i++) { ProjectStep value = steps[i]; _steps.add(InkWell( onTap: () { selectedStep = i; setState(() {}); }, child: Container( height: 30, decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: (selectedStep == i) ? Colors.black26 : null), padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 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; } Future showStepEditor(BuildContext context, {required Function(ProjectStep) onChange, ProjectStep? editStep, int? maxProgress}) async { TextEditingController nameController = TextEditingController(); int progress = 1; int eta = 1; bool editing = false; int _maxP = maxProgress ?? 100; if (editStep != null) { editing = true; nameController.text = editStep.stepName; eta = editStep.eta; progress = editStep.progress; } return showDialog( context: context, barrierDismissible: false, // user must tap button! builder: (BuildContext context) { return StatefulBuilder(builder: (context, setState) { setState(() {}); return AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), backgroundColor: Color(0xFF1F1F1F), title: Align(alignment: Alignment.center, child: Text((editing) ? 'Edit step' : 'Add new step')), content: Column( mainAxisSize: MainAxisSize.min, children: [ Column( mainAxisSize: MainAxisSize.min, children: [ Text('Step name'), TextField( controller: nameController, decoration: InputDecoration( filled: true, hintText: 'Collect resources', border: OutlineInputBorder(borderRadius: BorderRadius.circular(20))), style: TextStyle(fontSize: 15), ) ], ), SizedBox( height: 20, ), Column( mainAxisSize: MainAxisSize.min, children: [ Text('Progress : $progress%'), Slider( min: 1, max: _maxP.toDouble(), value: progress.toDouble(), onChanged: (val) { progress = val.toInt(); setState(() {}); }, label: 'Progress', ), ], ), SizedBox( height: 20, ), Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(4.0), child: Text('Estimated Time'), ), InkWell( onTap: () { showDurationSelector(context, selectedHour: eta, onChange: (newVal) { eta = newVal.inHours; setState(() {}); print("Selected $newVal"); }); }, child: Container( decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(30), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 10), child: Text("${eta} Hours"), ), ), ) ], ), ], ), actions: [ TextButton( child: const Text('Cancel'), onPressed: () { Navigator.of(context).pop(); }, ), MaterialButton( color: Colors.green, child: Text((editing) ? 'Apply' : 'Add'), onPressed: () { if(nameController.text.length <=0){Dialogs.showAlertDialog(context, 'No name?', 'Please enter a name for this step... Pleeeaassee...'); return;} ProjectStep step = ProjectStep(nameController.text, eta, progress); onChange(step); Navigator.of(context).pop(); }, ), ], ); }); }, ); } } void OnClickedAdd(){ }