update loaing

This commit is contained in:
Phuoc Nguyen
2025-12-02 18:09:20 +07:00
parent fc9b5e967f
commit 19d9a3dc2d
75 changed files with 216 additions and 292 deletions

View File

@@ -420,7 +420,7 @@ ref.watch(userProvider).when(
data: (user) => UserView(user), data: (user) => UserView(user),
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => ErrorView(error), error: (error, stack) => ErrorView(error),
@@ -443,7 +443,7 @@ switch (userState) {
case AsyncLoading(): case AsyncLoading():
return CircularProgressIndicator(); return const CustomLoadingIndicator();
} }

View File

@@ -1117,5 +1117,5 @@ All recent implementations follow:
- ✅ AppBar standardization - ✅ AppBar standardization
- ✅ CachedNetworkImage for all remote images - ✅ CachedNetworkImage for all remote images
- ✅ Proper error handling - ✅ Proper error handling
- ✅ Loading states (CircularProgressIndicator) - ✅ Loading states (CustomLoadingIndicator)
- ✅ Empty states with helpful messages - ✅ Empty states with helpful messages

View File

@@ -219,7 +219,7 @@ class _CartPageState extends ConsumerState<CartPage> {
} }
: null, : null,
child: _isSyncing child: _isSyncing
? CircularProgressIndicator() // Show loading while syncing ? const CustomLoadingIndicator() // Show loading while syncing
: Text('Tiến hành đặt hàng'), : Text('Tiến hành đặt hàng'),
); );
} }

View File

@@ -768,5 +768,5 @@ end
- ✅ Vietnamese localization - ✅ Vietnamese localization
- ✅ CachedNetworkImage for all remote images - ✅ CachedNetworkImage for all remote images
- ✅ Proper error handling - ✅ Proper error handling
- ✅ Loading states (CircularProgressIndicator) - ✅ Loading states (CustomLoadingIndicator)
- ✅ Empty states with helpful messages - ✅ Empty states with helpful messages

View File

@@ -257,7 +257,7 @@ int stars = apiRatingToStars(0.8); // 4
- Added date formatting function (`_formatDate`) - Added date formatting function (`_formatDate`)
**States**: **States**:
1. **Loading**: Shows CircularProgressIndicator 1. **Loading**: Shows CustomLoadingIndicator
2. **Error**: Shows error icon and message 2. **Error**: Shows error icon and message
3. **Empty**: Shows "Chưa có đánh giá nào" with call-to-action 3. **Empty**: Shows "Chưa có đánh giá nào" with call-to-action
4. **Data**: Shows rating overview and review list 4. **Data**: Shows rating overview and review list
@@ -553,7 +553,7 @@ Widget build(BuildContext context, WidgetRef ref) {
}, },
); );
}, },
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Text('Error: $error'), error: (error, stack) => Text('Error: $error'),
); );
} }

View File

@@ -416,7 +416,7 @@ RatingProvider CountProvider in UI components)
``` ```
1. Initial State (Loading) 1. Initial State (Loading)
├─► productReviewsProvider returns AsyncValue.loading() ├─► productReviewsProvider returns AsyncValue.loading()
└─► UI shows CircularProgressIndicator └─► UI shows CustomLoadingIndicator
2. Loading State → Data State 2. Loading State → Data State
├─► API call succeeds ├─► API call succeeds

View File

