# App Router Documentation

Complete navigation setup for the warehouse management application using GoRouter.

## Overview

The app router implements authentication-based navigation with proper redirect logic:
- **Unauthenticated users** are redirected to `/login`
- **Authenticated users** on `/login` are redirected to `/warehouses`
- Type-safe parameter passing between routes
- Integration with SecureStorage for authentication checks

## App Flow

```
Login → Warehouses → Operations → Products
```

1. **Login**: User authenticates and token is stored
2. **Warehouses**: User selects a warehouse
3. **Operations**: User chooses Import or Export
4. **Products**: Display products based on warehouse and operation

## Routes

### `/login` - Login Page
- **Name**: `login`
- **Purpose**: User authentication
- **Parameters**: None
- **Redirect**: If authenticated → `/warehouses`

### `/warehouses` - Warehouse Selection Page
- **Name**: `warehouses`
- **Purpose**: Display list of warehouses
- **Parameters**: None
- **Protected**: Requires authentication

### `/operations` - Operation Selection Page
- **Name**: `operations`
- **Purpose**: Choose Import or Export operation
- **Parameters**:
  - `extra`: `WarehouseEntity` object
- **Protected**: Requires authentication
- **Validation**: Redirects to `/warehouses` if warehouse data is missing

### `/products` - Products List Page
- **Name**: `products`
- **Purpose**: Display products for warehouse and operation
- **Parameters**:
  - `extra`: `Map<String, dynamic>` containing:
    - `warehouse`: `WarehouseEntity` object
    - `warehouseName`: `String`
    - `operationType`: `String` ('import' or 'export')
- **Protected**: Requires authentication
- **Validation**: Redirects to `/warehouses` if parameters are invalid

## Usage Examples

### Basic Navigation

```dart
import 'package:go_router/go_router.dart';

// Navigate to login
context.go('/login');

// Navigate to warehouses
context.go('/warehouses');
```

### Navigation with Extension Methods

```dart
import 'package:minhthu/core/router/app_router.dart';

// Navigate to login
context.goToLogin();

// Navigate to warehouses
context.goToWarehouses();

// Navigate to operations with warehouse
context.goToOperations(warehouse);

// Navigate to products with warehouse and operation type
context.goToProducts(
  warehouse: warehouse,
  operationType: 'import',
);

// Go back
context.goBack();
```

### Named Route Navigation

```dart
// Using named routes
context.goToLoginNamed();
context.goToWarehousesNamed();
context.goToOperationsNamed(warehouse);
context.goToProductsNamed(
  warehouse: warehouse,
  operationType: 'export',
);
```

## Integration with Warehouse Selection

### Example: Navigate from Warehouse to Operations

```dart
import 'package:flutter/material.dart';
import 'package:minhthu/core/router/app_router.dart';
import 'package:minhthu/features/warehouse/domain/entities/warehouse_entity.dart';

class WarehouseCard extends StatelessWidget {
  final WarehouseEntity warehouse;

  const WarehouseCard({required this.warehouse});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        title: Text(warehouse.name),
        subtitle: Text('Code: ${warehouse.code}'),
        trailing: Icon(Icons.arrow_forward),
        onTap: () {
          // Navigate to operations page
          context.goToOperations(warehouse);
        },
      ),
    );
  }
}
```

### Example: Navigate from Operations to Products

```dart
import 'package:flutter/material.dart';
import 'package:minhthu/core/router/app_router.dart';
import 'package:minhthu/features/warehouse/domain/entities/warehouse_entity.dart';

class OperationButton extends StatelessWidget {
  final WarehouseEntity warehouse;
  final String operationType;

  const OperationButton({
    required this.warehouse,
    required this.operationType,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        // Navigate to products page
        context.goToProducts(
          warehouse: warehouse,
          operationType: operationType,
        );
      },
      child: Text(operationType == 'import'
        ? 'Import Products'
        : 'Export Products'),
    );
  }
}
```

## Authentication Integration

The router automatically checks authentication status on every navigation:

```dart
// In app_router.dart
Future<String?> _handleRedirect(
  BuildContext context,
  GoRouterState state,
) async {
  // Check if user has access token
  final isAuthenticated = await secureStorage.isAuthenticated();
  final isOnLoginPage = state.matchedLocation == '/login';

  // Redirect logic
  if (!isAuthenticated && !isOnLoginPage) {
    return '/login'; // Redirect to login
  }

  if (isAuthenticated && isOnLoginPage) {
    return '/warehouses'; // Redirect to warehouses
  }

  return null; // Allow navigation
}
```

