update icon

This commit is contained in:
Phuoc Nguyen
2025-11-14 18:02:37 +07:00
parent aae3c9d080
commit b5f90c364d
54 changed files with 534 additions and 245 deletions

View File

@@ -0,0 +1,227 @@
# FontAwesome Icon Migration Guide
## Package Added
```yaml
font_awesome_flutter: ^10.7.0
```
## Import Statement
```dart
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
```
## Icon Mapping Reference
### Navigation Icons
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.arrow_back` | `FontAwesomeIcons.arrowLeft` | Back buttons |
| `Icons.arrow_forward` | `FontAwesomeIcons.arrowRight` | Forward navigation |
| `Icons.home` | `FontAwesomeIcons.house` | Home button |
| `Icons.menu` | `FontAwesomeIcons.bars` | Menu/hamburger |
| `Icons.close` | `FontAwesomeIcons.xmark` | Close buttons |
### Shopping & Cart Icons
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.shopping_cart` | `FontAwesomeIcons.cartShopping` | Shopping cart |
| `Icons.shopping_cart_outlined` | `FontAwesomeIcons.cartShopping` | Cart outline |
| `Icons.shopping_bag` | `FontAwesomeIcons.bagShopping` | Shopping bag |
| `Icons.shopping_bag_outlined` | `FontAwesomeIcons.bagShopping` | Bag outline |
| `Icons.add_shopping_cart` | `FontAwesomeIcons.cartPlus` | Add to cart |
### Action Icons
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.add` | `FontAwesomeIcons.plus` | Add/increment |
| `Icons.remove` | `FontAwesomeIcons.minus` | Remove/decrement |
| `Icons.delete` | `FontAwesomeIcons.trash` | Delete |
| `Icons.delete_outline` | `FontAwesomeIcons.trashCan` | Delete outline |
| `Icons.edit` | `FontAwesomeIcons.pen` | Edit |
| `Icons.check` | `FontAwesomeIcons.check` | Checkmark |
| `Icons.check_circle` | `FontAwesomeIcons.circleCheck` | Check circle |
| `Icons.refresh` | `FontAwesomeIcons.arrowsRotate` | Refresh |
### Status & Feedback Icons
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.error` | `FontAwesomeIcons.circleXmark` | Error |
| `Icons.error_outline` | `FontAwesomeIcons.circleExclamation` | Error outline |
| `Icons.warning` | `FontAwesomeIcons.triangleExclamation` | Warning |
| `Icons.info` | `FontAwesomeIcons.circleInfo` | Info |
| `Icons.info_outline` | `FontAwesomeIcons.circleInfo` | Info outline |
### UI Elements
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.search` | `FontAwesomeIcons.magnifyingGlass` | Search |
| `Icons.filter_list` | `FontAwesomeIcons.filter` | Filter |
| `Icons.sort` | `FontAwesomeIcons.arrowDownAZ` | Sort |
| `Icons.more_vert` | `FontAwesomeIcons.ellipsisVertical` | More options |
| `Icons.more_horiz` | `FontAwesomeIcons.ellipsis` | More horizontal |
### Calendar & Time
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.calendar_today` | `FontAwesomeIcons.calendar` | Calendar |
| `Icons.date_range` | `FontAwesomeIcons.calendarDays` | Date range |
| `Icons.access_time` | `FontAwesomeIcons.clock` | Time |
### Payment Icons
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.payment` | `FontAwesomeIcons.creditCard` | Credit card |
| `Icons.payments` | `FontAwesomeIcons.creditCard` | Payments |
| `Icons.payments_outlined` | `FontAwesomeIcons.creditCard` | Payment outline |
| `Icons.account_balance` | `FontAwesomeIcons.buildingColumns` | Bank |
| `Icons.account_balance_outlined` | `FontAwesomeIcons.buildingColumns` | Bank outline |
| `Icons.account_balance_wallet` | `FontAwesomeIcons.wallet` | Wallet |
### Media & Images
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.image` | `FontAwesomeIcons.image` | Image |
| `Icons.image_not_supported` | `FontAwesomeIcons.imageSlash` | No image |
| `Icons.photo_camera` | `FontAwesomeIcons.camera` | Camera |
| `Icons.photo_library` | `FontAwesomeIcons.images` | Gallery |
### User & Profile
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.person` | `FontAwesomeIcons.user` | User |
| `Icons.person_outline` | `FontAwesomeIcons.user` | User outline |
| `Icons.account_circle` | `FontAwesomeIcons.circleUser` | Account |
### Communication
| Material Icon | FontAwesome Icon | Usage |
|---------------|------------------|-------|
| `Icons.chat` | `FontAwesomeIcons.message` | Chat |
| `Icons.chat_bubble` | `FontAwesomeIcons.commentDots` | Chat bubble |
| `Icons.notifications` | `FontAwesomeIcons.bell` | Notifications |
| `Icons.phone` | `FontAwesomeIcons.phone` | Phone |
| `Icons.email` | `FontAwesomeIcons.envelope` | Email |
## Usage Examples
### Before (Material Icons)
```dart
Icon(Icons.shopping_cart, size: 24, color: Colors.blue)
Icon(Icons.add, size: 16)
IconButton(
icon: Icon(Icons.delete_outline),
onPressed: () {},
)
```
### After (FontAwesome)
```dart
FaIcon(FontAwesomeIcons.cartShopping, size: 24, color: Colors.blue)
FaIcon(FontAwesomeIcons.plus, size: 16)
IconButton(
icon: FaIcon(FontAwesomeIcons.trashCan),
onPressed: () {},
)
```
## Size Guidelines
FontAwesome icons tend to be slightly larger than Material icons at the same size. Recommended adjustments:
| Material Size | FontAwesome Size | Notes |
|---------------|------------------|-------|
| 24 (default) | 20-22 | Standard icons |
| 20 | 18 | Small icons |
| 16 | 14-15 | Tiny icons |
| 48 | 40-44 | Large icons |
| 64 | 56-60 | Extra large |
## Color Usage
FontAwesome icons use the same color properties:
```dart
// Both work the same
Icon(Icons.add, color: AppColors.primaryBlue)
FaIcon(FontAwesomeIcons.plus, color: AppColors.primaryBlue)
```
## Common Issues & Solutions
### Issue 1: Icon Size Mismatch
**Problem**: FontAwesome icons appear larger than expected
**Solution**: Reduce size by 2-4 pixels
```dart
// Before
Icon(Icons.add, size: 24)
// After
FaIcon(FontAwesomeIcons.plus, size: 20)
```
### Issue 2: Icon Alignment
**Problem**: Icons not centered properly
**Solution**: Use `IconTheme` or wrap in `SizedBox`
```dart
SizedBox(
width: 24,
height: 24,
child: FaIcon(FontAwesomeIcons.plus, size: 18),
)
```
### Issue 3: Icon Not Found
**Problem**: Icon name doesn't match
**Solution**: Check FontAwesome documentation or use search
```dart
// Use camelCase, not snake_case
// ❌ FontAwesomeIcons.shopping_cart
// ✅ FontAwesomeIcons.cartShopping
```
## Migration Checklist
- [x] Add `font_awesome_flutter` to pubspec.yaml
- [x] Run `flutter pub get`
- [ ] Update all `Icons.*` to `FontAwesomeIcons.*`
- [ ] Replace `Icon()` with `FaIcon()`
- [ ] Adjust icon sizes as needed
- [ ] Test visual appearance
- [ ] Update documentation
## Cart Feature Icon Updates
### Files to Update
1. `lib/features/cart/presentation/pages/cart_page.dart`
2. `lib/features/cart/presentation/pages/checkout_page.dart`
3. `lib/features/cart/presentation/widgets/cart_item_widget.dart`
4. `lib/features/cart/presentation/widgets/payment_method_section.dart`
5. `lib/features/cart/presentation/widgets/checkout_date_picker_field.dart`
### Specific Replacements
#### cart_page.dart
- `Icons.arrow_back``FontAwesomeIcons.arrowLeft`
- `Icons.delete_outline``FontAwesomeIcons.trashCan`
- `Icons.error_outline``FontAwesomeIcons.circleExclamation`
- `Icons.refresh``FontAwesomeIcons.arrowsRotate`
- `Icons.shopping_cart_outlined``FontAwesomeIcons.cartShopping`
- `Icons.shopping_bag_outlined``FontAwesomeIcons.bagShopping`
- `Icons.check``FontAwesomeIcons.check`
#### cart_item_widget.dart
- `Icons.image_not_supported``FontAwesomeIcons.imageSlash`
- `Icons.remove``FontAwesomeIcons.minus`
- `Icons.add``FontAwesomeIcons.plus`
- `Icons.check``FontAwesomeIcons.check`
#### payment_method_section.dart
- `Icons.account_balance_outlined``FontAwesomeIcons.buildingColumns`
- `Icons.payments_outlined``FontAwesomeIcons.creditCard`
#### checkout_date_picker_field.dart
- `Icons.calendar_today``FontAwesomeIcons.calendar`
## Resources
- [FontAwesome Flutter Package](https://pub.dev/packages/font_awesome_flutter)
- [FontAwesome Icon Gallery](https://fontawesome.com/icons)
- [FontAwesome Flutter Gallery](https://github.com/fluttercommunity/font_awesome_flutter/blob/master/GALLERY.md)

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -58,17 +59,17 @@ class CustomBottomNavBar extends StatelessWidget {
selectedFontSize: 12, selectedFontSize: 12,
unselectedFontSize: 12, unselectedFontSize: 12,
items: const [ items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), BottomNavigationBarItem(icon: FaIcon(FontAwesomeIcons.house, size: 20), label: 'Home'),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.shopping_bag), icon: FaIcon(FontAwesomeIcons.bagShopping, size: 20),
label: 'Products', label: 'Products',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.card_membership), icon: FaIcon(FontAwesomeIcons.gift, size: 20),
label: 'Loyalty', label: 'Loyalty',
), ),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Account'), BottomNavigationBarItem(icon: FaIcon(FontAwesomeIcons.user, size: 20), label: 'Account'),
BottomNavigationBarItem(icon: Icon(Icons.menu), label: 'More'), BottomNavigationBarItem(icon: FaIcon(FontAwesomeIcons.bars, size: 20), label: 'More'),
], ],
); );
} }

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -54,7 +55,7 @@ class EmptyState extends StatelessWidget {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon(icon, size: iconSize, color: AppColors.grey500), FaIcon(icon, size: iconSize, color: AppColors.grey500),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
title, title,

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -43,8 +44,8 @@ class CustomErrorWidget extends StatelessWidget {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( FaIcon(
icon ?? Icons.error_outline, icon ?? FontAwesomeIcons.circleExclamation,
size: iconSize, size: iconSize,
color: AppColors.danger, color: AppColors.danger,
), ),
@@ -62,7 +63,7 @@ class CustomErrorWidget extends StatelessWidget {
const SizedBox(height: 24), const SizedBox(height: 24),
ElevatedButton.icon( ElevatedButton.icon(
onPressed: onRetry, onPressed: onRetry,
icon: const Icon(Icons.refresh), icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 16),
label: const Text('Retry'), label: const Text('Retry'),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryBlue, backgroundColor: AppColors.primaryBlue,

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -43,10 +44,10 @@ class ChatFloatingButton extends StatelessWidget {
onPressed: onPressed, onPressed: onPressed,
backgroundColor: AppColors.accentCyan, backgroundColor: AppColors.accentCyan,
elevation: 6, elevation: 6,
child: const Icon( child: const FaIcon(
Icons.chat_bubble_outline, FontAwesomeIcons.message,
color: Colors.white, color: Colors.white,
size: 24, size: 22,
), ),
), ),
if (unreadCount != null && unreadCount! > 0) if (unreadCount != null && unreadCount! > 0)

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
@@ -162,7 +163,7 @@ class _BusinessUnitSelectionPageState extends State<BusinessUnitSelectionPage> {
backgroundColor: AppColors.white, backgroundColor: AppColors.white,
elevation: AppBarSpecs.elevation, elevation: AppBarSpecs.elevation,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -176,7 +177,7 @@ class _BusinessUnitSelectionPageState extends State<BusinessUnitSelectionPage> {
centerTitle: false, centerTitle: false,
actions: [ actions: [
IconButton( IconButton(
icon: const Icon(Icons.info_outline, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.circleInfo, color: Colors.black, size: 20),
onPressed: _showInfoDialog, onPressed: _showInfoDialog,
), ),
const SizedBox(width: AppSpacing.sm), const SizedBox(width: AppSpacing.sm),
@@ -331,7 +332,7 @@ class _BusinessUnitSelectionPageState extends State<BusinessUnitSelectionPage> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Icon( child: Icon(
Icons.business, FontAwesomeIcons.building,
color: isSelected color: isSelected
? AppColors.primaryBlue ? AppColors.primaryBlue
: AppColors.grey500, : AppColors.grey500,
@@ -387,7 +388,7 @@ class _BusinessUnitSelectionPageState extends State<BusinessUnitSelectionPage> {
), ),
child: isSelected child: isSelected
? const Icon( ? const Icon(
Icons.circle, FontAwesomeIcons.solidCircle,
size: 10, size: 10,
color: AppColors.white, color: AppColors.white,
) )

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -147,7 +148,7 @@ class _ForgotPasswordPageState extends ConsumerState<ForgotPasswordPage> {
), ),
centerTitle: false, centerTitle: false,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
actions: const [ actions: const [
@@ -205,7 +206,7 @@ class _ForgotPasswordPageState extends ConsumerState<ForgotPasswordPage> {
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: const Icon( child: const Icon(
Icons.lock_reset, FontAwesomeIcons.key,
size: 50, size: 50,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
), ),
@@ -349,7 +350,7 @@ class _ForgotPasswordPageState extends ConsumerState<ForgotPasswordPage> {
child: TextButton.icon( child: TextButton.icon(
onPressed: _showSupport, onPressed: _showSupport,
icon: const Icon( icon: const Icon(
Icons.headset_mic, FontAwesomeIcons.headset,
size: AppIconSize.sm, size: AppIconSize.sm,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
@@ -329,13 +330,13 @@ class _LoginPageState extends ConsumerState<LoginPage> {
color: AppColors.grey500, color: AppColors.grey500,
), ),
prefixIcon: const Icon( prefixIcon: const Icon(
Icons.lock, FontAwesomeIcons.lock,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
size: AppIconSize.md, size: AppIconSize.md,
), ),
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
isPasswordVisible ? Icons.visibility : Icons.visibility_off, isPasswordVisible ? FontAwesomeIcons.eye : FontAwesomeIcons.eyeSlash,
color: AppColors.grey500, color: AppColors.grey500,
size: AppIconSize.md, size: AppIconSize.md,
), ),
@@ -538,7 +539,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
child: TextButton.icon( child: TextButton.icon(
onPressed: _showSupport, onPressed: _showSupport,
icon: const Icon( icon: const Icon(
Icons.headset_mic, FontAwesomeIcons.headset,
size: AppIconSize.sm, size: AppIconSize.sm,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
), ),

View File

@@ -9,6 +9,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -242,7 +243,7 @@ class _OtpVerificationPageState extends ConsumerState<OtpVerificationPage> {
backgroundColor: AppColors.white, backgroundColor: AppColors.white,
elevation: AppBarSpecs.elevation, elevation: AppBarSpecs.elevation,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -280,7 +281,7 @@ class _OtpVerificationPageState extends ConsumerState<OtpVerificationPage> {
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: const Icon( child: const Icon(
Icons.shield_outlined, FontAwesomeIcons.shieldHalved,
size: 36, size: 36,
color: AppColors.white, color: AppColors.white,
), ),

View File

@@ -9,6 +9,7 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
@@ -174,12 +175,12 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
child: Wrap( child: Wrap(
children: [ children: [
ListTile( ListTile(
leading: const Icon(Icons.camera_alt), leading: const FaIcon(FontAwesomeIcons.camera, size: 20),
title: const Text('Chụp ảnh'), title: const Text('Chụp ảnh'),
onTap: () => Navigator.pop(context, ImageSource.camera), onTap: () => Navigator.pop(context, ImageSource.camera),
), ),
ListTile( ListTile(
leading: const Icon(Icons.photo_library), leading: const FaIcon(FontAwesomeIcons.images, size: 20),
title: const Text('Chọn từ thư viện'), title: const Text('Chọn từ thư viện'),
onTap: () => Navigator.pop(context, ImageSource.gallery), onTap: () => Navigator.pop(context, ImageSource.gallery),
), ),
@@ -392,7 +393,7 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
backgroundColor: AppColors.white, backgroundColor: AppColors.white,
elevation: AppBarSpecs.elevation, elevation: AppBarSpecs.elevation,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -470,7 +471,7 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: _buildInputDecoration( decoration: _buildInputDecoration(
hintText: 'Nhập họ và tên', hintText: 'Nhập họ và tên',
prefixIcon: Icons.person, prefixIcon: FontAwesomeIcons.user,
), ),
validator: (value) => Validators.minLength( validator: (value) => Validators.minLength(
value, value,
@@ -498,7 +499,7 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: _buildInputDecoration( decoration: _buildInputDecoration(
hintText: 'Nhập email', hintText: 'Nhập email',
prefixIcon: Icons.email, prefixIcon: FontAwesomeIcons.envelope,
), ),
validator: Validators.email, validator: Validators.email,
), ),
@@ -513,12 +514,12 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
decoration: _buildInputDecoration( decoration: _buildInputDecoration(
hintText: 'Tạo mật khẩu mới', hintText: 'Tạo mật khẩu mới',
prefixIcon: Icons.lock, prefixIcon: FontAwesomeIcons.lock,
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
_passwordVisible _passwordVisible
? Icons.visibility ? FontAwesomeIcons.eye
: Icons.visibility_off, : FontAwesomeIcons.eyeSlash,
color: AppColors.grey500, color: AppColors.grey500,
), ),
onPressed: () { onPressed: () {
@@ -560,7 +561,7 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: _buildInputDecoration( decoration: _buildInputDecoration(
hintText: 'Nhập tên công ty (không bắt buộc)', hintText: 'Nhập tên công ty (không bắt buộc)',
prefixIcon: Icons.business, prefixIcon: FontAwesomeIcons.building,
), ),
), ),
const SizedBox(height: AppSpacing.md), const SizedBox(height: AppSpacing.md),
@@ -761,7 +762,7 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
value: _selectedRole, value: _selectedRole,
decoration: _buildInputDecoration( decoration: _buildInputDecoration(
hintText: 'Chọn vai trò', hintText: 'Chọn vai trò',
prefixIcon: Icons.work, prefixIcon: FontAwesomeIcons.briefcase,
), ),
items: groups items: groups
.map( .map(

View File

@@ -6,6 +6,7 @@ library;
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -154,7 +155,7 @@ class FileUploadCard extends StatelessWidget {
height: 50, height: 50,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const Icon(
Icons.broken_image, FontAwesomeIcons.image,
color: AppColors.grey500, color: AppColors.grey500,
size: 24, size: 24,
), ),
@@ -203,7 +204,7 @@ class FileUploadCard extends StatelessWidget {
// Remove button // Remove button
IconButton( IconButton(
icon: const Icon(Icons.close, color: AppColors.danger, size: 20), icon: const FaIcon(FontAwesomeIcons.xmark, color: AppColors.danger, size: 18),
onPressed: onRemove, onPressed: onRemove,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
constraints: const BoxConstraints(), constraints: const BoxConstraints(),

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -93,7 +94,7 @@ class PhoneInputField extends StatelessWidget {
color: AppColors.grey500, color: AppColors.grey500,
), ),
prefixIcon: const Icon( prefixIcon: const Icon(
Icons.phone, FontAwesomeIcons.phone,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
size: AppIconSize.md, size: AppIconSize.md,
), ),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -62,7 +63,7 @@ class RoleDropdown extends StatelessWidget {
color: AppColors.grey500, color: AppColors.grey500,
), ),
prefixIcon: const Icon( prefixIcon: const Icon(
Icons.work, FontAwesomeIcons.briefcase,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
size: AppIconSize.md, size: AppIconSize.md,
), ),
@@ -104,7 +105,7 @@ class RoleDropdown extends StatelessWidget {
], ],
onChanged: onChanged, onChanged: onChanged,
validator: validator, validator: validator,
icon: const Icon(Icons.arrow_drop_down, color: AppColors.grey500), icon: const FaIcon(FontAwesomeIcons.chevronDown, color: AppColors.grey500, size: 16),
dropdownColor: AppColors.white, dropdownColor: AppColors.white,
style: const TextStyle( style: const TextStyle(
fontSize: InputFieldSpecs.fontSize, fontSize: InputFieldSpecs.fontSize,

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -66,7 +67,7 @@ class _CartPageState extends ConsumerState<CartPage> {
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: Text( title: Text(
@@ -81,7 +82,7 @@ class _CartPageState extends ConsumerState<CartPage> {
if (cartState.isNotEmpty) if (cartState.isNotEmpty)
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.delete_outline, FontAwesomeIcons.trashCan,
color: hasSelection ? AppColors.danger : AppColors.grey500, color: hasSelection ? AppColors.danger : AppColors.grey500,
), ),
onPressed: hasSelection onPressed: hasSelection
@@ -326,7 +327,7 @@ class _CartPageState extends ConsumerState<CartPage> {
color: AppColors.danger.withValues(alpha: 0.1), color: AppColors.danger.withValues(alpha: 0.1),
child: Row( child: Row(
children: [ children: [
const Icon(Icons.error_outline, color: AppColors.danger, size: 20), const FaIcon(FontAwesomeIcons.circleExclamation, color: AppColors.danger, size: 18),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
@@ -345,7 +346,7 @@ class _CartPageState extends ConsumerState<CartPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon(Icons.error_outline, size: 64, color: AppColors.danger), const FaIcon(FontAwesomeIcons.circleExclamation, size: 56, color: AppColors.danger),
const SizedBox(height: 16), const SizedBox(height: 16),
const Text( const Text(
'Không thể tải giỏ hàng', 'Không thể tải giỏ hàng',
@@ -365,7 +366,7 @@ class _CartPageState extends ConsumerState<CartPage> {
onPressed: () { onPressed: () {
ref.read(cartProvider.notifier).initialize(); ref.read(cartProvider.notifier).initialize();
}, },
icon: const Icon(Icons.refresh), icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 20),
label: const Text('Thử lại'), label: const Text('Thử lại'),
), ),
], ],
@@ -380,7 +381,7 @@ class _CartPageState extends ConsumerState<CartPage> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(
Icons.shopping_cart_outlined, FontAwesomeIcons.cartShopping,
size: 80, size: 80,
color: AppColors.grey500.withValues(alpha: 0.5), color: AppColors.grey500.withValues(alpha: 0.5),
), ),
@@ -399,7 +400,7 @@ class _CartPageState extends ConsumerState<CartPage> {
const SizedBox(height: 24), const SizedBox(height: 24),
ElevatedButton.icon( ElevatedButton.icon(
onPressed: () => context.go(RouteNames.products), onPressed: () => context.go(RouteNames.products),
icon: const Icon(Icons.shopping_bag_outlined), icon: const FaIcon(FontAwesomeIcons.bagShopping, size: 20),
label: const Text('Xem sản phẩm'), label: const Text('Xem sản phẩm'),
), ),
], ],
@@ -472,7 +473,7 @@ class _CustomCheckbox extends StatelessWidget {
), ),
child: value child: value
? const Icon( ? const Icon(
Icons.check, FontAwesomeIcons.check,
size: 16, size: 16,
color: AppColors.white, color: AppColors.white,
) )

View File

@@ -12,6 +12,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -95,7 +96,7 @@ class CheckoutPage extends HookConsumerWidget {
backgroundColor: Colors.white, backgroundColor: Colors.white,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/core/theme/typography.dart'; import 'package:worker/core/theme/typography.dart';
@@ -135,8 +136,8 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
width: 100, width: 100,
height: 100, height: 100,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_not_supported, FontAwesomeIcons.image,
color: AppColors.grey500, color: AppColors.grey500,
size: 32, size: 32,
), ),
@@ -181,7 +182,7 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
children: [ children: [
// Decrease button // Decrease button
_QuantityButton( _QuantityButton(
icon: Icons.remove, icon: FontAwesomeIcons.minus,
onPressed: () { onPressed: () {
ref ref
.read(cartProvider.notifier) .read(cartProvider.notifier)
@@ -239,7 +240,7 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
// Increase button // Increase button
_QuantityButton( _QuantityButton(
icon: Icons.add, icon: FontAwesomeIcons.plus,
onPressed: () { onPressed: () {
ref ref
.read(cartProvider.notifier) .read(cartProvider.notifier)
@@ -319,7 +320,7 @@ class _CustomCheckbox extends StatelessWidget {
), ),
child: value child: value
? const Icon( ? const Icon(
Icons.check, FontAwesomeIcons.check,
size: 14, size: 14,
color: AppColors.white, color: AppColors.white,
) )

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -69,7 +70,7 @@ class CheckoutDatePickerField extends HookWidget {
), ),
), ),
const Icon( const Icon(
Icons.calendar_today, FontAwesomeIcons.calendar,
size: 20, size: 20,
color: AppColors.grey500, color: AppColors.grey500,
), ),

View File

@@ -7,6 +7,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -66,7 +67,7 @@ class PaymentMethodSection extends HookWidget {
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
const Icon( const Icon(
Icons.account_balance_outlined, FontAwesomeIcons.buildingColumns,
color: AppColors.grey500, color: AppColors.grey500,
size: 24, size: 24,
), ),
@@ -117,7 +118,7 @@ class PaymentMethodSection extends HookWidget {
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
const Icon( const Icon(
Icons.payments_outlined, FontAwesomeIcons.creditCard,
color: AppColors.grey500, color: AppColors.grey500,
size: 24, size: 24,
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -82,7 +83,7 @@ class FavoritesPage extends ConsumerWidget {
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text('Yêu thích', style: TextStyle(color: Colors.black)), title: const Text('Yêu thích', style: TextStyle(color: Colors.black)),
@@ -110,7 +111,7 @@ class FavoritesPage extends ConsumerWidget {
// Clear all button // Clear all button
if (favoriteCount > 0) if (favoriteCount > 0)
IconButton( IconButton(
icon: const Icon(Icons.delete_outline, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.trashCan, color: Colors.black, size: 20),
tooltip: 'Xóa tất cả', tooltip: 'Xóa tất cả',
onPressed: () => _showClearAllDialog(context, ref, favoriteCount), onPressed: () => _showClearAllDialog(context, ref, favoriteCount),
), ),
@@ -165,8 +166,8 @@ class _EmptyState extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// Large icon // Large icon
Icon( FaIcon(
Icons.favorite_border, FontAwesomeIcons.heart,
size: 80.0, size: 80.0,
color: AppColors.grey500.withValues(alpha: 0.5), color: AppColors.grey500.withValues(alpha: 0.5),
), ),
@@ -360,8 +361,8 @@ class _ErrorState extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// Error icon // Error icon
Icon( FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 80.0, size: 80.0,
color: AppColors.danger.withValues(alpha: 0.7), color: AppColors.danger.withValues(alpha: 0.7),
), ),
@@ -406,7 +407,7 @@ class _ErrorState extends StatelessWidget {
borderRadius: BorderRadius.circular(AppRadius.button), borderRadius: BorderRadius.circular(AppRadius.button),
), ),
), ),
icon: const Icon(Icons.refresh), icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 18),
label: const Text( label: const Text(
'Thử lại', 'Thử lại',
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w600), style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w600),

View File

@@ -7,6 +7,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
@@ -106,8 +107,8 @@ class FavoriteProductCard extends ConsumerWidget {
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 48.0, size: 48.0,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -132,10 +133,10 @@ class FavoriteProductCard extends ConsumerWidget {
], ],
), ),
child: IconButton( child: IconButton(
icon: const Icon( icon: const FaIcon(
Icons.favorite, FontAwesomeIcons.solidHeart,
color: AppColors.danger, color: AppColors.danger,
size: 20.0, size: 18.0,
), ),
padding: const EdgeInsets.all(AppSpacing.sm), padding: const EdgeInsets.all(AppSpacing.sm),
constraints: const BoxConstraints( constraints: const BoxConstraints(

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -90,8 +91,8 @@ class _HomePageState extends ConsumerState<HomePage> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Icon( const FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
color: AppColors.danger, color: AppColors.danger,
size: 48, size: 48,
), ),
@@ -149,18 +150,18 @@ class _HomePageState extends ConsumerState<HomePage> {
title: 'Sản phẩm & Giỏ hàng', title: 'Sản phẩm & Giỏ hàng',
actions: [ actions: [
QuickAction( QuickAction(
icon: Icons.grid_view, icon: FontAwesomeIcons.grip,
label: 'Sản phẩm', label: 'Sản phẩm',
onTap: () => context.pushNamed(RouteNames.products), onTap: () => context.pushNamed(RouteNames.products),
), ),
QuickAction( QuickAction(
icon: Icons.shopping_cart, icon: FontAwesomeIcons.cartShopping,
label: 'Giỏ hàng', label: 'Giỏ hàng',
badge: cartItemCount > 0 ? '$cartItemCount' : null, badge: cartItemCount > 0 ? '$cartItemCount' : null,
onTap: () => context.push(RouteNames.cart), onTap: () => context.push(RouteNames.cart),
), ),
QuickAction( QuickAction(
icon: Icons.favorite, icon: FontAwesomeIcons.heart,
label: 'Yêu thích', label: 'Yêu thích',
onTap: () => context.push(RouteNames.favorites), onTap: () => context.push(RouteNames.favorites),
), ),
@@ -172,17 +173,17 @@ class _HomePageState extends ConsumerState<HomePage> {
title: 'Đơn hàng & thanh toán', title: 'Đơn hàng & thanh toán',
actions: [ actions: [
QuickAction( QuickAction(
icon: Icons.description, icon: FontAwesomeIcons.fileLines,
label: 'Chính sách giá', label: 'Chính sách giá',
onTap: () => context.push(RouteNames.pricePolicy), onTap: () => context.push(RouteNames.pricePolicy),
), ),
QuickAction( QuickAction(
icon: Icons.inventory_2, icon: FontAwesomeIcons.boxesStacked,
label: 'Đơn hàng', label: 'Đơn hàng',
onTap: () => context.push(RouteNames.orders), onTap: () => context.push(RouteNames.orders),
), ),
QuickAction( QuickAction(
icon: Icons.receipt_long, icon: FontAwesomeIcons.receipt,
label: 'Thanh toán', label: 'Thanh toán',
onTap: () => context.push(RouteNames.payments), onTap: () => context.push(RouteNames.payments),
), ),
@@ -194,18 +195,18 @@ class _HomePageState extends ConsumerState<HomePage> {
title: 'Khách hàng thân thiết', title: 'Khách hàng thân thiết',
actions: [ actions: [
QuickAction( QuickAction(
icon: Icons.add_circle_outline, icon: FontAwesomeIcons.circlePlus,
label: 'Ghi nhận điểm', label: 'Ghi nhận điểm',
onTap: () => onTap: () =>
_showComingSoon(context, 'Ghi nhận điểm', l10n), _showComingSoon(context, 'Ghi nhận điểm', l10n),
), ),
QuickAction( QuickAction(
icon: Icons.card_giftcard, icon: FontAwesomeIcons.gift,
label: 'Đổi quà', label: 'Đổi quà',
onTap: () => context.push('/loyalty/rewards'), onTap: () => context.push('/loyalty/rewards'),
), ),
QuickAction( QuickAction(
icon: Icons.history, icon: FontAwesomeIcons.clockRotateLeft,
label: 'Lịch sử điểm', label: 'Lịch sử điểm',
onTap: () => context.push(RouteNames.pointsHistory), onTap: () => context.push(RouteNames.pointsHistory),
), ),
@@ -217,12 +218,12 @@ class _HomePageState extends ConsumerState<HomePage> {
title: 'Nhà mẫu, dự án & tin tức', title: 'Nhà mẫu, dự án & tin tức',
actions: [ actions: [
QuickAction( QuickAction(
icon: Icons.home_work, icon: FontAwesomeIcons.houseCircleCheck,
label: 'Nhà mẫu', label: 'Nhà mẫu',
onTap: () => context.push(RouteNames.modelHouses), onTap: () => context.push(RouteNames.modelHouses),
), ),
QuickAction( QuickAction(
icon: Icons.business, icon: FontAwesomeIcons.building,
label: 'Đăng ký dự án', label: 'Đăng ký dự án',
onTap: () => onTap: () =>
_showComingSoon(context, 'Đăng ký dự án', l10n), _showComingSoon(context, 'Đăng ký dự án', l10n),

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -127,8 +128,8 @@ class _PromotionCard extends StatelessWidget {
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 140, height: 140,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 48, size: 48,
color: AppColors.grey500, color: AppColors.grey500,
), ),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -282,37 +283,37 @@ class LoyaltyPage extends ConsumerWidget {
List<Widget> _buildLoyaltyMenu(BuildContext context) { List<Widget> _buildLoyaltyMenu(BuildContext context) {
final menuItems = [ final menuItems = [
{ {
'icon': Icons.card_giftcard, 'icon': FontAwesomeIcons.gift,
'title': 'Đổi quà tặng', 'title': 'Đổi quà tặng',
'subtitle': 'Sử dụng điểm để đổi quà hấp dẫn', 'subtitle': 'Sử dụng điểm để đổi quà hấp dẫn',
'route': '/loyalty/rewards', 'route': '/loyalty/rewards',
}, },
{ {
'icon': Icons.add_circle_outline, 'icon': FontAwesomeIcons.circlePlus,
'title': 'Ghi nhận điểm', 'title': 'Ghi nhận điểm',
'subtitle': 'Gửi hóa đơn để nhận điểm thưởng', 'subtitle': 'Gửi hóa đơn để nhận điểm thưởng',
'route': null, 'route': null,
}, },
{ {
'icon': Icons.history, 'icon': FontAwesomeIcons.clockRotateLeft,
'title': 'Lịch sử điểm', 'title': 'Lịch sử điểm',
'subtitle': 'Xem chi tiết cộng/trừ điểm', 'subtitle': 'Xem chi tiết cộng/trừ điểm',
'route': '/loyalty/points-history', 'route': '/loyalty/points-history',
}, },
{ {
'icon': Icons.person_add, 'icon': FontAwesomeIcons.userPlus,
'title': 'Giới thiệu bạn bè', 'title': 'Giới thiệu bạn bè',
'subtitle': 'Nhận thưởng khi giới thiệu thành công', 'subtitle': 'Nhận thưởng khi giới thiệu thành công',
'route': null, 'route': null,
}, },
{ {
'icon': Icons.inventory_2_outlined, 'icon': FontAwesomeIcons.boxOpen,
'title': 'Quà của tôi', 'title': 'Quà của tôi',
'subtitle': 'Xem voucher và quà tặng đã đổi', 'subtitle': 'Xem voucher và quà tặng đã đổi',
'route': null, 'route': null,
}, },
{ {
'icon': Icons.diamond_outlined, 'icon': FontAwesomeIcons.gem,
'title': 'Quyền lợi hội viên', 'title': 'Quyền lợi hội viên',
'subtitle': 'Xem các ưu đãi dành cho hạng của bạn', 'subtitle': 'Xem các ưu đãi dành cho hạng của bạn',
'route': null, 'route': null,
@@ -386,7 +387,7 @@ class LoyaltyPage extends ConsumerWidget {
// Arrow // Arrow
const Icon( const Icon(
Icons.chevron_right, FontAwesomeIcons.chevronRight,
color: AppColors.grey500, color: AppColors.grey500,
size: 20, size: 20,
), ),
@@ -440,7 +441,7 @@ class LoyaltyPage extends ConsumerWidget {
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Icon(Icons.check_circle, size: 20, color: Color(0xFF4A00E0)), const FaIcon(FontAwesomeIcons.solidCircleCheck, size: 18, color: Color(0xFF4A00E0)),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -32,7 +33,7 @@ class PointsHistoryPage extends ConsumerWidget {
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -101,7 +102,7 @@ class PointsHistoryPage extends ConsumerWidget {
color: AppColors.grey900, color: AppColors.grey900,
), ),
), ),
Icon(Icons.filter_list, color: AppColors.primaryBlue, size: 20), FaIcon(FontAwesomeIcons.sliders, color: AppColors.primaryBlue, size: 18),
], ],
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -263,8 +264,8 @@ class PointsHistoryPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.history, FontAwesomeIcons.clockRotateLeft,
size: 80, size: 80,
color: AppColors.grey500.withValues(alpha: 0.5), color: AppColors.grey500.withValues(alpha: 0.5),
), ),
@@ -294,8 +295,8 @@ class PointsHistoryPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 80, size: 80,
color: AppColors.danger.withValues(alpha: 0.7), color: AppColors.danger.withValues(alpha: 0.7),
), ),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -34,7 +35,7 @@ class RewardsPage extends ConsumerWidget {
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -47,7 +48,7 @@ class RewardsPage extends ConsumerWidget {
centerTitle: false, centerTitle: false,
actions: [ actions: [
IconButton( IconButton(
icon: const Icon(Icons.info_outline, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.circleInfo, color: Colors.black, size: 20),
onPressed: () => _showInfoDialog(context), onPressed: () => _showInfoDialog(context),
), ),
const SizedBox(width: AppSpacing.sm), const SizedBox(width: AppSpacing.sm),
@@ -168,7 +169,7 @@ class RewardsPage extends ConsumerWidget {
children: [ children: [
const Padding( const Padding(
padding: EdgeInsets.only(top: 6), padding: EdgeInsets.only(top: 6),
child: Icon(Icons.circle, size: 6, color: AppColors.grey500), child: FaIcon(FontAwesomeIcons.solidCircle, size: 6, color: AppColors.grey500),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
@@ -299,8 +300,8 @@ class RewardsPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.card_giftcard_outlined, FontAwesomeIcons.gift,
size: 64, size: 64,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -434,7 +435,7 @@ class RewardsPage extends ConsumerWidget {
SnackBar( SnackBar(
content: Row( content: Row(
children: [ children: [
const Icon(Icons.check_circle, color: Colors.white), const FaIcon(FontAwesomeIcons.solidCircleCheck, color: Colors.white, size: 20),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded(child: Text('Đổi quà "${gift.name}" thành công!')), Expanded(child: Text('Đổi quà "${gift.name}" thành công!')),
], ],

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/loyalty/presentation/providers/loyalty_points_provider.dart'; import 'package:worker/features/loyalty/presentation/providers/loyalty_points_provider.dart';
@@ -75,8 +76,8 @@ class PointsBalanceCard extends ConsumerWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.info_outline, FontAwesomeIcons.circleInfo,
size: 14, size: 14,
color: Colors.white.withValues(alpha: 0.8), color: Colors.white.withValues(alpha: 0.8),
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/loyalty/domain/entities/gift_catalog.dart'; import 'package:worker/features/loyalty/domain/entities/gift_catalog.dart';
@@ -96,9 +97,9 @@ class RewardCard extends ConsumerWidget {
onPressed: hasEnoughPoints && gift.isAvailable onPressed: hasEnoughPoints && gift.isAvailable
? onRedeem ? onRedeem
: null, : null,
icon: Icon( icon: FaIcon(
Icons.card_giftcard, FontAwesomeIcons.gift,
size: 16, size: 14,
color: hasEnoughPoints && gift.isAvailable color: hasEnoughPoints && gift.isAvailable
? Colors.white ? Colors.white
: AppColors.grey500, : AppColors.grey500,
@@ -155,8 +156,8 @@ class RewardCard extends ConsumerWidget {
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.card_giftcard, FontAwesomeIcons.gift,
size: 48, size: 48,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -164,8 +165,8 @@ class RewardCard extends ConsumerWidget {
) )
: Container( : Container(
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.card_giftcard, FontAwesomeIcons.gift,
size: 48, size: 48,
color: AppColors.grey500, color: AppColors.grey500,
), ),

View File

@@ -9,6 +9,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:share_plus/share_plus.dart'; import 'package:share_plus/share_plus.dart';
import 'package:worker/core/constants/api_constants.dart'; import 'package:worker/core/constants/api_constants.dart';
@@ -77,20 +78,21 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
), ),
centerTitle: false, centerTitle: false,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
actions: [ actions: [
// Share button // Share button
IconButton( IconButton(
icon: const Icon(Icons.share, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.shareNodes, color: Colors.black, size: 20),
onPressed: _onShareTap, onPressed: _onShareTap,
), ),
// Bookmark button // Bookmark button
IconButton( IconButton(
icon: Icon( icon: FaIcon(
_isBookmarked ? Icons.bookmark : Icons.bookmark_border, _isBookmarked ? FontAwesomeIcons.solidBookmark : FontAwesomeIcons.bookmark,
color: _isBookmarked ? AppColors.warning : Colors.black, color: _isBookmarked ? AppColors.warning : Colors.black,
size: 20,
), ),
onPressed: _onBookmarkTap, onPressed: _onBookmarkTap,
), ),
@@ -126,8 +128,8 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 250, height: 250,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_outlined, FontAwesomeIcons.image,
size: 48, size: 48,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -276,7 +278,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
), ),
// Date // Date
_buildMetaItem(Icons.calendar_today, article.formattedDate), _buildMetaItem(FontAwesomeIcons.calendar, article.formattedDate),
// Reading time // Reading time
// _buildMetaItem(Icons.schedule, article.readingTimeText), // _buildMetaItem(Icons.schedule, article.readingTimeText),
@@ -295,7 +297,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon(icon, size: 12, color: const Color(0xFF64748B)), FaIcon(icon, size: 12, color: const Color(0xFF64748B)),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
text, text,
@@ -369,18 +371,18 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
_buildActionButton( _buildActionButton(
icon: _isLiked ? Icons.favorite : Icons.favorite_border, icon: _isLiked ? FontAwesomeIcons.solidHeart : FontAwesomeIcons.heart,
onPressed: _onLikeTap, onPressed: _onLikeTap,
color: _isLiked ? Colors.red : null, color: _isLiked ? Colors.red : null,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
_buildActionButton( _buildActionButton(
icon: _isBookmarked ? Icons.bookmark : Icons.bookmark_border, icon: _isBookmarked ? FontAwesomeIcons.solidBookmark : FontAwesomeIcons.bookmark,
onPressed: _onBookmarkTap, onPressed: _onBookmarkTap,
color: _isBookmarked ? AppColors.warning : null, color: _isBookmarked ? AppColors.warning : null,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
_buildActionButton(icon: Icons.share, onPressed: _onShareTap), _buildActionButton(icon: FontAwesomeIcons.shareNodes, onPressed: _onShareTap),
], ],
), ),
); );
@@ -414,7 +416,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
side: BorderSide(color: color ?? const Color(0xFFE2E8F0), width: 2), side: BorderSide(color: color ?? const Color(0xFFE2E8F0), width: 2),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
), ),
child: Icon(icon, size: 20, color: color ?? const Color(0xFF64748B)), child: FaIcon(icon, size: 18, color: color ?? const Color(0xFF64748B)),
); );
} }
@@ -458,7 +460,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.article_outlined, size: 64, color: AppColors.grey500), FaIcon(FontAwesomeIcons.fileLines, size: 64, color: AppColors.grey500),
const SizedBox(height: 16), const SizedBox(height: 16),
const Text( const Text(
'Không tìm thấy bài viết', 'Không tìm thấy bài viết',
@@ -490,7 +492,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.error_outline, size: 64, color: AppColors.danger), FaIcon(FontAwesomeIcons.circleExclamation, size: 64, color: AppColors.danger),
const SizedBox(height: 16), const SizedBox(height: 16),
const Text( const Text(
'Không thể tải bài viết', 'Không thể tải bài viết',

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -111,9 +112,9 @@ class _NewsListPageState extends ConsumerState<NewsListPage> {
padding: EdgeInsets.symmetric(horizontal: AppSpacing.md), padding: EdgeInsets.symmetric(horizontal: AppSpacing.md),
child: Row( child: Row(
children: [ children: [
Icon( FaIcon(
Icons.newspaper, FontAwesomeIcons.newspaper,
size: 18, size: 16,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
), ),
SizedBox(width: 8), SizedBox(width: 8),
@@ -194,7 +195,7 @@ class _NewsListPageState extends ConsumerState<NewsListPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.newspaper_outlined, size: 64, color: AppColors.grey500), FaIcon(FontAwesomeIcons.newspaper, size: 64, color: AppColors.grey500),
const SizedBox(height: 16), const SizedBox(height: 16),
const Text( const Text(
'Chưa có tin tức', 'Chưa có tin tức',
@@ -221,7 +222,7 @@ class _NewsListPageState extends ConsumerState<NewsListPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.error_outline, size: 64, color: AppColors.danger), FaIcon(FontAwesomeIcons.circleExclamation, size: 64, color: AppColors.danger),
const SizedBox(height: 16), const SizedBox(height: 16),
const Text( const Text(
'Không thể tải tin tức', 'Không thể tải tin tức',

View File

@@ -7,6 +7,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/news/domain/entities/blog_category.dart'; import 'package:worker/features/news/domain/entities/blog_category.dart';
@@ -121,7 +122,7 @@ class CategoryFilterChips extends ConsumerWidget {
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon(Icons.error_outline, size: 16, color: AppColors.grey500), FaIcon(FontAwesomeIcons.circleExclamation, size: 16, color: AppColors.grey500),
const SizedBox(width: AppSpacing.xs), const SizedBox(width: AppSpacing.xs),
Text( Text(
'Lỗi tải danh mục', 'Lỗi tải danh mục',
@@ -133,7 +134,7 @@ class CategoryFilterChips extends ConsumerWidget {
const SizedBox(width: AppSpacing.xs), const SizedBox(width: AppSpacing.xs),
GestureDetector( GestureDetector(
onTap: () => ref.refresh(blogCategoriesProvider), onTap: () => ref.refresh(blogCategoriesProvider),
child: Icon(Icons.refresh, size: 16, color: AppColors.primaryBlue), child: FaIcon(FontAwesomeIcons.arrowsRotate, size: 14, color: AppColors.primaryBlue),
), ),
], ],
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/news/domain/entities/news_article.dart'; import 'package:worker/features/news/domain/entities/news_article.dart';
@@ -68,8 +69,8 @@ class FeaturedNewsCard extends StatelessWidget {
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 200, height: 200,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_outlined, FontAwesomeIcons.image,
size: 48, size: 48,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -122,7 +123,7 @@ class FeaturedNewsCard extends StatelessWidget {
children: [ children: [
// Date // Date
_buildMetaItem( _buildMetaItem(
icon: Icons.calendar_today, icon: FontAwesomeIcons.calendar,
text: article.formattedDate, text: article.formattedDate,
), ),
@@ -176,7 +177,7 @@ class FeaturedNewsCard extends StatelessWidget {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon(icon, size: 12, color: const Color(0xFF64748B)), FaIcon(icon, size: 12, color: const Color(0xFF64748B)),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
text, text,

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
/// Highlight type enum /// Highlight type enum
@@ -65,7 +66,7 @@ class HighlightBox extends StatelessWidget {
// Title with icon // Title with icon
Row( Row(
children: [ children: [
Icon(_getIcon(), size: 20, color: const Color(0xFF92400E)), FaIcon(_getIcon(), size: 18, color: const Color(0xFF92400E)),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
title, title,
@@ -98,9 +99,9 @@ class HighlightBox extends StatelessWidget {
IconData _getIcon() { IconData _getIcon() {
switch (type) { switch (type) {
case HighlightType.tip: case HighlightType.tip:
return Icons.lightbulb; return FontAwesomeIcons.lightbulb;
case HighlightType.warning: case HighlightType.warning:
return Icons.error_outline; return FontAwesomeIcons.circleExclamation;
} }
} }
} }

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/news/domain/entities/news_article.dart'; import 'package:worker/features/news/domain/entities/news_article.dart';
@@ -67,8 +68,8 @@ class NewsCard extends StatelessWidget {
width: 80, width: 80,
height: 80, height: 80,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_outlined, FontAwesomeIcons.image,
size: 24, size: 24,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -116,8 +117,8 @@ class NewsCard extends StatelessWidget {
Row( Row(
children: [ children: [
// Date // Date
const Icon( const FaIcon(
Icons.calendar_today, FontAwesomeIcons.calendar,
size: 12, size: 12,
color: Color(0xFF64748B), color: Color(0xFF64748B),
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/news/domain/entities/news_article.dart'; import 'package:worker/features/news/domain/entities/news_article.dart';
@@ -66,8 +67,8 @@ class RelatedArticleCard extends StatelessWidget {
width: 60, width: 60,
height: 60, height: 60,
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const FaIcon(
Icons.image_outlined, FontAwesomeIcons.image,
size: 20, size: 20,
color: AppColors.grey500, color: AppColors.grey500,
), ),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/database/models/enums.dart'; import 'package:worker/core/database/models/enums.dart';
@@ -57,7 +58,7 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -137,17 +138,17 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Mã đơn hàng', hintText: 'Mã đơn hàng',
hintStyle: const TextStyle(color: AppColors.grey500, fontSize: 14), hintStyle: const TextStyle(color: AppColors.grey500, fontSize: 14),
prefixIcon: const Icon( prefixIcon: const FaIcon(
Icons.search, FontAwesomeIcons.magnifyingGlass,
color: AppColors.grey500, color: AppColors.grey500,
size: 20, size: 18,
), ),
suffixIcon: _searchController.text.isNotEmpty suffixIcon: _searchController.text.isNotEmpty
? IconButton( ? IconButton(
icon: const Icon( icon: const FaIcon(
Icons.clear, FontAwesomeIcons.xmark,
color: AppColors.grey500, color: AppColors.grey500,
size: 20, size: 18,
), ),
onPressed: () { onPressed: () {
_searchController.clear(); _searchController.clear();
@@ -283,8 +284,8 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.receipt_long_outlined, FontAwesomeIcons.receipt,
size: 80, size: 80,
color: AppColors.grey500.withValues(alpha: 0.5), color: AppColors.grey500.withValues(alpha: 0.5),
), ),
@@ -322,8 +323,8 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 80, size: 80,
color: AppColors.danger.withValues(alpha: 0.7), color: AppColors.danger.withValues(alpha: 0.7),
), ),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/database/models/enums.dart'; import 'package:worker/core/database/models/enums.dart';
@@ -140,7 +141,7 @@ class _PaymentsPageState extends ConsumerState<PaymentsPage>
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -256,7 +257,7 @@ class _PaymentsPageState extends ConsumerState<PaymentsPage>
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -274,7 +275,7 @@ class _PaymentsPageState extends ConsumerState<PaymentsPage>
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -290,8 +291,8 @@ class _PaymentsPageState extends ConsumerState<PaymentsPage>
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 80, size: 80,
color: AppColors.danger.withValues(alpha: 0.7), color: AppColors.danger.withValues(alpha: 0.7),
), ),
@@ -325,19 +326,19 @@ class _PaymentsPageState extends ConsumerState<PaymentsPage>
switch (tabLabel) { switch (tabLabel) {
case 'Chưa thanh toán': case 'Chưa thanh toán':
message = 'Không có hóa đơn chưa thanh toán'; message = 'Không có hóa đơn chưa thanh toán';
icon = Icons.receipt_long_outlined; icon = FontAwesomeIcons.receipt;
break; break;
case 'Quá hạn': case 'Quá hạn':
message = 'Không có hóa đơn quá hạn'; message = 'Không có hóa đơn quá hạn';
icon = Icons.warning_amber_outlined; icon = FontAwesomeIcons.triangleExclamation;
break; break;
case 'Đã thanh toán': case 'Đã thanh toán':
message = 'Không có hóa đơn đã thanh toán'; message = 'Không có hóa đơn đã thanh toán';
icon = Icons.check_circle_outline; icon = FontAwesomeIcons.circleCheck;
break; break;
default: default:
message = 'Không có hóa đơn nào'; message = 'Không có hóa đơn nào';
icon = Icons.receipt_long_outlined; icon = FontAwesomeIcons.receipt;
} }
return SliverFillRemaining( return SliverFillRemaining(
@@ -345,7 +346,7 @@ class _PaymentsPageState extends ConsumerState<PaymentsPage>
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
icon, icon,
size: 80, size: 80,
color: AppColors.grey500.withValues(alpha: 0.5), color: AppColors.grey500.withValues(alpha: 0.5),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/database/models/enums.dart'; import 'package:worker/core/database/models/enums.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -241,7 +242,7 @@ class InvoiceCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
spacing: 8, spacing: 8,
children: [ children: [
Icon(Icons.credit_card), FaIcon(FontAwesomeIcons.creditCard, size: 18),
Text( Text(
buttonText, buttonText,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -112,7 +113,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
// Share options // Share options
ListTile( ListTile(
leading: const Icon(Icons.chat, color: AppColors.primaryBlue), leading: const FaIcon(FontAwesomeIcons.message, color: AppColors.primaryBlue, size: 20),
title: const Text('Chia sẻ qua tin nhắn'), title: const Text('Chia sẻ qua tin nhắn'),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -124,7 +125,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
}, },
), ),
ListTile( ListTile(
leading: const Icon(Icons.share, color: AppColors.primaryBlue), leading: const FaIcon(FontAwesomeIcons.shareNodes, color: AppColors.primaryBlue, size: 20),
title: const Text('Chia sẻ khác'), title: const Text('Chia sẻ khác'),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -132,7 +133,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
}, },
), ),
ListTile( ListTile(
leading: const Icon(Icons.copy, color: AppColors.primaryBlue), leading: const FaIcon(FontAwesomeIcons.copy, color: AppColors.primaryBlue, size: 20),
title: const Text('Sao chép link'), title: const Text('Sao chép link'),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -178,7 +179,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
backgroundColor: const Color(0xFFF4F6F8), backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -192,7 +193,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
actions: [ actions: [
// Share button // Share button
IconButton( IconButton(
icon: const Icon(Icons.share, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.shareNodes, color: Colors.black, size: 20),
onPressed: () { onPressed: () {
productAsync.whenData((product) { productAsync.whenData((product) {
_shareProduct(product); _shareProduct(product);
@@ -202,7 +203,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
// Favorite button // Favorite button
IconButton( IconButton(
icon: Icon( icon: Icon(
isFavorite ? Icons.favorite : Icons.favorite_border, isFavorite ? FontAwesomeIcons.solidHeart : FontAwesomeIcons.heart,
color: isFavorite ? AppColors.danger : Colors.black, color: isFavorite ? AppColors.danger : Colors.black,
), ),
onPressed: _toggleFavorite, onPressed: _toggleFavorite,
@@ -265,7 +266,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon( const Icon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 80, size: 80,
color: AppColors.danger, color: AppColors.danger,
), ),
@@ -290,7 +291,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
// Invalidate to trigger refetch // Invalidate to trigger refetch
ref.invalidate(productDetailProvider(productId: widget.productId)); ref.invalidate(productDetailProvider(productId: widget.productId));
}, },
icon: const Icon(Icons.refresh), icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 18),
label: const Text('Thử lại'), label: const Text('Thử lại'),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryBlue, backgroundColor: AppColors.primaryBlue,

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
@@ -45,7 +46,7 @@ class ProductsPage extends ConsumerWidget {
endDrawer: const ProductFilterDrawer(), endDrawer: const ProductFilterDrawer(),
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text('Sản phẩm', style: TextStyle(color: Colors.black)), title: const Text('Sản phẩm', style: TextStyle(color: Colors.black)),
@@ -61,7 +62,7 @@ class ProductsPage extends ConsumerWidget {
backgroundColor: AppColors.danger, backgroundColor: AppColors.danger,
textColor: AppColors.white, textColor: AppColors.white,
isLabelVisible: cartItemCount > 0, isLabelVisible: cartItemCount > 0,
child: const Icon(Icons.shopping_cart_outlined, color: Colors.black), child: const FaIcon(FontAwesomeIcons.cartShopping, color: Colors.black, size: 20),
), ),
onPressed: () => context.push(RouteNames.cart), onPressed: () => context.push(RouteNames.cart),
), ),
@@ -88,7 +89,7 @@ class ProductsPage extends ConsumerWidget {
// Open filter drawer from right // Open filter drawer from right
Scaffold.of(scaffoldContext).openEndDrawer(); Scaffold.of(scaffoldContext).openEndDrawer();
}, },
icon: const Icon(Icons.filter_list, size: 20), icon: const FaIcon(FontAwesomeIcons.sliders, size: 18),
label: const Text('Lọc', style: TextStyle(fontSize: 12)), label: const Text('Lọc', style: TextStyle(fontSize: 12)),
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
foregroundColor: AppColors.grey900, foregroundColor: AppColors.grey900,
@@ -160,7 +161,7 @@ class ProductsPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.inventory_2_outlined, size: 80.0, color: AppColors.grey500.withAlpha(128)), FaIcon(FontAwesomeIcons.boxOpen, size: 80.0, color: AppColors.grey500.withAlpha(128)),
const SizedBox(height: AppSpacing.lg), const SizedBox(height: AppSpacing.lg),
Text( Text(
l10n.noProductsFound, l10n.noProductsFound,
@@ -186,7 +187,7 @@ class ProductsPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.error_outline, size: 80.0, color: AppColors.danger.withAlpha(128)), FaIcon(FontAwesomeIcons.circleExclamation, size: 80.0, color: AppColors.danger.withAlpha(128)),
const SizedBox(height: AppSpacing.lg), const SizedBox(height: AppSpacing.lg),
Text( Text(
l10n.error, l10n.error,
@@ -203,7 +204,7 @@ class ProductsPage extends ConsumerWidget {
onPressed: () async { onPressed: () async {
await ref.read(productsProvider.notifier).refresh(); await ref.read(productsProvider.notifier).refresh();
}, },
icon: const Icon(Icons.refresh), icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 18),
label: Text(l10n.tryAgain), label: Text(l10n.tryAgain),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryBlue, backgroundColor: AppColors.primaryBlue,

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
@@ -75,7 +76,7 @@ class ProductCard extends ConsumerWidget {
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const Icon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 48.0, size: 48.0,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -254,7 +255,7 @@ class ProductCard extends ConsumerWidget {
horizontal: AppSpacing.sm, horizontal: AppSpacing.sm,
), ),
), ),
icon: const Icon(Icons.shopping_cart, size: 16.0), icon: const FaIcon(FontAwesomeIcons.cartShopping, size: 14.0),
label: Text( label: Text(
!product.inStock ? 'Thêm vào giỏ' : l10n.outOfStock, !product.inStock ? 'Thêm vào giỏ' : l10n.outOfStock,
style: const TextStyle( style: const TextStyle(
@@ -299,7 +300,7 @@ class ProductCard extends ConsumerWidget {
horizontal: AppSpacing.sm, horizontal: AppSpacing.sm,
), ),
), ),
icon: const Icon(Icons.threed_rotation, size: 16.0), icon: const FaIcon(FontAwesomeIcons.cube, size: 14.0),
label: const Text( label: const Text(
'Phối cảnh 360°', 'Phối cảnh 360°',
style: TextStyle( style: TextStyle(

View File

@@ -5,6 +5,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -108,7 +109,7 @@ class _ImageGallerySectionState extends State<ImageGallerySection> {
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const Icon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 64, size: 64,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -144,7 +145,7 @@ class _ImageGallerySectionState extends State<ImageGallerySection> {
return Transform.rotate( return Transform.rotate(
angle: value * 2 * 3.14159, angle: value * 2 * 3.14159,
child: const Icon( child: const Icon(
Icons.sync, FontAwesomeIcons.arrowsRotate,
size: 10, size: 10,
color: AppColors.white, color: AppColors.white,
), ),
@@ -234,7 +235,7 @@ class _ImageGallerySectionState extends State<ImageGallerySection> {
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
color: AppColors.grey100, color: AppColors.grey100,
child: const Icon( child: const Icon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 20, size: 20,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -312,7 +313,7 @@ class _ImageLightboxState extends State<_ImageLightbox> {
foregroundColor: AppColors.white, foregroundColor: AppColors.white,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.close, size: 32), icon: const FaIcon(FontAwesomeIcons.xmark, size: 28),
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
title: Text( title: Text(
@@ -340,7 +341,7 @@ class _ImageLightboxState extends State<_ImageLightbox> {
imageUrl: widget.images[index], imageUrl: widget.images[index],
fit: BoxFit.contain, fit: BoxFit.contain,
errorWidget: (context, url, error) => const Icon( errorWidget: (context, url, error) => const Icon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
color: AppColors.white, color: AppColors.white,
size: 64, size: 64,
), ),
@@ -361,7 +362,7 @@ class _ImageLightboxState extends State<_ImageLightbox> {
child: Center( child: Center(
child: IconButton( child: IconButton(
icon: const Icon( icon: const Icon(
Icons.chevron_left, FontAwesomeIcons.chevronLeft,
color: AppColors.white, color: AppColors.white,
size: 32, size: 32,
), ),
@@ -382,7 +383,7 @@ class _ImageLightboxState extends State<_ImageLightbox> {
child: Center( child: Center(
child: IconButton( child: IconButton(
icon: const Icon( icon: const Icon(
Icons.chevron_right, FontAwesomeIcons.chevronRight,
color: AppColors.white, color: AppColors.white,
size: 32, size: 32,
), ),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/products/domain/entities/product.dart'; import 'package:worker/features/products/domain/entities/product.dart';
@@ -152,7 +153,7 @@ class _DescriptionTab extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Icon( const Icon(
Icons.check_circle, FontAwesomeIcons.circleCheck,
size: 18, size: 18,
color: AppColors.success, color: AppColors.success,
), ),
@@ -328,7 +329,7 @@ class _ReviewsTab extends StatelessWidget {
children: List.generate( children: List.generate(
5, 5,
(index) => Icon( (index) => Icon(
index < 4 ? Icons.star : Icons.star_half, index < 4 ? FontAwesomeIcons.solidStar : FontAwesomeIcons.starHalfStroke,
color: const Color(0xFFffc107), color: const Color(0xFFffc107),
size: 18, size: 18,
), ),
@@ -387,7 +388,7 @@ class _ReviewItem extends StatelessWidget {
color: Color(0xFFF4F6F8), color: Color(0xFFF4F6F8),
), ),
child: const Icon( child: const Icon(
Icons.person, FontAwesomeIcons.solidUser,
color: AppColors.grey500, color: AppColors.grey500,
size: 20, size: 20,
), ),
@@ -428,8 +429,8 @@ class _ReviewItem extends StatelessWidget {
5, 5,
(index) => Icon( (index) => Icon(
index < (review['rating'] as num? ?? 0).toInt() index < (review['rating'] as num? ?? 0).toInt()
? Icons.star ? FontAwesomeIcons.solidStar
: Icons.star_border, : FontAwesomeIcons.star,
color: const Color(0xFFffc107), color: const Color(0xFFffc107),
size: 14, size: 14,
), ),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -89,7 +90,7 @@ class StickyActionBar extends StatelessWidget {
children: [ children: [
// Decrease Button // Decrease Button
_QuantityButton( _QuantityButton(
icon: Icons.remove, icon: FontAwesomeIcons.minus,
onPressed: quantity > 1 ? onDecrease : null, onPressed: quantity > 1 ? onDecrease : null,
), ),
@@ -122,7 +123,7 @@ class StickyActionBar extends StatelessWidget {
), ),
// Increase Button // Increase Button
_QuantityButton(icon: Icons.add, onPressed: onIncrease), _QuantityButton(icon: FontAwesomeIcons.plus, onPressed: onIncrease),
], ],
), ),
), ),
@@ -160,7 +161,7 @@ class StickyActionBar extends StatelessWidget {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
icon: const Icon(Icons.shopping_cart, size: 20), icon: const FaIcon(FontAwesomeIcons.cartShopping, size: 18),
label: Text( label: Text(
isOutOfStock ? 'Hết hàng' : 'Thêm vào giỏ hàng', isOutOfStock ? 'Hết hàng' : 'Thêm vào giỏ hàng',
style: const TextStyle( style: const TextStyle(

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/products/presentation/providers/product_filters_provider.dart'; import 'package:worker/features/products/presentation/providers/product_filters_provider.dart';
@@ -51,7 +52,7 @@ class ProductFilterDrawer extends ConsumerWidget {
), ),
), ),
IconButton( IconButton(
icon: const Icon(Icons.close), icon: const FaIcon(FontAwesomeIcons.xmark, size: 20),
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -208,7 +209,7 @@ class ProductFilterDrawer extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon( const Icon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 48, size: 48,
color: AppColors.danger, color: AppColors.danger,
), ),

View File

@@ -5,6 +5,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/products/presentation/providers/search_query_provider.dart'; import 'package:worker/features/products/presentation/providers/search_query_provider.dart';
@@ -67,14 +68,14 @@ class _ProductSearchBarState extends ConsumerState<ProductSearchBar> {
color: AppColors.grey500, color: AppColors.grey500,
), ),
prefixIcon: const Icon( prefixIcon: const Icon(
Icons.search, FontAwesomeIcons.magnifyingGlass,
color: AppColors.grey500, color: AppColors.grey500,
size: AppIconSize.md, size: AppIconSize.md,
), ),
suffixIcon: _controller.text.isNotEmpty suffixIcon: _controller.text.isNotEmpty
? IconButton( ? IconButton(
icon: const Icon( icon: const Icon(
Icons.clear, FontAwesomeIcons.xmark,
color: AppColors.grey500, color: AppColors.grey500,
size: AppIconSize.md, size: AppIconSize.md,
), ),

View File

@@ -11,6 +11,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
@@ -56,7 +57,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
loading: () => Scaffold( loading: () => Scaffold(
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -73,7 +74,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
error: (error, stack) => Scaffold( error: (error, stack) => Scaffold(
appBar: AppBar( appBar: AppBar(
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -89,8 +90,8 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon( const FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
size: 64, size: 64,
color: AppColors.danger, color: AppColors.danger,
), ),
@@ -127,7 +128,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
foregroundColor: AppColors.grey900, foregroundColor: AppColors.grey900,
elevation: AppBarSpecs.elevation, elevation: AppBarSpecs.elevation,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: const Text( title: const Text(
@@ -138,15 +139,16 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
actions: [ actions: [
// Share Button // Share Button
IconButton( IconButton(
icon: const Icon(Icons.share, color: Colors.black), icon: const FaIcon(FontAwesomeIcons.shareNodes, color: Colors.black, size: 20),
onPressed: _handleShare, onPressed: _handleShare,
), ),
// Bookmark Button // Bookmark Button
IconButton( IconButton(
icon: Icon( icon: FaIcon(
_isBookmarked ? Icons.bookmark : Icons.bookmark_border, _isBookmarked ? FontAwesomeIcons.solidBookmark : FontAwesomeIcons.bookmark,
color: Colors.black, color: Colors.black,
size: 20,
), ),
onPressed: _handleBookmark, onPressed: _handleBookmark,
), ),
@@ -205,8 +207,8 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
height: 200, height: 200,
color: AppColors.grey100, color: AppColors.grey100,
child: const Center( child: const Center(
child: Icon( child: FaIcon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 64, size: 64,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -243,9 +245,9 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
crossAxisAlignment: WrapCrossAlignment.center, crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
// Clock icon and date // Clock icon and date
const Icon( const FaIcon(
Icons.access_time, FontAwesomeIcons.clock,
size: 18, size: 16,
color: Color(0xFFF59E0B), // warning color color: Color(0xFFF59E0B), // warning color
), ),
Text( Text(
@@ -270,8 +272,8 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
child: const Row( child: const Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( FaIcon(
Icons.local_fire_department, FontAwesomeIcons.fire,
size: 14, size: 14,
color: Colors.white, color: Colors.white,
), ),
@@ -298,7 +300,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
Widget _buildProgramContentSection() { Widget _buildProgramContentSection() {
return const PromotionSection( return const PromotionSection(
title: 'Nội dung chương trình', title: 'Nội dung chương trình',
icon: Icons.card_giftcard, icon: FontAwesomeIcons.gift,
content: Column( content: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -345,7 +347,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
Widget _buildTermsSection() { Widget _buildTermsSection() {
return const PromotionSection( return const PromotionSection(
title: 'Điều kiện áp dụng', title: 'Điều kiện áp dụng',
icon: Icons.description, icon: FontAwesomeIcons.fileLines,
content: PromotionBulletList( content: PromotionBulletList(
items: [ items: [
'Áp dụng cho tất cả khách hàng là thợ xây dựng đã đăng ký tài khoản', 'Áp dụng cho tất cả khách hàng là thợ xây dựng đã đăng ký tài khoản',
@@ -365,7 +367,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
Widget _buildContactSection() { Widget _buildContactSection() {
return const PromotionSection( return const PromotionSection(
title: 'Thông tin liên hệ', title: 'Thông tin liên hệ',
icon: Icons.phone, icon: FontAwesomeIcons.phone,
isLast: true, isLast: true,
content: Column( content: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -414,7 +416,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
child: const Row( child: const Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.visibility, size: 20), FaIcon(FontAwesomeIcons.eye, size: 18),
SizedBox(width: 8), SizedBox(width: 8),
Text( Text(
'Xem sản phẩm áp dụng', 'Xem sản phẩm áp dụng',

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/home/domain/entities/promotion.dart'; import 'package:worker/features/home/domain/entities/promotion.dart';
@@ -47,8 +48,8 @@ class PromotionsPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon( const FaIcon(
Icons.error_outline, FontAwesomeIcons.circleExclamation,
color: AppColors.danger, color: AppColors.danger,
size: 48, size: 48,
), ),
@@ -117,8 +118,8 @@ class PromotionsPage extends ConsumerWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( FaIcon(
Icons.local_offer_outlined, FontAwesomeIcons.tag,
size: 64, size: 64,
color: AppColors.grey500, color: AppColors.grey500,
), ),

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
/// Featured Promotion Card /// Featured Promotion Card
@@ -90,9 +91,9 @@ class FeaturedPromotionCard extends StatelessWidget {
const SizedBox(height: 12), const SizedBox(height: 12),
Row( Row(
children: [ children: [
Icon( FaIcon(
Icons.access_time, FontAwesomeIcons.clock,
size: 14, size: 12,
color: Colors.white.withValues(alpha: 0.8), color: Colors.white.withValues(alpha: 0.8),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
@@ -112,8 +113,8 @@ class FeaturedPromotionCard extends StatelessWidget {
// Right side - Icon // Right side - Icon
const SizedBox(width: 16), const SizedBox(width: 16),
Icon( FaIcon(
Icons.percent, FontAwesomeIcons.percent,
size: 48, size: 48,
color: Colors.white.withValues(alpha: 0.9), color: Colors.white.withValues(alpha: 0.9),
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -62,8 +63,8 @@ class PromotionCard extends StatelessWidget {
height: 150, height: 150,
color: AppColors.grey100, color: AppColors.grey100,
child: const Center( child: const Center(
child: Icon( child: FaIcon(
Icons.image_not_supported, FontAwesomeIcons.image,
size: 48, size: 48,
color: AppColors.grey500, color: AppColors.grey500,
), ),
@@ -109,8 +110,8 @@ class PromotionCard extends StatelessWidget {
Expanded( Expanded(
child: Row( child: Row(
children: [ children: [
const Icon( const FaIcon(
Icons.calendar_today, FontAwesomeIcons.calendar,
size: 12, size: 12,
color: AppColors.primaryBlue, color: AppColors.primaryBlue,
), ),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../core/constants/ui_constants.dart'; import '../../core/constants/ui_constants.dart';
/// Custom app bar with consistent styling /// Custom app bar with consistent styling
@@ -112,7 +113,7 @@ class SearchAppBar extends StatelessWidget implements PreferredSizeWidget {
leading: leading:
leading ?? leading ??
IconButton( IconButton(
icon: const Icon(Icons.arrow_back), icon: const FaIcon(FontAwesomeIcons.arrowLeft, size: 20),
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
title: TextField( title: TextField(
@@ -127,7 +128,7 @@ class SearchAppBar extends StatelessWidget implements PreferredSizeWidget {
border: InputBorder.none, border: InputBorder.none,
suffixIcon: controller?.text.isNotEmpty ?? false suffixIcon: controller?.text.isNotEmpty ?? false
? IconButton( ? IconButton(
icon: const Icon(Icons.clear, color: Colors.white), icon: const FaIcon(FontAwesomeIcons.xmark, color: Colors.white, size: 18),
onPressed: () { onPressed: () {
controller?.clear(); controller?.clear();
onClear?.call(); onClear?.call();

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../core/utils/formatters.dart'; import '../../core/utils/formatters.dart';
import '../../core/utils/validators.dart'; import '../../core/utils/validators.dart';
import '../../core/constants/ui_constants.dart'; import '../../core/constants/ui_constants.dart';
@@ -118,7 +119,7 @@ class _DatePickerFieldState extends State<DatePickerField> {
InputDecoration( InputDecoration(
labelText: widget.labelText ?? 'Ngày', labelText: widget.labelText ?? 'Ngày',
hintText: widget.hintText ?? 'dd/MM/yyyy', hintText: widget.hintText ?? 'dd/MM/yyyy',
prefixIcon: widget.prefixIcon ?? const Icon(Icons.calendar_today), prefixIcon: widget.prefixIcon ?? const FaIcon(FontAwesomeIcons.calendar, size: 20),
suffixIcon: widget.suffixIcon, suffixIcon: widget.suffixIcon,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius), borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
@@ -219,7 +220,7 @@ class _DateRangePickerFieldState extends State<DateRangePickerField> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: widget.labelText ?? 'Khoảng thời gian', labelText: widget.labelText ?? 'Khoảng thời gian',
hintText: widget.hintText ?? 'Chọn khoảng thời gian', hintText: widget.hintText ?? 'Chọn khoảng thời gian',
prefixIcon: widget.prefixIcon ?? const Icon(Icons.date_range), prefixIcon: widget.prefixIcon ?? const FaIcon(FontAwesomeIcons.calendarDays, size: 20),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius), borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
), ),
@@ -266,7 +267,7 @@ class DateOfBirthField extends StatelessWidget {
onDateSelected: onDateSelected, onDateSelected: onDateSelected,
validator: validator ?? (value) => Validators.age(value, minAge: minAge), validator: validator ?? (value) => Validators.age(value, minAge: minAge),
enabled: enabled, enabled: enabled,
prefixIcon: const Icon(Icons.cake), prefixIcon: const FaIcon(FontAwesomeIcons.cakeCandles, size: 20),
); );
} }
} }
@@ -364,7 +365,7 @@ class _TimePickerFieldState extends State<TimePickerField> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: widget.labelText ?? 'Thời gian', labelText: widget.labelText ?? 'Thời gian',
hintText: widget.hintText ?? 'HH:mm', hintText: widget.hintText ?? 'HH:mm',
prefixIcon: widget.prefixIcon ?? const Icon(Icons.access_time), prefixIcon: widget.prefixIcon ?? const FaIcon(FontAwesomeIcons.clock, size: 20),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius), borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
), ),

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/utils/formatters.dart'; import 'package:worker/core/utils/formatters.dart';
import 'package:worker/core/utils/validators.dart'; import 'package:worker/core/utils/validators.dart';
@@ -89,7 +90,7 @@ class _VietnamesePhoneFieldState extends State<VietnamesePhoneField> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: widget.labelText ?? 'Số điện thoại', labelText: widget.labelText ?? 'Số điện thoại',
hintText: widget.hintText ?? '0xxx xxx xxx', hintText: widget.hintText ?? '0xxx xxx xxx',
prefixIcon: widget.prefixIcon ?? const Icon(Icons.phone), prefixIcon: widget.prefixIcon ?? const FaIcon(FontAwesomeIcons.phone, size: 20),
suffixIcon: widget.suffixIcon, suffixIcon: widget.suffixIcon,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius), borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
@@ -158,8 +159,8 @@ class PhoneDisplayField extends StatelessWidget {
onTap: onTap, onTap: onTap,
decoration: InputDecoration( decoration: InputDecoration(
labelText: labelText ?? 'Số điện thoại', labelText: labelText ?? 'Số điện thoại',
prefixIcon: prefixIcon ?? const Icon(Icons.phone), prefixIcon: prefixIcon ?? const FaIcon(FontAwesomeIcons.phone, size: 20),
suffixIcon: onTap != null ? const Icon(Icons.edit) : null, suffixIcon: onTap != null ? const FaIcon(FontAwesomeIcons.penToSquare, size: 18) : null,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius), borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
), ),

View File

@@ -578,6 +578,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
font_awesome_flutter:
dependency: "direct main"
description:
name: font_awesome_flutter
sha256: b9011df3a1fa02993630b8fb83526368cf2206a711259830325bab2f1d2a4eb0
url: "https://pub.dev"
source: hosted
version: "10.12.0"
freezed: freezed:
dependency: "direct dev" dependency: "direct dev"
description: description:

View File

@@ -62,6 +62,7 @@ dependencies:
lottie: ^3.1.2 lottie: ^3.1.2
qr_flutter: ^4.1.0 qr_flutter: ^4.1.0
mobile_scanner: ^5.2.3 mobile_scanner: ^5.2.3
font_awesome_flutter: ^10.7.0
# Utilities # Utilities