@@ -60,7 +60,7 @@ class ReviewsListPage extends ConsumerWidget {
); );
}, },
loading: () => const Center( loading: () => const Center(
child: CircularProgressIndicator(), child: const CustomLoadingIndicator(),
), ),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Text('Error: $error'), child: Text('Error: $error'),
@@ -263,7 +263,7 @@ class _SimpleReviewFormState extends ConsumerState<SimpleReviewForm> {
child: ElevatedButton( child: ElevatedButton(
onPressed: _isSubmitting ? null : _submitReview, onPressed: _isSubmitting ? null : _submitReview,
child: _isSubmitting child: _isSubmitting
? const CircularProgressIndicator() ? const const CustomLoadingIndicator()
: const Text('Submit Review'), : const Text('Submit Review'),
), ),
), ),
@@ -351,7 +351,7 @@ class _PaginatedReviewsListState
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Center( child: Center(
child: _isLoading child: _isLoading
? const CircularProgressIndicator() ? const const CustomLoadingIndicator()
: ElevatedButton( : ElevatedButton(
onPressed: _loadMoreReviews, onPressed: _loadMoreReviews,
child: const Text('Load More'), child: const Text('Load More'),
@@ -430,7 +430,7 @@ class RefreshableReviewsList extends ConsumerWidget {
Center( Center(
child: Padding( child: Padding(
padding: EdgeInsets.all(40), padding: EdgeInsets.all(40),
child: CircularProgressIndicator(), child: const CustomLoadingIndicator(),
), ),
), ),
], ],
@@ -540,7 +540,7 @@ class _FilteredReviewsListState extends ConsumerState<FilteredReviewsList> {
); );
}, },
loading: () => const Center( loading: () => const Center(
child: CircularProgressIndicator(), child: const CustomLoadingIndicator(),
), ),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Text('Error: $error'), child: Text('Error: $error'),
@@ -662,7 +662,7 @@ class ReviewsWithRetry extends ConsumerWidget {
); );
}, },
loading: () => const Center( loading: () => const Center(
child: CircularProgressIndicator(), child: const CustomLoadingIndicator(),
), ),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(

View File

@@ -30,7 +30,7 @@ final reviewsAsync = ref.watch(productReviewsProvider(itemId));
reviewsAsync.when( reviewsAsync.when(
data: (reviews) => /* show reviews */, data: (reviews) => /* show reviews */,
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => /* show error */, error: (error, stack) => /* show error */,
); );
``` ```

View File

@@ -31,7 +31,7 @@ Future<User> user(UserRef ref, String id) async {
final userAsync = ref.watch(userProvider('123')); final userAsync = ref.watch(userProvider('123'));
userAsync.when( userAsync.when(
data: (user) => Text(user.name), data: (user) => Text(user.name),
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (e, _) => Text('Error: $e'), error: (e, _) => Text('Error: $e'),
); );
``` ```
@@ -202,7 +202,7 @@ final newValue = ref.refresh(userProvider);
```dart ```dart
asyncValue.when( asyncValue.when(
data: (value) => Text(value), data: (value) => Text(value),
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Text('Error: $error'), error: (error, stack) => Text('Error: $error'),
); );
``` ```
@@ -215,7 +215,7 @@ switch (asyncValue) {
case AsyncError(:final error): case AsyncError(:final error):
return Text('Error: $error'); return Text('Error: $error');
case AsyncLoading(): case AsyncLoading():
return CircularProgressIndicator(); return const CustomLoadingIndicator();
} }
``` ```

View File

@@ -30,7 +30,7 @@ Connectivity connectivity(Ref ref) {
/// final connectivityState = ref.watch(connectivityStreamProvider); /// final connectivityState = ref.watch(connectivityStreamProvider);
/// connectivityState.when( /// connectivityState.when(
/// data: (status) => Text('Status: $status'), /// data: (status) => Text('Status: $status'),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, _) => Text('Error: $error'), /// error: (error, _) => Text('Error: $error'),
/// ); /// );
/// ``` /// ```
@@ -83,7 +83,7 @@ Future<ConnectivityStatus> currentConnectivity(Ref ref) async {
/// final isOnlineAsync = ref.watch(isOnlineProvider); /// final isOnlineAsync = ref.watch(isOnlineProvider);
/// isOnlineAsync.when( /// isOnlineAsync.when(
/// data: (isOnline) => isOnline ? Text('Online') : Text('Offline'), /// data: (isOnline) => isOnline ? Text('Online') : Text('Offline'),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, _) => Text('Error: $error'), /// error: (error, _) => Text('Error: $error'),
/// ); /// );
/// ``` /// ```

View File

@@ -428,7 +428,7 @@ final version = ref.watch(appVersionProvider);
final userData = ref.watch(userDataProvider); final userData = ref.watch(userDataProvider);
userData.when( userData.when(
data: (data) => Text(data), data: (data) => Text(data),
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Text('Error: $error'), error: (error, stack) => Text('Error: $error'),
); );
@@ -466,7 +466,7 @@ switch (profileState) {
case AsyncError(:final error): case AsyncError(:final error):
return Text('Error: $error'); return Text('Error: $error');
case AsyncLoading(): case AsyncLoading():
return CircularProgressIndicator(); return const CustomLoadingIndicator();
} }
*/ */

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
/// Button variant types for different use cases. /// Button variant types for different use cases.
enum ButtonVariant { enum ButtonVariant {
@@ -106,14 +107,7 @@ class CustomButton extends StatelessWidget {
/// Builds the button content (text, icon, or loading indicator) /// Builds the button content (text, icon, or loading indicator)
Widget _buildContent() { Widget _buildContent() {
if (isLoading) { if (isLoading) {
return const SizedBox( return const CustomLoadingIndicator(size: 20, color: Colors.white);
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
);
} }
if (icon != null) { if (icon != null) {

View File

@@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
/// Custom loading indicator widget with optional message text. /// Custom loading indicator widget with optional message text.
/// ///
/// Displays a centered circular progress indicator with an optional /// Displays a centered three rotating dots animation with an optional
/// message below it. Used for loading states throughout the app. /// message below it. Used for loading states throughout the app.
/// ///
/// Example usage: /// Example usage:
@@ -32,19 +33,14 @@ class CustomLoadingIndicator extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Center( return Center(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox( LoadingAnimationWidget.threeRotatingDots(
width: size, color: color ?? colorScheme.primary,
height: size, size: size,
child: CircularProgressIndicator(
strokeWidth: 3,
valueColor: AlwaysStoppedAnimation<Color>(
color ?? AppColors.primaryBlue,
),
),
), ),
if (message != null) ...[ if (message != null) ...[
const SizedBox(height: 16), const SizedBox(height: 16),

View File

@@ -16,6 +16,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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/widgets/loading_indicator.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/database/hive_initializer.dart'; import 'package:worker/core/database/hive_initializer.dart';
import 'package:worker/core/database/models/enums.dart'; import 'package:worker/core/database/models/enums.dart';
@@ -360,12 +361,7 @@ class _ProfileCardSection extends ConsumerWidget {
shape: BoxShape.circle, shape: BoxShape.circle,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
), ),
child: Center( child: const CustomLoadingIndicator(),
child: CircularProgressIndicator(
color: colorScheme.primary,
strokeWidth: 2,
),
),
), ),
const SizedBox(width: AppSpacing.md), const SizedBox(width: AppSpacing.md),
Expanded( Expanded(
@@ -492,11 +488,8 @@ class _ProfileCardSection extends ConsumerWidget {
shape: BoxShape.circle, shape: BoxShape.circle,
color: colorScheme.primaryContainer, color: colorScheme.primaryContainer,
), ),
child: Center( child: CustomLoadingIndicator(
child: CircularProgressIndicator( color: colorScheme.onPrimaryContainer,
color: colorScheme.onPrimaryContainer,
strokeWidth: 2,
),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
@@ -676,7 +669,7 @@ class _LogoutButton extends ConsumerWidget {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
CircularProgressIndicator(), CustomLoadingIndicator(),
SizedBox(height: 16), SizedBox(height: 16),
Text('Đang đăng xuất...'), Text('Đang đăng xuất...'),
], ],

View File

@@ -10,6 +10,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -450,13 +451,9 @@ class AddressFormPage extends HookConsumerWidget {
isSaving, isSaving,
), ),
icon: isSaving.value icon: isSaving.value
? SizedBox( ? CustomLoadingIndicator(
width: 18, color: colorScheme.onPrimary,
height: 18, size: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
color: colorScheme.onPrimary,
),
) )
: const FaIcon(FontAwesomeIcons.floppyDisk, size: 18), : const FaIcon(FontAwesomeIcons.floppyDisk, size: 18),
label: Text( label: Text(
@@ -800,13 +797,9 @@ class AddressFormPage extends HookConsumerWidget {
), ),
if (isLoading) ...[ if (isLoading) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
SizedBox( CustomLoadingIndicator(
width: 12, color: colorScheme.primary,
height: 12, size: 12,
child: CircularProgressIndicator(
strokeWidth: 2,
color: colorScheme.primary,
),
), ),
], ],
], ],
@@ -856,13 +849,9 @@ class AddressFormPage extends HookConsumerWidget {
suffixIcon: isLoading suffixIcon: isLoading
? Padding( ? Padding(
padding: const EdgeInsets.only(right: 12), padding: const EdgeInsets.only(right: 12),
child: SizedBox( child: CustomLoadingIndicator(
width: 20, color: colorScheme.primary,
height: 20, size: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
color: colorScheme.primary,
),
), ),
) )
: null, : null,

View File

@@ -10,6 +10,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -253,7 +254,7 @@ class AddressesPage extends HookConsumerWidget {
), ),
], ],
), ),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@@ -9,6 +9,7 @@
library; library;
import 'dart:convert'; import 'dart:convert';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -61,21 +62,8 @@ class ProfileEditPage extends HookConsumerWidget {
), ),
centerTitle: false, centerTitle: false,
), ),
body: Center( body: const CustomLoadingIndicator(
child: Column( message: 'Đang tải thông tin...',
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(color: colorScheme.primary),
const SizedBox(height: AppSpacing.md),
Text(
'Đang tải thông tin...',
style: TextStyle(
fontSize: 14,
color: colorScheme.onSurfaceVariant,
),
),
],
),
), ),
), ),
error: (error, stack) => Scaffold( error: (error, stack) => Scaffold(

View File

@@ -67,7 +67,7 @@ Future<GetUserInfo> getUserInfoUseCase(Ref ref) async {
/// ///
/// userInfoAsync.when( /// userInfoAsync.when(
/// data: (userInfo) => Text(userInfo.fullName), /// data: (userInfo) => Text(userInfo.fullName),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, stack) => ErrorWidget(error), /// error: (error, stack) => ErrorWidget(error),
/// ); /// );
/// ///

View File

@@ -8,6 +8,7 @@ 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: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/widgets/loading_indicator.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/core/utils/validators.dart'; import 'package:worker/core/utils/validators.dart';
@@ -294,15 +295,9 @@ class _ForgotPasswordPageState extends ConsumerState<ForgotPasswordPage> {
), ),
), ),
child: _isLoading child: _isLoading
? SizedBox( ? CustomLoadingIndicator(
height: 20.0, color: colorScheme.onPrimary,
width: 20.0, size: 20,
child: CircularProgressIndicator(
strokeWidth: 2.0,
valueColor: AlwaysStoppedAnimation<Color>(
colorScheme.onPrimary,
),
),
) )
: const Text( : const Text(
'Gửi mã OTP', 'Gửi mã OTP',

View File

@@ -8,6 +8,7 @@ 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: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/widgets/loading_indicator.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';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -483,15 +484,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
), ),
), ),
child: isLoading child: isLoading
? SizedBox( ? CustomLoadingIndicator(
height: 20.0, color: colorScheme.onPrimary,
width: 20.0, size: 20,
child: CircularProgressIndicator(
strokeWidth: 2.0,
valueColor: AlwaysStoppedAnimation<Color>(
colorScheme.onPrimary,
),
),
) )
: const Text( : const Text(
'Đăng nhập', 'Đăng nhập',

View File

@@ -11,6 +11,7 @@ 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: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/widgets/loading_indicator.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';
@@ -377,15 +378,9 @@ class _OtpVerificationPageState extends ConsumerState<OtpVerificationPage> {
), ),
), ),
child: _isLoading child: _isLoading
? SizedBox( ? CustomLoadingIndicator(
height: 20, color: colorScheme.onPrimary,
width: 20, size: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
colorScheme.onPrimary,
),
),
) )
: const Text( : const Text(
'Xác nhận', 'Xác nhận',

View File

@@ -12,6 +12,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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';
import 'package:worker/core/widgets/loading_indicator.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';
@@ -410,18 +411,8 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
centerTitle: false, centerTitle: false,
), ),
body: _isLoadingData body: _isLoadingData
? Center( ? const CustomLoadingIndicator(
child: Column( message: 'Đang tải dữ liệu...',
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: AppSpacing.md),
Text(
'Đang tải dữ liệu...',
style: TextStyle(color: colorScheme.onSurfaceVariant),
),
],
),
) )
: SafeArea( : SafeArea(
child: Form( child: Form(
@@ -646,15 +637,9 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
), ),
), ),
child: _isLoading child: _isLoading
? SizedBox( ? CustomLoadingIndicator(
height: 20, color: colorScheme.onPrimary,
width: 20, size: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
colorScheme.onPrimary,
),
),
) )
: const Text( : const Text(
'Đăng ký', 'Đăng ký',
@@ -801,9 +786,12 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
}, },
); );
}, },
loading: () => const SizedBox( loading: () => SizedBox(
height: 48, height: 48,
child: Center(child: CircularProgressIndicator()), child: CustomLoadingIndicator(
color: colorScheme.primary,
size: 20,
),
), ),
error: (error, stack) => Container( error: (error, stack) => Container(
height: 48, height: 48,
@@ -867,9 +855,12 @@ class _RegisterPageState extends ConsumerState<RegisterPage> {
}, },
); );
}, },
loading: () => const SizedBox( loading: () => SizedBox(
height: 48, height: 48,
child: Center(child: CircularProgressIndicator()), child: CustomLoadingIndicator(
color: colorScheme.primary,
size: 20,
),
), ),
error: (error, stack) => Container( error: (error, stack) => Container(
height: 48, height: 48,

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
/// Splash Page /// Splash Page
@@ -61,10 +62,7 @@ class SplashPage extends StatelessWidget {
const SizedBox(height: 48.0), const SizedBox(height: 48.0),
// Loading Indicator // Loading Indicator
CircularProgressIndicator( const CustomLoadingIndicator(),
valueColor: AlwaysStoppedAnimation<Color>(colorScheme.primary),
strokeWidth: 3.0,
),
const SizedBox(height: 16.0), const SizedBox(height: 16.0),

View File

@@ -9,6 +9,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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/widgets/loading_indicator.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';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -102,7 +103,7 @@ class _CartPageState extends ConsumerState<CartPage> {
], ],
), ),
body: cartState.isLoading && cartState.isEmpty body: cartState.isLoading && cartState.isEmpty
? const Center(child: CircularProgressIndicator()) ? const CustomLoadingIndicator()
: cartState.errorMessage != null && cartState.isEmpty : cartState.errorMessage != null && cartState.isEmpty
? _buildErrorState(context, cartState.errorMessage!) ? _buildErrorState(context, cartState.errorMessage!)
: cartState.isEmpty : cartState.isEmpty
@@ -132,9 +133,7 @@ class _CartPageState extends ConsumerState<CartPage> {
if (cartState.isLoading) if (cartState.isLoading)
Container( Container(
color: colorScheme.onSurface.withValues(alpha: 0.1), color: colorScheme.onSurface.withValues(alpha: 0.1),
child: const Center( child: const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
), ),
], ],
), ),
@@ -315,14 +314,9 @@ class _CartPageState extends ConsumerState<CartPage> {
elevation: 0, elevation: 0,
), ),
child: _isSyncing child: _isSyncing
? SizedBox( ? CustomLoadingIndicator(
width: 20, color: colorScheme.surface,
height: 20, size: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor:
AlwaysStoppedAnimation<Color>(colorScheme.surface),
),
) )
: Text( : Text(
'Tiến hành đặt hàng', 'Tiến hành đặt hàng',

View File

@@ -15,6 +15,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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';
import 'package:worker/core/widgets/loading_indicator.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';
@@ -177,9 +178,7 @@ class CheckoutPage extends HookConsumerWidget {
), ),
], ],
), ),
child: const Center( child: const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
), ),
error: (error, stack) => Container( error: (error, stack) => Container(
margin: const EdgeInsets.symmetric(horizontal: AppSpacing.md), margin: const EdgeInsets.symmetric(horizontal: AppSpacing.md),

View File

@@ -8,6 +8,7 @@ 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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:worker/core/theme/typography.dart'; import 'package:worker/core/theme/typography.dart';
import 'package:worker/features/cart/presentation/providers/cart_provider.dart'; import 'package:worker/features/cart/presentation/providers/cart_provider.dart';
import 'package:worker/features/cart/presentation/providers/cart_state.dart'; import 'package:worker/features/cart/presentation/providers/cart_state.dart';
@@ -128,8 +129,8 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
width: 100, width: 100,
height: 100, height: 100,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center( child: Center(
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(

View File

@@ -6,6 +6,7 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.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';
import 'package:worker/core/widgets/loading_indicator.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';
@@ -93,8 +94,8 @@ class CheckoutSubmitButton extends HookConsumerWidget {
showDialog<void>( showDialog<void>(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (context) => const Center( builder: (context) => Center(
child: CircularProgressIndicator(), child: CustomLoadingIndicator(color: Theme.of(context).colorScheme.primary, size: 40),
), ),
); );

View File

@@ -201,7 +201,7 @@ class FavoritesPage extends ConsumerWidget {
return ProductCard(productId: productId); return ProductCard(productId: productId);
}, },
), ),
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Text('Error: $error'), error: (error, stack) => Text('Error: $error'),
); );
} }

