From 87392cc73c72ccfcdeb9b0f468ba9388fdc62ee8 Mon Sep 17 00:00:00 2001 From: Hyperling Date: Wed, 5 Feb 2025 13:33:07 -0700 Subject: [PATCH] Break code into multiple files. --- lib/main.dart | 296 +------------------------------------- lib/models/expense.dart | 18 +++ lib/models/frequency.dart | 12 ++ lib/pages/asset.dart | 12 ++ lib/pages/expense.dart | 214 +++++++++++++++++++++++++++ lib/pages/income.dart | 18 +++ lib/pages/report.dart | 12 ++ lib/pages/settings.dart | 12 ++ 8 files changed, 304 insertions(+), 290 deletions(-) create mode 100644 lib/models/expense.dart create mode 100644 lib/models/frequency.dart create mode 100644 lib/pages/asset.dart create mode 100644 lib/pages/expense.dart create mode 100644 lib/pages/income.dart create mode 100644 lib/pages/report.dart create mode 100644 lib/pages/settings.dart diff --git a/lib/main.dart b/lib/main.dart index 6dbb0cb..7afd692 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,42 +3,16 @@ import 'package:flutter/material.dart'; +import '/pages/expense.dart'; +import '/pages/income.dart'; +import '/pages/asset.dart'; +import '/pages/report.dart'; +import '/pages/settings.dart'; + void main() { runApp(const MainApp()); } -// https://www.tutorialspoint.com/dart_programming/dart_programming_enumeration.htm -enum Frequency { - daily(title: "Daily"), - weekly(title: "Weekly"), - biweekly(title: "Biweekly"), - montly(title: "Monthly"), - yearly(title: "Yearly"); - - const Frequency({required this.title}); - - final String title; -} - -class Expense { - final String name; - final double cost; - final Frequency frequency; - final String description; - - const Expense( - {required this.name, - required this.cost, - required this.frequency, - required this.description}); - - String toString() { - return "$name, $cost, ${frequency.title}, $description"; - } -} - -List expenses = []; - class MainApp extends StatelessWidget { const MainApp({super.key}); @@ -154,261 +128,3 @@ class _HomePageState extends State { }); } } - -class ExpensePage extends StatelessWidget { - const ExpensePage({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return ListView.builder( - itemCount: expenses.length, - itemBuilder: (_, index) { - final Expense curr = expenses[index]; - return Center( - child: Padding( - padding: const EdgeInsets.all(4.0), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - color: Colors.greenAccent, - ), - child: Column( - children: [ - Text(curr.name), - Text("${curr.cost.toString()} ${curr.frequency.title}"), - ], - ), - ), - ), - ); - }); - /* - return ListView( - children: [ - ListTile( - title: Text("Fake Item 1"), - subtitle: Text("30.00 / month"), - ), - ListTile( - title: Text("Fake Item 2"), - subtitle: Text("180.00 / year"), - ), - ], - ); - */ - } -} - -class ExpenseInputDialog extends StatefulWidget { - const ExpenseInputDialog({ - super.key, - }); - - @override - State createState() => _ExpenseInputDialogState(); -} - -class _ExpenseInputDialogState extends State { - final _expenseFormKey = GlobalKey(); - - String _name = ""; - double _cost = 0.0; - Frequency _freq = Frequency.montly; - String _desc = ""; - - @override - Widget build(BuildContext context) { - const inputWidth = 300.0; - const inputHeight = 50.0; - - List freqValues = []; - for (var freq in Frequency.values) { - freqValues.add(DropdownMenuItem(value: freq, child: Text(freq.title))); - } - ; - - return AlertDialog( - title: Center(child: Text("Add New Expense")), - content: Form( - key: _expenseFormKey, - autovalidateMode: AutovalidateMode.onUserInteraction, - child: Column(mainAxisSize: MainAxisSize.min, spacing: 10, children: [ - SizedBox( - width: inputWidth, - height: inputHeight, - child: TextFormField( - keyboardType: TextInputType.text, - decoration: InputDecoration( - labelText: "Name", - hintText: "Example: Red Pocket Phone Bill", - ), - validator: (value) { - if (value!.isEmpty) { - return "Name must be provided."; - } - return null; - }, - onSaved: (newValue) { - _name = newValue!; - }, - ), - ), - SizedBox( - width: inputWidth, - height: inputHeight, - child: TextFormField( - keyboardType: TextInputType.numberWithOptions(decimal: true), - decoration: InputDecoration( - labelText: "Cost", hintText: "Example: 10.00"), - validator: (value) { - if (value!.isEmpty) { - return "Cost must be provided."; - } - if (double.tryParse(value) == null) { - return "Cost must be a valid number."; - } - return null; - }, - onSaved: (newValue) { - _cost = double.parse(newValue!); - }, - ), - ), - SizedBox( - width: inputWidth, - height: inputHeight, - child: DropdownButtonFormField( - items: freqValues, - decoration: InputDecoration( - labelText: "Recurrence", hintText: "Example: Monthly"), - validator: (value) { - if (value == null) { - return "Frequency must be provided."; - } - if (!Frequency.values.contains(value)) { - return "Value not valid."; - } - return null; - }, - onChanged: (newValue) { - _freq = newValue; - }, - ), - ), - SizedBox( - width: inputWidth, - height: inputHeight, - child: TextFormField( - keyboardType: TextInputType.text, - decoration: InputDecoration( - labelText: "Description", - hintText: "Example: 1GB data with unlimited talk & text."), - validator: (value) { - return null; - }, - onSaved: (newValue) { - _desc = newValue!; - }, - ), - ), - ]), - ), - actions: [ - SizedBox( - width: inputWidth, - height: inputHeight, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - ElevatedButton.icon( - onPressed: () { - print("TODO: Clear fields!"); - Navigator.of(context).pop(); - }, - icon: Icon(Icons.cancel), - label: Text('Cancel'), - ), - ElevatedButton.icon( - onPressed: () { - print("TODO: Save expense!"); - if (_expenseFormKey.currentState!.validate()) { - _expenseFormKey.currentState!.save(); - setState(() { - expenses.add( - Expense( - name: _name, - cost: _cost, - frequency: _freq, - description: _desc), - ); - }); - print(expenses.toString()); - for (var expense in expenses) { - print(expense.toString()); - } - Navigator.of(context).pop(); - } - }, - icon: Icon(Icons.save), - label: Text('Submit'), - ), - ], - ), - ) - ], - ); - } -} - -class IncomePage extends StatelessWidget { - const IncomePage({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Center( - child: Column( - children: [ - Text("TBD"), - Placeholder(), - ], - )); - } -} - -class AssetPage extends StatelessWidget { - const AssetPage({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Placeholder(); - } -} - -class ProjectionPage extends StatelessWidget { - const ProjectionPage({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Placeholder(); - } -} - -class SettingsPage extends StatelessWidget { - const SettingsPage({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Placeholder(); - } -} diff --git a/lib/models/expense.dart b/lib/models/expense.dart new file mode 100644 index 0000000..374ec58 --- /dev/null +++ b/lib/models/expense.dart @@ -0,0 +1,18 @@ +import '/models/frequency.dart'; + +class Expense { + final String name; + final double cost; + final Frequency frequency; + final String description; + + const Expense( + {required this.name, + required this.cost, + required this.frequency, + required this.description}); + + String toString() { + return "$name, $cost, ${frequency.title}, $description"; + } +} diff --git a/lib/models/frequency.dart b/lib/models/frequency.dart new file mode 100644 index 0000000..d80de09 --- /dev/null +++ b/lib/models/frequency.dart @@ -0,0 +1,12 @@ +// https://www.tutorialspoint.com/dart_programming/dart_programming_enumeration.htm +enum Frequency { + daily(title: "Daily"), + weekly(title: "Weekly"), + biweekly(title: "Biweekly"), + montly(title: "Monthly"), + yearly(title: "Yearly"); + + const Frequency({required this.title}); + + final String title; +} diff --git a/lib/pages/asset.dart b/lib/pages/asset.dart new file mode 100644 index 0000000..b54b60b --- /dev/null +++ b/lib/pages/asset.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class AssetPage extends StatelessWidget { + const AssetPage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Placeholder(); + } +} diff --git a/lib/pages/expense.dart b/lib/pages/expense.dart new file mode 100644 index 0000000..d9a68af --- /dev/null +++ b/lib/pages/expense.dart @@ -0,0 +1,214 @@ +import 'package:flutter/material.dart'; + +import '/models/expense.dart'; +import '/models/frequency.dart'; + +List expenses = []; + +class ExpensePage extends StatelessWidget { + const ExpensePage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return ListView.builder( + itemCount: expenses.length, + itemBuilder: (_, index) { + final Expense curr = expenses[index]; + return Center( + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Colors.greenAccent, + ), + child: Column( + children: [ + Text(curr.name), + Text("${curr.cost.toString()} ${curr.frequency.title}"), + ], + ), + ), + ), + ); + }); + /* + return ListView( + children: [ + ListTile( + title: Text("Fake Item 1"), + subtitle: Text("30.00 / month"), + ), + ListTile( + title: Text("Fake Item 2"), + subtitle: Text("180.00 / year"), + ), + ], + ); + */ + } +} + +class ExpenseInputDialog extends StatefulWidget { + const ExpenseInputDialog({ + super.key, + }); + + @override + State createState() => _ExpenseInputDialogState(); +} + +class _ExpenseInputDialogState extends State { + final _expenseFormKey = GlobalKey(); + + String _name = ""; + double _cost = 0.0; + Frequency _freq = Frequency.montly; + String _desc = ""; + + @override + Widget build(BuildContext context) { + const inputWidth = 300.0; + const inputHeight = 50.0; + + List freqValues = []; + for (var freq in Frequency.values) { + freqValues.add(DropdownMenuItem(value: freq, child: Text(freq.title))); + } + ; + + return AlertDialog( + title: Center(child: Text("Add New Expense")), + content: Form( + key: _expenseFormKey, + autovalidateMode: AutovalidateMode.onUserInteraction, + child: Column(mainAxisSize: MainAxisSize.min, spacing: 10, children: [ + SizedBox( + width: inputWidth, + height: inputHeight, + child: TextFormField( + keyboardType: TextInputType.text, + decoration: InputDecoration( + labelText: "Name", + hintText: "Example: Red Pocket Phone Bill", + ), + validator: (value) { + if (value!.isEmpty) { + return "Name must be provided."; + } + return null; + }, + onSaved: (newValue) { + _name = newValue!; + }, + ), + ), + SizedBox( + width: inputWidth, + height: inputHeight, + child: TextFormField( + keyboardType: TextInputType.numberWithOptions(decimal: true), + decoration: InputDecoration( + labelText: "Cost", hintText: "Example: 10.00"), + validator: (value) { + if (value!.isEmpty) { + return "Cost must be provided."; + } + if (double.tryParse(value) == null) { + return "Cost must be a valid number."; + } + return null; + }, + onSaved: (newValue) { + _cost = double.parse(newValue!); + }, + ), + ), + SizedBox( + width: inputWidth, + height: inputHeight, + child: DropdownButtonFormField( + items: freqValues, + decoration: InputDecoration( + labelText: "Recurrence", hintText: "Example: Monthly"), + validator: (value) { + if (value == null) { + return "Frequency must be provided."; + } + if (!Frequency.values.contains(value)) { + return "Value not valid."; + } + return null; + }, + onChanged: (newValue) { + _freq = newValue; + }, + ), + ), + SizedBox( + width: inputWidth, + height: inputHeight, + child: TextFormField( + keyboardType: TextInputType.text, + decoration: InputDecoration( + labelText: "Description", + hintText: "Example: 1GB data with unlimited talk & text."), + validator: (value) { + return null; + }, + onSaved: (newValue) { + _desc = newValue!; + }, + ), + ), + ]), + ), + actions: [ + SizedBox( + width: inputWidth, + height: inputHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ElevatedButton.icon( + onPressed: () { + print("TODO: Clear fields!"); + Navigator.of(context).pop(); + }, + icon: Icon(Icons.cancel), + label: Text('Cancel'), + ), + ElevatedButton.icon( + onPressed: () { + print("TODO: Save expense!"); + if (_expenseFormKey.currentState!.validate()) { + _expenseFormKey.currentState!.save(); + setState(() { + expenses.add( + Expense( + name: _name, + cost: _cost, + frequency: _freq, + description: _desc), + ); + }); + print(expenses.toString()); + for (var expense in expenses) { + print(expense.toString()); + } + Navigator.of(context).pop(); + } + }, + icon: Icon(Icons.save), + label: Text('Submit'), + ), + ], + ), + ) + ], + ); + } +} diff --git a/lib/pages/income.dart b/lib/pages/income.dart new file mode 100644 index 0000000..60ba14e --- /dev/null +++ b/lib/pages/income.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class IncomePage extends StatelessWidget { + const IncomePage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + children: [ + Text("TBD"), + Placeholder(), + ], + )); + } +} diff --git a/lib/pages/report.dart b/lib/pages/report.dart new file mode 100644 index 0000000..af3eb3c --- /dev/null +++ b/lib/pages/report.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class ProjectionPage extends StatelessWidget { + const ProjectionPage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Placeholder(); + } +} diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart new file mode 100644 index 0000000..3d72429 --- /dev/null +++ b/lib/pages/settings.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class SettingsPage extends StatelessWidget { + const SettingsPage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Placeholder(); + } +}