From f5635d6120cce8a29021aa094af1f716e32ddd58 Mon Sep 17 00:00:00 2001 From: Hyperling Date: Fri, 7 Feb 2025 15:40:07 -0700 Subject: [PATCH] Add unique name check to entry form. --- lib/pages/expense.dart | 241 +++++++++++++++++++++-------------------- 1 file changed, 124 insertions(+), 117 deletions(-) diff --git a/lib/pages/expense.dart b/lib/pages/expense.dart index bbf7dab..98dd399 100644 --- a/lib/pages/expense.dart +++ b/lib/pages/expense.dart @@ -1,6 +1,4 @@ // Flutter -import 'dart:nativewrappers/_internal/vm/lib/ffi_allocation_patch.dart'; - import 'package:flutter/material.dart'; import 'package:flutter_expense_tracker/db.dart'; @@ -236,125 +234,134 @@ class _ExpenseInputDialogState extends State { ? Text("New Expense") : Text("Edit Expense"), ), - content: Form( - key: _expenseFormKey, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - keyboardType: TextInputType.text, - textCapitalization: TextCapitalization.words, - decoration: InputDecoration( - labelText: "Name", - hintText: "Example: Red Pocket", - hintStyle: TextStyle(fontSize: 10.0), - errorStyle: TextStyle(fontSize: 10.0), - ), - initialValue: _name, - validator: (value) { - if (value!.isEmpty) { - return "Name must be provided."; - } - // TODO: Figure out how to check the DB if a name already exists. - /* - if (DatabaseHelper.instance.checkExpenseNameExists(value)) { - return "Name must be unique, already in use."; - } - */ - return null; - }, - onSaved: (value) { - _name = value!; - }, - ), - TextFormField( - keyboardType: TextInputType.numberWithOptions(decimal: true), - decoration: InputDecoration( - labelText: "Cost", - hintText: "Example: 10.00", - hintStyle: TextStyle(fontSize: 10.0), - errorStyle: TextStyle(fontSize: 10.0), - ), - initialValue: _cost != 0 ? _cost.toString() : "", - validator: (value) { - if (value == null || value.isEmpty) { - return "Cost must be provided."; - } - if (double.parse(value) < 0) { - return "Please use the Income page rather than having negative expenses."; - } - if (double.parse(value) < 0.01) { - return "Cost must be one hundreth (0.01) or higher."; - } - if (double.tryParse(value) == null) { - return "Cost must be a valid number."; - } - return null; - }, - onSaved: (value) { - _cost = double.parse(value!); - }, - ), - DropdownButtonFormField( - items: Frequency.values - .map( - (freq) => DropdownMenuItem( - value: freq, - child: Row( - children: [ - Text( - freq.title, - ), - Padding( - padding: EdgeInsets.all(1.0), - child: Text( - " (${freq.hint})", - style: TextStyle(fontSize: 10.0), + content: FutureBuilder>( + future: DatabaseHelper.instance.getExpenses(), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + if (!snapshot.hasData) { + return Center(child: Text('Loading...')); + } + List expenses = snapshot.data!; + return Form( + key: _expenseFormKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + keyboardType: TextInputType.text, + textCapitalization: TextCapitalization.words, + decoration: InputDecoration( + labelText: "Name", + hintText: "Example: Red Pocket", + hintStyle: TextStyle(fontSize: 10.0), + errorStyle: TextStyle(fontSize: 10.0), + ), + initialValue: _name, + validator: (value) { + if (value!.isEmpty) { + return "Name must be provided."; + } + if (!expenses + .every((expense) => expense.name != value)) { + return "Name must be unique, already in use."; + } + return null; + }, + onSaved: (value) { + _name = value!; + }, + ), + TextFormField( + keyboardType: + TextInputType.numberWithOptions(decimal: true), + decoration: InputDecoration( + labelText: "Cost", + hintText: "Example: 10.00", + hintStyle: TextStyle(fontSize: 10.0), + errorStyle: TextStyle(fontSize: 10.0), + ), + initialValue: _cost != 0 ? _cost.toString() : "", + validator: (value) { + if (value == null || value.isEmpty) { + return "Cost must be provided."; + } + if (double.parse(value) < 0) { + return "Please use the Income page rather than having negative expenses."; + } + if (double.parse(value) < 0.01) { + return "Cost must be one hundreth (0.01) or higher."; + } + if (double.tryParse(value) == null) { + return "Cost must be a valid number."; + } + return null; + }, + onSaved: (value) { + _cost = double.parse(value!); + }, + ), + DropdownButtonFormField( + items: Frequency.values + .map( + (freq) => DropdownMenuItem( + value: freq, + child: Row( + children: [ + Text( + freq.title, + ), + Padding( + padding: EdgeInsets.all(1.0), + child: Text( + " (${freq.hint})", + style: TextStyle(fontSize: 10.0), + ), + ), + ], ), ), - ], - ), + ) + .toList(), + value: _freq, + decoration: InputDecoration( + labelText: "Frequency", + errorStyle: TextStyle(fontSize: 10.0), ), - ) - .toList(), - value: _freq, - decoration: InputDecoration( - labelText: "Frequency", - errorStyle: TextStyle(fontSize: 10.0), + validator: (value) { + if (value == null) { + return "Frequency must be provided."; + } + if (!Frequency.values.contains(value)) { + return "Value not valid."; + } + return null; + }, + onChanged: (value) { + _freq = value!; + }, + ), + TextFormField( + keyboardType: TextInputType.text, + textCapitalization: TextCapitalization.sentences, + decoration: InputDecoration( + labelText: "Description", + hintText: + "Example: 1GB data with unlimited talk & text.", + hintStyle: TextStyle(fontSize: 8.0), + errorStyle: TextStyle(fontSize: 10.0), + ), + initialValue: _desc, + validator: (value) { + return null; + }, + onSaved: (value) { + _desc = value!; + }, + ), + ], ), - validator: (value) { - if (value == null) { - return "Frequency must be provided."; - } - if (!Frequency.values.contains(value)) { - return "Value not valid."; - } - return null; - }, - onChanged: (value) { - _freq = value!; - }, - ), - TextFormField( - keyboardType: TextInputType.text, - textCapitalization: TextCapitalization.sentences, - decoration: InputDecoration( - labelText: "Description", - hintText: "Example: 1GB data with unlimited talk & text.", - hintStyle: TextStyle(fontSize: 8.0), - errorStyle: TextStyle(fontSize: 10.0), - ), - initialValue: _desc, - validator: (value) { - return null; - }, - onSaved: (value) { - _desc = value!; - }, - ), - ], - ), - ), + ); + }), actions: [ Center( child: ElevatedButton.icon(