import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../auth/application/auth_notifier.dart'; import '../../application/suggestions_notifier.dart'; /// Form for submitting a new community suggestion. /// /// Owns its own [TextEditingController] and the "anonymous" toggle. Wires /// into [suggestionsNotifierProvider] for submission state — the FilledButton /// switches to a spinner while loading, and shows snackbars on success/error. class SuggestionForm extends ConsumerStatefulWidget { const SuggestionForm({super.key}); static const int _maxChars = 500; static const int _minChars = 10; @override ConsumerState createState() => _SuggestionFormState(); } class _SuggestionFormState extends ConsumerState { final _formKey = GlobalKey(); final _controller = TextEditingController(); bool _isAnonymous = false; @override void dispose() { _controller.dispose(); super.dispose(); } String? _validate(String? value) { final text = value?.trim() ?? ''; if (text.length < SuggestionForm._minChars) { return 'Please write at least ${SuggestionForm._minChars} characters.'; } return null; } Future _onSubmit() async { if (!(_formKey.currentState?.validate() ?? false)) return; FocusScope.of(context).unfocus(); final user = ref.read(authNotifierProvider).valueOrNull; final messenger = ScaffoldMessenger.of(context); await ref.read(suggestionsNotifierProvider.notifier).submit( text: _controller.text, isAnonymous: _isAnonymous, userId: user?.uid, displayName: user?.displayName, ); if (!mounted) return; final state = ref.read(suggestionsNotifierProvider); state.when( data: (_) { _controller.clear(); _formKey.currentState?.reset(); setState(() {}); messenger.showSnackBar( const SnackBar(content: Text('Thanks for your suggestion!')), ); }, loading: () {}, error: (err, _) { messenger.showSnackBar( SnackBar( content: Text('Could not submit suggestion: $err'), ), ); }, ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final colors = theme.colorScheme; final submissionState = ref.watch(suggestionsNotifierProvider); final isSubmitting = submissionState.isLoading; final authUser = ref.watch(authNotifierProvider).valueOrNull; final submittingAs = (!_isAnonymous && authUser != null) ? (authUser.displayName?.trim().isNotEmpty ?? false ? authUser.displayName!.trim() : authUser.email) : null; return Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Share an idea', style: theme.textTheme.titleLarge, ), const SizedBox(height: 4), Text( 'Tell us what would make Winded better — new features, ' 'tournament formats, anything.', style: theme.textTheme.bodyMedium?.copyWith( color: colors.onSurfaceVariant, ), ), const SizedBox(height: 16), TextFormField( controller: _controller, enabled: !isSubmitting, minLines: 3, maxLines: 8, maxLength: SuggestionForm._maxChars, textInputAction: TextInputAction.newline, keyboardType: TextInputType.multiline, inputFormatters: [ LengthLimitingTextInputFormatter(SuggestionForm._maxChars), ], validator: _validate, autovalidateMode: AutovalidateMode.onUserInteraction, onChanged: (_) => setState(() {}), decoration: const InputDecoration( hintText: 'Type your suggestion here…', border: OutlineInputBorder(), alignLabelWithHint: true, ), ), const SizedBox(height: 8), SwitchListTile.adaptive( value: _isAnonymous, onChanged: isSubmitting ? null : (value) => setState(() => _isAnonymous = value), contentPadding: EdgeInsets.zero, title: const Text('Submit anonymously'), subtitle: Text( _isAnonymous ? 'Your name will not be attached to this suggestion.' : 'Admins will see who submitted this.', style: theme.textTheme.bodySmall?.copyWith( color: colors.onSurfaceVariant, ), ), ), if (submittingAs != null) ...[ const SizedBox(height: 4), Row( children: [ Icon( Icons.person_outline, size: 16, color: colors.onSurfaceVariant, ), const SizedBox(width: 6), Expanded( child: Text( 'Submitting as: $submittingAs', style: theme.textTheme.bodySmall?.copyWith( color: colors.onSurfaceVariant, ), ), ), ], ), ], const SizedBox(height: 16), FilledButton.icon( onPressed: isSubmitting ? null : _onSubmit, icon: isSubmitting ? SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, color: colors.onPrimary, ), ) : const Icon(Icons.send_outlined), label: Text(isSubmitting ? 'Submitting…' : 'Submit Suggestion'), ), ], ), ); } }