### SecureStorage Integration

The router uses `SecureStorage` to check authentication:

```dart
// Check if authenticated
final isAuthenticated = await secureStorage.isAuthenticated();

// This checks if access token exists
Future<bool> isAuthenticated() async {
  final token = await getAccessToken();
  return token != null && token.isNotEmpty;
}
```

## Reactive Navigation

The router automatically reacts to authentication state changes:

```dart
class GoRouterRefreshStream extends ChangeNotifier {
  final Ref ref;

  GoRouterRefreshStream(this.ref) {
    // Listen to auth state changes
    ref.listen(
      authProvider, // From auth_dependency_injection.dart
      (_, __) => notifyListeners(),
    );
  }
}
```

When authentication state changes (login/logout), the router:
1. Receives notification
2. Re-evaluates redirect logic
3. Automatically redirects to appropriate page

## Error Handling

### Missing Parameters

If route parameters are missing, the user is redirected:

```dart
GoRoute(
  path: '/operations',
  builder: (context, state) {
    final warehouse = state.extra as WarehouseEntity?;

    if (warehouse == null) {
      // Show error and redirect
      WidgetsBinding.instance.addPostFrameCallback((_) {
        context.go('/warehouses');
      });
      return const _ErrorScreen(
        message: 'Warehouse data is required',
      );
    }

    return OperationSelectionPage(warehouse: warehouse);
  },
),
```

### Page Not Found

Custom 404 error page:

```dart
errorBuilder: (context, state) {
  return Scaffold(
    appBar: AppBar(title: const Text('Page Not Found')),
    body: Center(
      child: Column(
        children: [
          Icon(Icons.error_outline, size: 64),
          Text('Page "${state.uri.path}" does not exist'),
          ElevatedButton(
            onPressed: () => context.go('/login'),
            child: const Text('Go to Login'),
          ),
        ],
      ),
    ),
  );
}
```

## Setup in main.dart

```dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:minhthu/core/router/app_router.dart';
import 'package:minhthu/core/theme/app_theme.dart';

void main() {
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Get router from provider
    final router = ref.watch(appRouterProvider);

    return MaterialApp.router(
      title: 'Warehouse Manager',
      theme: AppTheme.lightTheme,
      routerConfig: router,
    );
  }
}
```

## Best Practices

### 1. Use Extension Methods
Prefer extension methods for type-safe navigation:
```dart
// Good
context.goToProducts(warehouse: warehouse, operationType: 'import');

// Avoid
context.go('/products', extra: {'warehouse': warehouse, 'operationType': 'import'});
```

### 2. Validate Parameters
Always validate route parameters:
```dart
final warehouse = state.extra as WarehouseEntity?;
if (warehouse == null) {
  // Handle error
}
```

### 3. Handle Async Operations
Use post-frame callbacks for navigation in builders:
```dart
WidgetsBinding.instance.addPostFrameCallback((_) {
  context.go('/warehouses');
});
```

### 4. Logout Implementation
Clear storage and let router handle redirect:
```dart
Future<void> logout() async {
  await ref.read(authProvider.notifier).logout();
  // Router will automatically redirect to /login
}
```

## Troubleshooting

### Issue: Redirect loop
**Cause**: Authentication check is not working properly
**Solution**: Verify SecureStorage has access token

### Issue: Parameters are null
**Cause**: Wrong parameter passing format
**Solution**: Use extension methods with correct types

### Issue: Navigation doesn't update
**Cause**: Auth state changes not triggering refresh
**Solution**: Verify GoRouterRefreshStream is listening to authProvider

## Related Files

- `/lib/core/router/app_router.dart` - Main router configuration
- `/lib/core/storage/secure_storage.dart` - Authentication storage
- `/lib/features/auth/di/auth_dependency_injection.dart` - Auth providers
- `/lib/features/auth/presentation/pages/login_page.dart` - Login page
- `/lib/features/warehouse/presentation/pages/warehouse_selection_page.dart` - Warehouse page
- `/lib/features/operation/presentation/pages/operation_selection_page.dart` - Operation page
- `/lib/features/products/presentation/pages/products_page.dart` - Products page
