import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../data/sources/localiser/realtime_data_client.dart'; import '../../../providers.dart'; class StepAdminUser extends ConsumerStatefulWidget { const StepAdminUser({super.key, required this.onComplete}); final VoidCallback onComplete; @override ConsumerState createState() => _StepAdminUserState(); } class _StepAdminUserState extends ConsumerState { final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); bool _loading = false; String? _error; @override void dispose() { _usernameController.dispose(); _passwordController.dispose(); super.dispose(); } Future _submit() async { setState(() { _loading = true; _error = null; }); try { final username = _usernameController.text.trim(); final password = _passwordController.text; final token = await ref.read(onboardingRepositoryProvider).createAdminUser( username: username, password: password, ); ref.read(authTokenProvider.notifier).state = token; final config = ref.read(serverConfigProvider)!; final realtime = RealtimeDataClient(config: config, token: token); await realtime.connect(); ref.read(realtimeDataClientProvider.notifier).state = realtime; await ref .read(credentialStoreProvider) .save((username: username, password: password)); widget.onComplete(); } catch (e) { setState(() => _error = e.toString()); } finally { if (mounted) setState(() => _loading = false); } } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text('Create admin account', style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 24), TextField( controller: _usernameController, decoration: const InputDecoration( labelText: 'Username', border: OutlineInputBorder(), ), ), const SizedBox(height: 12), TextField( controller: _passwordController, decoration: const InputDecoration( labelText: 'Password', border: OutlineInputBorder(), ), obscureText: true, ), const SizedBox(height: 16), if (_error != null) Padding( padding: const EdgeInsets.only(bottom: 12), child: Text(_error!, style: TextStyle(color: Theme.of(context).colorScheme.error)), ), FilledButton( onPressed: _loading ? null : _submit, child: _loading ? const SizedBox.square( dimension: 20, child: CircularProgressIndicator(strokeWidth: 2)) : const Text('Create account'), ), ], ), ); } }