Merge pull request #4 from DieLustigenTierwesen/copilot/sub-pr-1-another-one
Add input validation for collection names
This commit is contained in:
commit
69b54de89d
2 changed files with 63 additions and 37 deletions
|
|
@ -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'),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -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'),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue