import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../providers/auth_provider.dart'; import '../../../providers/database_provider.dart'; class InitPage extends ConsumerStatefulWidget { const InitPage({super.key}); @override ConsumerState createState() => _InitPageState(); } class _InitPageState extends ConsumerState { final _codiceCtrl = TextEditingController(); final _passwordCtrl = TextEditingController(); final _ragsocCtrl = TextEditingController(); final _urlCtrl = TextEditingController(); final _formKey = GlobalKey(); bool _obscurePassword = true; @override void initState() { super.initState(); _loadUrl(); } Future _loadUrl() async { final url = await ref.read(parametriDaoProvider).read('URL'); _urlCtrl.text = url ?? 'https://'; } @override void dispose() { _codiceCtrl.dispose(); _passwordCtrl.dispose(); _ragsocCtrl.dispose(); _urlCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final authState = ref.watch(authProvider); final theme = Theme.of(context); final cs = theme.colorScheme; return Scaffold( body: SafeArea( top: false, child: Stack( children: [ Positioned( top: -MediaQuery.of(context).size.height * 0.08, right: -MediaQuery.of(context).size.width * 0.05, child: Container( width: 320, height: 320, decoration: BoxDecoration( color: cs.secondaryContainer.withValues(alpha: 0.15), shape: BoxShape.circle, ), ), ), Positioned( bottom: -MediaQuery.of(context).size.height * 0.08, left: -MediaQuery.of(context).size.width * 0.05, child: Container( width: 320, height: 320, decoration: BoxDecoration( color: cs.primaryContainer.withValues(alpha: 0.08), shape: BoxShape.circle, ), ), ), Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 400), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 32), _buildBrandHeader(theme, cs), const SizedBox(height: 32), _buildFormCard(authState, theme, cs), const SizedBox(height: 32), const SizedBox(height: 24), ], ), ), ), ), ], ), ), ); } Widget _buildBrandHeader(ThemeData theme, ColorScheme cs) { return Column( children: [ Container( width: 64, height: 64, decoration: BoxDecoration( color: cs.primary, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.15), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: const Icon(Icons.store, color: Colors.white, size: 40), ), const SizedBox(height: 16), Text( 'Benvenuto in PowerAge', style: theme.textTheme.headlineLarge?.copyWith( color: cs.primary, letterSpacing: -0.02, ), ), const SizedBox(height: 8), Text( 'Configura il tuo account agente per iniziare', textAlign: TextAlign.center, style: theme.textTheme.bodyMedium?.copyWith( color: cs.onSurfaceVariant, ), ), ], ); } Widget _buildFormCard(AuthState authState, ThemeData theme, ColorScheme cs) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: cs.outlineVariant), boxShadow: [ BoxShadow( color: const Color(0xFF0F172A).withValues(alpha: 0.05), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Padding( padding: const EdgeInsets.all(24), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildLabeledField( label: 'Codice Agente', icon: Icons.badge_outlined, controller: _codiceCtrl, hintText: 'Inserisci il codice agente', validator: (v) => v == null || v.isEmpty ? 'Campo obbligatorio' : null, ), const SizedBox(height: 16), _buildPasswordField(cs), const SizedBox(height: 16), _buildLabeledField( label: 'Ragione Sociale (opzionale)', icon: Icons.person_outline, controller: _ragsocCtrl, hintText: 'Inserisci la ragione sociale', ), const SizedBox(height: 16), _buildLabeledField( label: 'URL Backend', icon: Icons.link, controller: _urlCtrl, hintText: 'https://api.powerage.cloud', validator: (v) => v == null || v.isEmpty ? 'Campo obbligatorio' : null, ), const SizedBox(height: 24), FilledButton.icon( onPressed: authState.isLoading ? null : () { if (_formKey.currentState!.validate()) { ref .read(authProvider.notifier) .initialize( idAgente: 1, codAgente: _codiceCtrl.text, password: _passwordCtrl.text, ragioneSociale: _ragsocCtrl.text.isEmpty ? null : _ragsocCtrl.text, url: _urlCtrl.text, ); } }, icon: authState.isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Icon(Icons.arrow_forward), label: Text( authState.isLoading ? 'Configurazione...' : 'Configura', ), ), if (authState.error != null) ...[ const SizedBox(height: 16), _buildErrorCard(authState.error!, cs), ], ], ), ), ), ); } Widget _buildLabeledField({ required String label, required IconData icon, required TextEditingController controller, required String hintText, String? Function(String?)? validator, }) { final cs = Theme.of(context).colorScheme; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12, height: 16 / 12, fontWeight: FontWeight.w600, color: cs.onSurface, ), ), const SizedBox(height: 8), TextFormField( controller: controller, decoration: InputDecoration( hintText: hintText, prefixIcon: Icon(icon, size: 20), ), validator: validator, ), ], ); } Widget _buildPasswordField(ColorScheme cs) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Password', style: TextStyle( fontSize: 12, height: 16 / 12, fontWeight: FontWeight.w600, color: cs.onSurface, ), ), const SizedBox(height: 8), TextFormField( controller: _passwordCtrl, obscureText: _obscurePassword, decoration: InputDecoration( hintText: '', prefixIcon: const Icon(Icons.lock_outline, size: 20), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_outlined : Icons.visibility_off_outlined, size: 20, ), onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), ), validator: (v) => v == null || v.isEmpty ? 'Campo obbligatorio' : null, ), ], ); } Widget _buildErrorCard(String error, ColorScheme cs) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: cs.errorContainer, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Icon(Icons.error_outline, color: cs.error, size: 20), const SizedBox(width: 8), Expanded( child: Text( error, style: TextStyle(color: cs.onErrorContainer, fontSize: 14), ), ), ], ), ); } }