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

View File

@ -1,4 +1,4 @@
# EnakloPOS
# ApskelPOS
A new Flutter project.

View File

@ -11,7 +11,7 @@
<!-- Izin khusus untuk akses foto (media images) di Android 33 ke atas -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<application
android:label="EnakloPOS"
android:label="ApskelPOS"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
<activity

View File

@ -5,7 +5,7 @@ import 'lib/core/utils/app_icon_generator.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
print('Generating EnakloPOS app icon...');
print('Generating ApskelPOS app icon...');
try {
final iconData = await AppIconGenerator.generateAppIcon();
@ -20,14 +20,14 @@ void main() async {
final iconFile = File('assets/logo/logo_app_icon.png');
await iconFile.writeAsBytes(iconData);
print('✅ App icon generated successfully at: assets/logo/logo_app_icon.png');
print(
'✅ App icon generated successfully at: assets/logo/logo_app_icon.png');
print('📱 The icon features:');
print(' - White background for visibility');
print(' - Blue circular background');
print(' - Gift box with "e" inside');
print(' - "ENAKLO" and "POS" text');
print(' - 1024x1024 resolution for high quality');
} catch (e) {
print('❌ Error generating app icon: $e');
}

View File

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>EnakloPOS</string>
<string>ApskelPOS</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>

View File

@ -38,7 +38,7 @@ class ItemSalesInvoice {
return HelperPdfService.saveDocument(
name:
'Enaklo POS | Item Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
'Apskel POS | Item Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
pdf: pdf);
}
@ -48,7 +48,7 @@ class ItemSalesInvoice {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 1 * PdfPageFormat.cm),
Text('Enaklo POS | Item Sales Report',
Text('Apskel POS | Item Sales Report',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,

View File

@ -28,7 +28,8 @@ class RevenueInvoice {
// Load logo image
log("Loading logo image...");
final ByteData dataImage = await rootBundle.load('assets/images/logo.png');
final ByteData dataImage =
await rootBundle.load('assets/images/logo.png');
final Uint8List bytes = dataImage.buffer.asUint8List();
final image = pw.MemoryImage(bytes);
log("Logo image loaded successfully, size: ${bytes.length} bytes");
@ -49,7 +50,7 @@ class RevenueInvoice {
log("Saving PDF document...");
return HelperPdfService.saveDocument(
name:
'Enaklo POS | Summary Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
'Apskel POS | Summary Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
pdf: pdf,
);
} catch (e) {
@ -69,7 +70,7 @@ class RevenueInvoice {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 1 * PdfPageFormat.cm),
Text('Enaklo POS | Summary Sales Report',
Text('Apskel POS | Summary Sales Report',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
@ -125,7 +126,8 @@ class RevenueInvoice {
buildText(
title: 'Discount',
titleStyle: TextStyle(fontWeight: FontWeight.normal),
value: "- ${safeParseInt(summaryModel.totalDiscount).currencyFormatRp}",
value:
"- ${safeParseInt(summaryModel.totalDiscount).currencyFormatRp}",
unite: true,
textStyle: TextStyle(
color: PdfColor.fromHex('#FF0000'),
@ -147,7 +149,8 @@ class RevenueInvoice {
titleStyle: TextStyle(
fontWeight: FontWeight.normal,
),
value: safeParseInt(summaryModel.totalServiceCharge).currencyFormatRp,
value:
safeParseInt(summaryModel.totalServiceCharge).currencyFormatRp,
unite: true,
),
Divider(),

View File

@ -38,7 +38,7 @@ class TransactionSalesInvoice {
return HelperPdfService.saveDocument(
name:
'Enaklo POS | Transaction Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
'Apskel POS | Transaction Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
pdf: pdf);
}
@ -48,7 +48,7 @@ class TransactionSalesInvoice {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 1 * PdfPageFormat.cm),
Text('Enaklo POS | Transaction Sales Report',
Text('Apskel POS | Transaction Sales Report',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,

View File

@ -35,7 +35,7 @@ class PrintDataoutputs {
final total = totalPrice + pajak;
bytes += generator.reset();
bytes += generator.text('Enaklo POS',
bytes += generator.text('Apskel POS',
styles: const PosStyles(
bold: true,
align: PosAlign.center,
@ -202,7 +202,7 @@ class PrintDataoutputs {
// bytes += generator.feed(3);
// }
bytes += generator.text('Enaklo POS',
bytes += generator.text('Apskel POS',
styles: const PosStyles(
bold: true,
align: PosAlign.center,
@ -474,21 +474,21 @@ class PrintDataoutputs {
}
Future<List<int>> printOrderV3(
List<ProductQuantity> products,
int totalQuantity,
int totalPrice,
String paymentMethod,
int nominalBayar,
int kembalian,
int subTotal,
int discount,
int pajak,
int serviceCharge,
String namaKasir,
String customerName,
int paper,
{int taxPercentage = 11, int serviceChargePercentage = 5}
) async {
List<ProductQuantity> products,
int totalQuantity,
int totalPrice,
String paymentMethod,
int nominalBayar,
int kembalian,
int subTotal,
int discount,
int pajak,
int serviceCharge,
String namaKasir,
String customerName,
int paper,
{int taxPercentage = 11,
int serviceChargePercentage = 5}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
@ -778,8 +778,13 @@ class PrintDataoutputs {
return bytes;
}
Future<List<int>> printChecker(List<ProductQuantity> products,
String tableName, String draftName, String cashierName, int paper, String orderType) async {
Future<List<int>> printChecker(
List<ProductQuantity> products,
String tableName,
String draftName,
String cashierName,
int paper,
String orderType) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
@ -908,8 +913,13 @@ class PrintDataoutputs {
return bytes;
}
Future<List<int>> printKitchen(List<ProductQuantity> products,
String tableNumber, String draftName, String cashierName, int paper, String orderType) async {
Future<List<int>> printKitchen(
List<ProductQuantity> products,
String tableNumber,
String draftName,
String cashierName,
int paper,
String orderType) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();

View File

@ -49,7 +49,7 @@ class _LoginPageState extends State<LoginPage> {
const SpaceHeight(24.0),
const Center(
child: Text(
'Enaklo POS',
'Apskel POS',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,

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),
];
}

View File

@ -4,12 +4,12 @@ import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/utils/helper_pdf_service.dart';
import 'package:enaklo_pos/presentation/report/widgets/report_page_title.dart';
import 'package:flutter/material.dart';
import 'package:enaklo_pos/core/utils/item_sales_invoice.dart';
import 'package:enaklo_pos/core/utils/permession_handler.dart';
import 'package:enaklo_pos/data/models/response/item_sales_response_model.dart';
import 'package:horizontal_data_table/horizontal_data_table.dart';
import 'package:permission_handler/permission_handler.dart';
class ItemSalesReportWidget extends StatelessWidget {
final String title;
@ -26,166 +26,123 @@ class ItemSalesReportWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Card(
color: const Color.fromARGB(255, 255, 255, 255),
child: Column(
children: [
const SpaceHeight(24.0),
Center(
child: Text(
title,
style:
const TextStyle(fontWeight: FontWeight.w800, fontSize: 16.0),
),
),
const SizedBox(
height: 8.0,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
searchDateFormatted,
style: const TextStyle(fontSize: 16.0),
return Column(
children: [
ReportPageTitle(
title: title,
searchDateFormatted: searchDateFormatted,
onExport: () async {
try {
final status = await PermessionHelper().checkPermission();
if (status) {
final pdfFile = await ItemSalesInvoice.generate(
itemSales, searchDateFormatted);
log("pdfFile: $pdfFile");
await HelperPdfService.openFile(pdfFile);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Storage permission is required to save PDF'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
log("Error generating PDF: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to generate PDF: $e'),
backgroundColor: Colors.red,
),
GestureDetector(
onTap: () async {
try {
final status = await PermessionHelper().checkPermission();
if (status) {
final pdfFile = await ItemSalesInvoice.generate(
itemSales, searchDateFormatted);
log("pdfFile: $pdfFile");
await HelperPdfService.openFile(pdfFile);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Storage permission is required to save PDF'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
log("Error generating PDF: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to generate PDF: $e'),
backgroundColor: Colors.red,
),
);
}
},
child: const Row(
children: [
Text(
"PDF",
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
);
}
},
),
const SpaceHeight(16.0),
Expanded(
child: Padding(
padding: const EdgeInsets.all(12),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: HorizontalDataTable(
leftHandSideColumnWidth: 80,
rightHandSideColumnWidth: 670,
isFixedHeader: true,
headerWidgets: headerWidgets,
// isFixedFooter: true,
// footerWidgets: _getTitleWidget(),
leftSideItemBuilder: (context, index) {
return Container(
width: 80,
height: 52,
alignment: Alignment.centerLeft,
child: Center(child: Text(itemSales[index].id.toString())),
);
},
rightSideItemBuilder: (context, index) {
return Row(
children: <Widget>[
Container(
width: 100,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child: Text(itemSales[index].orderId.toString())),
),
Container(
width: 200,
height: 52,
alignment: Alignment.centerLeft,
child:
Center(child: Text(itemSales[index].productName!)),
),
Container(
width: 60,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child: Text(itemSales[index].quantity.toString())),
),
Container(
width: 150,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
itemSales[index].price!.currencyFormatRp,
)),
),
Container(
width: 160,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
(itemSales[index].price! * itemSales[index].quantity!)
.currencyFormatRp,
)),
),
Icon(
Icons.download_outlined,
color: AppColors.primary,
)
],
),
);
},
itemCount: itemSales.length,
rowSeparatorWidget: const Divider(
color: Colors.black38,
height: 1.0,
thickness: 0.0,
),
],
),
),
const SpaceHeight(16.0),
Expanded(
child: Padding(
padding: const EdgeInsets.all(12),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: HorizontalDataTable(
leftHandSideColumnWidth: 80,
rightHandSideColumnWidth: 560,
isFixedHeader: true,
headerWidgets: headerWidgets,
leftHandSideColBackgroundColor: AppColors.white,
rightHandSideColBackgroundColor: AppColors.white,
// isFixedFooter: true,
// footerWidgets: _getTitleWidget(),
leftSideItemBuilder: (context, index) {
return Container(
width: 80,
height: 52,
alignment: Alignment.centerLeft,
child:
Center(child: Text(itemSales[index].id.toString())),
);
},
rightSideItemBuilder: (context, index) {
return Row(
children: <Widget>[
Container(
width: 60,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child: Text(itemSales[index].orderId.toString())),
),
Container(
width: 160,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child: Text(itemSales[index].productName!)),
),
Container(
width: 60,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child:
Text(itemSales[index].quantity.toString())),
),
Container(
width: 140,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
itemSales[index].price!.currencyFormatRp,
)),
),
Container(
width: 140,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
(itemSales[index].price! *
itemSales[index].quantity!)
.currencyFormatRp,
)),
),
],
);
},
itemCount: itemSales.length,
rowSeparatorWidget: const Divider(
color: Colors.black38,
height: 1.0,
thickness: 0.0,
),
leftHandSideColBackgroundColor: AppColors.white,
rightHandSideColBackgroundColor: AppColors.white,
itemExtent: 55,
),
itemExtent: 55,
),
),
),
],
),
),
],
);
}
}

View File

@ -1,9 +1,7 @@
import 'package:flutter/material.dart';
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/extensions/string_ext.dart';
import 'package:enaklo_pos/data/models/response/payment_method_response_model.dart';
import 'package:enaklo_pos/presentation/report/widgets/report_title.dart';
import '../../../core/components/spaces.dart';
@ -109,20 +107,20 @@ class PaymentMethodReportWidget extends StatelessWidget {
),
),
child: Row(
children: [
_getBodyItemWidget(
item.paymentMethod ?? '-',
180,
),
_getBodyItemWidget(
item.totalAmount?.currencyFormatRpV2 ?? 'Rp 0',
180,
),
_getBodyItemWidget(
item.transactionCount?.toString() ?? '0',
180,
),
],
children: [
_getBodyItemWidget(
item.paymentMethod ?? '-',
180,
),
_getBodyItemWidget(
item.totalAmount?.currencyFormatRpV2 ?? 'Rp 0',
180,
),
_getBodyItemWidget(
item.transactionCount?.toString() ?? '0',
180,
),
],
),
);
}).toList() ??

View File

@ -1,6 +1,7 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/presentation/report/widgets/report_page_title.dart';
import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
@ -67,59 +68,61 @@ class _ProductSalesChartWidgetsState extends State<ProductSalesChartWidgets> {
@override
Widget build(BuildContext context) {
return Card(
color: const Color.fromARGB(255, 255, 255, 255),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: Column(
children: [
const SpaceHeight(24.0),
Center(
child: Text(
widget.title,
style: const TextStyle(
fontWeight: FontWeight.w800, fontSize: 16.0),
),
),
Center(
child: Text(
widget.searchDateFormatted,
style: const TextStyle(fontSize: 16.0),
),
),
const SpaceHeight(16.0),
PieChart(
dataMap: dataMap2,
animationDuration: Duration(milliseconds: 800),
chartLegendSpacing: 32,
chartRadius: MediaQuery.of(context).size.width / 3.2,
colorList: colorList,
initialAngleInDegree: 0,
chartType: ChartType.disc,
ringStrokeWidth: 32,
// centerText: "HYBRID",
legendOptions: LegendOptions(
showLegendsInRow: false,
legendPosition: LegendPosition.right,
showLegends: true,
legendShape: BoxShape.circle,
legendTextStyle: TextStyle(
fontWeight: FontWeight.bold,
),
),
chartValuesOptions: ChartValuesOptions(
showChartValueBackground: true,
showChartValues: true,
showChartValuesInPercentage: false,
showChartValuesOutside: false,
decimalPlaces: 0,
),
// gradientList: ---To add gradient colors---
// emptyColorGradient: ---Empty Color gradient---
)
],
return Column(
children: [
ReportPageTitle(
title: widget.title,
searchDateFormatted: widget.searchDateFormatted,
onExport: () async {},
isExport: false, // Set to false if export is not needed
),
),
const SpaceHeight(16.0),
Expanded(
child: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(16.0),
margin: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
PieChart(
dataMap: dataMap2,
animationDuration: Duration(milliseconds: 800),
chartLegendSpacing: 32,
chartRadius: MediaQuery.of(context).size.width / 3.2,
colorList: colorList,
initialAngleInDegree: 0,
chartType: ChartType.disc,
ringStrokeWidth: 32,
// centerText: "HYBRID",
legendOptions: LegendOptions(
showLegendsInRow: false,
legendPosition: LegendPosition.right,
showLegends: true,
legendShape: BoxShape.circle,
legendTextStyle: TextStyle(
fontWeight: FontWeight.bold,
),
),
chartValuesOptions: ChartValuesOptions(
showChartValueBackground: true,
showChartValues: true,
showChartValuesInPercentage: false,
showChartValuesOutside: false,
decimalPlaces: 0,
),
// gradientList: ---To add gradient colors---
// emptyColorGradient: ---Empty Color gradient---
),
],
),
),
),
)
],
);
}
}

View File

@ -1,13 +1,12 @@
import 'package:flutter/material.dart';
import 'package:enaklo_pos/core/assets/assets.gen.dart';
import '../../../core/components/spaces.dart';
import '../../../core/constants/colors.dart';
class ReportMenu extends StatelessWidget {
final String label;
final String subtitle;
final IconData icon;
final VoidCallback onPressed;
final bool isActive;
@ -16,6 +15,8 @@ class ReportMenu extends StatelessWidget {
required this.label,
required this.onPressed,
required this.isActive,
required this.subtitle,
required this.icon,
});
@override
@ -23,38 +24,43 @@ class ReportMenu extends StatelessWidget {
return GestureDetector(
onTap: onPressed,
child: Container(
margin: const EdgeInsets.all(5.0),
width: 180.0,
height: 160.0,
alignment: Alignment.center,
padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
color:
isActive ? AppColors.primary.withOpacity(0.13) : AppColors.white,
borderRadius: BorderRadius.circular(18.0),
border: Border.all(
color: isActive ? AppColors.primary : AppColors.stroke,
border: Border(
right: BorderSide(
color: isActive ? AppColors.primary : Colors.transparent,
width: 4.0,
),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
child: Row(
children: [
Assets.icons.report.svg(
colorFilter: isActive
? const ColorFilter.mode(
AppColors.primary,
BlendMode.srcIn,
)
: null,
Icon(
icon,
size: 24.0,
color: isActive ? AppColors.primary : AppColors.grey,
),
const SpaceHeight(28.0),
Text(
label,
style: TextStyle(
color: isActive ? AppColors.primary : AppColors.black,
fontWeight: FontWeight.w600,
const SpaceWidth(12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4.0),
Text(
subtitle,
style:
const TextStyle(fontSize: 14.0, color: AppColors.grey),
),
],
),
),
const SpaceHeight(24.0),
],
),
),

View File

@ -0,0 +1,65 @@
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:flutter/material.dart';
class ReportPageTitle extends StatelessWidget {
final String title;
final String searchDateFormatted;
final Function() onExport;
final bool isExport;
const ReportPageTitle(
{super.key,
required this.title,
required this.searchDateFormatted,
required this.onExport,
this.isExport = true});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(color: AppColors.white),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w800, fontSize: 16.0),
),
const SizedBox(
height: 8.0,
),
Text(
searchDateFormatted,
style: const TextStyle(fontSize: 16.0),
),
],
),
if (isExport)
GestureDetector(
onTap: onExport,
child: const Row(
children: [
Text(
"PDF",
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
),
Icon(
Icons.download_outlined,
color: AppColors.primary,
)
],
),
),
],
),
);
}
}

View File

@ -1,38 +1,60 @@
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:flutter/material.dart';
import 'package:enaklo_pos/core/components/components.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import '../../../core/constants/colors.dart';
class ReportTitle extends StatelessWidget {
const ReportTitle({super.key});
final List<Widget>? actionWidget;
const ReportTitle({super.key, this.actionWidget});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Report',
style: TextStyle(
color: AppColors.primary,
fontSize: 28,
fontWeight: FontWeight.w600,
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 10.0,
),
width: double.infinity,
height: context.deviceHeight * 0.1,
decoration: const BoxDecoration(
color: AppColors.white,
border: Border(
bottom: BorderSide(
color: AppColors.background,
width: 1.0,
),
),
const SpaceHeight(4.0),
Text(
DateTime.now().toFormattedDate(),
style: const TextStyle(
color: AppColors.subtitle,
fontSize: 16,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Laporan',
style: TextStyle(
color: AppColors.black,
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
Text(
DateTime.now().toFormattedDate2(),
style: TextStyle(
color: AppColors.grey,
fontSize: 14,
),
),
],
),
),
const SpaceHeight(20.0),
const Divider(),
],
if (actionWidget != null)
Row(
children: actionWidget!,
),
],
),
);
}
}

