400 lines
18 KiB
Dart
400 lines
18 KiB
Dart
import 'dart:developer';
|
|
|
|
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';
|
|
import 'package:enaklo_pos/presentation/report/widgets/product_sales_chart_widget.dart';
|
|
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/summary_report_widget.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> {
|
|
int selectedMenu = 0;
|
|
String title = 'Transaction Report';
|
|
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(
|
|
backgroundColor: AppColors.background,
|
|
body: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
ReportTitle(
|
|
actionWidget: [
|
|
SizedBox(
|
|
width: 300,
|
|
child: CustomDatePicker(
|
|
prefix: const Text('From: '),
|
|
initialDate: fromDate,
|
|
onDateSelected: (selectedDate) {
|
|
fromDate = selectedDate;
|
|
|
|
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()),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
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),
|
|
_getTitleItemWidget('Order', 100),
|
|
_getTitleItemWidget('Product', 200),
|
|
_getTitleItemWidget('Qty', 60),
|
|
_getTitleItemWidget('Price', 150),
|
|
_getTitleItemWidget('Total Price', 160),
|
|
];
|
|
}
|
|
|
|
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,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|