feat: report page

This commit is contained in:
efrilm
2025-08-01 18:27:40 +07:00
parent 8e4a289625
commit e825e5daed
21 changed files with 851 additions and 776 deletions
+301 -251
View File
@@ -34,264 +34,314 @@ class _ReportPageState extends State<ReportPage> {
DateTime fromDate = DateTime.now().subtract(const Duration(days: 30));
DateTime toDate = DateTime.now();
@override
void initState() {
super.initState();
context.read<TransactionReportBloc>().add(
TransactionReportEvent.getReport(
startDate: DateFormatter.formatDateTime(fromDate),
endDate: DateFormatter.formatDateTime(toDate)),
);
}
@override
Widget build(BuildContext context) {
String searchDateFormatted =
'${fromDate.toFormattedDate2()} to ${toDate.toFormattedDate2()}';
return Scaffold(
body: Row(
backgroundColor: AppColors.background,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// LEFT CONTENT
Expanded(
flex: 2,
child: Align(
alignment: Alignment.topLeft,
child: SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const ReportTitle(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: CustomDatePicker(
prefix: const Text('From: '),
initialDate: fromDate,
onDateSelected: (selectedDate) {
fromDate = selectedDate;
ReportTitle(
actionWidget: [
SizedBox(
width: 300,
child: CustomDatePicker(
prefix: const Text('From: '),
initialDate: fromDate,
onDateSelected: (selectedDate) {
fromDate = selectedDate;
setState(() {});
},
),
),
const SpaceWidth(24.0),
Flexible(
child: CustomDatePicker(
prefix: const Text('To: '),
initialDate: toDate,
onDateSelected: (selectedDate) {
toDate = selectedDate;
setState(() {});
// context.read<TransactionReportBloc>().add(
// TransactionReportEvent.getReport(
// startDate:
// DateFormatter.formatDateTime(
// fromDate),
// endDate: DateFormatter.formatDateTime(
// toDate)),
// );
// context.read<ItemSalesReportBloc>().add(
// ItemSalesReportEvent.getItemSales(
// startDate:
// DateFormatter.formatDateTime(
// fromDate),
// endDate: DateFormatter.formatDateTime(
// toDate)),
// );
},
),
),
],
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Wrap(
children: [
ReportMenu(
label: 'Transaction Report',
onPressed: () {
selectedMenu = 0;
title = 'Transaction Report';
setState(() {});
//enddate is 1 month before the current date
context.read<TransactionReportBloc>().add(
TransactionReportEvent.getReport(
startDate: DateFormatter.formatDateTime(
fromDate),
endDate: DateFormatter.formatDateTime(
toDate)),
);
},
isActive: selectedMenu == 0,
),
ReportMenu(
label: 'Item Sales Report',
onPressed: () {
selectedMenu = 1;
title = 'Item Sales Report';
setState(() {});
context.read<ItemSalesReportBloc>().add(
ItemSalesReportEvent.getItemSales(
startDate: DateFormatter.formatDateTime(
fromDate),
endDate: DateFormatter.formatDateTime(
toDate)),
);
},
isActive: selectedMenu == 1,
),
ReportMenu(
label: 'Product Sales Chart',
onPressed: () {
selectedMenu = 2;
title = 'Product Sales Chart';
setState(() {});
context.read<ProductSalesBloc>().add(
ProductSalesEvent.getProductSales(
DateFormatter.formatDateTime(fromDate),
DateFormatter.formatDateTime(toDate)),
);
},
isActive: selectedMenu == 2,
),
ReportMenu(
label: 'Summary Sales Report',
onPressed: () {
selectedMenu = 3;
title = 'Summary Sales Report';
setState(() {});
context.read<SummaryBloc>().add(
SummaryEvent.getSummary(
DateFormatter.formatDateTime(fromDate),
DateFormatter.formatDateTime(toDate)),
);
log("Date ${DateFormatter.formatDateTime(fromDate)}");
},
isActive: selectedMenu == 3,
),
ReportMenu(
label: 'Payment Method Report',
onPressed: () {
selectedMenu = 4;
title = 'Payment Method Report';
setState(() {});
context.read<PaymentMethodReportBloc>().add(
PaymentMethodReportEvent.getPaymentMethodReport(
startDate: DateFormatter.formatDateTime(fromDate),
endDate: DateFormatter.formatDateTime(toDate)),
);
},
isActive: selectedMenu == 4,
),
],
),
),
],
setState(() {});
},
),
),
const SpaceWidth(24.0),
SizedBox(
width: 300,
child: CustomDatePicker(
prefix: const Text('To: '),
initialDate: toDate,
onDateSelected: (selectedDate) {
toDate = selectedDate;
setState(() {});
// context.read<TransactionReportBloc>().add(
// TransactionReportEvent.getReport(
// startDate:
// DateFormatter.formatDateTime(
// fromDate),
// endDate: DateFormatter.formatDateTime(
// toDate)),
// );
// context.read<ItemSalesReportBloc>().add(
// ItemSalesReportEvent.getItemSales(
// startDate:
// DateFormatter.formatDateTime(
// fromDate),
// endDate: DateFormatter.formatDateTime(
// toDate)),
// );
},
),
),
],
),
Expanded(
child: Row(
children: [
// LEFT CONTENT
Expanded(
flex: 2,
child: Material(
color: AppColors.white,
child: Align(
alignment: Alignment.topLeft,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ReportMenu(
label: 'Laporan Transaksi',
subtitle:
'Menampilkan riwayat lengkap semua transaksi yang telah dilakukan.',
icon: Icons.receipt_long_outlined,
onPressed: () {
selectedMenu = 0;
title = 'Laporan Transaksi';
setState(() {});
//enddate is 1 month before the current date
context.read<TransactionReportBloc>().add(
TransactionReportEvent.getReport(
startDate:
DateFormatter.formatDateTime(
fromDate),
endDate: DateFormatter.formatDateTime(
toDate)),
);
},
isActive: selectedMenu == 0,
),
ReportMenu(
label: 'Laporan Penjualan Item',
subtitle:
'Laporan penjualan berdasarkan masing-masing item atau produk.',
icon: Icons.inventory_2_outlined,
onPressed: () {
selectedMenu = 1;
title = 'Laporan Penjualan Item';
setState(() {});
context.read<ItemSalesReportBloc>().add(
ItemSalesReportEvent.getItemSales(
startDate:
DateFormatter.formatDateTime(
fromDate),
endDate: DateFormatter.formatDateTime(
toDate)),
);
},
isActive: selectedMenu == 1,
),
ReportMenu(
label: 'Chart Penjualan Produk',
subtitle:
'Grafik visual penjualan produk untuk analisa performa penjualan.',
icon: Icons.bar_chart_outlined,
onPressed: () {
selectedMenu = 2;
title = 'Chart Penjualan Produk';
setState(() {});
context.read<ProductSalesBloc>().add(
ProductSalesEvent.getProductSales(
DateFormatter.formatDateTime(
fromDate),
DateFormatter.formatDateTime(toDate)),
);
},
isActive: selectedMenu == 2,
),
ReportMenu(
label: 'Ringkasan Laporan Penjualan',
subtitle:
'Ringkasan total penjualan dalam periode tertentu.',
icon: Icons.insert_drive_file_outlined,
onPressed: () {
selectedMenu = 3;
title = 'Ringkasan Laporan Penjualan';
setState(() {});
context.read<SummaryBloc>().add(
SummaryEvent.getSummary(
DateFormatter.formatDateTime(
fromDate),
DateFormatter.formatDateTime(toDate)),
);
log("Date ${DateFormatter.formatDateTime(fromDate)}");
},
isActive: selectedMenu == 3,
),
ReportMenu(
label: 'Laporan Metode Pembayaran',
subtitle:
'Laporan metode pembayaran yang digunakan.',
icon: Icons.payment_outlined,
onPressed: () {
selectedMenu = 4;
title = 'Laporan Metode Pembayaran';
setState(() {});
context.read<PaymentMethodReportBloc>().add(
PaymentMethodReportEvent
.getPaymentMethodReport(
startDate:
DateFormatter.formatDateTime(
fromDate),
endDate:
DateFormatter.formatDateTime(
toDate)),
);
},
isActive: selectedMenu == 4,
),
],
),
),
),
),
),
// RIGHT CONTENT
Expanded(
flex: 4,
child: selectedMenu == 0
? BlocBuilder<TransactionReportBloc,
TransactionReportState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
loaded: (transactionReport) {
return TransactionReportWidget(
transactionReport: transactionReport,
title: title,
searchDateFormatted: searchDateFormatted,
headerWidgets: _getTitleReportPageWidget(),
);
},
);
},
)
: selectedMenu == 1
? BlocBuilder<ItemSalesReportBloc,
ItemSalesReportState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
loaded: (itemSales) {
return ItemSalesReportWidget(
itemSales: itemSales,
title: title,
searchDateFormatted:
searchDateFormatted,
headerWidgets:
_getItemSalesPageWidget(),
);
},
);
},
)
: selectedMenu == 2
? BlocBuilder<ProductSalesBloc,
ProductSalesState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
success: (productSales) {
return ProductSalesChartWidgets(
title: title,
searchDateFormatted:
searchDateFormatted,
productSales: productSales,
);
},
);
},
)
: selectedMenu == 3
? BlocBuilder<SummaryBloc, SummaryState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child:
CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
success: (summary) {
return SummaryReportWidget(
summary: summary,
title: title,
searchDateFormatted:
searchDateFormatted,
);
},
);
},
)
: selectedMenu == 4
? BlocBuilder<PaymentMethodReportBloc,
PaymentMethodReportState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child:
CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
loaded: (paymentMethodData) {
return PaymentMethodReportWidget(
paymentMethodData:
paymentMethodData,
title: title,
searchDateFormatted:
searchDateFormatted,
headerWidgets:
_getPaymentMethodPageWidget(),
);
},
);
},
)
: const SizedBox.shrink()),
],
),
),
// RIGHT CONTENT
Expanded(
flex: 2,
child: selectedMenu == 0
? BlocBuilder<TransactionReportBloc, TransactionReportState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
loaded: (transactionReport) {
return TransactionReportWidget(
transactionReport: transactionReport,
title: title,
searchDateFormatted: searchDateFormatted,
headerWidgets: _getTitleReportPageWidget(),
);
},
);
},
)
: selectedMenu == 1
? BlocBuilder<ItemSalesReportBloc, ItemSalesReportState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
loaded: (itemSales) {
return ItemSalesReportWidget(
itemSales: itemSales,
title: title,
searchDateFormatted: searchDateFormatted,
headerWidgets: _getItemSalesPageWidget(),
);
},
);
},
)
: selectedMenu == 2
? BlocBuilder<ProductSalesBloc, ProductSalesState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
success: (productSales) {
return ProductSalesChartWidgets(
title: title,
searchDateFormatted: searchDateFormatted,
productSales: productSales,
);
},
);
},
)
: selectedMenu == 3
? BlocBuilder<SummaryBloc, SummaryState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
success: (summary) {
return SummaryReportWidget(
summary: summary,
title: title,
searchDateFormatted: searchDateFormatted,
);
},
);
},
)
: selectedMenu == 4
? BlocBuilder<PaymentMethodReportBloc, PaymentMethodReportState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
loaded: (paymentMethodData) {
return PaymentMethodReportWidget(
paymentMethodData: paymentMethodData,
title: title,
searchDateFormatted: searchDateFormatted,
headerWidgets: _getPaymentMethodPageWidget(),
);
},
);
},
)
: const SizedBox.shrink()),
],
),
);
@@ -314,11 +364,11 @@ class _ReportPageState extends State<ReportPage> {
List<Widget> _getItemSalesPageWidget() {
return [
_getTitleItemWidget('ID', 80),
_getTitleItemWidget('Order', 60),
_getTitleItemWidget('Product', 160),
_getTitleItemWidget('Order', 100),
_getTitleItemWidget('Product', 200),
_getTitleItemWidget('Qty', 60),
_getTitleItemWidget('Price', 140),
_getTitleItemWidget('Total Price', 140),
_getTitleItemWidget('Price', 150),
_getTitleItemWidget('Total Price', 160),
];
}