diff --git a/lib/main.dart b/lib/main.dart index 5fc1e8c..aca717a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -166,59 +166,106 @@ class ExpenseInputDialog extends StatefulWidget { } class _ExpenseInputDialogState extends State { + final _expenseFormKey = GlobalKey(); + @override Widget build(BuildContext context) { const inputWidth = 300.0; const inputHeight = 50.0; - const recurrenceValues = [ - DropdownMenuEntry(value: Recurrence.daily, label: "Daily"), - DropdownMenuEntry(value: Recurrence.weekly, label: "Weekly"), - DropdownMenuEntry(value: Recurrence.biweekly, label: "Biweekly"), - DropdownMenuEntry(value: Recurrence.montly, label: "Monthly"), - DropdownMenuEntry(value: Recurrence.yearly, label: "Yearly"), + const recurrenceValues = [ + DropdownMenuItem(value: Recurrence.daily, child: Text("Daily")), + DropdownMenuItem(value: Recurrence.weekly, child: Text("Weekly")), + DropdownMenuItem(value: Recurrence.biweekly, child: Text("Biweekly")), + DropdownMenuItem(value: Recurrence.montly, child: Text("Monthly")), + DropdownMenuItem( + value: Recurrence.yearly, + child: Text( + "Yearly", + )), ]; return AlertDialog( title: Center(child: Text("Add New Expense")), - content: Column(mainAxisSize: MainAxisSize.min, spacing: 10, children: [ - SizedBox( + 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; + }, + onChanged: (newValue) { + // _expenseFormKey.currentState!.reset(); + }, + )), + SizedBox( width: inputWidth, height: inputHeight, - child: TextField( - keyboardType: TextInputType.text, + child: TextFormField( + keyboardType: TextInputType.numberWithOptions(decimal: true), decoration: InputDecoration( - labelText: "Name", - hintText: "Example: Red Pocket Phone Bill", - ), - // https://docs.flutter.dev/cookbook/forms/retrieve-input - //controller: nameFieldController, - )), - SizedBox( - width: inputWidth, - height: inputHeight, - child: TextField( - keyboardType: TextInputType.numberWithOptions(decimal: true), - decoration: - InputDecoration(labelText: "Cost", hintText: "Example: 10.00"), + 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; + }, + onChanged: (newValue) { + //_expenseFormKey.currentState!.reset(); + }, + ), ), - ), - DropdownMenu( - dropdownMenuEntries: recurrenceValues, - width: inputWidth, - label: Text("Recurrence"), - hintText: "Example: Monthly", - ), - SizedBox( + SizedBox( width: inputWidth, height: inputHeight, - child: TextField( - keyboardType: TextInputType.text, + child: DropdownButtonFormField( + items: recurrenceValues, decoration: InputDecoration( - labelText: "Description", - hintText: "Example: 1GB data with unlimited talk & text."), - )), - ]), + labelText: "Recurrence", hintText: "Example: Monthly"), + validator: (value) { + if (value == null) { + return "Recurrence must be provided."; + } + return null; + }, + onChanged: (newValue) { + //_expenseFormKey.currentState!.reset(); + }, + ), + ), + 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; + }, + onChanged: (newValue) { + //_expenseFormKey.currentState!.reset(); + }, + )), + ]), + ), actions: [ SizedBox( width: inputWidth, @@ -238,7 +285,10 @@ class _ExpenseInputDialogState extends State { ElevatedButton.icon( onPressed: () { print("TODO: Save expense!"); - Navigator.of(context).pop(); + if (_expenseFormKey.currentState!.validate()) { + _expenseFormKey.currentState!.save(); + Navigator.of(context).pop(); + } }, icon: Icon(Icons.save), label: Text('Submit'),