import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/constants.dart'; import '../../providers/settings_provider.dart'; class SetupScreen extends ConsumerStatefulWidget { const SetupScreen({super.key}); @override ConsumerState createState() => _SetupScreenState(); } class _SetupScreenState extends ConsumerState { final _formKey = GlobalKey(); final _urlController = TextEditingController(); bool _testing = false; String? _error; @override void dispose() { _urlController.dispose(); super.dispose(); } Future _testAndSave() async { if (!_formKey.currentState!.validate()) return; setState(() { _testing = true; _error = null; }); var url = _urlController.text.trim(); if (url.endsWith('/')) url = url.substring(0, url.length - 1); try { final dio = Dio(BaseOptions(connectTimeout: const Duration(seconds: 5))); await dio.get('$url/api/auth/status'); // 401 is fine — server is reachable } on DioException catch (_) { setState(() { _testing = false; _error = 'Could not reach server. Check the URL and try again.'; }); return; } catch (e) { setState(() { _testing = false; _error = 'Could not reach server. Check the URL and try again.'; }); return; } await ref.read(serverUrlProvider.notifier).setUrl(url); if (mounted) context.go(Routes.login); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Padding( padding: const EdgeInsets.all(24), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( 'Welcome to Fabled', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), const SizedBox(height: 8), const Text( 'Enter your FabledAssistant server URL to get started.', textAlign: TextAlign.center, ), const SizedBox(height: 32), TextFormField( controller: _urlController, decoration: const InputDecoration( labelText: 'Server URL', hintText: 'https://fabled.example.com', border: OutlineInputBorder(), ), keyboardType: TextInputType.url, autocorrect: false, validator: (v) { if (v == null || v.trim().isEmpty) return 'Required'; final uri = Uri.tryParse(v.trim()); if (uri == null || !uri.hasScheme) { return 'Enter a valid URL (include http:// or https://)'; } return null; }, ), if (_error != null) ...[ const SizedBox(height: 8), Text(_error!, style: TextStyle(color: Theme.of(context).colorScheme.error)), ], const SizedBox(height: 24), FilledButton( onPressed: _testing ? null : _testAndSave, child: _testing ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Text('Connect'), ), ], ), ), ), ), ); } }