diff --git a/lib/presentation/pages/main/pages/report/sections/report_payment_method_section.dart b/lib/presentation/pages/main/pages/report/sections/report_payment_method_section.dart index 1e7277f..0ee5be5 100644 --- a/lib/presentation/pages/main/pages/report/sections/report_payment_method_section.dart +++ b/lib/presentation/pages/main/pages/report/sections/report_payment_method_section.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../../../application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart'; import '../../../../../../common/data/report_menu.dart'; import '../../../../../../common/extension/extension.dart'; import '../../../../../../common/theme/theme.dart'; import '../../../../../../domain/analytic/analytic.dart'; +import '../../../../../components/error/analytic_error_state_widget.dart'; import '../../../../../components/loader/loader_with_text.dart'; import '../../../../../components/spaces/space.dart'; import '../../../../../components/widgets/report/report_header.dart'; @@ -29,44 +31,69 @@ class ReportPaymentMethodSection extends StatelessWidget { return const Center(child: LoaderWithText()); } - return ListView( - padding: EdgeInsets.all(16), - children: [ - ReportHeader(menu: menu, endDate: endDate, startDate: startDate), - _buildSummary(), - Container( - padding: const EdgeInsets.all(12), - margin: EdgeInsets.only(top: 16), - decoration: BoxDecoration( - color: AppColor.white, - borderRadius: BorderRadius.circular(14), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Rincian Metode Pembayaran', - style: AppStyle.lg.copyWith( - fontWeight: FontWeight.w600, - color: AppColor.textPrimary, - ), + return state.failureOption.fold( + () => RefreshIndicator( + onRefresh: () { + context.read().add( + PaymentMethodAnalyticLoaderEvent.fetched( + startDate: startDate, + endDate: endDate, + ), + ); + return Future.value(); + }, + child: ListView( + padding: EdgeInsets.all(16), + children: [ + ReportHeader(menu: menu, endDate: endDate, startDate: startDate), + _buildSummary(), + Container( + padding: const EdgeInsets.all(12), + margin: EdgeInsets.only(top: 16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(14), ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Rincian Metode Pembayaran', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), - SpaceHeight(16), + SpaceHeight(16), - ...List.generate(state.paymentMethodAnalytic.data.length, ( - index, - ) { - final item = state.paymentMethodAnalytic.data[index]; - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: _buildPaymentCard(item), - ); - }), - ], - ), + ...List.generate(state.paymentMethodAnalytic.data.length, ( + index, + ) { + final item = state.paymentMethodAnalytic.data[index]; + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _buildPaymentCard(item), + ); + }), + ], + ), + ), + ], ), - ], + ), + (f) => AnalyticErrorStateWidget( + failure: f, + menu: menu, + onRefresh: () { + context.read().add( + PaymentMethodAnalyticLoaderEvent.fetched( + startDate: startDate, + endDate: endDate, + ), + ); + }, + ), ); } diff --git a/lib/presentation/pages/main/pages/report/sections/report_product_section.dart b/lib/presentation/pages/main/pages/report/sections/report_product_section.dart index 212f5a5..c6540ee 100644 --- a/lib/presentation/pages/main/pages/report/sections/report_product_section.dart +++ b/lib/presentation/pages/main/pages/report/sections/report_product_section.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../../../application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart'; import '../../../../../../common/data/report_menu.dart'; import '../../../../../../common/extension/extension.dart'; import '../../../../../../common/theme/theme.dart'; import '../../../../../../domain/analytic/analytic.dart'; +import '../../../../../components/error/analytic_error_state_widget.dart'; import '../../../../../components/loader/loader_with_text.dart'; import '../../../../../components/spaces/space.dart'; import '../../../../../components/widgets/report/report_header.dart'; @@ -29,114 +31,142 @@ class ReportProductSection extends StatelessWidget { return const Center(child: LoaderWithText()); } - return Column( - children: [ - Expanded( - child: SingleChildScrollView( - padding: EdgeInsets.all(16), - child: Column( - children: [ - ReportHeader( - menu: menu, - endDate: endDate, - startDate: startDate, - ), - Container( - height: 90, - margin: EdgeInsets.only(top: 16), - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: state.productAnalytic.categories.length, - itemBuilder: (context, index) { - final category = state.productAnalytic.categories[index]; - return Container( - width: 200, - padding: EdgeInsets.only( - right: - index == - state.productAnalytic.categories.length - 1 - ? 0 - : 12, - ), - child: ReportSummaryCard( - color: AppColor.primary, - icon: Icons.category_outlined, - title: category.categoryName, - value: category.totalRevenue.currencyFormatRpV2, - subtitle: "${category.productCount} Item", - ), - ); - }, + return state.failureOption.fold( + () => Column( + children: [ + Expanded( + child: RefreshIndicator( + onRefresh: () { + context.read().add( + ProductAnalyticLoaderEvent.fetched( + startDate: startDate, + endDate: endDate, ), - ), - Container( - margin: EdgeInsets.only(top: 16), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: AppColor.white, - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Produk Berkinerja Terbaik', - style: AppStyle.lg.copyWith( - fontWeight: FontWeight.w600, - color: AppColor.textPrimary, - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - decoration: BoxDecoration( - color: AppColor.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: AppColor.primary, - width: 1, - ), - ), - child: Text( - 'Berdasarkan Pendapatan', - style: AppStyle.xs.copyWith( - fontWeight: FontWeight.w500, - color: AppColor.primary, - fontSize: 10, - ), - ), - ), - ], - ), - SpaceHeight(12), - ListView.builder( - itemCount: state.productAnalytic.data.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + ); + return Future.value(); + }, + child: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Column( + children: [ + ReportHeader( + menu: menu, + endDate: endDate, + startDate: startDate, + ), + Container( + height: 90, + margin: EdgeInsets.only(top: 16), + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: state.productAnalytic.categories.length, itemBuilder: (context, index) { - final product = state.productAnalytic.data[index]; - return _buildProductItem( - rank: index + 1, - product: product, - isTopPerformer: - product == state.productAnalytic.bestProduct, - categoryColor: AppColor.primary, + final category = + state.productAnalytic.categories[index]; + return Container( + width: 200, + padding: EdgeInsets.only( + right: + index == + state.productAnalytic.categories.length - + 1 + ? 0 + : 12, + ), + child: ReportSummaryCard( + color: AppColor.primary, + icon: Icons.category_outlined, + title: category.categoryName, + value: category.totalRevenue.currencyFormatRpV2, + subtitle: "${category.productCount} Item", + ), ); }, ), - ], - ), + ), + Container( + margin: EdgeInsets.only(top: 16), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Produk Berkinerja Terbaik', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: AppColor.primary, + width: 1, + ), + ), + child: Text( + 'Berdasarkan Pendapatan', + style: AppStyle.xs.copyWith( + fontWeight: FontWeight.w500, + color: AppColor.primary, + fontSize: 10, + ), + ), + ), + ], + ), + SpaceHeight(12), + ListView.builder( + itemCount: state.productAnalytic.data.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final product = state.productAnalytic.data[index]; + return _buildProductItem( + rank: index + 1, + product: product, + isTopPerformer: + product == + state.productAnalytic.bestProduct, + categoryColor: AppColor.primary, + ); + }, + ), + ], + ), + ), + ], ), - ], + ), ), ), - ), - _buildBottomSummary(), - ], + _buildBottomSummary(), + ], + ), + (f) => AnalyticErrorStateWidget( + failure: f, + menu: menu, + onRefresh: () { + context.read().add( + ProductAnalyticLoaderEvent.fetched( + startDate: startDate, + endDate: endDate, + ), + ); + }, + ), ); } diff --git a/lib/presentation/pages/main/pages/report/sections/report_sales_section.dart b/lib/presentation/pages/main/pages/report/sections/report_sales_section.dart index 58cfc57..34988f6 100644 --- a/lib/presentation/pages/main/pages/report/sections/report_sales_section.dart +++ b/lib/presentation/pages/main/pages/report/sections/report_sales_section.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../../../application/analytic/sales_analytic_loader/sales_analytic_loader_bloc.dart'; import '../../../../../../common/data/report_menu.dart'; import '../../../../../../common/extension/extension.dart'; import '../../../../../../common/theme/theme.dart'; +import '../../../../../components/error/analytic_error_state_widget.dart'; import '../../../../../components/loader/loader_with_text.dart'; import '../../../../../components/spaces/space.dart'; import '../../../../../components/widgets/report/report_header.dart'; @@ -28,50 +30,78 @@ class ReportSalesSection extends StatelessWidget { return const Center(child: LoaderWithText()); } - return ListView( - padding: EdgeInsets.all(16), - children: [ - ReportHeader(menu: menu, endDate: endDate, startDate: startDate), - _buildSummary(), - Container( - margin: EdgeInsets.only(top: 16), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColor.white, - borderRadius: BorderRadius.circular(14), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Kinerja Harian', - style: AppStyle.lg.copyWith( - fontWeight: FontWeight.w600, - color: AppColor.textPrimary, - ), + return state.failureOption.fold( + () => RefreshIndicator( + onRefresh: () { + context.read().add( + SalesAnalyticLoaderEvent.fetched( + startDate: startDate, + endDate: endDate, + ), + ); + + return Future.value(); + }, + child: ListView( + padding: EdgeInsets.all(16), + children: [ + ReportHeader(menu: menu, endDate: endDate, startDate: startDate), + _buildSummary(), + Container( + margin: EdgeInsets.only(top: 16), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(14), ), - SpaceHeight(12), - ListView.builder( - itemCount: state.salesAnalytic.sortedDailyData.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - final dayData = state.salesAnalytic.sortedDailyData[index]; - return _buildDailyPerformanceItem( - date: dayData.date.toSimpleMonthDate(), - sales: dayData.sales.currencyFormatRpV2, - orders: dayData.orders, - items: dayData.items, - isHighest: dayData == state.salesAnalytic.highestRevenueDay, - ); - }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Kinerja Harian', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + SpaceHeight(12), + ListView.builder( + itemCount: state.salesAnalytic.sortedDailyData.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final dayData = + state.salesAnalytic.sortedDailyData[index]; + return _buildDailyPerformanceItem( + date: dayData.date.toSimpleMonthDate(), + sales: dayData.sales.currencyFormatRpV2, + orders: dayData.orders, + items: dayData.items, + isHighest: + dayData == state.salesAnalytic.highestRevenueDay, + ); + }, + ), + ], ), - ], - ), + ), + SpaceHeight(16), + _buildSummaryFooter(), + ], ), - SpaceHeight(16), - _buildSummaryFooter(), - ], + ), + (f) => AnalyticErrorStateWidget( + failure: f, + menu: menu, + onRefresh: () { + context.read().add( + SalesAnalyticLoaderEvent.fetched( + startDate: startDate, + endDate: endDate, + ), + ); + }, + ), ); }