380 lines
17 KiB
Dart
Raw Normal View History

2025-07-30 22:38:44 +07:00
import 'dart:developer';
2025-08-06 12:06:34 +07:00
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
2025-08-06 13:05:58 +07:00
import 'package:enaklo_pos/presentation/report/widgets/dashboard_analytic_widget.dart';
2025-08-06 12:06:34 +07:00
import 'package:enaklo_pos/presentation/sales/pages/sales_page.dart';
2025-07-30 22:38:44 +07:00
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:enaklo_pos/core/components/custom_date_picker.dart';
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/core/utils/date_formatter.dart';
import 'package:enaklo_pos/presentation/report/blocs/item_sales_report/item_sales_report_bloc.dart';
import 'package:enaklo_pos/presentation/report/blocs/payment_method_report/payment_method_report_bloc.dart';
import 'package:enaklo_pos/presentation/report/blocs/product_sales/product_sales_bloc.dart';
import 'package:enaklo_pos/presentation/report/blocs/summary/summary_bloc.dart';
import 'package:enaklo_pos/presentation/report/blocs/transaction_report/transaction_report_bloc.dart';
import 'package:enaklo_pos/presentation/report/widgets/item_sales_report_widget.dart';
import 'package:enaklo_pos/presentation/report/widgets/payment_method_report_widget.dart';
2025-08-06 12:32:53 +07:00
import 'package:enaklo_pos/presentation/report/widgets/product_analytic_widget.dart';
2025-07-30 22:38:44 +07:00
import 'package:enaklo_pos/presentation/report/widgets/report_menu.dart';
import 'package:enaklo_pos/presentation/report/widgets/report_title.dart';
import 'package:flutter/material.dart';
import 'package:enaklo_pos/presentation/report/widgets/transaction_report_widget.dart';
import '../../../core/components/spaces.dart';
class ReportPage extends StatefulWidget {
const ReportPage({super.key});
@override
State<ReportPage> createState() => _ReportPageState();
}
class _ReportPageState extends State<ReportPage> {
2025-08-06 13:10:40 +07:00
int selectedMenu = 0;
String title = 'Ringkasan Laporan Penjualan';
2025-07-30 22:38:44 +07:00
DateTime fromDate = DateTime.now().subtract(const Duration(days: 30));
DateTime toDate = DateTime.now();
2025-08-01 18:27:40 +07:00
@override
void initState() {
super.initState();
2025-08-06 13:10:40 +07:00
context.read<SummaryBloc>().add(
SummaryEvent.getSummary(fromDate, toDate),
2025-08-01 18:27:40 +07:00
);
}
2025-07-30 22:38:44 +07:00
@override
Widget build(BuildContext context) {
String searchDateFormatted =
'${fromDate.toFormattedDate2()} to ${toDate.toFormattedDate2()}';
return Scaffold(
2025-08-01 18:27:40 +07:00
backgroundColor: AppColors.background,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
2025-07-30 22:38:44 +07:00
children: [
2025-08-01 18:27:40 +07:00
ReportTitle(
actionWidget: [
SizedBox(
width: 300,
child: CustomDatePicker(
prefix: const Text('From: '),
initialDate: fromDate,
onDateSelected: (selectedDate) {
fromDate = selectedDate;
2025-07-30 22:38:44 +07:00
2025-08-01 18:27:40 +07:00
setState(() {});
},
2025-07-30 22:38:44 +07:00
),
),
2025-08-01 18:27:40 +07:00
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)),
// );
},
),
),
],
2025-07-30 22:38:44 +07:00
),
Expanded(
2025-08-01 18:27:40 +07:00
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: [
2025-08-06 13:10:40 +07:00
ReportMenu(
label: 'Ringkasan Laporan Penjualan',
subtitle:
'Ringkasan total penjualan dalam periode tertentu.',
icon: Icons.insert_drive_file_outlined,
onPressed: () {
selectedMenu = 0;
title = 'Ringkasan Laporan Penjualan';
setState(() {});
context.read<SummaryBloc>().add(
SummaryEvent.getSummary(fromDate, toDate),
);
log("Date ${DateFormatter.formatDateTime(fromDate)}");
},
isActive: selectedMenu == 0,
),
2025-08-01 18:27:40 +07:00
ReportMenu(
label: 'Laporan Transaksi',
subtitle:
'Menampilkan riwayat lengkap semua transaksi yang telah dilakukan.',
icon: Icons.receipt_long_outlined,
onPressed: () {
2025-08-06 12:06:34 +07:00
context.push(SalesPage(status: 'completed'));
2025-07-30 22:38:44 +07:00
},
2025-08-06 13:10:40 +07:00
isActive: selectedMenu == 1,
2025-08-01 18:27:40 +07:00
),
ReportMenu(
label: 'Laporan Penjualan Item',
subtitle:
'Laporan penjualan berdasarkan masing-masing item atau produk.',
icon: Icons.inventory_2_outlined,
onPressed: () {
2025-08-06 13:10:40 +07:00
selectedMenu = 2;
2025-08-01 18:27:40 +07:00
title = 'Laporan Penjualan Item';
setState(() {});
context.read<ItemSalesReportBloc>().add(
ItemSalesReportEvent.getItemSales(
2025-08-06 12:06:34 +07:00
startDate: fromDate, endDate: toDate),
2025-08-01 18:27:40 +07:00
);
2025-07-30 22:38:44 +07:00
},
2025-08-06 13:10:40 +07:00
isActive: selectedMenu == 2,
2025-08-01 18:27:40 +07:00
),
ReportMenu(
2025-08-06 12:32:53 +07:00
label: 'Laporan Penjualan Produk',
2025-08-01 18:27:40 +07:00
subtitle:
2025-08-06 12:32:53 +07:00
'Laporan penjualan berdasarkan masing-masing produk.',
2025-08-01 18:27:40 +07:00
icon: Icons.bar_chart_outlined,
onPressed: () {
2025-08-06 13:10:40 +07:00
selectedMenu = 3;
2025-08-06 12:32:53 +07:00
title = 'Laporan Penjualan Produk';
2025-08-01 18:27:40 +07:00
setState(() {});
context.read<ProductSalesBloc>().add(
ProductSalesEvent.getProductSales(
2025-08-06 12:32:53 +07:00
fromDate,
toDate,
),
2025-07-30 22:38:44 +07:00
);
},
2025-08-01 18:27:40 +07:00
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(
2025-08-06 11:23:03 +07:00
startDate: fromDate,
endDate: toDate,
),
2025-08-01 18:27:40 +07:00
);
},
isActive: selectedMenu == 4,
),
],
),
),
),
),
),
// RIGHT CONTENT
Expanded(
flex: 4,
child: selectedMenu == 0
2025-08-06 13:10:40 +07:00
? BlocBuilder<SummaryBloc, SummaryState>(
2025-08-01 18:27:40 +07:00
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
2025-08-06 13:10:40 +07:00
success: (data) {
return DashboardAnalyticWidget(
data: data,
2025-08-01 18:27:40 +07:00
title: title,
searchDateFormatted: searchDateFormatted,
);
},
);
},
)
: selectedMenu == 1
2025-08-06 13:10:40 +07:00
? BlocBuilder<TransactionReportBloc,
TransactionReportState>(
2025-08-01 18:27:40 +07:00
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
2025-08-06 13:10:40 +07:00
loaded: (transactionReport) {
return TransactionReportWidget(
transactionReport: transactionReport,
2025-08-01 18:27:40 +07:00
title: title,
searchDateFormatted:
searchDateFormatted,
headerWidgets:
2025-08-06 13:10:40 +07:00
_getTitleReportPageWidget(),
2025-08-01 18:27:40 +07:00
);
},
);
},
)
: selectedMenu == 2
2025-08-06 13:10:40 +07:00
? BlocBuilder<ItemSalesReportBloc,
ItemSalesReportState>(
2025-08-01 18:27:40 +07:00
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child: CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
2025-08-06 13:10:40 +07:00
loaded: (itemSales) {
return ItemSalesReportWidget(
sales: itemSales,
2025-08-01 18:27:40 +07:00
title: title,
searchDateFormatted:
searchDateFormatted,
2025-08-06 13:10:40 +07:00
headerWidgets:
_getItemSalesPageWidget(),
2025-08-01 18:27:40 +07:00
);
},
);
},
)
: selectedMenu == 3
2025-08-06 13:10:40 +07:00
? BlocBuilder<ProductSalesBloc,
ProductSalesState>(
2025-08-01 18:27:40 +07:00
builder: (context, state) {
return state.maybeWhen(
orElse: () => const Center(
child:
CircularProgressIndicator(),
),
error: (message) {
return Text(message);
},
2025-08-06 13:10:40 +07:00
success: (products) {
return ProductAnalyticsWidget(
2025-08-01 18:27:40 +07:00
title: title,
searchDateFormatted:
searchDateFormatted,
2025-08-06 13:10:40 +07:00
productData: products,
2025-08-01 18:27:40 +07:00
);
},
);
},
)
: 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()),
],
),
),
2025-07-30 22:38:44 +07:00
],
),
);
}
List<Widget> _getTitleReportPageWidget() {
return [
_getTitleItemWidget('ID', 120),
_getTitleItemWidget('Total', 100),
_getTitleItemWidget('Sub Total', 100),
_getTitleItemWidget('Tax', 100),
_getTitleItemWidget('Disocunt', 100),
_getTitleItemWidget('Service', 100),
_getTitleItemWidget('Total Item', 100),
_getTitleItemWidget('Cashier', 180),
_getTitleItemWidget('Time', 200),
];
}
List<Widget> _getItemSalesPageWidget() {
return [
_getTitleItemWidget('ID', 80),
2025-08-01 18:27:40 +07:00
_getTitleItemWidget('Order', 100),
_getTitleItemWidget('Product', 200),
2025-07-30 22:38:44 +07:00
_getTitleItemWidget('Qty', 60),
2025-08-01 18:27:40 +07:00
_getTitleItemWidget('Price', 150),
_getTitleItemWidget('Total Price', 160),
2025-07-30 22:38:44 +07:00
];
}
List<Widget> _getPaymentMethodPageWidget() {
return [
_getTitleItemWidget('Payment Method', 180),
_getTitleItemWidget('Total Amount', 180),
_getTitleItemWidget('Transaction Count', 180),
];
}
Widget _getTitleItemWidget(String label, double width) {
return Container(
width: width,
height: 56,
color: AppColors.primary,
alignment: Alignment.centerLeft,
child: Center(
child: Text(
label,
style: TextStyle(
color: Colors.white,
),
),
),
);
}
}