import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:odoo_rpc/odoo_rpc.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../services/odoo_service.dart'; import '../services/config.dart'; import 'loyalty_dashboard.dart'; import 'branches_screen.dart'; import 'activation_screen.dart'; import 'signup_screen.dart'; import 'forgot_password_screen.dart'; import '../theme/app_theme.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { final _phoneController = TextEditingController(); final _passwordController = TextEditingController(); bool _isLoading = false; void _login() async { setState(() => _isLoading = true); try { final service = OdooService(); service.connect(AppConfig.odooUrl); final session = await service.login( AppConfig.odooDb, _phoneController.text.trim(), _passwordController.text.trim(), ); final prefs = await SharedPreferences.getInstance(); await prefs.setString('odoo_url', AppConfig.odooUrl); // Use the library's own toJson() to ensure keys exactly match fromJson() on restore await prefs.setString('odoo_session', json.encode(session.toJson())); if (mounted) { Navigator.pushReplacement( context, MaterialPageRoute( builder: (_) => LoyaltyDashboard(partnerId: session.partnerId), ), ); } } on OdooException catch (e) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text('Login failed: ${e.message}'))); } catch (e) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text('Error: $e'))); } finally { if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.only( left: 32.0, right: 32.0, top: 80.0, bottom: 48.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 64), Text( 'Mie Mapan\nMembership.', style: Theme.of(context).textTheme.displayLarge?.copyWith( color: AppTheme.onSurface, fontSize: 48, ), ), const SizedBox(height: 12), Text( 'Sign in to access your culinary loyalty tier and discover exclusive offers.', style: Theme.of(context).textTheme.bodyLarge?.copyWith( color: AppTheme.onSurfaceVariant, ), ), const SizedBox(height: 80), TextField( controller: _phoneController, keyboardType: TextInputType.phone, decoration: const InputDecoration( labelText: 'Phone Number', hintText: 'e.g. 08123456789', ), ), const SizedBox(height: 20), TextField( controller: _passwordController, decoration: const InputDecoration(labelText: 'Password'), obscureText: true, ), const SizedBox(height: 8), Align( alignment: Alignment.centerRight, child: TextButton( onPressed: () => Navigator.push( context, MaterialPageRoute( builder: (_) => const ForgotPasswordScreen(), ), ), style: TextButton.styleFrom( foregroundColor: AppTheme.onSurfaceVariant, padding: EdgeInsets.zero, ), child: const Text( 'Forgot Password?', style: TextStyle( fontSize: 13, ), ), ), ), const SizedBox(height: 24), SizedBox( height: 56, child: _isLoading ? const Center(child: CircularProgressIndicator()) : ElevatedButton( onPressed: _login, child: const Text( 'Access Membership', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( onPressed: () => Navigator.push( context, MaterialPageRoute( builder: (_) => const ActivationScreen(), ), ), style: TextButton.styleFrom( foregroundColor: AppTheme.secondary, padding: EdgeInsets.zero, ), child: const Text( 'Activate Account', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 13, ), ), ), TextButton( onPressed: () => Navigator.push( context, MaterialPageRoute(builder: (_) => const SignupScreen()), ), style: TextButton.styleFrom( foregroundColor: AppTheme.secondary, padding: EdgeInsets.zero, ), child: const Text( 'Sign Up', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 13, ), ), ), ], ), const SizedBox(height: 24), Center( child: GestureDetector( onTap: () => Navigator.push( context, MaterialPageRoute(builder: (_) => const BranchesScreen()), ), child: Container( decoration: const BoxDecoration( border: Border( bottom: BorderSide(color: AppTheme.primary, width: 4), ), ), padding: const EdgeInsets.only(bottom: 2), child: const Text( 'Find Nearest Branch', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, color: AppTheme.onSurface, ), ), ), ), ), ], ), ), ), ); } }