From 19d9a3dc2d046b853ca7c45c4544a4e8ae0740c3 Mon Sep 17 00:00:00 2001 From: Phuoc Nguyen Date: Tue, 2 Dec 2025 18:09:20 +0700 Subject: [PATCH] update loaing --- .claude/agents/riverpod-expert.md | 4 +- CLAUDE.md | 2 +- docs/md/CART_DEBOUNCE.md | 2 +- docs/md/CODE_EXAMPLES.md | 2 +- docs/md/REVIEWS_API_INTEGRATION_SUMMARY.md | 4 +- docs/md/REVIEWS_ARCHITECTURE.md | 2 +- docs/md/REVIEWS_CODE_EXAMPLES.md | 12 +++--- docs/md/REVIEWS_QUICK_REFERENCE.md | 2 +- lib/core/providers/QUICK_REFERENCE.md | 6 +-- lib/core/providers/connectivity_provider.dart | 4 +- lib/core/providers/provider_examples.dart | 4 +- lib/core/widgets/custom_button.dart | 10 +---- lib/core/widgets/loading_indicator.dart | 16 +++----- .../presentation/pages/account_page.dart | 17 +++----- .../presentation/pages/address_form_page.dart | 31 +++++--------- .../presentation/pages/addresses_page.dart | 3 +- .../presentation/pages/profile_edit_page.dart | 18 ++------ .../providers/user_info_provider.dart | 2 +- .../pages/forgot_password_page.dart | 13 ++---- .../auth/presentation/pages/login_page.dart | 13 ++---- .../pages/otp_verification_page.dart | 13 ++---- .../presentation/pages/register_page.dart | 41 ++++++++----------- .../auth/presentation/pages/splash_page.dart | 6 +-- .../cart/presentation/pages/cart_page.dart | 18 +++----- .../presentation/pages/checkout_page.dart | 5 +-- .../widgets/cart_item_widget.dart | 5 ++- .../widgets/checkout_submit_button.dart | 5 ++- lib/features/favorites/INTEGRATION_SUMMARY.md | 2 +- lib/features/favorites/README.md | 2 +- lib/features/favorites/USAGE_EXAMPLES.md | 10 ++--- .../presentation/pages/favorites_page.dart | 5 +-- .../home/presentation/pages/home_page.dart | 3 +- .../providers/member_card_provider.dart | 2 +- .../providers/promotions_provider.dart | 2 +- .../widgets/promotion_slider.dart | 3 +- .../pages/invoice_detail_page.dart | 3 +- .../presentation/pages/invoices_page.dart | 3 +- .../pages/points_history_page.dart | 3 +- .../pages/points_records_page.dart | 5 +-- .../presentation/widgets/reward_card.dart | 5 ++- .../presentation/pages/news_detail_page.dart | 5 ++- .../presentation/pages/news_list_page.dart | 5 ++- .../widgets/featured_news_card.dart | 3 +- .../news/presentation/widgets/news_card.dart | 3 +- .../widgets/related_article_card.dart | 3 +- .../pages/notifications_page.dart | 3 +- .../presentation/pages/order_detail_page.dart | 15 +++---- .../presentation/pages/orders_page.dart | 3 +- .../pages/payment_detail_page.dart | 3 +- .../presentation/pages/payment_qr_page.dart | 10 ++--- .../presentation/pages/payments_page.dart | 3 +- .../presentation/pages/price_policy_page.dart | 3 +- lib/features/products/README.md | 2 +- .../pages/product_detail_page.dart | 5 +-- .../presentation/pages/products_page.dart | 3 +- .../presentation/pages/write_review_page.dart | 17 +++----- .../product_filter_options_provider.dart | 2 +- .../providers/products_provider.dart | 4 +- .../widgets/brand_filter_chips.dart | 5 ++- .../product_detail/product_tabs_section.dart | 5 +-- .../widgets/product_filter_drawer.dart | 7 +--- .../presentation/widgets/product_grid.dart | 5 +-- .../pages/submission_create_page.dart | 22 ++++------ .../presentation/pages/submissions_page.dart | 5 +-- .../pages/promotion_detail_page.dart | 5 ++- .../presentation/pages/promotions_page.dart | 3 +- .../presentation/widgets/promotion_card.dart | 3 +- .../presentation/pages/quotes_page.dart | 3 +- .../pages/design_request_create_page.dart | 6 +-- .../pages/design_request_detail_page.dart | 7 ++-- .../pages/model_house_detail_page.dart | 9 ++-- .../presentation/pages/model_houses_page.dart | 11 ++--- .../widgets/image_viewer_dialog.dart | 3 +- pubspec.lock | 8 ++++ pubspec.yaml | 1 + 75 files changed, 216 insertions(+), 292 deletions(-) diff --git a/.claude/agents/riverpod-expert.md b/.claude/agents/riverpod-expert.md index da440a5..a975e6b 100644 --- a/.claude/agents/riverpod-expert.md +++ b/.claude/agents/riverpod-expert.md @@ -420,7 +420,7 @@ ref.watch(userProvider).when( data: (user) => UserView(user), - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => ErrorView(error), @@ -443,7 +443,7 @@ switch (userState) { case AsyncLoading(): - return CircularProgressIndicator(); + return const CustomLoadingIndicator(); } diff --git a/CLAUDE.md b/CLAUDE.md index c866b34..500eae6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1117,5 +1117,5 @@ All recent implementations follow: - ✅ AppBar standardization - ✅ CachedNetworkImage for all remote images - ✅ Proper error handling -- ✅ Loading states (CircularProgressIndicator) +- ✅ Loading states (CustomLoadingIndicator) - ✅ Empty states with helpful messages diff --git a/docs/md/CART_DEBOUNCE.md b/docs/md/CART_DEBOUNCE.md index 85cccc3..4fe4ca2 100644 --- a/docs/md/CART_DEBOUNCE.md +++ b/docs/md/CART_DEBOUNCE.md @@ -219,7 +219,7 @@ class _CartPageState extends ConsumerState { } : null, child: _isSyncing - ? CircularProgressIndicator() // Show loading while syncing + ? const CustomLoadingIndicator() // Show loading while syncing : Text('Tiến hành đặt hàng'), ); } diff --git a/docs/md/CODE_EXAMPLES.md b/docs/md/CODE_EXAMPLES.md index e92273a..6da64f4 100644 --- a/docs/md/CODE_EXAMPLES.md +++ b/docs/md/CODE_EXAMPLES.md @@ -768,5 +768,5 @@ end - ✅ Vietnamese localization - ✅ CachedNetworkImage for all remote images - ✅ Proper error handling -- ✅ Loading states (CircularProgressIndicator) +- ✅ Loading states (CustomLoadingIndicator) - ✅ Empty states with helpful messages diff --git a/docs/md/REVIEWS_API_INTEGRATION_SUMMARY.md b/docs/md/REVIEWS_API_INTEGRATION_SUMMARY.md index bab736f..6693726 100644 --- a/docs/md/REVIEWS_API_INTEGRATION_SUMMARY.md +++ b/docs/md/REVIEWS_API_INTEGRATION_SUMMARY.md @@ -257,7 +257,7 @@ int stars = apiRatingToStars(0.8); // 4 - Added date formatting function (`_formatDate`) **States**: -1. **Loading**: Shows CircularProgressIndicator +1. **Loading**: Shows CustomLoadingIndicator 2. **Error**: Shows error icon and message 3. **Empty**: Shows "Chưa có đánh giá nào" with call-to-action 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'), ); } diff --git a/docs/md/REVIEWS_ARCHITECTURE.md b/docs/md/REVIEWS_ARCHITECTURE.md index bf0e22a..791c042 100644 --- a/docs/md/REVIEWS_ARCHITECTURE.md +++ b/docs/md/REVIEWS_ARCHITECTURE.md @@ -416,7 +416,7 @@ RatingProvider CountProvider in UI components) ``` 1. Initial State (Loading) ├─► productReviewsProvider returns AsyncValue.loading() - └─► UI shows CircularProgressIndicator + └─► UI shows CustomLoadingIndicator 2. Loading State → Data State ├─► API call succeeds diff --git a/docs/md/REVIEWS_CODE_EXAMPLES.md b/docs/md/REVIEWS_CODE_EXAMPLES.md index ac57b7b..26bf9bd 100644 --- a/docs/md/REVIEWS_CODE_EXAMPLES.md +++ b/docs/md/REVIEWS_CODE_EXAMPLES.md @@ -60,7 +60,7 @@ class ReviewsListPage extends ConsumerWidget { ); }, loading: () => const Center( - child: CircularProgressIndicator(), + child: const CustomLoadingIndicator(), ), error: (error, stack) => Center( child: Text('Error: $error'), @@ -263,7 +263,7 @@ class _SimpleReviewFormState extends ConsumerState { child: ElevatedButton( onPressed: _isSubmitting ? null : _submitReview, child: _isSubmitting - ? const CircularProgressIndicator() + ? const const CustomLoadingIndicator() : const Text('Submit Review'), ), ), @@ -351,7 +351,7 @@ class _PaginatedReviewsListState padding: const EdgeInsets.all(16), child: Center( child: _isLoading - ? const CircularProgressIndicator() + ? const const CustomLoadingIndicator() : ElevatedButton( onPressed: _loadMoreReviews, child: const Text('Load More'), @@ -430,7 +430,7 @@ class RefreshableReviewsList extends ConsumerWidget { Center( child: Padding( padding: EdgeInsets.all(40), - child: CircularProgressIndicator(), + child: const CustomLoadingIndicator(), ), ), ], @@ -540,7 +540,7 @@ class _FilteredReviewsListState extends ConsumerState { ); }, loading: () => const Center( - child: CircularProgressIndicator(), + child: const CustomLoadingIndicator(), ), error: (error, stack) => Center( child: Text('Error: $error'), @@ -662,7 +662,7 @@ class ReviewsWithRetry extends ConsumerWidget { ); }, loading: () => const Center( - child: CircularProgressIndicator(), + child: const CustomLoadingIndicator(), ), error: (error, stack) => Center( child: Column( diff --git a/docs/md/REVIEWS_QUICK_REFERENCE.md b/docs/md/REVIEWS_QUICK_REFERENCE.md index bfba69a..613c001 100644 --- a/docs/md/REVIEWS_QUICK_REFERENCE.md +++ b/docs/md/REVIEWS_QUICK_REFERENCE.md @@ -30,7 +30,7 @@ final reviewsAsync = ref.watch(productReviewsProvider(itemId)); reviewsAsync.when( data: (reviews) => /* show reviews */, - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => /* show error */, ); ``` diff --git a/lib/core/providers/QUICK_REFERENCE.md b/lib/core/providers/QUICK_REFERENCE.md index 829062d..7225bcd 100644 --- a/lib/core/providers/QUICK_REFERENCE.md +++ b/lib/core/providers/QUICK_REFERENCE.md @@ -31,7 +31,7 @@ Future user(UserRef ref, String id) async { final userAsync = ref.watch(userProvider('123')); userAsync.when( data: (user) => Text(user.name), - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (e, _) => Text('Error: $e'), ); ``` @@ -202,7 +202,7 @@ final newValue = ref.refresh(userProvider); ```dart asyncValue.when( data: (value) => Text(value), - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => Text('Error: $error'), ); ``` @@ -215,7 +215,7 @@ switch (asyncValue) { case AsyncError(:final error): return Text('Error: $error'); case AsyncLoading(): - return CircularProgressIndicator(); + return const CustomLoadingIndicator(); } ``` diff --git a/lib/core/providers/connectivity_provider.dart b/lib/core/providers/connectivity_provider.dart index 29f5740..7091322 100644 --- a/lib/core/providers/connectivity_provider.dart +++ b/lib/core/providers/connectivity_provider.dart @@ -30,7 +30,7 @@ Connectivity connectivity(Ref ref) { /// final connectivityState = ref.watch(connectivityStreamProvider); /// connectivityState.when( /// data: (status) => Text('Status: $status'), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, _) => Text('Error: $error'), /// ); /// ``` @@ -83,7 +83,7 @@ Future currentConnectivity(Ref ref) async { /// final isOnlineAsync = ref.watch(isOnlineProvider); /// isOnlineAsync.when( /// data: (isOnline) => isOnline ? Text('Online') : Text('Offline'), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, _) => Text('Error: $error'), /// ); /// ``` diff --git a/lib/core/providers/provider_examples.dart b/lib/core/providers/provider_examples.dart index 4bebb02..a14cc91 100644 --- a/lib/core/providers/provider_examples.dart +++ b/lib/core/providers/provider_examples.dart @@ -428,7 +428,7 @@ final version = ref.watch(appVersionProvider); final userData = ref.watch(userDataProvider); userData.when( data: (data) => Text(data), - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => Text('Error: $error'), ); @@ -466,7 +466,7 @@ switch (profileState) { case AsyncError(:final error): return Text('Error: $error'); case AsyncLoading(): - return CircularProgressIndicator(); + return const CustomLoadingIndicator(); } */ diff --git a/lib/core/widgets/custom_button.dart b/lib/core/widgets/custom_button.dart index fe865aa..5da7ca9 100644 --- a/lib/core/widgets/custom_button.dart +++ b/lib/core/widgets/custom_button.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:worker/core/theme/colors.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; /// Button variant types for different use cases. enum ButtonVariant { @@ -106,14 +107,7 @@ class CustomButton extends StatelessWidget { /// Builds the button content (text, icon, or loading indicator) Widget _buildContent() { if (isLoading) { - return const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ); + return const CustomLoadingIndicator(size: 20, color: Colors.white); } if (icon != null) { diff --git a/lib/core/widgets/loading_indicator.dart b/lib/core/widgets/loading_indicator.dart index 7c32fec..c0ba7b4 100644 --- a/lib/core/widgets/loading_indicator.dart +++ b/lib/core/widgets/loading_indicator.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:worker/core/theme/colors.dart'; /// 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. /// /// Example usage: @@ -32,19 +33,14 @@ class CustomLoadingIndicator extends StatelessWidget { @override Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ - SizedBox( - width: size, - height: size, - child: CircularProgressIndicator( - strokeWidth: 3, - valueColor: AlwaysStoppedAnimation( - color ?? AppColors.primaryBlue, - ), - ), + LoadingAnimationWidget.threeRotatingDots( + color: color ?? colorScheme.primary, + size: size, ), if (message != null) ...[ const SizedBox(height: 16), diff --git a/lib/features/account/presentation/pages/account_page.dart b/lib/features/account/presentation/pages/account_page.dart index 8ff7919..3c6c008 100644 --- a/lib/features/account/presentation/pages/account_page.dart +++ b/lib/features/account/presentation/pages/account_page.dart @@ -16,6 +16,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.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/database/hive_initializer.dart'; import 'package:worker/core/database/models/enums.dart'; @@ -360,12 +361,7 @@ class _ProfileCardSection extends ConsumerWidget { shape: BoxShape.circle, color: colorScheme.surfaceContainerHighest, ), - child: Center( - child: CircularProgressIndicator( - color: colorScheme.primary, - strokeWidth: 2, - ), - ), + child: const CustomLoadingIndicator(), ), const SizedBox(width: AppSpacing.md), Expanded( @@ -492,11 +488,8 @@ class _ProfileCardSection extends ConsumerWidget { shape: BoxShape.circle, color: colorScheme.primaryContainer, ), - child: Center( - child: CircularProgressIndicator( - color: colorScheme.onPrimaryContainer, - strokeWidth: 2, - ), + child: CustomLoadingIndicator( + color: colorScheme.onPrimaryContainer, ), ), errorWidget: (context, url, error) => Container( @@ -676,7 +669,7 @@ class _LogoutButton extends ConsumerWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - CircularProgressIndicator(), + CustomLoadingIndicator(), SizedBox(height: 16), Text('Đang đăng xuất...'), ], diff --git a/lib/features/account/presentation/pages/address_form_page.dart b/lib/features/account/presentation/pages/address_form_page.dart index a315dbf..e2ecada 100644 --- a/lib/features/account/presentation/pages/address_form_page.dart +++ b/lib/features/account/presentation/pages/address_form_page.dart @@ -10,6 +10,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -450,13 +451,9 @@ class AddressFormPage extends HookConsumerWidget { isSaving, ), icon: isSaving.value - ? SizedBox( - width: 18, - height: 18, - child: CircularProgressIndicator( - strokeWidth: 2, - color: colorScheme.onPrimary, - ), + ? CustomLoadingIndicator( + color: colorScheme.onPrimary, + size: 18, ) : const FaIcon(FontAwesomeIcons.floppyDisk, size: 18), label: Text( @@ -800,13 +797,9 @@ class AddressFormPage extends HookConsumerWidget { ), if (isLoading) ...[ const SizedBox(width: 8), - SizedBox( - width: 12, - height: 12, - child: CircularProgressIndicator( - strokeWidth: 2, - color: colorScheme.primary, - ), + CustomLoadingIndicator( + color: colorScheme.primary, + size: 12, ), ], ], @@ -856,13 +849,9 @@ class AddressFormPage extends HookConsumerWidget { suffixIcon: isLoading ? Padding( padding: const EdgeInsets.only(right: 12), - child: SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - color: colorScheme.primary, - ), + child: CustomLoadingIndicator( + color: colorScheme.primary, + size: 20, ), ) : null, diff --git a/lib/features/account/presentation/pages/addresses_page.dart b/lib/features/account/presentation/pages/addresses_page.dart index 9a39a0c..212606b 100644 --- a/lib/features/account/presentation/pages/addresses_page.dart +++ b/lib/features/account/presentation/pages/addresses_page.dart @@ -10,6 +10,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.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( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/features/account/presentation/pages/profile_edit_page.dart b/lib/features/account/presentation/pages/profile_edit_page.dart index f712f96..9a72ef7 100644 --- a/lib/features/account/presentation/pages/profile_edit_page.dart +++ b/lib/features/account/presentation/pages/profile_edit_page.dart @@ -9,6 +9,7 @@ library; import 'dart:convert'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -61,21 +62,8 @@ class ProfileEditPage extends HookConsumerWidget { ), centerTitle: false, ), - body: Center( - child: Column( - 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, - ), - ), - ], - ), + body: const CustomLoadingIndicator( + message: 'Đang tải thông tin...', ), ), error: (error, stack) => Scaffold( diff --git a/lib/features/account/presentation/providers/user_info_provider.dart b/lib/features/account/presentation/providers/user_info_provider.dart index 24b855a..1d566bb 100644 --- a/lib/features/account/presentation/providers/user_info_provider.dart +++ b/lib/features/account/presentation/providers/user_info_provider.dart @@ -67,7 +67,7 @@ Future getUserInfoUseCase(Ref ref) async { /// /// userInfoAsync.when( /// data: (userInfo) => Text(userInfo.fullName), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// diff --git a/lib/features/auth/presentation/pages/forgot_password_page.dart b/lib/features/auth/presentation/pages/forgot_password_page.dart index b8b594e..3e44127 100644 --- a/lib/features/auth/presentation/pages/forgot_password_page.dart +++ b/lib/features/auth/presentation/pages/forgot_password_page.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/theme/colors.dart'; import 'package:worker/core/utils/validators.dart'; @@ -294,15 +295,9 @@ class _ForgotPasswordPageState extends ConsumerState { ), ), child: _isLoading - ? SizedBox( - height: 20.0, - width: 20.0, - child: CircularProgressIndicator( - strokeWidth: 2.0, - valueColor: AlwaysStoppedAnimation( - colorScheme.onPrimary, - ), - ), + ? CustomLoadingIndicator( + color: colorScheme.onPrimary, + size: 20, ) : const Text( 'Gửi mã OTP', diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index f73e34b..f5c010a 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/theme/colors.dart'; @@ -483,15 +484,9 @@ class _LoginPageState extends ConsumerState { ), ), child: isLoading - ? SizedBox( - height: 20.0, - width: 20.0, - child: CircularProgressIndicator( - strokeWidth: 2.0, - valueColor: AlwaysStoppedAnimation( - colorScheme.onPrimary, - ), - ), + ? CustomLoadingIndicator( + color: colorScheme.onPrimary, + size: 20, ) : const Text( 'Đăng nhập', diff --git a/lib/features/auth/presentation/pages/otp_verification_page.dart b/lib/features/auth/presentation/pages/otp_verification_page.dart index 4a5370d..d7c18be 100644 --- a/lib/features/auth/presentation/pages/otp_verification_page.dart +++ b/lib/features/auth/presentation/pages/otp_verification_page.dart @@ -11,6 +11,7 @@ import 'package:flutter/services.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.dart'; @@ -377,15 +378,9 @@ class _OtpVerificationPageState extends ConsumerState { ), ), child: _isLoading - ? SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - colorScheme.onPrimary, - ), - ), + ? CustomLoadingIndicator( + color: colorScheme.onPrimary, + size: 20, ) : const Text( 'Xác nhận', diff --git a/lib/features/auth/presentation/pages/register_page.dart b/lib/features/auth/presentation/pages/register_page.dart index 03c10a8..ebf2669 100644 --- a/lib/features/auth/presentation/pages/register_page.dart +++ b/lib/features/auth/presentation/pages/register_page.dart @@ -12,6 +12,7 @@ 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: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/router/app_router.dart'; @@ -410,18 +411,8 @@ class _RegisterPageState extends ConsumerState { centerTitle: false, ), body: _isLoadingData - ? Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: AppSpacing.md), - Text( - 'Đang tải dữ liệu...', - style: TextStyle(color: colorScheme.onSurfaceVariant), - ), - ], - ), + ? const CustomLoadingIndicator( + message: 'Đang tải dữ liệu...', ) : SafeArea( child: Form( @@ -646,15 +637,9 @@ class _RegisterPageState extends ConsumerState { ), ), child: _isLoading - ? SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - colorScheme.onPrimary, - ), - ), + ? CustomLoadingIndicator( + color: colorScheme.onPrimary, + size: 20, ) : const Text( 'Đăng ký', @@ -801,9 +786,12 @@ class _RegisterPageState extends ConsumerState { }, ); }, - loading: () => const SizedBox( + loading: () => SizedBox( height: 48, - child: Center(child: CircularProgressIndicator()), + child: CustomLoadingIndicator( + color: colorScheme.primary, + size: 20, + ), ), error: (error, stack) => Container( height: 48, @@ -867,9 +855,12 @@ class _RegisterPageState extends ConsumerState { }, ); }, - loading: () => const SizedBox( + loading: () => SizedBox( height: 48, - child: Center(child: CircularProgressIndicator()), + child: CustomLoadingIndicator( + color: colorScheme.primary, + size: 20, + ), ), error: (error, stack) => Container( height: 48, diff --git a/lib/features/auth/presentation/pages/splash_page.dart b/lib/features/auth/presentation/pages/splash_page.dart index aa93f7d..4e38c57 100644 --- a/lib/features/auth/presentation/pages/splash_page.dart +++ b/lib/features/auth/presentation/pages/splash_page.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/theme/colors.dart'; /// Splash Page @@ -61,10 +62,7 @@ class SplashPage extends StatelessWidget { const SizedBox(height: 48.0), // Loading Indicator - CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(colorScheme.primary), - strokeWidth: 3.0, - ), + const CustomLoadingIndicator(), const SizedBox(height: 16.0), diff --git a/lib/features/cart/presentation/pages/cart_page.dart b/lib/features/cart/presentation/pages/cart_page.dart index d465480..c01a431 100644 --- a/lib/features/cart/presentation/pages/cart_page.dart +++ b/lib/features/cart/presentation/pages/cart_page.dart @@ -9,6 +9,7 @@ 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:intl/intl.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/theme/colors.dart'; @@ -102,7 +103,7 @@ class _CartPageState extends ConsumerState { ], ), body: cartState.isLoading && cartState.isEmpty - ? const Center(child: CircularProgressIndicator()) + ? const CustomLoadingIndicator() : cartState.errorMessage != null && cartState.isEmpty ? _buildErrorState(context, cartState.errorMessage!) : cartState.isEmpty @@ -132,9 +133,7 @@ class _CartPageState extends ConsumerState { if (cartState.isLoading) Container( color: colorScheme.onSurface.withValues(alpha: 0.1), - child: const Center( - child: CircularProgressIndicator(), - ), + child: const CustomLoadingIndicator(), ), ], ), @@ -315,14 +314,9 @@ class _CartPageState extends ConsumerState { elevation: 0, ), child: _isSyncing - ? SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation(colorScheme.surface), - ), + ? CustomLoadingIndicator( + color: colorScheme.surface, + size: 20, ) : Text( 'Tiến hành đặt hàng', diff --git a/lib/features/cart/presentation/pages/checkout_page.dart b/lib/features/cart/presentation/pages/checkout_page.dart index f9045f9..33d2440 100644 --- a/lib/features/cart/presentation/pages/checkout_page.dart +++ b/lib/features/cart/presentation/pages/checkout_page.dart @@ -15,6 +15,7 @@ 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: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/theme/colors.dart'; @@ -177,9 +178,7 @@ class CheckoutPage extends HookConsumerWidget { ), ], ), - child: const Center( - child: CircularProgressIndicator(), - ), + child: const CustomLoadingIndicator(), ), error: (error, stack) => Container( margin: const EdgeInsets.symmetric(horizontal: AppSpacing.md), diff --git a/lib/features/cart/presentation/widgets/cart_item_widget.dart b/lib/features/cart/presentation/widgets/cart_item_widget.dart index 4a3a7e1..a4c96f7 100644 --- a/lib/features/cart/presentation/widgets/cart_item_widget.dart +++ b/lib/features/cart/presentation/widgets/cart_item_widget.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; +import 'package:worker/core/widgets/loading_indicator.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_state.dart'; @@ -128,8 +129,8 @@ class _CartItemWidgetState extends ConsumerState { width: 100, height: 100, color: colorScheme.surfaceContainerHighest, - child: const Center( - child: CircularProgressIndicator(strokeWidth: 2), + child: Center( + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), errorWidget: (context, url, error) => Container( diff --git a/lib/features/cart/presentation/widgets/checkout_submit_button.dart b/lib/features/cart/presentation/widgets/checkout_submit_button.dart index 4f5a389..a497383 100644 --- a/lib/features/cart/presentation/widgets/checkout_submit_button.dart +++ b/lib/features/cart/presentation/widgets/checkout_submit_button.dart @@ -6,6 +6,7 @@ library; import 'package:flutter/material.dart'; import 'package:go_router/go_router.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/router/app_router.dart'; @@ -93,8 +94,8 @@ class CheckoutSubmitButton extends HookConsumerWidget { showDialog( context: context, barrierDismissible: false, - builder: (context) => const Center( - child: CircularProgressIndicator(), + builder: (context) => Center( + child: CustomLoadingIndicator(color: Theme.of(context).colorScheme.primary, size: 40), ), ); diff --git a/lib/features/favorites/INTEGRATION_SUMMARY.md b/lib/features/favorites/INTEGRATION_SUMMARY.md index 8c75165..76253bd 100644 --- a/lib/features/favorites/INTEGRATION_SUMMARY.md +++ b/lib/features/favorites/INTEGRATION_SUMMARY.md @@ -201,7 +201,7 @@ class FavoritesPage extends ConsumerWidget { return ProductCard(productId: productId); }, ), - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => Text('Error: $error'), ); } diff --git a/lib/features/favorites/README.md b/lib/features/favorites/README.md index 475c562..e7d002a 100644 --- a/lib/features/favorites/README.md +++ b/lib/features/favorites/README.md @@ -119,7 +119,7 @@ class FavoritesPage extends ConsumerWidget { return ProductTile(productId: productId); }, ), - loading: () => CircularProgressIndicator(), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => ErrorWidget(error), ); } diff --git a/lib/features/favorites/USAGE_EXAMPLES.md b/lib/features/favorites/USAGE_EXAMPLES.md index 6341159..5960e75 100644 --- a/lib/features/favorites/USAGE_EXAMPLES.md +++ b/lib/features/favorites/USAGE_EXAMPLES.md @@ -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')), ); }, - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const Center(child: const CustomLoadingIndicator()), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -368,7 +368,7 @@ class FavoriteProductsList extends ConsumerWidget { ); }, ), - loading: () => const CircularProgressIndicator(), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Text('Error: $error'), ); } @@ -417,7 +417,7 @@ class FavoritesPageWithRefresh extends ConsumerWidget { 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')), ), ), @@ -466,7 +466,7 @@ class FavoriteButtonWithLoadingState extends ConsumerWidget { loading: () => const SizedBox( width: 24, height: 24, - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(strokeWidth: 2), ), error: (error, stack) => IconButton( icon: const Icon(Icons.error, color: Colors.grey), diff --git a/lib/features/favorites/presentation/pages/favorites_page.dart b/lib/features/favorites/presentation/pages/favorites_page.dart index fcf0231..dd862b4 100644 --- a/lib/features/favorites/presentation/pages/favorites_page.dart +++ b/lib/features/favorites/presentation/pages/favorites_page.dart @@ -5,6 +5,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -319,9 +320,7 @@ class FavoritesPage extends HookConsumerWidget { SizedBox( width: 16, height: 16, - child: CircularProgressIndicator( - strokeWidth: 2, - ), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), SizedBox(width: 8), Text('Đang tải...'), diff --git a/lib/features/home/presentation/pages/home_page.dart b/lib/features/home/presentation/pages/home_page.dart index 16dd24f..71bd7e2 100644 --- a/lib/features/home/presentation/pages/home_page.dart +++ b/lib/features/home/presentation/pages/home_page.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:shimmer/shimmer.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/utils/extensions.dart'; @@ -82,7 +83,7 @@ class _HomePageState extends ConsumerState { color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(16), ), - child: const Center(child: CircularProgressIndicator()), + child: const CustomLoadingIndicator(), ), error: (error, stack) => Container( margin: const EdgeInsets.all(16), diff --git a/lib/features/home/presentation/providers/member_card_provider.dart b/lib/features/home/presentation/providers/member_card_provider.dart index b703d01..65b5acb 100644 --- a/lib/features/home/presentation/providers/member_card_provider.dart +++ b/lib/features/home/presentation/providers/member_card_provider.dart @@ -26,7 +26,7 @@ part 'member_card_provider.g.dart'; /// /// memberCardAsync.when( /// data: (memberCard) => MemberCardWidget(memberCard: memberCard), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// ``` diff --git a/lib/features/home/presentation/providers/promotions_provider.dart b/lib/features/home/presentation/providers/promotions_provider.dart index 74d4a8f..166621f 100644 --- a/lib/features/home/presentation/providers/promotions_provider.dart +++ b/lib/features/home/presentation/providers/promotions_provider.dart @@ -28,7 +28,7 @@ const int _maxPromotions = 5; /// /// promotionsAsync.when( /// data: (promotions) => PromotionSlider(promotions: promotions), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// ``` diff --git a/lib/features/home/presentation/widgets/promotion_slider.dart b/lib/features/home/presentation/widgets/promotion_slider.dart index 7f7e2ff..37c040a 100644 --- a/lib/features/home/presentation/widgets/promotion_slider.dart +++ b/lib/features/home/presentation/widgets/promotion_slider.dart @@ -5,6 +5,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -126,7 +127,7 @@ class _PromotionCard extends StatelessWidget { placeholder: (context, url) => Container( height: 140, color: colorScheme.surfaceContainerHighest, - child: const Center(child: CircularProgressIndicator()), + child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 140, diff --git a/lib/features/invoices/presentation/pages/invoice_detail_page.dart b/lib/features/invoices/presentation/pages/invoice_detail_page.dart index 22c4011..c36d6de 100644 --- a/lib/features/invoices/presentation/pages/invoice_detail_page.dart +++ b/lib/features/invoices/presentation/pages/invoice_detail_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:share_plus/share_plus.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/utils/extensions.dart'; @@ -66,7 +67,7 @@ class InvoiceDetailPage extends ConsumerWidget { ), body: invoiceAsync.when( data: (invoice) => _buildContent(context, invoice), - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => _buildErrorState(context, ref, error), ), ); diff --git a/lib/features/invoices/presentation/pages/invoices_page.dart b/lib/features/invoices/presentation/pages/invoices_page.dart index 7ae869e..450b6e5 100644 --- a/lib/features/invoices/presentation/pages/invoices_page.dart +++ b/lib/features/invoices/presentation/pages/invoices_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.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), ), ); diff --git a/lib/features/loyalty/presentation/pages/points_history_page.dart b/lib/features/loyalty/presentation/pages/points_history_page.dart index ea71dc2..37e430d 100644 --- a/lib/features/loyalty/presentation/pages/points_history_page.dart +++ b/lib/features/loyalty/presentation/pages/points_history_page.dart @@ -8,6 +8,7 @@ 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:intl/intl.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/database/models/enums.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), ), ), diff --git a/lib/features/loyalty/presentation/pages/points_records_page.dart b/lib/features/loyalty/presentation/pages/points_records_page.dart index a896c66..c8a5af4 100644 --- a/lib/features/loyalty/presentation/pages/points_records_page.dart +++ b/lib/features/loyalty/presentation/pages/points_records_page.dart @@ -8,6 +8,7 @@ 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:intl/intl.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/theme/colors.dart'; import 'package:worker/features/loyalty/domain/entities/points_record.dart'; @@ -183,9 +184,7 @@ class PointsRecordsPage extends ConsumerWidget { ), ); }, - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => RefreshIndicator( onRefresh: () async { await ref.read(allPointsRecordsProvider.notifier).refresh(); diff --git a/lib/features/loyalty/presentation/widgets/reward_card.dart b/lib/features/loyalty/presentation/widgets/reward_card.dart index 262f39a..8034b52 100644 --- a/lib/features/loyalty/presentation/widgets/reward_card.dart +++ b/lib/features/loyalty/presentation/widgets/reward_card.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.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/presentation/providers/loyalty_points_provider.dart'; @@ -150,8 +151,8 @@ class RewardCard extends ConsumerWidget { fit: BoxFit.cover, placeholder: (context, url) => Container( color: colorScheme.surfaceContainerHighest, - child: const Center( - child: CircularProgressIndicator(strokeWidth: 2), + child: Center( + child: CustomLoadingIndicator(color: Theme.of(context).colorScheme.primary, size: 40), ), ), errorWidget: (context, url, error) => Container( diff --git a/lib/features/news/presentation/pages/news_detail_page.dart b/lib/features/news/presentation/pages/news_detail_page.dart index b479428..60c75a2 100644 --- a/lib/features/news/presentation/pages/news_detail_page.dart +++ b/lib/features/news/presentation/pages/news_detail_page.dart @@ -5,6 +5,7 @@ library; 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_html/flutter_html.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -60,7 +61,7 @@ class _NewsDetailPageState extends ConsumerState { } return _buildContent(context, article); }, - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => _buildErrorState(context, error.toString()), ), ); @@ -126,7 +127,7 @@ class _NewsDetailPageState extends ConsumerState { placeholder: (context, url) => Container( height: 250, color: colorScheme.surfaceContainerHighest, - child: const Center(child: CircularProgressIndicator()), + child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 250, diff --git a/lib/features/news/presentation/pages/news_list_page.dart b/lib/features/news/presentation/pages/news_list_page.dart index 3d57d67..ab1af3a 100644 --- a/lib/features/news/presentation/pages/news_list_page.dart +++ b/lib/features/news/presentation/pages/news_list_page.dart @@ -5,6 +5,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -98,7 +99,7 @@ class _NewsListPageState extends ConsumerState { loading: () => const SliverToBoxAdapter( child: Padding( padding: EdgeInsets.all(AppSpacing.md), - child: Center(child: CircularProgressIndicator()), + child: const CustomLoadingIndicator(), ), ), error: (error, stack) => @@ -158,7 +159,7 @@ class _NewsListPageState extends ConsumerState { ); }, loading: () => const SliverFillRemaining( - child: Center(child: CircularProgressIndicator()), + child: const CustomLoadingIndicator(), ), error: (error, stack) => SliverFillRemaining( child: _buildErrorState(error.toString()), diff --git a/lib/features/news/presentation/widgets/featured_news_card.dart b/lib/features/news/presentation/widgets/featured_news_card.dart index 6282d12..f2ac623 100644 --- a/lib/features/news/presentation/widgets/featured_news_card.dart +++ b/lib/features/news/presentation/widgets/featured_news_card.dart @@ -5,6 +5,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:worker/core/constants/ui_constants.dart'; @@ -65,7 +66,7 @@ class FeaturedNewsCard extends StatelessWidget { placeholder: (context, url) => Container( height: 200, color: colorScheme.surfaceContainerHighest, - child: const Center(child: CircularProgressIndicator()), + child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 200, diff --git a/lib/features/news/presentation/widgets/news_card.dart b/lib/features/news/presentation/widgets/news_card.dart index 3159b30..a51027d 100644 --- a/lib/features/news/presentation/widgets/news_card.dart +++ b/lib/features/news/presentation/widgets/news_card.dart @@ -5,6 +5,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:worker/core/constants/ui_constants.dart'; @@ -61,7 +62,7 @@ class NewsCard extends StatelessWidget { child: SizedBox( width: 20, height: 20, - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), ), diff --git a/lib/features/news/presentation/widgets/related_article_card.dart b/lib/features/news/presentation/widgets/related_article_card.dart index e9137a2..78f3211 100644 --- a/lib/features/news/presentation/widgets/related_article_card.dart +++ b/lib/features/news/presentation/widgets/related_article_card.dart @@ -5,6 +5,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:worker/core/constants/ui_constants.dart'; @@ -60,7 +61,7 @@ class RelatedArticleCard extends StatelessWidget { child: SizedBox( width: 16, height: 16, - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), ), diff --git a/lib/features/notifications/presentation/pages/notifications_page.dart b/lib/features/notifications/presentation/pages/notifications_page.dart index 9d90f24..9d42188 100644 --- a/lib/features/notifications/presentation/pages/notifications_page.dart +++ b/lib/features/notifications/presentation/pages/notifications_page.dart @@ -9,6 +9,7 @@ library; import 'package:flutter/material.dart' hide Notification; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -52,7 +53,7 @@ class NotificationsPage extends HookConsumerWidget { notifications, selectedCategory, ), - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => _buildErrorState(ref, selectedCategory), ), diff --git a/lib/features/orders/presentation/pages/order_detail_page.dart b/lib/features/orders/presentation/pages/order_detail_page.dart index d7be466..773a05a 100644 --- a/lib/features/orders/presentation/pages/order_detail_page.dart +++ b/lib/features/orders/presentation/pages/order_detail_page.dart @@ -14,6 +14,7 @@ import 'package:worker/core/enums/status_color.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/theme/colors.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/orders/domain/entities/order_detail.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( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -1001,7 +1002,7 @@ class OrderDetailPage extends ConsumerWidget { height: 60, color: colorScheme.surfaceContainerHighest, child: const Center( - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(size: 20), ), ), errorWidget: (context, url, error) => Container( @@ -1524,13 +1525,9 @@ class OrderDetailPage extends ConsumerWidget { SnackBar( content: Row( children: [ - SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Theme.of(context).colorScheme.onPrimary), - ), + CustomLoadingIndicator( + size: 20, + color: Theme.of(context).colorScheme.onPrimary, ), const SizedBox(width: 12), const Text('Đang hủy đơn hàng...'), diff --git a/lib/features/orders/presentation/pages/orders_page.dart b/lib/features/orders/presentation/pages/orders_page.dart index f2c71c0..760a285 100644 --- a/lib/features/orders/presentation/pages/orders_page.dart +++ b/lib/features/orders/presentation/pages/orders_page.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -351,7 +352,7 @@ class _OrdersPageState extends ConsumerState { /// Build loading state Widget _buildLoadingState() { return const SliverFillRemaining( - child: Center(child: CircularProgressIndicator()), + child: const CustomLoadingIndicator(), ); } diff --git a/lib/features/orders/presentation/pages/payment_detail_page.dart b/lib/features/orders/presentation/pages/payment_detail_page.dart index 4a7176b..5e4a44a 100644 --- a/lib/features/orders/presentation/pages/payment_detail_page.dart +++ b/lib/features/orders/presentation/pages/payment_detail_page.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:flutter_riverpod/flutter_riverpod.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( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/features/orders/presentation/pages/payment_qr_page.dart b/lib/features/orders/presentation/pages/payment_qr_page.dart index 2840adf..ac65ff4 100644 --- a/lib/features/orders/presentation/pages/payment_qr_page.dart +++ b/lib/features/orders/presentation/pages/payment_qr_page.dart @@ -10,6 +10,7 @@ library; import 'dart:async'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -225,9 +226,7 @@ class PaymentQrPage extends HookConsumerWidget { border: Border.all(color: colorScheme.outlineVariant), ), child: isLoading - ? const Center( - child: CircularProgressIndicator(), - ) + ? const const CustomLoadingIndicator() : qrCodeData != null && qrCodeData.isNotEmpty ? QrImageView( data: qrCodeData, @@ -580,10 +579,7 @@ class PaymentQrPage extends HookConsumerWidget { ? SizedBox( width: 18, height: 18, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(colorScheme.surface), - ), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ) : const FaIcon(FontAwesomeIcons.camera, size: 18), label: Text( diff --git a/lib/features/orders/presentation/pages/payments_page.dart b/lib/features/orders/presentation/pages/payments_page.dart index 6d20402..9a2f35a 100644 --- a/lib/features/orders/presentation/pages/payments_page.dart +++ b/lib/features/orders/presentation/pages/payments_page.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.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), ), ); diff --git a/lib/features/price_policy/presentation/pages/price_policy_page.dart b/lib/features/price_policy/presentation/pages/price_policy_page.dart index f1a832e..941d0bb 100644 --- a/lib/features/price_policy/presentation/pages/price_policy_page.dart +++ b/lib/features/price_policy/presentation/pages/price_policy_page.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -164,7 +165,7 @@ class _PricePolicyPageState extends ConsumerState ), ); }, - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/features/products/README.md b/lib/features/products/README.md index f23c932..bd21c15 100644 --- a/lib/features/products/README.md +++ b/lib/features/products/README.md @@ -81,7 +81,7 @@ UI components and state management. ### UI/UX Features - Pull-to-refresh support -- Loading states with CircularProgressIndicator +- Loading states with CustomLoadingIndicator - Error states with retry button - Empty states with helpful messages - Vietnamese localization diff --git a/lib/features/products/presentation/pages/product_detail_page.dart b/lib/features/products/presentation/pages/product_detail_page.dart index 679690d..3cbdbf6 100644 --- a/lib/features/products/presentation/pages/product_detail_page.dart +++ b/lib/features/products/presentation/pages/product_detail_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/theme/colors.dart'; import 'package:worker/features/favorites/presentation/providers/favorites_provider.dart'; @@ -262,9 +263,7 @@ class _ProductDetailPageState extends ConsumerState { ], ); }, - loading: () => Center( - child: CircularProgressIndicator(color: colorScheme.primary), - ), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => Center( child: Padding( padding: const EdgeInsets.all(AppSpacing.xl), diff --git a/lib/features/products/presentation/pages/products_page.dart b/lib/features/products/presentation/pages/products_page.dart index 7cf0b95..b05c3b9 100644 --- a/lib/features/products/presentation/pages/products_page.dart +++ b/lib/features/products/presentation/pages/products_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/theme/colors.dart'; @@ -192,7 +193,7 @@ class ProductsPage extends ConsumerWidget { /// Build loading state Widget _buildLoadingState(ColorScheme colorScheme) { - return Center(child: CircularProgressIndicator(color: colorScheme.primary)); + return const CustomLoadingIndicator(); } /// Build error state diff --git a/lib/features/products/presentation/pages/write_review_page.dart b/lib/features/products/presentation/pages/write_review_page.dart index 52e710c..dfd8464 100644 --- a/lib/features/products/presentation/pages/write_review_page.dart +++ b/lib/features/products/presentation/pages/write_review_page.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.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:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/theme/colors.dart'; import 'package:worker/features/products/domain/entities/product.dart'; @@ -186,7 +187,7 @@ class _WriteReviewPageState extends ConsumerState { body: productAsync.when( data: (product) => _buildForm(product), - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -249,8 +250,8 @@ class _WriteReviewPageState extends ConsumerState { width: 80, height: 80, color: colorScheme.surfaceContainerLowest, - child: const Center( - child: CircularProgressIndicator(strokeWidth: 2), + child: Center( + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), errorWidget: (context, url, error) => Container( @@ -510,15 +511,7 @@ class _WriteReviewPageState extends ConsumerState { elevation: 0, ), child: _isSubmitting - ? SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation(colorScheme.onPrimary), - ), - ) + ? CustomLoadingIndicator(color: colorScheme.onPrimary, size: 20) : Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/lib/features/products/presentation/providers/product_filter_options_provider.dart b/lib/features/products/presentation/providers/product_filter_options_provider.dart index 5751b52..50d19ad 100644 --- a/lib/features/products/presentation/providers/product_filter_options_provider.dart +++ b/lib/features/products/presentation/providers/product_filter_options_provider.dart @@ -99,7 +99,7 @@ class FilterOption { /// /// filterOptionsAsync.when( /// data: (options) => ProductFilterDrawer(options: options), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// ``` diff --git a/lib/features/products/presentation/providers/products_provider.dart b/lib/features/products/presentation/providers/products_provider.dart index 8869d9d..710c4bd 100644 --- a/lib/features/products/presentation/providers/products_provider.dart +++ b/lib/features/products/presentation/providers/products_provider.dart @@ -59,7 +59,7 @@ Future productsRepository(Ref ref) async { /// /// productsAsync.when( /// data: (products) => ProductGrid(products: products), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// ``` @@ -251,7 +251,7 @@ Future> allProducts(Ref ref) async { /// /// productAsync.when( /// data: (product) => ProductDetailView(product: product), -/// loading: () => CircularProgressIndicator(), +/// loading: () => const CustomLoadingIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// ``` diff --git a/lib/features/products/presentation/widgets/brand_filter_chips.dart b/lib/features/products/presentation/widgets/brand_filter_chips.dart index 04ee78f..850d5ed 100644 --- a/lib/features/products/presentation/widgets/brand_filter_chips.dart +++ b/lib/features/products/presentation/widgets/brand_filter_chips.dart @@ -5,6 +5,7 @@ library; import 'package:flutter/material.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/features/products/presentation/providers/product_filter_options_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, child: Center( - child: CircularProgressIndicator(strokeWidth: 2.0), + child: CustomLoadingIndicator(color: Theme.of(context).colorScheme.primary, size: 40), ), ), error: (error, stack) => const SizedBox.shrink(), diff --git a/lib/features/products/presentation/widgets/product_detail/product_tabs_section.dart b/lib/features/products/presentation/widgets/product_detail/product_tabs_section.dart index 71b3463..8646799 100644 --- a/lib/features/products/presentation/widgets/product_detail/product_tabs_section.dart +++ b/lib/features/products/presentation/widgets/product_detail/product_tabs_section.dart @@ -6,6 +6,7 @@ library; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/theme/colors.dart'; import 'package:worker/features/products/domain/entities/product.dart'; @@ -469,9 +470,7 @@ class _ReviewsTab extends ConsumerWidget { loading: () => Center( child: Padding( padding: const EdgeInsets.all(40), - child: CircularProgressIndicator( - color: colorScheme.primary, - ), + child: const CustomLoadingIndicator(), ), ), error: (error, stack) => _buildErrorState(colorScheme, error.toString()), diff --git a/lib/features/products/presentation/widgets/product_filter_drawer.dart b/lib/features/products/presentation/widgets/product_filter_drawer.dart index df5188a..9e256b4 100644 --- a/lib/features/products/presentation/widgets/product_filter_drawer.dart +++ b/lib/features/products/presentation/widgets/product_filter_drawer.dart @@ -6,6 +6,7 @@ library; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/theme/colors.dart'; import 'package:worker/features/products/presentation/providers/product_filters_provider.dart'; @@ -209,11 +210,7 @@ class ProductFilterDrawer extends ConsumerWidget { ), ], ), - loading: () => Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(colorScheme.primary), - ), - ), + loading: () => const CustomLoadingIndicator(), error: (error, stack) => Center( child: Padding( padding: const EdgeInsets.all(AppSpacing.lg), diff --git a/lib/features/products/presentation/widgets/product_grid.dart b/lib/features/products/presentation/widgets/product_grid.dart index d5362d6..d8d6073 100644 --- a/lib/features/products/presentation/widgets/product_grid.dart +++ b/lib/features/products/presentation/widgets/product_grid.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/features/products/domain/entities/product.dart'; import 'package:worker/features/products/presentation/widgets/product_card.dart'; @@ -80,9 +81,7 @@ class _ProductGridState extends State { return Center( child: Padding( padding: const EdgeInsets.all(AppSpacing.md), - child: CircularProgressIndicator( - color: colorScheme.primary, - ), + child: const CustomLoadingIndicator(), ), ); } diff --git a/lib/features/projects/presentation/pages/submission_create_page.dart b/lib/features/projects/presentation/pages/submission_create_page.dart index daa9b8f..bdc8251 100644 --- a/lib/features/projects/presentation/pages/submission_create_page.dart +++ b/lib/features/projects/presentation/pages/submission_create_page.dart @@ -4,6 +4,7 @@ library; import 'dart:io'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; @@ -168,7 +169,7 @@ class _SubmissionCreatePageState extends ConsumerState { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const CircularProgressIndicator(), + const CustomLoadingIndicator(), const SizedBox(height: 16), Text( 'Đang tải thông tin dự án...', @@ -641,7 +642,7 @@ class _SubmissionCreatePageState extends ConsumerState { const SizedBox( width: 16, height: 16, - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), const SizedBox(width: 12), Text('Đang tải...', style: TextStyle(color: colorScheme.onSurfaceVariant)), @@ -787,10 +788,7 @@ class _SubmissionCreatePageState extends ConsumerState { child: SizedBox( width: 24, height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), + child: CustomLoadingIndicator(color: Colors.white, size: 20), ), ), ), @@ -901,7 +899,7 @@ class _SubmissionCreatePageState extends ConsumerState { child: SizedBox( width: 16, height: 16, - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), ), @@ -931,10 +929,7 @@ class _SubmissionCreatePageState extends ConsumerState { child: SizedBox( width: 24, height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), + child: CustomLoadingIndicator(color: Colors.white, size: 20), ), ), ), @@ -1150,10 +1145,7 @@ class _SubmissionCreatePageState extends ConsumerState { ? const SizedBox( width: 24, height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), + child: CustomLoadingIndicator(color: Colors.white, size: 20), ) : const Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/features/projects/presentation/pages/submissions_page.dart b/lib/features/projects/presentation/pages/submissions_page.dart index 4cd21ca..e616f1a 100644 --- a/lib/features/projects/presentation/pages/submissions_page.dart +++ b/lib/features/projects/presentation/pages/submissions_page.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -179,9 +180,7 @@ class SubmissionsPage extends ConsumerWidget { ), ); }, - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => RefreshIndicator( onRefresh: () async { await ref.read(allSubmissionsProvider.notifier).refresh(); diff --git a/lib/features/promotions/presentation/pages/promotion_detail_page.dart b/lib/features/promotions/presentation/pages/promotion_detail_page.dart index b154231..0aa9eb9 100644 --- a/lib/features/promotions/presentation/pages/promotion_detail_page.dart +++ b/lib/features/promotions/presentation/pages/promotion_detail_page.dart @@ -9,6 +9,7 @@ library; 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_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -69,7 +70,7 @@ class _PromotionDetailPageState extends ConsumerState { foregroundColor: AppColors.grey900, centerTitle: false, ), - body: const Center(child: CircularProgressIndicator()), + body: const const CustomLoadingIndicator(), ), error: (error, stack) => Scaffold( appBar: AppBar( @@ -201,7 +202,7 @@ class _PromotionDetailPageState extends ConsumerState { placeholder: (context, url) => Container( height: 200, color: AppColors.grey100, - child: const Center(child: CircularProgressIndicator()), + child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 200, diff --git a/lib/features/promotions/presentation/pages/promotions_page.dart b/lib/features/promotions/presentation/pages/promotions_page.dart index 90b6d53..190b4f8 100644 --- a/lib/features/promotions/presentation/pages/promotions_page.dart +++ b/lib/features/promotions/presentation/pages/promotions_page.dart @@ -5,6 +5,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -43,7 +44,7 @@ class PromotionsPage extends ConsumerWidget { child: promotionsAsync.when( data: (promotions) => _buildPromotionsContent(context, promotions), - loading: () => const Center(child: CircularProgressIndicator()), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/features/promotions/presentation/widgets/promotion_card.dart b/lib/features/promotions/presentation/widgets/promotion_card.dart index 83a521c..5d383c1 100644 --- a/lib/features/promotions/presentation/widgets/promotion_card.dart +++ b/lib/features/promotions/presentation/widgets/promotion_card.dart @@ -5,6 +5,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; @@ -57,7 +58,7 @@ class PromotionCard extends StatelessWidget { placeholder: (context, url) => Container( height: 150, color: AppColors.grey100, - child: const Center(child: CircularProgressIndicator()), + child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 150, diff --git a/lib/features/quotes/presentation/pages/quotes_page.dart b/lib/features/quotes/presentation/pages/quotes_page.dart index ba1bbe1..4ada751 100644 --- a/lib/features/quotes/presentation/pages/quotes_page.dart +++ b/lib/features/quotes/presentation/pages/quotes_page.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; @@ -450,7 +451,7 @@ class _QuotesPageState extends ConsumerState { /// Build loading state Widget _buildLoadingState() { return const SliverFillRemaining( - child: Center(child: CircularProgressIndicator()), + child: const CustomLoadingIndicator(), ); } diff --git a/lib/features/showrooms/presentation/pages/design_request_create_page.dart b/lib/features/showrooms/presentation/pages/design_request_create_page.dart index 49805c0..8c317b0 100644 --- a/lib/features/showrooms/presentation/pages/design_request_create_page.dart +++ b/lib/features/showrooms/presentation/pages/design_request_create_page.dart @@ -4,6 +4,7 @@ library; import 'dart:async'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; @@ -810,10 +811,7 @@ class DesignRequestCreatePage extends HookConsumerWidget { SizedBox( height: 20, width: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - color: colorScheme.surface, - ), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), const SizedBox(width: 12), Text( diff --git a/lib/features/showrooms/presentation/pages/design_request_detail_page.dart b/lib/features/showrooms/presentation/pages/design_request_detail_page.dart index a6b0e4a..78dde8f 100644 --- a/lib/features/showrooms/presentation/pages/design_request_detail_page.dart +++ b/lib/features/showrooms/presentation/pages/design_request_detail_page.dart @@ -4,6 +4,7 @@ library; 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_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -491,9 +492,7 @@ class DesignRequestDetailPage extends ConsumerWidget { ], ), ), - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Center( child: Padding( padding: const EdgeInsets.all(40), @@ -560,7 +559,7 @@ class DesignRequestDetailPage extends ConsumerWidget { placeholder: (context, url) => Container( color: colorScheme.surfaceContainerHighest, child: const Center( - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), errorWidget: (context, url, error) => Container( diff --git a/lib/features/showrooms/presentation/pages/model_house_detail_page.dart b/lib/features/showrooms/presentation/pages/model_house_detail_page.dart index 343eb42..ec0291a 100644 --- a/lib/features/showrooms/presentation/pages/model_house_detail_page.dart +++ b/lib/features/showrooms/presentation/pages/model_house_detail_page.dart @@ -4,6 +4,7 @@ library; 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_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -85,9 +86,7 @@ class ModelHouseDetailPage extends ConsumerWidget { ], ), ), - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Center( child: Padding( padding: const EdgeInsets.all(40), @@ -410,7 +409,7 @@ class ModelHouseDetailPage extends ConsumerWidget { placeholder: (context, url) => Container( color: colorScheme.surfaceContainerHighest, child: const Center( - child: CircularProgressIndicator(strokeWidth: 2), + child: CustomLoadingIndicator(color: colorScheme.primary, size: 20), ), ), errorWidget: (context, url, error) => Container( @@ -522,7 +521,7 @@ class _ImageViewerDialogState extends State<_ImageViewerDialog> { imageUrl: widget.images[index].fileUrl, fit: BoxFit.contain, placeholder: (context, url) => const Center( - child: CircularProgressIndicator(color: Colors.white), + child: CustomLoadingIndicator(color: Colors.white, size: 40), ), errorWidget: (context, url, error) => const Icon( Icons.error, diff --git a/lib/features/showrooms/presentation/pages/model_houses_page.dart b/lib/features/showrooms/presentation/pages/model_houses_page.dart index ea9a6d0..7cda13a 100644 --- a/lib/features/showrooms/presentation/pages/model_houses_page.dart +++ b/lib/features/showrooms/presentation/pages/model_houses_page.dart @@ -4,6 +4,7 @@ library; 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_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -214,9 +215,7 @@ class _LibraryTab extends ConsumerWidget { ), ); }, - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Center( child: Padding( padding: const EdgeInsets.all(40), @@ -288,7 +287,7 @@ class _LibraryCard extends StatelessWidget { placeholder: (context, url) => Container( height: 200, color: colorScheme.surfaceContainerHighest, - child: const Center(child: CircularProgressIndicator()), + child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 200, @@ -425,9 +424,7 @@ class _DesignRequestsTab extends ConsumerWidget { ), ); }, - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const const CustomLoadingIndicator(), error: (error, stack) => Center( child: Padding( padding: const EdgeInsets.all(40), diff --git a/lib/features/showrooms/presentation/widgets/image_viewer_dialog.dart b/lib/features/showrooms/presentation/widgets/image_viewer_dialog.dart index 84a9566..74e756c 100644 --- a/lib/features/showrooms/presentation/widgets/image_viewer_dialog.dart +++ b/lib/features/showrooms/presentation/widgets/image_viewer_dialog.dart @@ -4,6 +4,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:worker/features/showrooms/domain/entities/sample_project.dart'; @@ -70,7 +71,7 @@ class _ImageViewerDialogState extends State { imageUrl: widget.images[index].fileUrl, fit: BoxFit.contain, placeholder: (context, url) => const Center( - child: CircularProgressIndicator(color: Colors.white), + child: CustomLoadingIndicator(color: Colors.white, size: 40), ), errorWidget: (context, url, error) => const Icon( Icons.error, diff --git a/pubspec.lock b/pubspec.lock index 70718df..9d806d9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -876,6 +876,14 @@ packages: url: "https://pub.dev" source: hosted 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: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e133517..e1cd116 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: qr_flutter: ^4.1.0 mobile_scanner: ^5.2.3 font_awesome_flutter: ^10.7.0 + loading_animation_widget: ^1.3.0 # Utilities