Add input validation for collection names (min 2, max 50 chars)

Co-authored-by: derkauzigekoala <79001016+derkauzigekoala@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-02-24 19:20:50 +00:00
parent 0539a7725a
commit f789bb7eff
2 changed files with 63 additions and 37 deletions

View file

@ -50,6 +50,7 @@ class CollectionsScreenState extends State<CollectionsScreen> {
} }
Future<void> _createCollection() async { Future<void> _createCollection() async {
final formKey = GlobalKey<FormState>();
final nameCtrl = TextEditingController(); final nameCtrl = TextEditingController();
final descCtrl = TextEditingController(); final descCtrl = TextEditingController();
@ -65,16 +66,26 @@ class CollectionsScreenState extends State<CollectionsScreen> {
child: const Icon(Icons.add, color: Colors.white, size: 28), child: const Icon(Icons.add, color: Colors.white, size: 28),
), ),
title: const Text('New Collection'), title: const Text('New Collection'),
content: Column( content: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
TextField( TextFormField(
controller: nameCtrl, controller: nameCtrl,
autofocus: true, autofocus: true,
maxLength: 50,
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Name', labelText: 'Name',
hintText: 'e.g. Hot Wheels, Matchbox…', hintText: 'e.g. Hot Wheels, Matchbox…',
), ),
validator: (value) {
final trimmed = value?.trim() ?? '';
if (trimmed.isEmpty) return 'Name is required';
if (trimmed.length < 2) return 'Name must be at least 2 characters';
if (trimmed.length > 50) return 'Name must be 50 characters or fewer';
return null;
},
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
TextField( TextField(
@ -86,6 +97,7 @@ class CollectionsScreenState extends State<CollectionsScreen> {
), ),
], ],
), ),
),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
@ -93,8 +105,9 @@ class CollectionsScreenState extends State<CollectionsScreen> {
), ),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
if (nameCtrl.text.trim().isEmpty) return; if (formKey.currentState!.validate()) {
Navigator.pop(context, true); Navigator.pop(context, true);
}
}, },
child: const Text('Create'), child: const Text('Create'),
), ),

View file

@ -44,6 +44,7 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
} }
Future<void> _rename() async { Future<void> _rename() async {
final formKey = GlobalKey<FormState>();
final ctrl = TextEditingController(text: _collection.name); final ctrl = TextEditingController(text: _collection.name);
final descCtrl = final descCtrl =
TextEditingController(text: _collection.description ?? ''); TextEditingController(text: _collection.description ?? '');
@ -52,13 +53,23 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
context: context, context: context,
builder: (_) => AlertDialog( builder: (_) => AlertDialog(
title: const Text('Rename Collection'), title: const Text('Rename Collection'),
content: Column( content: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
TextField( TextFormField(
controller: ctrl, controller: ctrl,
autofocus: true, autofocus: true,
maxLength: 50,
decoration: const InputDecoration(labelText: 'Name'), decoration: const InputDecoration(labelText: 'Name'),
validator: (value) {
final trimmed = value?.trim() ?? '';
if (trimmed.isEmpty) return 'Name is required';
if (trimmed.length < 2) return 'Name must be at least 2 characters';
if (trimmed.length > 50) return 'Name must be 50 characters or fewer';
return null;
},
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
TextField( TextField(
@ -68,6 +79,7 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
), ),
], ],
), ),
),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
@ -75,8 +87,9 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
), ),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
if (ctrl.text.trim().isEmpty) return; if (formKey.currentState!.validate()) {
Navigator.pop(context, true); Navigator.pop(context, true);
}
}, },
child: const Text('Save'), child: const Text('Save'),
), ),