# Authentication Feature Integration Guide Quick guide to integrate the authentication feature into the warehouse management app. ## Prerequisites Ensure these dependencies are in `pubspec.yaml`: ```yaml dependencies: flutter_riverpod: ^2.4.9 dartz: ^0.10.1 flutter_secure_storage: ^9.0.0 dio: ^5.3.2 equatable: ^2.0.5 go_router: ^12.1.3 ``` ## Step 1: Update Main App ### Update `lib/main.dart` ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'core/routing/app_router.dart'; import 'core/theme/app_theme.dart'; void main() { runApp( const ProviderScope( child: MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp.router( title: 'Warehouse Manager', theme: AppTheme.lightTheme, darkTheme: AppTheme.darkTheme, routerConfig: appRouter, debugShowCheckedModeBanner: false, ); } } ``` ## Step 2: Update Router Configuration ### Update `lib/core/routing/app_router.dart` ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../features/auth/auth.dart'; import '../../features/auth/di/auth_dependency_injection.dart'; // Create a global key for navigator final navigatorKey = GlobalKey(); // Router provider final appRouterProvider = Provider((ref) { return GoRouter( navigatorKey: navigatorKey, initialLocation: '/login', routes: [ // Login route GoRoute( path: '/login', name: 'login', builder: (context, state) => const LoginPage(), ), // Warehouses route (protected) GoRoute( path: '/warehouses', name: 'warehouses', builder: (context, state) => const WarehouseSelectionPage(), // TODO: Create this ), // Add more routes as needed... ], // Redirect logic for authentication redirect: (context, state) { // Get auth state from provider container final container = ProviderScope.containerOf(context); final authState = container.read(authProvider); final isAuthenticated = authState.isAuthenticated; final isLoggingIn = state.matchedLocation == '/login'; // If not authenticated and not on login page, redirect to login if (!isAuthenticated && !isLoggingIn) { return '/login'; } // If authenticated and on login page, redirect to warehouses if (isAuthenticated && isLoggingIn) { return '/warehouses'; } // No redirect needed return null; }, ); }); // Export the router instance final appRouter = GoRouter( navigatorKey: navigatorKey, initialLocation: '/login', routes: [ GoRoute( path: '/login', name: 'login', builder: (context, state) => const LoginPage(), ), GoRoute( path: '/warehouses', name: 'warehouses', builder: (context, state) => const Scaffold( body: Center(child: Text('Warehouses Page - TODO')), ), ), ], ); ``` ## Step 3: Configure API Base URL ### Update `lib/core/constants/app_constants.dart` ```dart class AppConstants { // API Configuration static const String apiBaseUrl = 'https://your-api-url.com'; static const int connectionTimeout = 30000; static const int receiveTimeout = 30000; static const int sendTimeout = 30000; // Other constants... } ``` ## Step 4: Create Protected Route Wrapper (Optional) ### Create `lib/core/widgets/protected_route.dart` ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../features/auth/di/auth_dependency_injection.dart'; class ProtectedRoute extends ConsumerWidget { final Widget child; const ProtectedRoute({ super.key, required this.child, }); @override Widget build(BuildContext context, WidgetRef ref) { final authState = ref.watch(authProvider); // Show loading while checking auth if (authState.isLoading) { return const Scaffold( body: Center( child: CircularProgressIndicator(), ), ); } // Redirect to login if not authenticated if (!authState.isAuthenticated) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go('/login'); }); return const SizedBox.shrink(); } // Show protected content return child; } } ``` ## Step 5: Add Logout Button (Optional) ### Example usage in any page: ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:minhthu/features/auth/di/auth_dependency_injection.dart'; class SettingsPage extends ConsumerWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar( title: const Text('Settings'), actions: [ IconButton( icon: const Icon(Icons.logout), onPressed: () { // Show confirmation dialog showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Logout'), content: const Text('Are you sure you want to logout?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Cancel'), ), TextButton( onPressed: () { Navigator.pop(context); ref.read(authProvider.notifier).logout(); }, child: const Text('Logout'), ), ], ), ); }, ), ], ), body: const Center( child: Text('Settings'), ), ); } } ``` ## Step 6: Handle API Client Setup ### Update `lib/core/di/core_providers.dart` (create if needed) ```dart import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../network/api_client.dart'; import '../storage/secure_storage.dart'; /// Provider for SecureStorage singleton final secureStorageProvider = Provider((ref) { return SecureStorage(); }); /// Provider for ApiClient final apiClientProvider = Provider((ref) { final secureStorage = ref.watch(secureStorageProvider); final apiClient = ApiClient(secureStorage); // Set up unauthorized callback to handle 401 errors apiClient.onUnauthorized = () { // Navigate to login when unauthorized // This can be enhanced with proper navigation context }; return apiClient; }); ``` ## Step 7: Test the Integration ### Manual Testing Checklist 1. **Login Flow** - [ ] App starts on login page - [ ] Form validation works - [ ] Login with valid credentials succeeds - [ ] Navigate to warehouses page after login - [ ] Tokens saved in secure storage 2. **Error Handling** - [ ] Invalid credentials show error message - [ ] Network errors display properly - [ ] Error messages are user-friendly 3. **Persistence** - [ ] Close and reopen app stays logged in - [ ] Tokens persisted in secure storage - [ ] Auto-redirect to warehouses if authenticated 4. **Logout** - [ ] Logout clears tokens - [ ] Redirect to login page after logout - [ ] Cannot access protected routes after logout 5. **Loading States** - [ ] Loading indicator shows during login - [ ] Form disabled during loading - [ ] No double submissions ## Step 8: Environment Configuration (Optional) ### Create `lib/core/config/environment.dart` ```dart enum Environment { development, staging, production, } class EnvironmentConfig { static Environment current = Environment.development; static String get apiBaseUrl { switch (current) { case Environment.development: return 'https://dev-api.example.com'; case Environment.staging: return 'https://staging-api.example.com'; case Environment.production: return 'https://api.example.com'; } } } ``` ## Troubleshooting ### Issue: "Provider not found" **Solution**: Ensure `ProviderScope` wraps your app in `main.dart` ### Issue: "Navigation doesn't work" **Solution**: Verify router configuration and route names match ### Issue: "Secure storage error" **Solution**: - Add platform-specific configurations - Check app permissions - Clear app data and reinstall ### Issue: "API calls fail" **Solution**: - Verify API base URL in `app_constants.dart` - Check network connectivity - Verify API endpoint paths in `api_endpoints.dart` ## Next Steps 1. **Create Warehouse Feature** - Follow similar pattern 2. **Add Token Refresh** - Implement auto token refresh 3. **Add Remember Me** - Optional persistent login 4. **Add Biometric Auth** - Face ID / Touch ID 5. **Add Unit Tests** - Test use cases and repositories 6. **Add Widget Tests** - Test UI components ## Additional Resources - [Riverpod Documentation](https://riverpod.dev/) - [Go Router Documentation](https://pub.dev/packages/go_router) - [Clean Architecture Guide](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) - [Flutter Secure Storage](https://pub.dev/packages/flutter_secure_storage) ## Support For issues or questions: 1. Check the main README in `lib/features/auth/README.md` 2. Review the CLAUDE.md for project guidelines 3. Check existing code examples in the codebase