diff --git a/lib/main.dart b/lib/main.dart index 202509b..6ef8d07 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,28 +1,26 @@ import 'package:flutter/material.dart'; +import 'package:todo/utils/dialog_box.dart'; +import 'package:todo/utils/todo_tile.dart'; void main() { runApp(const MyApp()); } -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', + title: 'Todo', theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, + primarySwatch: Colors.red, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); @@ -32,15 +30,6 @@ class MyApp extends StatelessWidget { class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - final String title; @override @@ -48,65 +37,57 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - int _counter = 0; + final _controller = TextEditingController(); + List todoList = [ + ["Make Tutorial", true], + ["Buy car", false], + ["Buy new wife", true], + ["buy card", false], + ]; - void _incrementCounter() { + void checkBoxChanged(bool? value, int index) { setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; + todoList[index][1] = !todoList[index][1]; }); } + void saveNewTask() { + setState(() { + todoList.add([_controller.text, false]); + _controller.clear(); + }); + Navigator.of(context).pop(); + } + + void createNewTask() { + showDialog( + context: context, + builder: (context) { + return DialogBox( + controller: _controller, + onCancel: () => Navigator.of(context).pop(), + onSave: saveNewTask, + ); + }); + } + @override Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. return Scaffold( appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. title: Text(widget.title), ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Invoke "debug painting" (press "p" in the console, choose the - // "Toggle Debug Paint" action from the Flutter Inspector in Android - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) - // to see the wireframe for each widget. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], - ), - ), + body: ListView.builder( + itemCount: todoList.length, + itemBuilder: (context, index) { + return ToDoTile( + taskName: todoList[index][0], + taskCompleted: todoList[index][1], + onChanged: (value) => checkBoxChanged(value, index), + ); + }), floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, + onPressed: createNewTask, tooltip: 'Increment', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. diff --git a/lib/utils/dialog_box.dart b/lib/utils/dialog_box.dart new file mode 100644 index 0000000..6a38042 --- /dev/null +++ b/lib/utils/dialog_box.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:todo/utils/my_button.dart'; + +class DialogBox extends StatelessWidget { + DialogBox( + {Key? key, + required this.controller, + required this.onSave, + required this.onCancel}) + : super(key: key); + + final controller; + VoidCallback onSave; + VoidCallback onCancel; + + @override + Widget build(BuildContext context) { + return AlertDialog( + backgroundColor: Theme.of(context).primaryColor, + title: Text("New Task"), + content: Container( + height: 120, + child: Column( + children: [ + TextField( + controller: controller, + decoration: InputDecoration( + border: OutlineInputBorder(), hintText: "Add new task"), + ), + SizedBox( + height: 40, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + MyButton(text: "Cancel", onPressed: onCancel), + MyButton(text: "Save", onPressed: onSave), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/utils/my_button.dart b/lib/utils/my_button.dart new file mode 100644 index 0000000..01221e7 --- /dev/null +++ b/lib/utils/my_button.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class MyButton extends StatelessWidget { + MyButton({Key? key, required this.text, required this.onPressed}) + : super(key: key); + + final String text; + VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return MaterialButton( + onPressed: onPressed, + color: Theme.of(context).primaryColor, + child: Text(text), + ); + } +} diff --git a/lib/utils/todo_tile.dart b/lib/utils/todo_tile.dart new file mode 100644 index 0000000..ab49530 --- /dev/null +++ b/lib/utils/todo_tile.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +class ToDoTile extends StatelessWidget { + const ToDoTile( + {Key? key, + required this.taskName, + required this.taskCompleted, + required this.onChanged}) + : super(key: key); + + final String taskName; + final bool taskCompleted; + final Function(bool?)? onChanged; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(25.0, 25, 25, 0), + child: Container( + padding: EdgeInsets.all(24.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + taskName, + style: TextStyle( + decoration: taskCompleted + ? TextDecoration.lineThrough + : TextDecoration.none), + ), + Checkbox( + value: taskCompleted, + onChanged: onChanged, + activeColor: Colors.redAccent, + ) + ], + ), + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.circular(10.0), + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 306911b..47fe749 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,58 +5,58 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: "1989d917fbe8e6b39806207df5a3fdd3d816cbd090fac2ce26fb45e9a71476e5" + url: "https://pub.dev" source: hosted version: "1.0.4" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -66,7 +66,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" source: hosted version: "1.0.4" flutter_test: @@ -78,30 +79,42 @@ packages: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.9.1" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.8.3" sky_engine: dependency: transitive description: flutter @@ -111,57 +124,65 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" source: hosted - version: "0.4.3" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" + version: "0.6.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" sdks: - dart: ">=2.15.1 <3.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0"