Files
companion/lib/features/onboarding/steps/step_admin_user.dart
T
2026-05-07 18:35:58 +02:00

109 lines
3.2 KiB
Dart

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<StepAdminUser> createState() => _StepAdminUserState();
}
class _StepAdminUserState extends ConsumerState<StepAdminUser> {
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
bool _loading = false;
String? _error;
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
Future<void> _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'),
),
],
),
);
}
}