View File

@@ -119,7 +119,7 @@ class FavoritesPage extends ConsumerWidget {
return ProductTile(productId: productId); return ProductTile(productId: productId);
}, },
), ),
loading: () => CircularProgressIndicator(), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => ErrorWidget(error), error: (error, stack) => ErrorWidget(error),
); );
} }

View File

@@ -204,11 +204,11 @@ class FavoritesPage extends ConsumerWidget {
}, },
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: const CustomLoadingIndicator()),
error: (error, stack) => Center(child: Text('Error: $error')), error: (error, stack) => Center(child: Text('Error: $error')),
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: const CustomLoadingIndicator()),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -368,7 +368,7 @@ class FavoriteProductsList extends ConsumerWidget {
); );
}, },
), ),
loading: () => const CircularProgressIndicator(), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => Text('Error: $error'), error: (error, stack) => Text('Error: $error'),
); );
} }
@@ -417,7 +417,7 @@ class FavoritesPageWithRefresh extends ConsumerWidget {
return ListTile(title: Text('Product: $productId')); return ListTile(title: Text('Product: $productId'));
}, },
), ),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: const CustomLoadingIndicator()),
error: (error, stack) => Center(child: Text('Error: $error')), error: (error, stack) => Center(child: Text('Error: $error')),
), ),
), ),
@@ -466,7 +466,7 @@ class FavoriteButtonWithLoadingState extends ConsumerWidget {
loading: () => const SizedBox( loading: () => const SizedBox(
width: 24, width: 24,
height: 24, height: 24,
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(strokeWidth: 2),
), ),
error: (error, stack) => IconButton( error: (error, stack) => IconButton(
icon: const Icon(Icons.error, color: Colors.grey), icon: const Icon(Icons.error, color: Colors.grey),

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -319,9 +320,7 @@ class FavoritesPage extends HookConsumerWidget {
SizedBox( SizedBox(
width: 16, width: 16,
height: 16, height: 16,
child: CircularProgressIndicator( child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
strokeWidth: 2,
),
), ),
SizedBox(width: 8), SizedBox(width: 8),
Text('Đang tải...'), Text('Đang tải...'),

View File

@@ -8,6 +8,7 @@ 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: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/widgets/loading_indicator.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/router/app_router.dart';
import 'package:worker/core/utils/extensions.dart'; import 'package:worker/core/utils/extensions.dart';
@@ -82,7 +83,7 @@ class _HomePageState extends ConsumerState<HomePage> {
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
child: const Center(child: CircularProgressIndicator()), child: const CustomLoadingIndicator(),
), ),
error: (error, stack) => Container( error: (error, stack) => Container(
margin: const EdgeInsets.all(16), margin: const EdgeInsets.all(16),

View File

@@ -26,7 +26,7 @@ part 'member_card_provider.g.dart';
/// ///
/// memberCardAsync.when( /// memberCardAsync.when(
/// data: (memberCard) => MemberCardWidget(memberCard: memberCard), /// data: (memberCard) => MemberCardWidget(memberCard: memberCard),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, stack) => ErrorWidget(error), /// error: (error, stack) => ErrorWidget(error),
/// ); /// );
/// ``` /// ```

View File

@@ -28,7 +28,7 @@ const int _maxPromotions = 5;
/// ///
/// promotionsAsync.when( /// promotionsAsync.when(
/// data: (promotions) => PromotionSlider(promotions: promotions), /// data: (promotions) => PromotionSlider(promotions: promotions),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, stack) => ErrorWidget(error), /// error: (error, stack) => ErrorWidget(error),
/// ); /// );
/// ``` /// ```

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -126,7 +127,7 @@ class _PromotionCard extends StatelessWidget {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
height: 140, height: 140,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center(child: CircularProgressIndicator()), child: const const CustomLoadingIndicator(),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 140, height: 140,

View File

@@ -7,6 +7,7 @@ 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: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/widgets/loading_indicator.dart';
import 'package:share_plus/share_plus.dart'; import 'package:share_plus/share_plus.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/utils/extensions.dart'; import 'package:worker/core/utils/extensions.dart';
@@ -66,7 +67,7 @@ class InvoiceDetailPage extends ConsumerWidget {
), ),
body: invoiceAsync.when( body: invoiceAsync.when(
data: (invoice) => _buildContent(context, invoice), data: (invoice) => _buildContent(context, invoice),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => _buildErrorState(context, ref, error), error: (error, stack) => _buildErrorState(context, ref, error),
), ),
); );

View File

@@ -7,6 +7,7 @@ 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: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/widgets/loading_indicator.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';
import 'package:worker/core/utils/extensions.dart'; import 'package:worker/core/utils/extensions.dart';
@@ -74,7 +75,7 @@ class InvoicesPage extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => _buildErrorState(context, ref, error), error: (error, stack) => _buildErrorState(context, ref, error),
), ),
); );

