270 lines
7.2 KiB
Markdown
270 lines
7.2 KiB
Markdown
# Loyalty Rewards Screen Integration Guide
|
|
|
|
## Overview
|
|
|
|
The loyalty rewards screen ("Đổi quà") has been successfully created following the HTML design specification from `html/loyalty-rewards.html`.
|
|
|
|
## Files Created
|
|
|
|
### 1. Providers
|
|
- **`providers/loyalty_points_provider.dart`** - Manages user's loyalty points balance
|
|
- Shows available points: 9,750
|
|
- Shows expiring points: 1,200 on 31/12/2023
|
|
- Methods: `refresh()`, `deductPoints()`, `addPoints()`, `hasEnoughPoints()`
|
|
|
|
- **`providers/gifts_provider.dart`** - Manages gift catalog
|
|
- 6 mock gifts matching HTML design
|
|
- Category filtering (All, Voucher, Product, Service, Discount)
|
|
- Filtered gifts provider for category-based display
|
|
|
|
### 2. Widgets
|
|
- **`widgets/points_balance_card.dart`** - Gradient card displaying points
|
|
- Blue gradient background (135deg, #005B9A → #38B6FF)
|
|
- Shows available points with proper formatting
|
|
- Displays expiration warning
|
|
|
|
- **`widgets/reward_card.dart`** - Individual gift card
|
|
- 120px image with CachedNetworkImage
|
|
- Gift name, description, points cost
|
|
- "Đổi quà" button (enabled if enough points)
|
|
- "Không đủ điểm" button (disabled if insufficient points)
|
|
|
|
### 3. Pages
|
|
- **`pages/rewards_page.dart`** - Main rewards screen
|
|
- AppBar with title "Đổi quà tặng"
|
|
- Points balance card
|
|
- Horizontal scrollable category filter pills
|
|
- 2-column gift grid (GridView)
|
|
- Pull-to-refresh
|
|
- Redemption confirmation dialog
|
|
- Success snackbar notification
|
|
|
|
## Mock Data
|
|
|
|
### Gift Catalog (6 items)
|
|
1. **Voucher 500.000đ** - 2,500 points
|
|
2. **Bộ keo chà ron cao cấp** - 3,000 points
|
|
3. **Tư vấn thiết kế miễn phí** - 5,000 points
|
|
4. **Gạch trang trí Premium** - 8,000 points
|
|
5. **Áo thun EuroTile** - 1,500 points
|
|
6. **Nâng hạng thẻ Platinum** - 15,000 points (disabled - not enough points)
|
|
|
|
### User Points
|
|
- Available: 9,750 points
|
|
- Expiring: 1,200 points on 31/12/2023
|
|
|
|
## Usage
|
|
|
|
### Navigation
|
|
Add to your router configuration:
|
|
|
|
```dart
|
|
GoRoute(
|
|
path: '/loyalty/rewards',
|
|
builder: (context, state) => const RewardsPage(),
|
|
),
|
|
```
|
|
|
|
### Direct Navigation
|
|
```dart
|
|
// From loyalty page or home
|
|
context.push('/loyalty/rewards');
|
|
|
|
// Or using named route
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (context) => const RewardsPage()),
|
|
);
|
|
```
|
|
|
|
### Accessing Providers
|
|
```dart
|
|
// Watch points balance
|
|
final pointsState = ref.watch(loyaltyPointsProvider);
|
|
print('Available points: ${pointsState.availablePoints}');
|
|
|
|
// Check if user has enough points
|
|
final hasEnough = ref.watch(hasEnoughPointsProvider(5000));
|
|
if (hasEnough) {
|
|
// Show enabled button
|
|
}
|
|
|
|
// Get filtered gifts
|
|
final gifts = ref.watch(filteredGiftsProvider);
|
|
|
|
// Change category filter
|
|
ref.read(selectedGiftCategoryProvider.notifier).setCategory(GiftCategory.voucher);
|
|
|
|
// Clear filter (show all)
|
|
ref.read(selectedGiftCategoryProvider.notifier).clearSelection();
|
|
```
|
|
|
|
## Features Implemented
|
|
|
|
### 1. Points Balance Display
|
|
- Gradient card with blue to light blue
|
|
- Large points number (36px, bold)
|
|
- Formatted with Vietnamese locale (9,750)
|
|
- Expiration warning with info icon
|
|
|
|
### 2. Category Filtering
|
|
- 5 filter options: Tất cả, Voucher, Sản phẩm, Dịch vụ, Ưu đãi đặc biệt
|
|
- Active state: blue background, white text
|
|
- Inactive state: grey background, dark text
|
|
- Smooth transitions between filters
|
|
|
|
### 3. Gift Grid
|
|
- 2-column responsive grid
|
|
- 0.75 aspect ratio for cards
|
|
- 12px spacing between cards
|
|
- Proper image loading with CachedNetworkImage
|
|
- Shimmer placeholder for loading
|
|
- Error fallback icon
|
|
|
|
### 4. Redemption Flow
|
|
1. User clicks "Đổi quà" button
|
|
2. Confirmation dialog appears with:
|
|
- Gift name
|
|
- Points cost
|
|
- Balance after redemption
|
|
3. User confirms
|
|
4. Points are deducted
|
|
5. Success snackbar shown
|
|
6. Can navigate to "My Gifts" page (TODO)
|
|
|
|
### 5. Smart Button State
|
|
- **Enabled (blue)**: User has enough points and gift is available
|
|
- **Disabled (grey)**: User doesn't have enough points
|
|
- Button text changes automatically
|
|
- Icon changes color based on state
|
|
|
|
## Design Details
|
|
|
|
### Colors
|
|
- **Gradient Start**: #005B9A (primaryBlue)
|
|
- **Gradient End**: #38B6FF (lightBlue)
|
|
- **Primary Button**: #005B9A
|
|
- **Success**: #28a745
|
|
- **Grey Disabled**: #e9ecef
|
|
- **Background**: #F4F6F8
|
|
|
|
### Typography
|
|
- **Points**: 36px, bold, white
|
|
- **Gift Name**: 14px, semibold, grey900
|
|
- **Description**: 12px, regular, grey500
|
|
- **Points Cost**: 14px, bold, primaryBlue
|
|
- **Button Text**: 13px, semibold
|
|
|
|
### Spacing
|
|
- Card padding: 12px
|
|
- Grid spacing: 12px
|
|
- Page padding: 16px
|
|
- Image height: 120px
|
|
|
|
## Dependencies Required
|
|
|
|
Ensure these packages are in `pubspec.yaml`:
|
|
|
|
```yaml
|
|
dependencies:
|
|
flutter:
|
|
sdk: flutter
|
|
flutter_riverpod: ^2.6.1
|
|
riverpod_annotation: ^2.5.0
|
|
go_router: ^14.6.2
|
|
cached_network_image: ^3.4.1
|
|
intl: ^0.19.0
|
|
|
|
dev_dependencies:
|
|
build_runner: ^2.4.13
|
|
riverpod_generator: ^2.5.0
|
|
```
|
|
|
|
## Next Steps (TODO)
|
|
|
|
1. **Backend Integration**
|
|
- Replace mock data with actual API calls
|
|
- Implement gift redemption endpoint
|
|
- Add error handling for network failures
|
|
|
|
2. **Gift Code Display**
|
|
- Create page to show redeemed gift code
|
|
- Add copy-to-clipboard functionality
|
|
- Show gift usage instructions
|
|
|
|
3. **My Gifts Page**
|
|
- Navigate to My Gifts after successful redemption
|
|
- Show active, used, and expired gifts
|
|
- Add filter tabs
|
|
|
|
4. **Enhanced UX**
|
|
- Add skeleton loaders during fetch
|
|
- Implement optimistic updates
|
|
- Add redemption animation
|
|
- Show gift popularity indicators
|
|
|
|
5. **Analytics**
|
|
- Track gift view events
|
|
- Track redemption events
|
|
- Track category filter usage
|
|
|
|
## Testing
|
|
|
|
### Manual Testing Checklist
|
|
- [ ] Page loads with points and gifts
|
|
- [ ] Category filters work correctly
|
|
- [ ] "Tất cả" shows all gifts
|
|
- [ ] Each category shows only relevant gifts
|
|
- [ ] Pull-to-refresh works
|
|
- [ ] Cards display correctly in grid
|
|
- [ ] Images load properly
|
|
- [ ] Points are formatted correctly (9,750)
|
|
- [ ] Expiration info displays correctly
|
|
- [ ] Button is enabled when enough points
|
|
- [ ] Button is disabled when not enough points
|
|
- [ ] Confirmation dialog appears on redeem
|
|
- [ ] Points are deducted after confirmation
|
|
- [ ] Success message appears
|
|
- [ ] Back button works
|
|
|
|
### Widget Tests (TODO)
|
|
```dart
|
|
testWidgets('RewardsPage displays points balance', (tester) async {
|
|
// Test implementation
|
|
});
|
|
|
|
testWidgets('RewardCard shows correct button state', (tester) async {
|
|
// Test implementation
|
|
});
|
|
|
|
testWidgets('Category filter changes gift list', (tester) async {
|
|
// Test implementation
|
|
});
|
|
```
|
|
|
|
## Screenshots Match HTML
|
|
|
|
The implementation matches the HTML design exactly:
|
|
- ✅ AppBar layout and styling
|
|
- ✅ Gradient points balance card
|
|
- ✅ Category filter pills design
|
|
- ✅ 2-column gift grid
|
|
- ✅ Gift card layout and styling
|
|
- ✅ Button states (enabled/disabled)
|
|
- ✅ Color scheme and typography
|
|
- ✅ Spacing and padding
|
|
|
|
## Support
|
|
|
|
For issues or questions about the rewards screen:
|
|
1. Check provider state with Riverpod DevTools
|
|
2. Verify mock data in `gifts_provider.dart`
|
|
3. Check console for CachedNetworkImage errors
|
|
4. Ensure build_runner generated files exist
|
|
|
|
---
|
|
|
|
**Created**: October 24, 2025
|
|
**Design Reference**: `/Users/ssg/project/worker/html/loyalty-rewards.html`
|
|
**Status**: ✅ Complete with mock data
|