Merge pull request #4 from DieLustigenTierwesen/copilot/sub-pr-1-another-one

Add input validation for collection names
This commit is contained in:
Lukas Müllner 2026-02-24 20:44:39 +01:00 committed by GitHub
commit 69b54de89d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 63 additions and 37 deletions

View file

@ -50,6 +50,7 @@ class CollectionsScreenState extends State<CollectionsScreen> {
}
Future<void> _createCollection() async {
final formKey = GlobalKey<FormState>();
final nameCtrl = TextEditingController();
final descCtrl = TextEditingController();
@ -65,26 +66,37 @@ class CollectionsScreenState extends State<CollectionsScreen> {
child: const Icon(Icons.add, color: Colors.white, size: 28),
),
title: const Text('New Collection'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: nameCtrl,
autofocus: true,
decoration: const InputDecoration(
labelText: 'Name',
hintText: 'e.g. Hot Wheels, Matchbox…',
content: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: nameCtrl,
autofocus: true,
maxLength: 50,
decoration: const InputDecoration(
labelText: 'Name',
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),
TextField(
controller: descCtrl,
decoration: const InputDecoration(
labelText: 'Description (optional)',
hintText: 'What is this collection for?',
const SizedBox(height: 12),
TextField(
controller: descCtrl,
decoration: const InputDecoration(
labelText: 'Description (optional)',
hintText: 'What is this collection for?',
),
),
),
],
],
),
),
actions: [
TextButton(
@ -93,8 +105,9 @@ class CollectionsScreenState extends State<CollectionsScreen> {
),
ElevatedButton(
onPressed: () {
if (nameCtrl.text.trim().isEmpty) return;
Navigator.pop(context, true);
if (formKey.currentState!.validate()) {
Navigator.pop(context, true);
}
},
child: const Text('Create'),
),

View file

@ -44,6 +44,7 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
}
Future<void> _rename() async {
final formKey = GlobalKey<FormState>();
final ctrl = TextEditingController(text: _collection.name);
final descCtrl =
TextEditingController(text: _collection.description ?? '');
@ -52,21 +53,32 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
context: context,
builder: (_) => AlertDialog(
title: const Text('Rename Collection'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: ctrl,
autofocus: true,
decoration: const InputDecoration(labelText: 'Name'),
),
const SizedBox(height: 12),
TextField(
controller: descCtrl,
decoration:
const InputDecoration(labelText: 'Description (optional)'),
),
],
content: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: ctrl,
autofocus: true,
maxLength: 50,
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),
TextField(
controller: descCtrl,
decoration:
const InputDecoration(labelText: 'Description (optional)'),
),
],
),
),
actions: [
TextButton(
@ -75,8 +87,9 @@ class _ManageCollectionScreenState extends State<ManageCollectionScreen> {
),
ElevatedButton(
onPressed: () {
if (ctrl.text.trim().isEmpty) return;
Navigator.pop(context, true);
if (formKey.currentState!.validate()) {
Navigator.pop(context, true);
}
},
child: const Text('Save'),
),