View File

@@ -8,6 +8,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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/widgets/loading_indicator.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';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -74,7 +75,7 @@ class PointsHistoryPage extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => _buildErrorState(error, colorScheme), error: (error, stack) => _buildErrorState(error, colorScheme),
), ),
), ),

View File

@@ -8,6 +8,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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/widgets/loading_indicator.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/loyalty/domain/entities/points_record.dart'; import 'package:worker/features/loyalty/domain/entities/points_record.dart';
@@ -183,9 +184,7 @@ class PointsRecordsPage extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center( loading: () => const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
error: (error, stack) => RefreshIndicator( error: (error, stack) => RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await ref.read(allPointsRecordsProvider.notifier).refresh(); await ref.read(allPointsRecordsProvider.notifier).refresh();

View File

@@ -8,6 +8,7 @@ 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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:worker/features/loyalty/domain/entities/gift_catalog.dart'; import 'package:worker/features/loyalty/domain/entities/gift_catalog.dart';
import 'package:worker/features/loyalty/presentation/providers/loyalty_points_provider.dart'; import 'package:worker/features/loyalty/presentation/providers/loyalty_points_provider.dart';
@@ -150,8 +151,8 @@ class RewardCard extends ConsumerWidget {
fit: BoxFit.cover, fit: BoxFit.cover,
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center( child: Center(
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: Theme.of(context).colorScheme.primary, size: 40),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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';
@@ -60,7 +61,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
} }
return _buildContent(context, article); return _buildContent(context, article);
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => _buildErrorState(context, error.toString()), error: (error, stack) => _buildErrorState(context, error.toString()),
), ),
); );
@@ -126,7 +127,7 @@ class _NewsDetailPageState extends ConsumerState<NewsDetailPage> {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
height: 250, height: 250,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center(child: CircularProgressIndicator()), child: const const CustomLoadingIndicator(),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 250, height: 250,

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -98,7 +99,7 @@ class _NewsListPageState extends ConsumerState<NewsListPage> {
loading: () => const SliverToBoxAdapter( loading: () => const SliverToBoxAdapter(
child: Padding( child: Padding(
padding: EdgeInsets.all(AppSpacing.md), padding: EdgeInsets.all(AppSpacing.md),
child: Center(child: CircularProgressIndicator()), child: const CustomLoadingIndicator(),
), ),
), ),
error: (error, stack) => error: (error, stack) =>
@@ -158,7 +159,7 @@ class _NewsListPageState extends ConsumerState<NewsListPage> {
); );
}, },
loading: () => const SliverFillRemaining( loading: () => const SliverFillRemaining(
child: Center(child: CircularProgressIndicator()), child: const CustomLoadingIndicator(),
), ),
error: (error, stack) => SliverFillRemaining( error: (error, stack) => SliverFillRemaining(
child: _buildErrorState(error.toString()), child: _buildErrorState(error.toString()),

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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';
@@ -65,7 +66,7 @@ class FeaturedNewsCard extends StatelessWidget {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
height: 200, height: 200,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center(child: CircularProgressIndicator()), child: const const CustomLoadingIndicator(),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 200, height: 200,

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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';
@@ -61,7 +62,7 @@ class NewsCard extends StatelessWidget {
child: SizedBox( child: SizedBox(
width: 20, width: 20,
height: 20, height: 20,
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
), ),

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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';
@@ -60,7 +61,7 @@ class RelatedArticleCard extends StatelessWidget {
child: SizedBox( child: SizedBox(
width: 16, width: 16,
height: 16, height: 16,
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
), ),

View File

@@ -9,6 +9,7 @@
library; library;
import 'package:flutter/material.dart' hide Notification; import 'package:flutter/material.dart' hide Notification;
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -52,7 +53,7 @@ class NotificationsPage extends HookConsumerWidget {
notifications, notifications,
selectedCategory, selectedCategory,
), ),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => error: (error, stack) =>
_buildErrorState(ref, selectedCategory), _buildErrorState(ref, selectedCategory),
), ),

View File

@@ -14,6 +14,7 @@ import 'package:worker/core/enums/status_color.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';
import 'package:worker/core/utils/extensions.dart'; import 'package:worker/core/utils/extensions.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:worker/features/account/domain/entities/address.dart'; import 'package:worker/features/account/domain/entities/address.dart';
import 'package:worker/features/orders/domain/entities/order_detail.dart'; import 'package:worker/features/orders/domain/entities/order_detail.dart';
import 'package:worker/features/orders/presentation/providers/orders_provider.dart'; import 'package:worker/features/orders/presentation/providers/orders_provider.dart';
@@ -135,7 +136,7 @@ class OrderDetailPage extends ConsumerWidget {
], ],
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -1001,7 +1002,7 @@ class OrderDetailPage extends ConsumerWidget {
height: 60, height: 60,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center( child: const Center(
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(size: 20),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
@@ -1524,13 +1525,9 @@ class OrderDetailPage extends ConsumerWidget {
SnackBar( SnackBar(
content: Row( content: Row(
children: [ children: [
SizedBox( CustomLoadingIndicator(
width: 20, size: 20,
height: 20, color: Theme.of(context).colorScheme.onPrimary,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).colorScheme.onPrimary),
),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
const Text('Đang hủy đơn hàng...'), const Text('Đang hủy đơn hàng...'),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -351,7 +352,7 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
/// Build loading state /// Build loading state
Widget _buildLoadingState() { Widget _buildLoadingState() {
return const SliverFillRemaining( return const SliverFillRemaining(
child: Center(child: CircularProgressIndicator()), child: const CustomLoadingIndicator(),
); );
} }

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -192,7 +193,7 @@ class PaymentDetailPage extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@@ -10,6 +10,7 @@
library; library;
import 'dart:async'; import 'dart:async';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -225,9 +226,7 @@ class PaymentQrPage extends HookConsumerWidget {
border: Border.all(color: colorScheme.outlineVariant), border: Border.all(color: colorScheme.outlineVariant),
), ),
child: isLoading child: isLoading
? const Center( ? const const CustomLoadingIndicator()
child: CircularProgressIndicator(),
)
: qrCodeData != null && qrCodeData.isNotEmpty : qrCodeData != null && qrCodeData.isNotEmpty
? QrImageView( ? QrImageView(
data: qrCodeData, data: qrCodeData,
@@ -580,10 +579,7 @@ class PaymentQrPage extends HookConsumerWidget {
? SizedBox( ? SizedBox(
width: 18, width: 18,
height: 18, height: 18,
child: CircularProgressIndicator( child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(colorScheme.surface),
),
) )
: const FaIcon(FontAwesomeIcons.camera, size: 18), : const FaIcon(FontAwesomeIcons.camera, size: 18),
label: Text( label: Text(

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -71,7 +72,7 @@ class PaymentsPage extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => _buildErrorState(context, ref, error), error: (error, stack) => _buildErrorState(context, ref, error),
), ),
); );

View File

@@ -1,4 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'package:worker/core/widgets/loading_indicator.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';
@@ -164,7 +165,7 @@ class _PricePolicyPageState extends ConsumerState<PricePolicyPage>
), ),
); );
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@@ -81,7 +81,7 @@ UI components and state management.
### UI/UX Features ### UI/UX Features
- Pull-to-refresh support - Pull-to-refresh support
- Loading states with CircularProgressIndicator - Loading states with CustomLoadingIndicator
- Error states with retry button - Error states with retry button
- Empty states with helpful messages - Empty states with helpful messages
- Vietnamese localization - Vietnamese localization

View File

@@ -7,6 +7,7 @@ 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: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/widgets/loading_indicator.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/favorites/presentation/providers/favorites_provider.dart'; import 'package:worker/features/favorites/presentation/providers/favorites_provider.dart';
@@ -262,9 +263,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
], ],
); );
}, },
loading: () => Center( loading: () => const CustomLoadingIndicator(),
child: CircularProgressIndicator(color: colorScheme.primary),
),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(AppSpacing.xl), padding: const EdgeInsets.all(AppSpacing.xl),

View File

@@ -7,6 +7,7 @@ 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: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/widgets/loading_indicator.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';
import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/theme/colors.dart';
@@ -192,7 +193,7 @@ class ProductsPage extends ConsumerWidget {
/// Build loading state /// Build loading state
Widget _buildLoadingState(ColorScheme colorScheme) { Widget _buildLoadingState(ColorScheme colorScheme) {
return Center(child: CircularProgressIndicator(color: colorScheme.primary)); return const CustomLoadingIndicator();
} }
/// Build error state /// Build error state

View File

@@ -8,6 +8,7 @@ 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: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/widgets/loading_indicator.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';
@@ -186,7 +187,7 @@ class _WriteReviewPageState extends ConsumerState<WriteReviewPage> {
body: productAsync.when( body: productAsync.when(
data: (product) => _buildForm(product), data: (product) => _buildForm(product),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const CustomLoadingIndicator(),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -249,8 +250,8 @@ class _WriteReviewPageState extends ConsumerState<WriteReviewPage> {
width: 80, width: 80,
height: 80, height: 80,
color: colorScheme.surfaceContainerLowest, color: colorScheme.surfaceContainerLowest,
child: const Center( child: Center(
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
@@ -510,15 +511,7 @@ class _WriteReviewPageState extends ConsumerState<WriteReviewPage> {
elevation: 0, elevation: 0,
), ),
child: _isSubmitting child: _isSubmitting
? SizedBox( ? CustomLoadingIndicator(color: colorScheme.onPrimary, size: 20)
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor:
AlwaysStoppedAnimation<Color>(colorScheme.onPrimary),
),
)
: Row( : Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [

View File

@@ -99,7 +99,7 @@ class FilterOption {
/// ///
/// filterOptionsAsync.when( /// filterOptionsAsync.when(
/// data: (options) => ProductFilterDrawer(options: options), /// data: (options) => ProductFilterDrawer(options: options),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, stack) => ErrorWidget(error), /// error: (error, stack) => ErrorWidget(error),
/// ); /// );
/// ``` /// ```

View File

@@ -59,7 +59,7 @@ Future<ProductsRepository> productsRepository(Ref ref) async {
/// ///
/// productsAsync.when( /// productsAsync.when(
/// data: (products) => ProductGrid(products: products), /// data: (products) => ProductGrid(products: products),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, stack) => ErrorWidget(error), /// error: (error, stack) => ErrorWidget(error),
/// ); /// );
/// ``` /// ```
@@ -251,7 +251,7 @@ Future<List<Product>> allProducts(Ref ref) async {
/// ///
/// productAsync.when( /// productAsync.when(
/// data: (product) => ProductDetailView(product: product), /// data: (product) => ProductDetailView(product: product),
/// loading: () => CircularProgressIndicator(), /// loading: () => const CustomLoadingIndicator(),
/// error: (error, stack) => ErrorWidget(error), /// error: (error, stack) => ErrorWidget(error),
/// ); /// );
/// ``` /// ```

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:worker/core/widgets/loading_indicator.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/features/products/presentation/providers/product_filter_options_provider.dart'; import 'package:worker/features/products/presentation/providers/product_filter_options_provider.dart';
import 'package:worker/features/products/presentation/providers/product_filters_provider.dart'; import 'package:worker/features/products/presentation/providers/product_filters_provider.dart';
@@ -105,10 +106,10 @@ class BrandFilterChips extends ConsumerWidget {
), ),
); );
}, },
loading: () => const SizedBox( loading: () => SizedBox(
height: 48.0, height: 48.0,
child: Center( child: Center(
child: CircularProgressIndicator(strokeWidth: 2.0), child: CustomLoadingIndicator(color: Theme.of(context).colorScheme.primary, size: 40),
), ),
), ),
error: (error, stack) => const SizedBox.shrink(), error: (error, stack) => const SizedBox.shrink(),

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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/widgets/loading_indicator.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';
@@ -469,9 +470,7 @@ class _ReviewsTab extends ConsumerWidget {
loading: () => Center( loading: () => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),
child: CircularProgressIndicator( child: const CustomLoadingIndicator(),
color: colorScheme.primary,
),
), ),
), ),
error: (error, stack) => _buildErrorState(colorScheme, error.toString()), error: (error, stack) => _buildErrorState(colorScheme, error.toString()),

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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:worker/core/widgets/loading_indicator.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';
@@ -209,11 +210,7 @@ class ProductFilterDrawer extends ConsumerWidget {
), ),
], ],
), ),
loading: () => Center( loading: () => const CustomLoadingIndicator(),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(colorScheme.primary),
),
),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(AppSpacing.lg), padding: const EdgeInsets.all(AppSpacing.lg),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/features/products/domain/entities/product.dart'; import 'package:worker/features/products/domain/entities/product.dart';
import 'package:worker/features/products/presentation/widgets/product_card.dart'; import 'package:worker/features/products/presentation/widgets/product_card.dart';
@@ -80,9 +81,7 @@ class _ProductGridState extends State<ProductGrid> {
return Center( return Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(AppSpacing.md), padding: const EdgeInsets.all(AppSpacing.md),
child: CircularProgressIndicator( child: const CustomLoadingIndicator(),
color: colorScheme.primary,
),
), ),
); );
} }