View File

@ -9,7 +9,6 @@ import 'package:enaklo_pos/core/utils/helper_pdf_service.dart';
import 'package:enaklo_pos/core/utils/permession_handler.dart';
import 'package:enaklo_pos/data/models/response/summary_response_model.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../../core/utils/revenue_invoice.dart';
@ -55,7 +54,8 @@ class SummaryReportWidget extends StatelessWidget {
log("PDF button clicked for summary report");
try {
log("Checking permissions...");
final status = await PermessionHelper().checkPermission();
final status =
await PermessionHelper().checkPermission();
log("Permission status: $status");
if (status) {
@ -75,7 +75,8 @@ class SummaryReportWidget extends StatelessWidget {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('PDF saved successfully: ${pdfFile.path}'),
content: Text(
'PDF saved successfully: ${pdfFile.path}'),
backgroundColor: Colors.green,
),
);
@ -83,7 +84,8 @@ class SummaryReportWidget extends StatelessWidget {
log("Permission denied");
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Storage permission is required to save PDF'),
content: Text(
'Storage permission is required to save PDF'),
backgroundColor: Colors.red,
),
);

View File

@ -5,12 +5,12 @@ import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/utils/helper_pdf_service.dart';
import 'package:enaklo_pos/presentation/report/widgets/report_page_title.dart';
import 'package:flutter/material.dart';
import 'package:enaklo_pos/core/utils/permession_handler.dart';
import 'package:enaklo_pos/core/utils/transaction_sales_invoice.dart';
import 'package:enaklo_pos/data/models/response/order_remote_datasource.dart';
import 'package:horizontal_data_table/horizontal_data_table.dart';
import 'package:permission_handler/permission_handler.dart';
class TransactionReportWidget extends StatelessWidget {
final String title;
@ -27,208 +27,168 @@ class TransactionReportWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Card(
color: const Color.fromARGB(255, 255, 255, 255),
child: Column(
children: [
const SpaceHeight(24.0),
Center(
child: Text(
title,
style:
const TextStyle(fontWeight: FontWeight.w800, fontSize: 16.0),
),
),
const SizedBox(
height: 8.0,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
searchDateFormatted,
style: const TextStyle(fontSize: 16.0),
return Column(
children: [
ReportPageTitle(
title: title,
searchDateFormatted: searchDateFormatted,
onExport: () async {
try {
final status = await PermessionHelper().checkPermission();
if (status) {
final pdfFile = await TransactionSalesInvoice.generate(
transactionReport, searchDateFormatted);
log("pdfFile: $pdfFile");
await HelperPdfService.openFile(pdfFile);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Storage permission is required to save PDF'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
log("Error generating PDF: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to generate PDF: $e'),
backgroundColor: Colors.red,
),
GestureDetector(
onTap: () async {
try {
final status = await PermessionHelper().checkPermission();
if (status) {
final pdfFile = await TransactionSalesInvoice.generate(
transactionReport, searchDateFormatted);
log("pdfFile: $pdfFile");
await HelperPdfService.openFile(pdfFile);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Storage permission is required to save PDF'),
backgroundColor: Colors.red,
);
}
},
),
const SpaceHeight(16.0),
Expanded(
child: Padding(
padding: const EdgeInsets.all(12),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: HorizontalDataTable(
leftHandSideColumnWidth: 50,
rightHandSideColumnWidth: 1020,
isFixedHeader: true,
headerWidgets: headerWidgets,
// isFixedFooter: true,
// footerWidgets: _getTitleWidget(),
leftSideItemBuilder: (context, index) {
return Container(
width: 40,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child: Text(transactionReport[index].id.toString())),
);
},
rightSideItemBuilder: (context, index) {
return Row(
children: <Widget>[
Container(
width: 120,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].total!.currencyFormatRp,
)),
),
Container(
width: 120,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].subTotal!.currencyFormatRp,
)),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].tax!.currencyFormatRp,
)),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
int.parse(transactionReport[index]
.discountAmount!
.replaceAll('.00', ''))
.currencyFormatRp,
),
);
}
} catch (e) {
log("Error generating PDF: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to generate PDF: $e'),
backgroundColor: Colors.red,
),
);
}
},
child: const Row(
children: [
Text(
"PDF",
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
),
Icon(
Icons.download_outlined,
color: AppColors.primary,
)
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index]
.serviceCharge!
.currencyFormatRp,
),
),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].totalItem.toString()),
),
),
Container(
width: 150,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(transactionReport[index].namaKasir!),
),
),
Container(
width: 230,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(transactionReport[index]
.transactionTime!
.toFormattedDate()),
),
),
],
),
);
},
itemCount: transactionReport.length,
rowSeparatorWidget: const Divider(
color: Colors.black38,
height: 1.0,
thickness: 0.0,
),
],
),
),
const SpaceHeight(16.0),
Expanded(
child: Padding(
padding: const EdgeInsets.all(12),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: HorizontalDataTable(
leftHandSideColumnWidth: 50,
rightHandSideColumnWidth: 1020,
isFixedHeader: true,
headerWidgets: headerWidgets,
// isFixedFooter: true,
// footerWidgets: _getTitleWidget(),
leftSideItemBuilder: (context, index) {
return Container(
width: 40,
height: 52,
alignment: Alignment.centerLeft,
child: Center(
child: Text(transactionReport[index].id.toString())),
);
},
rightSideItemBuilder: (context, index) {
return Row(
children: <Widget>[
Container(
width: 120,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].total!.currencyFormatRp,
)),
),
Container(
width: 120,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].subTotal!.currencyFormatRp,
)),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].tax!.currencyFormatRp,
)),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
int.parse(transactionReport[index]
.discountAmount!
.replaceAll('.00', ''))
.currencyFormatRp,
),
),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index]
.serviceCharge!
.currencyFormatRp,
),
),
),
Container(
width: 100,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(
transactionReport[index].totalItem.toString()),
),
),
Container(
width: 150,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(transactionReport[index].namaKasir!),
),
),
Container(
width: 230,
height: 52,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Center(
child: Text(transactionReport[index]
.transactionTime!
.toFormattedDate()),
),
),
],
);
},
itemCount: transactionReport.length,
rowSeparatorWidget: const Divider(
color: Colors.black38,
height: 1.0,
thickness: 0.0,
),
leftHandSideColBackgroundColor: AppColors.white,
rightHandSideColBackgroundColor: AppColors.white,
leftHandSideColBackgroundColor: AppColors.white,
rightHandSideColBackgroundColor: AppColors.white,
itemExtent: 55,
),
itemExtent: 55,
),
),
),
],
),
),
],
);
}
}

View File

@ -32,7 +32,7 @@ class _SalesPageState extends State<SalesPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Enaklo POS ',
'Apskel POS ',
style: TextStyle(
color: AppColors.primary,
fontSize: 22,

View File

@ -171,8 +171,7 @@ class _ManagePrinterPageState extends State<ManagePrinterPage> {
//bytes += generator.setGlobalFont(PosFontType.fontA);
bytes += generator.reset();
bytes +=
generator.text('Enaklo POS', styles: const PosStyles(bold: true));
bytes += generator.text('Apskel POS', styles: const PosStyles(bold: true));
bytes +=
generator.text('Reverse text', styles: const PosStyles(reverse: true));
bytes += generator.text('Underlined text',

View File

@ -1,5 +1,5 @@
name: enaklo_pos
description: "EnakloPOS - Point of Sale Application"
description: "ApskelPOS - Point of Sale Application"
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev