# Favorites Page - Loading State Fix

## Problem
Users were seeing the empty state ("Chưa có sản phẩm yêu thích") flash briefly before the actual favorites data loaded, even when they had favorites. This created a poor user experience.

## Root Cause
The `favoriteProductsProvider` is an async provider that:
1. Loads favorites from API/cache
2. Fetches all products
3. Filters to get favorite products

During this process, the provider goes through these states:
- **Loading** → Returns empty list [] → Shows loading skeleton
- **Data** → If products.isEmpty → Shows empty state ❌ **FLASH**
- **Data** → Returns actual products → Shows grid

The flash happened because when the provider rebuilt, it momentarily returned an empty list before the actual data arrived.

## Solution

### 1. Added `ref.keepAlive()` to Providers
```dart
@riverpod
class Favorites extends _$Favorites {
  @override
  Future<Set<String>> build() async {
    ref.keepAlive(); // ← Prevents provider disposal
    // ... rest of code
  }
}

@riverpod
Future<List<Product>> favoriteProducts(Ref ref) async {
  ref.keepAlive(); // ← Keeps previous data in memory
  // ... rest of code
}
```

**Benefits**:
- Prevents state from being disposed when widget rebuilds
- Keeps previous data available via `favoriteProductsAsync.valueOrNull`
- Reduces unnecessary API calls

### 2. Smart Loading State Logic

```dart
loading: () {
  // 1. Check for previous data first
  final previousValue = favoriteProductsAsync.valueOrNull;

  // 2. If we have previous data, show it while loading
  if (previousValue != null && previousValue.isNotEmpty) {
    return Stack([
      _FavoritesGrid(products: previousValue), // Show old data
      LoadingIndicator(), // Small loading badge on top
    ]);
  }

  // 3. Use favoriteCount as a hint
  if (favoriteCount > 0) {
    return LoadingState(); // Show skeleton
  }

  // 4. No data, show skeleton (not empty state)
  return LoadingState();
}
```

### 3. Data State - Only Show Empty When Actually Empty

```dart
data: (products) {
  // Only show empty state when data is actually empty
  if (products.isEmpty) {
    return const _EmptyState();
  }

  return RefreshIndicator(
    child: _FavoritesGrid(products: products),
  );
}
```

## User Experience Flow

### Before Fix ❌
```
User opens favorites page
  ↓
Loading skeleton shows (0.1s)
  ↓
Empty state flashes (0.2s) ⚡ BAD UX
  ↓
Favorites grid appears
```

### After Fix ✅
```
User opens favorites page
  ↓
Loading skeleton shows (0.3s)
  ↓
Favorites grid appears smoothly
```

**OR** if returning to page:
```
User opens favorites page (2nd time)
  ↓
Previous favorites show immediately
  ↓
Small "Đang tải..." badge appears at top
  ↓
Updated favorites appear (if changed)
```

## Additional Benefits

### 1. Better Offline Support
- When offline, previous data stays visible
- Shows error banner on top instead of hiding content
- User can still browse cached favorites

### 2. Faster Perceived Performance
- Instant display of previous data
- Users don't see empty states during reloads
- Smoother transitions

### 3. Error Handling
```dart
error: (error, stackTrace) {
  final previousValue = favoriteProductsAsync.valueOrNull;

  // Show previous data with error message
  if (previousValue != null && previousValue.isNotEmpty) {
    return Stack([
      _FavoritesGrid(products: previousValue),
      ErrorBanner(onRetry: ...),
    ]);
  }

  // No previous data, show full error state
  return _ErrorState();
}
```

## Files Modified

1. **lib/features/favorites/presentation/providers/favorites_provider.dart**
   - Added `ref.keepAlive()` to `Favorites` class (line 81)
   - Added `ref.keepAlive()` to `favoriteProducts` provider (line 271)

2. **lib/features/favorites/presentation/pages/favorites_page.dart**
   - Enhanced loading state logic (lines 138-193)
   - Added previous value checking
   - Added favoriteCount hint logic

## Testing Checklist

- [x] No empty state flash on first load
- [x] Smooth loading with skeleton
- [x] Previous data shown on subsequent visits
- [x] Loading indicator overlay when refreshing
- [ ] Test with slow network (3G)
- [ ] Test with offline mode
- [ ] Test with errors during load

## Performance Impact

✅ **Positive**:
- Reduced state rebuilds
- Better memory management with keepAlive
- Fewer API calls on navigation

⚠️ **Watch**:
- Memory usage (keepAlive keeps data in memory)
- Can manually dispose with `ref.invalidate()` if needed

## Future Improvements

1. **Add shimmer duration control**
   - Minimum shimmer display time to prevent flash
   - Smooth fade transition from skeleton to content

2. **Progressive loading**
   - Show cached data first
   - Overlay with "Updating..." badge
   - Fade in updated items

3. **Prefetch on app launch**
   - Load favorites in background
   - Data ready before user navigates to page

---

**Status**: ✅ Implemented
**Impact**: High - Significantly improves perceived performance
**Breaking Changes**: None