View File

@@ -4,6 +4,7 @@
library; library;
import 'dart:io'; import 'dart:io';
import 'package:worker/core/widgets/loading_indicator.dart';
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';
@@ -168,7 +169,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const CircularProgressIndicator(), const CustomLoadingIndicator(),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Đang tải thông tin dự án...', 'Đang tải thông tin dự án...',
@@ -641,7 +642,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox( const SizedBox(
width: 16, width: 16,
height: 16, height: 16,
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
Text('Đang tải...', style: TextStyle(color: colorScheme.onSurfaceVariant)), Text('Đang tải...', style: TextStyle(color: colorScheme.onSurfaceVariant)),
@@ -787,10 +788,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: SizedBox( child: SizedBox(
width: 24, width: 24,
height: 24, height: 24,
child: CircularProgressIndicator( child: CustomLoadingIndicator(color: Colors.white, size: 20),
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
), ),
), ),
), ),
@@ -901,7 +899,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: SizedBox( child: SizedBox(
width: 16, width: 16,
height: 16, height: 16,
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
), ),
@@ -931,10 +929,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: SizedBox( child: SizedBox(
width: 24, width: 24,
height: 24, height: 24,
child: CircularProgressIndicator( child: CustomLoadingIndicator(color: Colors.white, size: 20),
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
), ),
), ),
), ),
@@ -1150,10 +1145,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
? const SizedBox( ? const SizedBox(
width: 24, width: 24,
height: 24, height: 24,
child: CircularProgressIndicator( child: CustomLoadingIndicator(color: Colors.white, size: 20),
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
) )
: const Row( : const Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -179,9 +180,7 @@ class SubmissionsPage extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center( loading: () => const const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
error: (error, stack) => RefreshIndicator( error: (error, stack) => RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await ref.read(allSubmissionsProvider.notifier).refresh(); await ref.read(allSubmissionsProvider.notifier).refresh();

View File

@@ -9,6 +9,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
@@ -69,7 +70,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
foregroundColor: AppColors.grey900, foregroundColor: AppColors.grey900,
centerTitle: false, centerTitle: false,
), ),
body: const Center(child: CircularProgressIndicator()), body: const const CustomLoadingIndicator(),
), ),
error: (error, stack) => Scaffold( error: (error, stack) => Scaffold(
appBar: AppBar( appBar: AppBar(
@@ -201,7 +202,7 @@ class _PromotionDetailPageState extends ConsumerState<PromotionDetailPage> {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
height: 200, height: 200,
color: AppColors.grey100, color: AppColors.grey100,
child: const Center(child: CircularProgressIndicator()), child: const const CustomLoadingIndicator(),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 200, height: 200,

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -43,7 +44,7 @@ class PromotionsPage extends ConsumerWidget {
child: promotionsAsync.when( child: promotionsAsync.when(
data: (promotions) => data: (promotions) =>
_buildPromotionsContent(context, promotions), _buildPromotionsContent(context, promotions),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const const CustomLoadingIndicator(),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@@ -5,6 +5,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -57,7 +58,7 @@ class PromotionCard extends StatelessWidget {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
height: 150, height: 150,
color: AppColors.grey100, color: AppColors.grey100,
child: const Center(child: CircularProgressIndicator()), child: const const CustomLoadingIndicator(),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 150, height: 150,

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.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';
@@ -450,7 +451,7 @@ class _QuotesPageState extends ConsumerState<QuotesPage> {
/// Build loading state /// Build loading state
Widget _buildLoadingState() { Widget _buildLoadingState() {
return const SliverFillRemaining( return const SliverFillRemaining(
child: Center(child: CircularProgressIndicator()), child: const CustomLoadingIndicator(),
); );
} }

View File

@@ -4,6 +4,7 @@
library; library;
import 'dart:async'; import 'dart:async';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -810,10 +811,7 @@ class DesignRequestCreatePage extends HookConsumerWidget {
SizedBox( SizedBox(
height: 20, height: 20,
width: 20, width: 20,
child: CircularProgressIndicator( child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
strokeWidth: 2,
color: colorScheme.surface,
),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
Text( Text(

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.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:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -491,9 +492,7 @@ class DesignRequestDetailPage extends ConsumerWidget {
], ],
), ),
), ),
loading: () => const Center( loading: () => const const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),
@@ -560,7 +559,7 @@ class DesignRequestDetailPage extends ConsumerWidget {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center( child: const Center(
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.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:font_awesome_flutter/font_awesome_flutter.dart';
@@ -85,9 +86,7 @@ class ModelHouseDetailPage extends ConsumerWidget {
], ],
), ),
), ),
loading: () => const Center( loading: () => const const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),
@@ -410,7 +409,7 @@ class ModelHouseDetailPage extends ConsumerWidget {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center( child: const Center(
child: CircularProgressIndicator(strokeWidth: 2), child: CustomLoadingIndicator(color: colorScheme.primary, size: 20),
), ),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
@@ -522,7 +521,7 @@ class _ImageViewerDialogState extends State<_ImageViewerDialog> {
imageUrl: widget.images[index].fileUrl, imageUrl: widget.images[index].fileUrl,
fit: BoxFit.contain, fit: BoxFit.contain,
placeholder: (context, url) => const Center( placeholder: (context, url) => const Center(
child: CircularProgressIndicator(color: Colors.white), child: CustomLoadingIndicator(color: Colors.white, size: 40),
), ),
errorWidget: (context, url, error) => const Icon( errorWidget: (context, url, error) => const Icon(
Icons.error, Icons.error,

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.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:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -214,9 +215,7 @@ class _LibraryTab extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center( loading: () => const const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),
@@ -288,7 +287,7 @@ class _LibraryCard extends StatelessWidget {
placeholder: (context, url) => Container( placeholder: (context, url) => Container(
height: 200, height: 200,
color: colorScheme.surfaceContainerHighest, color: colorScheme.surfaceContainerHighest,
child: const Center(child: CircularProgressIndicator()), child: const const CustomLoadingIndicator(),
), ),
errorWidget: (context, url, error) => Container( errorWidget: (context, url, error) => Container(
height: 200, height: 200,
@@ -425,9 +424,7 @@ class _DesignRequestsTab extends ConsumerWidget {
), ),
); );
}, },
loading: () => const Center( loading: () => const const CustomLoadingIndicator(),
child: CircularProgressIndicator(),
),
error: (error, stack) => Center( error: (error, stack) => Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),

View File

@@ -4,6 +4,7 @@
library; library;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:worker/features/showrooms/domain/entities/sample_project.dart'; import 'package:worker/features/showrooms/domain/entities/sample_project.dart';
@@ -70,7 +71,7 @@ class _ImageViewerDialogState extends State<ImageViewerDialog> {
imageUrl: widget.images[index].fileUrl, imageUrl: widget.images[index].fileUrl,
fit: BoxFit.contain, fit: BoxFit.contain,
placeholder: (context, url) => const Center( placeholder: (context, url) => const Center(
child: CircularProgressIndicator(color: Colors.white), child: CustomLoadingIndicator(color: Colors.white, size: 40),
), ),
errorWidget: (context, url, error) => const Icon( errorWidget: (context, url, error) => const Icon(
Icons.error, Icons.error,

View File

@@ -876,6 +876,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
loading_animation_widget:
dependency: "direct main"
description:
name: loading_animation_widget
sha256: "9fe23381f3096e902f39e87e487648ff7f74925e86234353fa885bb9f6c98004"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:

View File

@@ -64,6 +64,7 @@ dependencies:
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 font_awesome_flutter: ^10.7.0
loading_animation_widget: ^1.3.0
# Utilities # Utilities