diff --git a/lib/application/order/order_loader/order_loader_bloc.dart b/lib/application/order/order_loader/order_loader_bloc.dart index ac60cc3..870790d 100644 --- a/lib/application/order/order_loader/order_loader_bloc.dart +++ b/lib/application/order/order_loader/order_loader_bloc.dart @@ -12,6 +12,11 @@ part 'order_loader_bloc.freezed.dart'; @injectable class OrderLoaderBloc extends Bloc { final IOrderRepository _repository; + + int _fetchRequestId = 0; + int _summaryRequestId = 0; + bool _isLoadingMore = false; + OrderLoaderBloc(this._repository) : super(OrderLoaderState.initial()) { on(_onOrderLoaderEvent); } @@ -34,19 +39,43 @@ class OrderLoaderBloc extends Bloc { emit(state.copyWith(outletId: e.outletId)); }, fetched: (e) async { - var newState = state; - if (e.isRefresh) { - newState = state.copyWith(isFetching: true); - - emit(newState); + _fetchRequestId++; + emit(state.copyWith(isFetching: true)); + } else if (state.isFetching || _isLoadingMore) { + return; } - newState = await _mapFetchedToState(state, isRefresh: e.isRefresh); + final requestId = _fetchRequestId; + _isLoadingMore = !e.isRefresh; - emit(newState); + try { + final result = await _mapFetchedToState( + state, + isRefresh: e.isRefresh, + ); + + // Filter berubah selama request berjalan, buang hasil lama + if (requestId != _fetchRequestId) return; + + // Hanya ambil field list, supaya status/filter/summary terbaru + // tidak tertimpa snapshot lama + emit( + state.copyWith( + orders: result.orders, + failureOptionOrder: result.failureOptionOrder, + page: result.page, + hasReachedMax: result.hasReachedMax, + isFetching: false, + ), + ); + } finally { + if (!e.isRefresh) _isLoadingMore = false; + } }, summaryFetched: (e) async { + final requestId = ++_summaryRequestId; + emit(state.copyWith(isFetchingSummary: true)); final results = await Future.wait([ @@ -63,6 +92,8 @@ class OrderLoaderBloc extends Bloc { ), ]); + if (requestId != _summaryRequestId) return; + emit( state.copyWith( isFetchingSummary: false, diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index c799fbc..c3408e2 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -234,7 +234,7 @@ "@active": {}, "inactive": "Tidak Aktif", "@inactive": {}, - "total_amount": "Jumlah Total", + "total_amount": "Total", "@total_amount": {}, "table": "Meja", "@table": {}, diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart index 9ef0c4a..cb4b6ba 100644 --- a/lib/l10n/app_localizations_id.dart +++ b/lib/l10n/app_localizations_id.dart @@ -343,7 +343,7 @@ class AppLocalizationsId extends AppLocalizations { String get inactive => 'Tidak Aktif'; @override - String get total_amount => 'Jumlah Total'; + String get total_amount => 'Total'; @override String get table => 'Meja'; diff --git a/lib/presentation/pages/home/home_page.dart b/lib/presentation/pages/home/home_page.dart index 4f7fe29..515caab 100644 --- a/lib/presentation/pages/home/home_page.dart +++ b/lib/presentation/pages/home/home_page.dart @@ -12,6 +12,7 @@ import '../../../common/theme/theme.dart'; import '../../../injection.dart'; import '../../components/button/button.dart'; import '../../components/spacer/spacer.dart'; +import '../../router/app_router.gr.dart'; import 'widgets/feature.dart'; import 'widgets/header.dart'; import 'widgets/home_top_products.dart'; @@ -53,6 +54,9 @@ class _HomePageState extends State with TickerProviderStateMixin { late AnimationController _headerAnimationController; late AnimationController _contentAnimationController; + TabsRouter? _tabsRouter; + bool _isActiveTab = true; + @override void initState() { super.initState(); @@ -77,8 +81,29 @@ class _HomePageState extends State with TickerProviderStateMixin { }); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + + final tabsRouter = AutoTabsRouter.of(context); + if (_tabsRouter != tabsRouter) { + _tabsRouter?.removeListener(_onTabChanged); + _tabsRouter = tabsRouter..addListener(_onTabChanged); + } + } + + // Refresh setiap kali tab Home dibuka lagi dari bottom nav + void _onTabChanged() { + final isActiveTab = _tabsRouter?.current.name == HomeRoute.name; + + if (isActiveTab && !_isActiveTab) _refreshAll(context); + + _isActiveTab = isActiveTab; + } + @override void dispose() { + _tabsRouter?.removeListener(_onTabChanged); _headerAnimationController.dispose(); _contentAnimationController.dispose(); super.dispose(); @@ -88,6 +113,13 @@ class _HomePageState extends State with TickerProviderStateMixin { context.read().add(HomeEvent.fetchedDashboard()); } + void _refreshAll(BuildContext context) { + _refetchDashboard(context); + context.read().add( + const ExclusiveSummaryLoaderEvent.fetched(), + ); + } + @override Widget build(BuildContext context) { return BlocListener( @@ -100,7 +132,7 @@ class _HomePageState extends State with TickerProviderStateMixin { backgroundColor: AppColor.white, color: AppColor.primary, onRefresh: () { - _refetchDashboard(context); + _refreshAll(context); return Future.value(); }, child: BlocBuilder( diff --git a/lib/presentation/pages/order/order_list/order_page.dart b/lib/presentation/pages/order/order_list/order_page.dart index 6455d1d..aed5f21 100644 --- a/lib/presentation/pages/order/order_list/order_page.dart +++ b/lib/presentation/pages/order/order_list/order_page.dart @@ -50,6 +50,9 @@ class _OrderPageState extends State with TickerProviderStateMixin { late Animation _slideAnimation; final ScrollController _scrollController = ScrollController(); + TabsRouter? _tabsRouter; + bool _isActiveTab = true; + // Filter state final List filterOptions = ['All', 'Pending', 'Completed']; @@ -80,8 +83,33 @@ class _OrderPageState extends State with TickerProviderStateMixin { _slideController.forward(); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + + final tabsRouter = AutoTabsRouter.of(context); + if (_tabsRouter != tabsRouter) { + _tabsRouter?.removeListener(_onTabChanged); + _tabsRouter = tabsRouter..addListener(_onTabChanged); + } + } + + // Refresh setiap kali tab Order dibuka lagi dari bottom nav + void _onTabChanged() { + final isActiveTab = _tabsRouter?.current.name == OrderRoute.name; + + if (isActiveTab && !_isActiveTab) { + context.read() + ..add(OrderLoaderEvent.fetched(isRefresh: true)) + ..add(const OrderLoaderEvent.summaryFetched()); + } + + _isActiveTab = isActiveTab; + } + @override void dispose() { + _tabsRouter?.removeListener(_onTabChanged); _fadeController.dispose(); _slideController.dispose(); super.dispose(); diff --git a/pubspec.yaml b/pubspec.yaml index 0b6796b..b5bea6c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: "A new Flutter project." publish_to: "none" -version: 1.0.4+18 +version: 1.0.4+19 environment: sdk: ^3.8.1